diff --git a/.gitignore b/.gitignore index 3aa34d9c5..2b7352d95 100644 --- a/.gitignore +++ b/.gitignore @@ -457,3 +457,4 @@ soh/properties.h # Tools /clang-format /clang-format.exe +*.o2r diff --git a/run-clang-format.ps1 b/run-clang-format.ps1 index 063cec7af..3ff6998a6 100644 --- a/run-clang-format.ps1 +++ b/run-clang-format.ps1 @@ -25,7 +25,7 @@ if (-not (Test-Path $clangFormatFilePath) -or ($currentVersion -ne $requiredVers } $wc = New-Object net.webclient - $wc.Downloadfile($url, $llvmInstallerPath) + $wc.Downloadfile($url, $PSScriptRoot + $llvmInstallerPath) $sevenZipPath = "C:\Program Files\7-Zip\7z.exe" $specificFileInArchive = "bin\clang-format.exe" diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json b/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json index a89c12889..04fc1f8f2 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_eng.json @@ -2,6 +2,7 @@ "health": "Health - $0 Hearts", "magic": "Magic - $0", "rupees": "Rupees - $0", + "keys": "Keys - $0", "floor": "Floor $0", "basement": "Basement $0", "item_menu": "Select Item", diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json b/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json index 116c19a41..93e0058dc 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_fra.json @@ -2,6 +2,7 @@ "health": "Vie - $0 Coeurs", "magic": "Magie - $0", "rupees": "Rubis - $0", + "keys": "Clés - $0", "floor": "Étage $0", "basement": "Sous-sol $0", "item_menu": "Inventaire", diff --git a/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json b/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json index 649790da3..f66b82736 100644 --- a/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json +++ b/soh/assets/custom/accessibility/texts/kaleidoscope_ger.json @@ -2,6 +2,7 @@ "health": "Energie - $0 Herzen", "magic": "Magie - $0", "rupees": "Rubine - $0", + "keys": "Schlüssel - $0", "floor": "Etage $0", "basement": "Keller $0", "item_menu": "Gegenstände", diff --git a/soh/assets/custom/presets/Main Enhanced.json b/soh/assets/custom/presets/Main Enhanced.json index 026a78de7..5e63d651f 100644 --- a/soh/assets/custom/presets/Main Enhanced.json +++ b/soh/assets/custom/presets/Main Enhanced.json @@ -44,6 +44,9 @@ "SkipText": 1, "TextSpeed": 5, "TimeFlowFileSelect": 1, + "TimeSavers": { + "SkipJabuJabuFish": 1 + }, "TwoHandedIdle": 1, "VisualAgony": 1, "WidescreenActorCulling": 1 diff --git a/soh/assets/custom/presets/Main Randomizer.json b/soh/assets/custom/presets/Main Randomizer.json index 59c24e982..7ece7315a 100644 --- a/soh/assets/custom/presets/Main Randomizer.json +++ b/soh/assets/custom/presets/Main Randomizer.json @@ -116,6 +116,7 @@ "Story": 1 }, "SkipForcedDialog": 3, + "SkipJabuJabuFish": 1, "SkipMiscInteractions": 1, "SkipOwlInteractions": 1, "SkipTowerEscape": 1, diff --git a/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp b/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp index d078316c9..aca55d714 100644 --- a/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp +++ b/soh/soh/Enhancements/Cheats/Infinite/Magic.cpp @@ -1,9 +1,10 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" -#include "z64save.h" -extern "C" SaveContext gSaveContext; +extern "C" { +#include "z64save.h" +extern SaveContext gSaveContext; +} #define CVAR_INFINITE_MAGIC_NAME CVAR_CHEAT("InfiniteMagic") #define CVAR_INFINITE_MAGIC_DEFAULT 0 diff --git a/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp b/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp index 3e7660b84..277868b20 100644 --- a/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp +++ b/soh/soh/Enhancements/ExtraModes/RupeeDash.cpp @@ -1,11 +1,12 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" + +extern "C" { #include "functions.h" #include "macros.h" #include "variables.h" - -extern "C" PlayState* gPlayState; +extern PlayState* gPlayState; +} static constexpr int32_t CVAR_RUPEE_DASH_DEFAULT = 0; #define CVAR_RUPEE_DASH_NAME CVAR_ENHANCEMENT("RupeeDash") diff --git a/soh/soh/Enhancements/ExtraTraps.cpp b/soh/soh/Enhancements/ExtraTraps.cpp index e88a8f1fe..155b1af71 100644 --- a/soh/soh/Enhancements/ExtraTraps.cpp +++ b/soh/soh/Enhancements/ExtraTraps.cpp @@ -82,7 +82,7 @@ static void RollRandomTrap(uint32_t seed) { case ADD_SPEED_TRAP: Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - GameInteractor::State::RunSpeedModifier = -2; + GameInteractor::State::MovementSpeedMultiplier = 0.5f; statusTimer = 200; Notification::Emit({ .message = "Speed Decreased!" }); break; @@ -112,7 +112,7 @@ static void RollRandomTrap(uint32_t seed) { static void OnPlayerUpdate() { Player* player = GET_PLAYER(gPlayState); if (statusTimer == 0) { - GameInteractor::State::RunSpeedModifier = 0; + GameInteractor::State::MovementSpeedMultiplier = 1.0f; } if (eventTimer == 0) { switch (roll) { diff --git a/soh/soh/Enhancements/FileSelectEnhancements.cpp b/soh/soh/Enhancements/FileSelectEnhancements.cpp index ec8810d02..d2671f20e 100644 --- a/soh/soh/Enhancements/FileSelectEnhancements.cpp +++ b/soh/soh/Enhancements/FileSelectEnhancements.cpp @@ -4,7 +4,6 @@ #include #include -#include std::array RandomizerSettingsMenuText[RSM_MAX] = { { diff --git a/soh/soh/Enhancements/Fixes/BrokenGiantsKnife.cpp b/soh/soh/Enhancements/Fixes/BrokenGiantsKnife.cpp index 6d21d812b..1bde4e50c 100644 --- a/soh/soh/Enhancements/Fixes/BrokenGiantsKnife.cpp +++ b/soh/soh/Enhancements/Fixes/BrokenGiantsKnife.cpp @@ -1,12 +1,13 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" + +extern "C" { #include "functions.h" #include "macros.h" #include "variables.h" #include "z64save.h" - -extern "C" PlayState* gPlayState; +extern PlayState* gPlayState; +} static constexpr int32_t CVAR_BGS_FIX_DEFAULT = 0; #define CVAR_BGS_FIX_NAME CVAR_ENHANCEMENT("FixBrokenGiantsKnife") diff --git a/soh/soh/Enhancements/Fixes/DekuNutUpgradeFix.cpp b/soh/soh/Enhancements/Fixes/DekuNutUpgradeFix.cpp index 2e095c59f..8096f2075 100644 --- a/soh/soh/Enhancements/Fixes/DekuNutUpgradeFix.cpp +++ b/soh/soh/Enhancements/Fixes/DekuNutUpgradeFix.cpp @@ -1,12 +1,13 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" + +extern "C" { #include "functions.h" #include "macros.h" #include "variables.h" #include "z64save.h" - -extern "C" PlayState* gPlayState; +extern PlayState* gPlayState; +} static constexpr int32_t CVAR_NUT_UPGRADE_FIX_DEFAULT = 0; #define CVAR_NUT_UPGRADE_FIX_NAME CVAR_ENHANCEMENT("DekuNutUpgradeFix") diff --git a/soh/soh/Enhancements/QoL/DaytimeGS.cpp b/soh/soh/Enhancements/QoL/DaytimeGS.cpp index 869945cb5..fabf7457b 100644 --- a/soh/soh/Enhancements/QoL/DaytimeGS.cpp +++ b/soh/soh/Enhancements/QoL/DaytimeGS.cpp @@ -1,10 +1,9 @@ -#include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/ShipInit.hpp" -#include "functions.h" -#include "macros.h" extern "C" { +#include "functions.h" +#include "macros.h" extern PlayState* gPlayState; extern SaveContext gSaveContext; } diff --git a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp index 39417d5de..d90391c0f 100644 --- a/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp +++ b/soh/soh/Enhancements/TimeSavers/SkipMiscInteractions/SkipChildRutoInteractions.cpp @@ -14,7 +14,7 @@ void Ru1Init(void* actorRef) { if (enRu1->action == 22) { enRu1->action = 27; enRu1->drawConfig = 1; - enRu1->actor.flags |= ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY; + enRu1->actor.flags &= ~(ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY); Animation_Change(&enRu1->skelAnime, (AnimationHeader*)&gRutoChildSittingAnim, 1.0f, 0.0f, Animation_GetLastFrame((void*)&gRutoChildSittingAnim), ANIMMODE_LOOP, 0.0f); } diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c index dde827ec5..b9838cf66 100644 --- a/soh/soh/Enhancements/bootcommands.c +++ b/soh/soh/Enhancements/bootcommands.c @@ -1,15 +1,7 @@ -#include "bootcommands.h" -#include "gameconsole.h" -#include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include -#include "soh/OTRGlobals.h" +#include "bootcommands.h" #include "soh/cvar_prefixes.h" void BootCommands_Init() { diff --git a/soh/soh/Enhancements/bootcommands.h b/soh/soh/Enhancements/bootcommands.h index 5c6cb8c8c..48b361b13 100644 --- a/soh/soh/Enhancements/bootcommands.h +++ b/soh/soh/Enhancements/bootcommands.h @@ -1,7 +1,5 @@ #ifndef _BOOTCOMMANDS_H_ #define _BOOTCOMMANDS_H_ -#include -#include void BootCommands_Init(); diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index 8a8227073..41a31f8be 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -1366,10 +1366,10 @@ void SohInputEditorWindow::DrawCameraControlPanel() { .Color(THEME_COLOR) .Tooltip("Allows for aiming with the right stick in:\n-First-Person/C-Up view\n-Weapon Aiming")); if (CVarGetInteger(CVAR_SETTING("Controls.RightStickAim"), 0)) { - CVarCheckbox("Allow moving while in first person mode", CVAR_SETTING("MoveInFirstPerson"), + CVarCheckbox("Allow moving while in first-person mode", CVAR_SETTING("MoveInFirstPerson"), CheckboxOptions() .Color(THEME_COLOR) - .Tooltip("Changes the left stick to move the player while in first person mode")); + .Tooltip("Changes the left stick to move the player while in first-person mode")); } CVarCheckbox("Invert Aiming X Axis", CVAR_SETTING("Controls.InvertAimingXAxis"), CheckboxOptions() @@ -1432,7 +1432,9 @@ void SohInputEditorWindow::DrawCameraControlPanel() { CheckboxOptions() .Color(THEME_COLOR) .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.")); + "controller config menu, and map the camera stick to the right stick.\n" + "Doesn't work in areas were the game locks the camera.\n" + "Scene reload may be necessary to enable.")); CVarCheckbox("Invert Camera X Axis", CVAR_SETTING("FreeLook.InvertXAxis"), CheckboxOptions().Color(THEME_COLOR).Tooltip("Inverts the Camera X Axis in:\n-Free look")); CVarCheckbox( diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 51bb84eb8..43b898476 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -47,6 +47,7 @@ class CustomMessage { TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(std::string english_, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); + // RANDOTODO trying to declare this with capital and type causes ambiguity with the first signature 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); diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index d25c3cfff..7713b48b8 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1130,7 +1130,7 @@ static bool SpeedModifierHandler(std::shared_ptr Console, const s ERROR_MESSAGE("[SOH] Unexpected arguments passed"); return 1; } - GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyRunSpeedModifier(); + GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); try { dynamic_cast(effect)->parameters[0] = std::stoi(args[1], nullptr, 10); @@ -1471,10 +1471,7 @@ static bool AvailableChecksProcessUndiscoveredExitsHandler(std::shared_ptrACProcessUndiscoveredExits ? "enabled" : "disabled"); - if (GameInteractor::IsSaveLoaded(true)) { - CheckTracker::RecalculateAvailableChecks(); - } - + CheckTracker::RecalculateAvailableChecks(); return 0; } diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index 88e943f87..e180e93ef 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -6,8 +6,6 @@ #include #include #include -#include -#include #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 547d1907a..7b514a16c 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1305,6 +1305,15 @@ void DrawQuestStatusTab() { ImGui::Text("Dungeon Items"); static int32_t dungeonItemsScene = SCENE_DEKU_TREE; + static int32_t lastDungeonScene = -1; + if (gPlayState != nullptr) { + int32_t sceneNum = gPlayState->sceneNum; + if (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_JABU_JABU_BOSS && lastDungeonScene != sceneNum) { + dungeonItemsScene = sceneNum; + lastDungeonScene = sceneNum; + } + } + PushStyleCombobox(THEME_COLOR); if (ImGui::BeginCombo("##DungeonSelect", SohUtils::GetSceneName(dungeonItemsScene).c_str())) { for (int32_t dungeonIndex = SCENE_DEKU_TREE; dungeonIndex < SCENE_JABU_JABU_BOSS + 1; dungeonIndex++) { diff --git a/soh/soh/Enhancements/enemyrandomizer.cpp b/soh/soh/Enhancements/enemyrandomizer.cpp index ec9168e69..71c02f9f4 100644 --- a/soh/soh/Enhancements/enemyrandomizer.cpp +++ b/soh/soh/Enhancements/enemyrandomizer.cpp @@ -28,33 +28,66 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy); EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play); const char* enemyCVarList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { - CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"), CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"), CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"), CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"), CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"), - CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"), - CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"), - CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlareDancer"), - CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"), CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"), - CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"), CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"), CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"), - CVAR_ENHANCEMENT("RandomizedEnemyList.GohmaLarva"), CVAR_ENHANCEMENT("RandomizedEnemyList.Guay"), - CVAR_ENHANCEMENT("RandomizedEnemyList.IceKeese"), CVAR_ENHANCEMENT("RandomizedEnemyList.InvisSkulltula"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"), CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"), - CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"), CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"), CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"), - CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), /*CVAR_ENHANCEMENT("RandomizedEnemyList.Poe"),*/ - CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"), CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"), CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"), CVAR_ENHANCEMENT("RandomizedEnemyList.SkullKid"), - CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"), CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"), - CVAR_ENHANCEMENT("RandomizedEnemyList.SpearMoblin"), CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"), CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"), - CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"), CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"), - CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"), CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Anubis"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Beamos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BigSkulltula"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BigStalchild"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Biri"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BlackKnuckle"), + CVAR_ENHANCEMENT("RandomizedEnemyList.BlueTektite"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Bubble"), + CVAR_ENHANCEMENT("RandomizedEnemyList.ClubMoblin"), + CVAR_ENHANCEMENT("RandomizedEnemyList.DarkLink"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Dinolfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Dodongo"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FireKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FlareDancer"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FloorTile"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Floormaster"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPeahat"), + CVAR_ENHANCEMENT("RandomizedEnemyList.FlyingPot"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Freezard"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Gibdo"), + CVAR_ENHANCEMENT("RandomizedEnemyList.GohmaLarva"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Guay"), + CVAR_ENHANCEMENT("RandomizedEnemyList.IceKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisFireKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisFloormaster"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisIceKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisKeese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisRedead"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisSkulltula"), + CVAR_ENHANCEMENT("RandomizedEnemyList.InvisStalfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Keese"), + CVAR_ENHANCEMENT("RandomizedEnemyList.LargeBaba"), + CVAR_ENHANCEMENT("RandomizedEnemyList.LikeLike"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Lizalfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.MadScrub"), + CVAR_ENHANCEMENT("RandomizedEnemyList.NormalWolfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.PeahatLarva"), + // CVAR_ENHANCEMENT("RandomizedEnemyList.Poe"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Redead"), + CVAR_ENHANCEMENT("RandomizedEnemyList.RedTektite"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Shabom"), + CVAR_ENHANCEMENT("RandomizedEnemyList.ShellBlade"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Skulltula"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SkullKid"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SmallBaba"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SmallStalchild"), + CVAR_ENHANCEMENT("RandomizedEnemyList.SpearMoblin"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Spike"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Stalfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Stinger"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Tailparasan"), + CVAR_ENHANCEMENT("RandomizedEnemyList.TorchSlug"), + CVAR_ENHANCEMENT("RandomizedEnemyList.Wallmaster"), + CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteKnuckle"), + CVAR_ENHANCEMENT("RandomizedEnemyList.WhiteWolfos"), + CVAR_ENHANCEMENT("RandomizedEnemyList.WitheredBaba"), }; const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { @@ -85,7 +118,13 @@ const char* enemyNameList[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { "Gohma Larva", "Guay", "Ice Keese", + "Invisible Fire Keese", + "Invisible Floormaster", + "Invisible Ice Keese", + "Invisible Keese", + "Invisible Redead", "Invisible Skulltula", + "Invisible Stalfos", "Keese", "Large Deku Baba", "Like-Like", @@ -134,20 +173,26 @@ static EnemyEntry randomizedEnemySpawnTable[RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE] = { ACTOR_EN_FIREFLY, 1 }, // Fire Keese { ACTOR_EN_FD, 0 }, // Flare Dancer (possible cause of crashes because of spawning flame actors on // sloped ground) - { ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile - { ACTOR_EN_FLOORMAS, 0 }, // Floormaster - { ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva) - { ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot - { ACTOR_EN_FZ, 0 }, // Freezard - { ACTOR_EN_RD, 32766 }, // Gibdo (standing) - { ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms) - { ACTOR_EN_CROW, 0 }, // Guay - { ACTOR_EN_FIREFLY, 4 }, // Ice Keese - { ACTOR_EN_ST, 2 }, // Skulltula (invisible) - { ACTOR_EN_FIREFLY, 2 }, // Regular Keese - { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) - // Doesn't work (reliant on surface and also normally used in tandem with a leever spawner, kills itself too quickly - // otherwise) { ACTOR_EN_REEBA, 0 }, // Leever + { ACTOR_EN_YUKABYUN, 0 }, // Flying Floor Tile + { ACTOR_EN_FLOORMAS, 0 }, // Floormaster + { ACTOR_EN_PEEHAT, -1 }, // Flying Peahat (big grounded, doesn't spawn larva) + { ACTOR_EN_TUBO_TRAP, 0 }, // Flying pot + { ACTOR_EN_FZ, 0 }, // Freezard + { ACTOR_EN_RD, 32766 }, // Gibdo (standing) + { ACTOR_EN_GOMA, 7 }, // Gohma Larva (Non-Gohma rooms) + { ACTOR_EN_CROW, 0 }, // Guay + { ACTOR_EN_FIREFLY, 4 }, // Ice Keese + { ACTOR_EN_FIREFLY, 0x8001 }, // Fire Keese (invisible) + { ACTOR_EN_FLOORMAS, 0x8000 }, // Floormaster (invisible) + { ACTOR_EN_FIREFLY, 0x8004 }, // Ice Keese (invisible) + { ACTOR_EN_FIREFLY, 0x8002 }, // Keese (invisible) + { ACTOR_EN_RD, 3 }, // Redead (invisible) + { ACTOR_EN_ST, 2 }, // Skulltula (invisible) + { ACTOR_EN_TEST, 0 }, // Stalfos (invisible) + { ACTOR_EN_FIREFLY, 2 }, // Regular Keese + { ACTOR_EN_DEKUBABA, 1 }, // Deku Baba (large) + // Doesn't work (reliant on surface, without a spawner it kills itself too quickly) + // { ACTOR_EN_REEBA, 0 }, // Leever { ACTOR_EN_RR, 0 }, // Like-Like { ACTOR_EN_ZF, -1 }, // Lizalfos { ACTOR_EN_DEKUNUTS, 768 }, // Mad Scrub (triple attack) (projectiles don't work) diff --git a/soh/soh/Enhancements/enemyrandomizer.h b/soh/soh/Enhancements/enemyrandomizer.h index c42b9da60..729d255fc 100644 --- a/soh/soh/Enhancements/enemyrandomizer.h +++ b/soh/soh/Enhancements/enemyrandomizer.h @@ -3,7 +3,7 @@ #include #include "item-tables/ItemTableTypes.h" -#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 53 +#define RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE 59 extern const char* enemyCVarList[]; extern const char* enemyNameList[]; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp index 95455926b..03667dd86 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp @@ -11,6 +11,7 @@ have functions to both enable and disable said effect. #include "GameInteractionEffect.h" #include "GameInteractor.h" #include +#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" extern "C" { #include @@ -371,19 +372,23 @@ void ForceEquipBoots::_Remove() { GameInteractor::RawAction::ForceEquipBoots(EQUIP_VALUE_BOOTS_KOKIRI); } -// MARK: - ModifyRunSpeedModifier -GameInteractionEffectQueryResult ModifyRunSpeedModifier::CanBeApplied() { +// MARK: - ModifyMovementSpeedMultiplier +GameInteractionEffectQueryResult ModifyMovementSpeedMultiplier::CanBeApplied() { if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } else { return GameInteractionEffectQueryResult::Possible; } } -void ModifyRunSpeedModifier::_Apply() { - GameInteractor::State::RunSpeedModifier = parameters[0]; +void ModifyMovementSpeedMultiplier::_Apply() { + if (parameters[0] == -2) { + GameInteractor::State::MovementSpeedMultiplier = 0.5f; + } else if (parameters[0] == 2) { + GameInteractor::State::MovementSpeedMultiplier = 2.0f; + } } -void ModifyRunSpeedModifier::_Remove() { - GameInteractor::State::RunSpeedModifier = 0; +void ModifyMovementSpeedMultiplier::_Remove() { + GameInteractor::State::MovementSpeedMultiplier = 1.0f; } // MARK: - OneHitKO @@ -485,18 +490,6 @@ void SetCollisionViewer::_Remove() { GameInteractor::RawAction::SetCollisionViewer(false); } -// MARK: - SetCosmeticsColor -GameInteractionEffectQueryResult SetCosmeticsColor::CanBeApplied() { - if (!GameInteractor::IsSaveLoaded()) { - return GameInteractionEffectQueryResult::TemporarilyNotPossible; - } else { - return GameInteractionEffectQueryResult::Possible; - } -} -void SetCosmeticsColor::_Apply() { - GameInteractor::RawAction::SetCosmeticsColor(parameters[0], parameters[1]); -} - // MARK: - RandomizeCosmetics GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { if (!GameInteractor::IsSaveLoaded()) { @@ -506,7 +499,7 @@ GameInteractionEffectQueryResult RandomizeCosmetics::CanBeApplied() { } } void RandomizeCosmetics::_Apply() { - GameInteractor::RawAction::RandomizeCosmeticsColors(true); + CosmeticsEditor_RandomizeAll(); } // MARK: - PressButton diff --git a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h index 72eb101b0..9243621d1 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractionEffect.h @@ -156,7 +156,7 @@ class ForceEquipBoots : public RemovableGameInteractionEffect, public Parameteri void _Remove() override; }; -class ModifyRunSpeedModifier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { +class ModifyMovementSpeedMultiplier : public RemovableGameInteractionEffect, public ParameterizedGameInteractionEffect { GameInteractionEffectQueryResult CanBeApplied() override; void _Apply() override; void _Remove() override; @@ -200,11 +200,6 @@ class SetCollisionViewer : public RemovableGameInteractionEffect { void _Remove() override; }; -class SetCosmeticsColor : public GameInteractionEffectBase, public ParameterizedGameInteractionEffect { - GameInteractionEffectQueryResult CanBeApplied() override; - void _Apply() override; -}; - class RandomizeCosmetics : public GameInteractionEffectBase { GameInteractionEffectQueryResult CanBeApplied() override; void _Apply() override; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index db68ad86a..8ac2d9dda 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -76,7 +76,7 @@ uint8_t GameInteractor_PacifistModeActive(); uint8_t GameInteractor_DisableZTargetingActive(); uint8_t GameInteractor_ReverseControlsActive(); int32_t GameInteractor_DefenseModifier(); -int32_t GameInteractor_RunSpeedModifier(); +float GameInteractor_MovementSpeedMultiplier(); GIGravityLevel GameInteractor_GravityLevel(); uint32_t GameInteractor_GetEmulatedButtons(); void GameInteractor_SetEmulatedButtons(uint32_t buttons); @@ -204,7 +204,7 @@ class GameInteractor { static bool DisableZTargetingActive; static bool ReverseControlsActive; static int32_t DefenseModifier; - static int32_t RunSpeedModifier; + static float MovementSpeedMultiplier; static GIGravityLevel GravityLevel; static uint32_t EmulatedButtons; static uint8_t RandomBombFuseTimerActive; @@ -566,8 +566,6 @@ class GameInteractor { static void ClearAssignedButtons(uint8_t buttonSet); static void SetTimeOfDay(uint32_t time); static void SetCollisionViewer(bool active); - static void SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue); - static void RandomizeCosmeticsColors(bool excludeBiddingWarColors); static void EmulateButtonPress(int32_t button); static void AddOrTakeAmmo(int16_t amount, int16_t item); static void EmulateRandomButtonPress(uint32_t chancePercentage = 100); @@ -575,8 +573,10 @@ class GameInteractor { static void SetPlayerInvincibility(bool active); static void ClearCutscenePointer(); - static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams); - static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams); + static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams, + std::string nameTag = ""); + static GameInteractionEffectQueryResult SpawnActor(uint32_t actorId, int32_t actorParams, + std::string nameTag = ""); }; }; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp index 779b37981..793466c19 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp @@ -1,9 +1,9 @@ #include "GameInteractor.h" #include -#include "soh/Enhancements/cosmetics/CosmeticsEditor.h" #include "soh/Enhancements/randomizer/3drando/random.hpp" #include #include "soh/Enhancements/debugger/colViewer.h" +#include "soh/Enhancements/nametag.h" extern "C" { #include "variables.h" @@ -405,125 +405,6 @@ void GameInteractor::RawAction::SetCollisionViewer(bool active) { } } -void GameInteractor::RawAction::SetCosmeticsColor(uint8_t cosmeticCategory, uint8_t colorValue) { - Color_RGBA8 newColor; - newColor.r = 255; - newColor.g = 255; - newColor.b = 255; - newColor.a = 255; - - switch (colorValue) { - case GI_COLOR_RED: - newColor.r = 200; - newColor.g = 30; - newColor.b = 30; - break; - case GI_COLOR_GREEN: - newColor.r = 50; - newColor.g = 200; - newColor.b = 50; - break; - case GI_COLOR_BLUE: - newColor.r = 50; - newColor.g = 50; - newColor.b = 200; - break; - case GI_COLOR_ORANGE: - newColor.r = 200; - newColor.g = 120; - newColor.b = 0; - break; - case GI_COLOR_YELLOW: - newColor.r = 234; - newColor.g = 240; - newColor.b = 33; - break; - case GI_COLOR_PURPLE: - newColor.r = 144; - newColor.g = 13; - newColor.b = 178; - break; - case GI_COLOR_PINK: - newColor.r = 215; - newColor.g = 93; - newColor.b = 246; - break; - case GI_COLOR_BROWN: - newColor.r = 108; - newColor.g = 72; - newColor.b = 15; - break; - case GI_COLOR_BLACK: - newColor.r = 0; - newColor.g = 0; - newColor.b = 0; - break; - default: - break; - } - - switch (cosmeticCategory) { - case GI_COSMETICS_TUNICS: - 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(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(CVAR_COSMETIC("Link.Hair.Value"), newColor); - CVarSetInteger(CVAR_COSMETIC("Link.Hair.Changed"), 1); - break; - } - - Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); - ApplyOrResetCustomGfxPatches(); -} - -void GameInteractor::RawAction::RandomizeCosmeticsColors(bool excludeBiddingWarColors) { - const char* cvarsToLock[12] = { - 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) { - for (uint8_t i = 0; i < 12; i++) { - CVarSetInteger(cvarsToLock[i], 1); - } - } - - CosmeticsEditor_RandomizeAll(); - - if (excludeBiddingWarColors) { - for (uint8_t i = 0; i < 12; i++) { - CVarSetInteger(cvarsToLock[i], 0); - } - } -} - void GameInteractor::RawAction::EmulateButtonPress(int32_t button) { GameInteractor::State::EmulatedButtons |= button; } @@ -580,8 +461,8 @@ void GameInteractor::RawAction::ClearCutscenePointer() { gPlayState->csCtx.segment = &null_cs; } -GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, - int32_t enemyParams) { +GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams, + std::string nameTag) { if (!GameInteractor::CanSpawnActor()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; @@ -651,15 +532,29 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset pos.x += 10; pos.y += 10; pos.z += 10; - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) == - NULL) { + Actor* actor = + Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0); + if (actor == NULL) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; } + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor(actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } } return GameInteractionEffectQueryResult::Possible; } else { - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0) != - NULL) { + Actor* actor = + Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, pos.x, pos.y, pos.z, 0, 0, 0, enemyParams, 0); + if (actor != NULL) { + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor(actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } return GameInteractionEffectQueryResult::Possible; } } @@ -667,7 +562,8 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset return GameInteractionEffectQueryResult::TemporarilyNotPossible; } -GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t actorId, int32_t actorParams) { +GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t actorId, int32_t actorParams, + std::string nameTag) { if (!GameInteractor::CanSpawnActor()) { return GameInteractionEffectQueryResult::TemporarilyNotPossible; @@ -684,6 +580,9 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t return GameInteractionEffectQueryResult::TemporarilyNotPossible; } + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor((Actor*)cucco, nameTag.c_str()); + } cucco->actionFunc = func_80AB70A0_nocutscene; return GameInteractionEffectQueryResult::Possible; } else if (actorId == ACTOR_EN_BOM) { @@ -703,8 +602,15 @@ GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnActor(uint32_t return GameInteractionEffectQueryResult::Possible; } else { // Generic spawn an actor at Link's position - if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, - player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0) != NULL) { + Actor* actor = Actor_Spawn(&gPlayState->actorCtx, gPlayState, actorId, player->actor.world.pos.x, + player->actor.world.pos.y, player->actor.world.pos.z, 0, 0, 0, actorParams, 0); + if (actor != NULL) { + if (nameTag != "" && CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags"), 0)) { + NameTag_RegisterForActor((Actor*)actor, nameTag.c_str()); + } + if (CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, actor, ACTORCAT_NPC); + } return GameInteractionEffectQueryResult::Possible; } } diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp index 21642dded..bdcb4f37a 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_State.cpp @@ -10,7 +10,7 @@ bool GameInteractor::State::PacifistModeActive = 0; bool GameInteractor::State::DisableZTargetingActive = 0; bool GameInteractor::State::ReverseControlsActive = 0; int32_t GameInteractor::State::DefenseModifier = 0; -int32_t GameInteractor::State::RunSpeedModifier = 0; +float GameInteractor::State::MovementSpeedMultiplier = 1.0f; GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL; uint32_t GameInteractor::State::EmulatedButtons = 0; uint8_t GameInteractor::State::RandomBombFuseTimerActive = 0; @@ -81,8 +81,8 @@ int32_t GameInteractor_DefenseModifier() { } // MARK: - GameInteractor::State::DisableCameraRotationActive -int32_t GameInteractor_RunSpeedModifier() { - return GameInteractor::State::RunSpeedModifier; +float GameInteractor_MovementSpeedMultiplier() { + return GameInteractor::State::MovementSpeedMultiplier; } // MARK: - GameInteractor::State::DisableCameraRotationActive diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 2d597bc95..21891ff81 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -1972,27 +1972,27 @@ 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 Schloß gelegt#...^", /*french*/ "$lLes êtres de sagesse ont#déjà créé un pont# vers le repaire du mal.^", - {QM_LBLUE})); + {QM_LBLUE}, {}, TEXTBOX_TYPE_BLUE)); // /*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, die 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})); + {QM_RED, QM_YELLOW}, {}, TEXTBOX_TYPE_BLUE)); // /*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, 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})); + {QM_BLUE}, {}, TEXTBOX_TYPE_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, daß der Held&#[[d]] Amulett||e|# sammelt.^", /*french*/ "$8Les êtres de sagesse attendront le héros muni de #[[d]] Médaillon||s|#.^", - {QM_RED})); + {QM_RED}, {}, TEXTBOX_TYPE_BLUE)); // /*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#|" @@ -2001,26 +2001,26 @@ void StaticData::HintTable_Init() { "#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})); + {QM_YELLOW, QM_BLUE, QM_RED}, {}, TEXTBOX_TYPE_BLUE)); // /*spanish*/$CLos sabios aguardarán a que el héroe obtenga #[[d]]# |#piedra espiritual# o #medallón#| //#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, daß der Held&#[[d]] Labyrinth||e|# abschließt.^", /*french*/ "$mLes êtres de sagesse attendront la conquête de #[[d]] Donjon||s|#.^", - {QM_PINK})); + {QM_PINK}, {}, TEXTBOX_TYPE_BLUE)); // /*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, 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})); + {QM_YELLOW}, {}, TEXTBOX_TYPE_BLUE)); // /*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#.^", /*german*/ "$gDie Weisen werden darauf&warten, daß der Held&#Greg# findet.^", /*french*/ "$gLes êtres de sagesse attendront le héros muni de #Greg#.^", - {QM_GREEN})); + {QM_GREEN}, {}, TEXTBOX_TYPE_BLUE)); /*-------------------------- @@ -2174,22 +2174,22 @@ void StaticData::HintTable_Init() { hintTextTable[RHT_CHILD_ALTAR_STONES] = HintText(CustomMessage("3 Spiritual Stones 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})); + {QM_GREEN, QM_RED, QM_BLUE}, {true, true, true}, TEXTBOX_TYPE_BLUE)); // /*spanish*/ Tres piedras espirituales halladas por Hyrule...$0#[[1]]#...^$1#[[2]]#...^$2#[[3]]#...^ 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...")); + /*french*/ "$oÀ celui qui a quête de devenir&héros...&Le futur vous accueille béant...", TEXTBOX_TYPE_BLUE)); // /*spanish*/$oPara aquel que se convierta en el héroe...&La puerta al futuro está a su disposición... 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.")); + /*french*/ "$cÀ celui qui a quête de devenir&héros...&Portez l'Ocarina et jouez&le chant du temps.", TEXTBOX_TYPE_BLUE)); // /*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 er 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.")); + /*french*/ "$iÀ celui qui a quête de devenir&héros... Présentez les Pierres&Ancestrales et jouez&le chant du temps.", TEXTBOX_TYPE_BLUE)); // /*spanish*/$iPara aquel que se convierta en el héroe...&Tome las piedras espirituales y&entone la Canción del Tiempo. 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#.^" 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 a8afd7cb2..5fcb213ff 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 @@ -313,11 +313,11 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*german*/ "Man erzählt sich, daß ein #Tauchexperiment# #[[1]]# einbrächte.", /*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]]#.", /*german*/ "Man erzählt sich, daß ein #Fisch nahe eines Wasserfalls# #[[1]]# horte.", - /*french*/ "Selon moi, #[[1]]#.", {QM_RED, QM_GREEN})); - // /*spanish*/ Según dicen, #[[1]]#. + /*french*/ "Selon moi, un #poisson près d'une cascade# a #[[1]]#.", {QM_RED, QM_GREEN})); + // /*spanish*/ Según dicen, un #pez junto a una cascada# otorga #[[1]]#. hintTextTable[RHT_GC_ROLLING_GORON_AS_ADULT] = HintText(CustomMessage("They say that #reassuring a young Goron# is rewarded with #[[1]]#.", @@ -1492,9 +1492,17 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*french*/ "Selon moi, une #rucheau derrière le Roi des Zoras# cache #[[1]]#.", {QM_RED, QM_GREEN})); // /*spanish*/ Según dicen, una #colmena detrás del rey de los zoras# esconde #[[1]]#. - hintTextTable[RHT_POT_KOKIRI_FOREST] = HintText(CustomMessage("They say that a #pot in Kokiri Forest# contains #[[1]]#.", - /*german*/ "Man erzählt sich, daß ein #Krug im Kokiri-Wald# #[[1]]# enthielte.", - /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_POT_LINKS_HOUSE] = HintText(CustomMessage("They say that the #pot in the hero's house# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_TWINS_HOUSE] = HintText(CustomMessage("They say that a #pot shared by twins# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_KNOW_IT_ALL] = HintText(CustomMessage("They say that a #know-it-all bother's pot# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Vase im Kokiri-Wald# #[[1]]# enthielte.", //TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Fôret Kokiri# contient #[[1]]#.", {QM_RED, QM_GREEN})); //TODO_TRANSLATE update to match hintTextTable[RHT_TH_BREAK_ROOM_FRONT_POT] = HintText(CustomMessage("They say that the #front pot watched by resting thieves# contains #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE @@ -1532,15 +1540,24 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*german*/ "Man erzählt sich, daß ein #Krug in der Gespensterwüste# #[[1]]# enthielte.", /*french*/ "Selon moi, une #jarre dans le Désert Hanté# contient #[[1]]#.", {QM_RED, QM_GREEN})); - hintTextTable[RHT_POT_MARKET] = HintText(CustomMessage("They say that a #pot in Market# contains #[[1]]#.", - /*german*/ "Man erzählt sich, daß ein #Krug auf dem Markt# #[[1]]# enthielte.", - /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_POT_GUARD_HOUSE] = HintText(CustomMessage("They say that a #pot in the Guard House# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Krug auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_POE_SHOP] = HintText(CustomMessage("They say that a #pot in the Poe Shop# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Krug auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_ALLEY_HOUSE] = HintText(CustomMessage("They say that a #bearded man's pot# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Krug auf dem Markt# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Place du Marché# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match hintTextTable[RHT_POT_KAKARIKO] = HintText(CustomMessage("They say that a #pot in Kakariko Village# contains #[[1]]#.", /*german*/ "Man erzählt sich, daß ein #Krug in Kakariko# #[[1]]# enthielte.", /*french*/ "Selon moi, une #jarre dans le Village de Cocorico# contient #[[1]]#.", {QM_RED, QM_GREEN})); - hintTextTable[RHT_POT_GRAVEYARD] = HintText(CustomMessage("They say that a #pot in Graveyard# contains #[[1]]#.", + hintTextTable[RHT_POT_DAMPE] = HintText(CustomMessage("They say that a #pot in gravekeeper's tomb# contains #[[1]]#.", + //TODO_TRANSLATE check these to make sure they refernce dampe's tomb not the graveyard area /*german*/ "Man erzählt sich, daß ein #Krug auf dem Friedhof# #[[1]]# enthielte.", /*french*/ "Selon moi, une #jarre dans le Cimetière# contient #[[1]]#.", {QM_RED, QM_GREEN})); @@ -1564,13 +1581,17 @@ void StaticData::HintTable_Init_Exclude_Overworld() { /*german*/ "Man erzählt sich, daß ein #Krug auf der Lon Lon-Farm# #[[1]]# enthielte.", /*french*/ "Selon moi, une #jarre dans le Ranch Lon Lon# contient #[[1]]#.", {QM_RED, QM_GREEN})); - hintTextTable[RHT_POT_HYRULE_FIELD] = HintText(CustomMessage("They say that a #pot in Hyrule Field# contains #[[1]]#.", - /*german*/ "Man erzählt sich, daß ein #Krug in der Hylianischen Steppe# #[[1]]# enthielte.", - /*french*/ "Selon moi, une #jarre dans la Plaine d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_POT_TALONS_HOUSE] = HintText(CustomMessage("They say that a #pot in Talon's Bedroom# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Krug auf der Lon Lon-Farm# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans le Ranch Lon Lon# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match - hintTextTable[RHT_POT_HYRULE_CASTLE] = HintText(CustomMessage("They say that a #pot in Hyrule Castle# contains #[[1]]#.", - /*german*/ "Man erzählt sich, daß ein #Krug in Schloß Hyrule# #[[1]]# enthielte.", - /*french*/ "Selon moi, une #jarre dans le Château d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN})); + hintTextTable[RHT_POT_WEB_GROTTO] = HintText(CustomMessage("They say that a #pot behind a grotto's webbing# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Krug in der Hylianischen Steppe# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans la Plaine d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match + + hintTextTable[RHT_POT_MUD_WALL_GROTTO] = HintText(CustomMessage("They say that a #pot walled off in a grotto# contains #[[1]]#.", + /*german*/ "Man erzählt sich, daß eine #Krug in Schloß Hyrule# #[[1]]# enthielte.",//TODO_TRANSLATE update to match + /*french*/ "Selon moi, une #jarre dans le Château d'Hyrule# contient #[[1]]#.", {QM_RED, QM_GREEN}));//TODO_TRANSLATE update to match hintTextTable[RHT_KOKIRI_FOREST_RUPEE] = HintText(CustomMessage("They say that a rupee in a #tranquil forest# hides #[[1]]#.", /*german*/ "Man erzählt sich, daß ein Rubin in einem #ruhigen Wald# #[[1]]# verstecke.", diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 65cc6eb8c..d59331776 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -728,20 +728,22 @@ std::vector FindItemsAndMarkHinted(std::vector i void CreateChildAltarHint() { auto ctx = Rando::Context::GetInstance(); - if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled() && ctx->GetOption(RSK_TOT_ALTAR_HINT)) { + if (!ctx->GetHint(RH_ALTAR_CHILD)->IsEnabled()) { std::vector stoneLocs = {}; - // force marking the rewards as hinted if they are at the end of dungeons as they can be inferred - if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || - ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { - 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 }); - } std::vector stoneAreas = {}; - for (auto loc : stoneLocs) { - if (loc != RC_UNKNOWN_CHECK) { - stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + 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 inferred + if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || + ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_VANILLA)) { + 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 }); + } + for (auto loc : stoneLocs) { + if (loc != RC_UNKNOWN_CHECK) { + stoneAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + } } } ctx->AddHint(RH_ALTAR_CHILD, Hint(RH_ALTAR_CHILD, HINT_TYPE_ALTAR_CHILD, {}, stoneLocs, stoneAreas)); @@ -752,6 +754,7 @@ void CreateAdultAltarHint() { auto ctx = Rando::Context::GetInstance(); if (!ctx->GetHint(RH_ALTAR_ADULT)->IsEnabled()) { std::vector medallionLocs = {}; + std::vector medallionAreas = {}; 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 inferred if (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON) || @@ -764,11 +767,10 @@ void CreateAdultAltarHint() { RG_WATER_MEDALLION, RG_SPIRIT_MEDALLION, RG_SHADOW_MEDALLION }, { RC_ALTAR_HINT_ADULT }); } - } - std::vector medallionAreas = {}; - for (auto loc : medallionLocs) { - if (loc != RC_UNKNOWN_CHECK) { - medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + for (auto loc : medallionLocs) { + if (loc != RC_UNKNOWN_CHECK) { + medallionAreas.push_back(ctx->GetItemLocation(loc)->GetRandomArea()); + } } } ctx->AddHint(RH_ALTAR_ADULT, Hint(RH_ALTAR_ADULT, HINT_TYPE_ALTAR_ADULT, {}, medallionLocs, medallionAreas)); diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index c97ae35ce..3e6588646 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -354,7 +354,7 @@ void PlaceJunkInExcludedLocation(const RandomizerCheck il) { // place a non-advancement item in this location auto ctx = Rando::Context::GetInstance(); for (size_t i = 0; i < ItemPool.size(); i++) { - if (!Rando::StaticData::RetrieveItem(ItemPool[i]).IsAdvancement()) { + if (Rando::StaticData::RetrieveItem(ItemPool[i]).GetCategory() == ITEM_CATEGORY_JUNK) { ctx->PlaceItemInLocation(il, ItemPool[i]); ItemPool.erase(ItemPool.begin() + i); return; diff --git a/soh/soh/Enhancements/randomizer/ShufflePots.cpp b/soh/soh/Enhancements/randomizer/ShufflePots.cpp index ad23f9d26..869af92e4 100644 --- a/soh/soh/Enhancements/randomizer/ShufflePots.cpp +++ b/soh/soh/Enhancements/randomizer/ShufflePots.cpp @@ -108,149 +108,149 @@ void Rando::StaticData::RegisterPotLocations() { registered = true; // clang-format off // Overworld Pots - // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check - locationTable[RC_KF_LINKS_HOUSE_POT] = Location::Pot(RC_KF_LINKS_HOUSE_POT, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_LINKS_HOUSE, TWO_ACTOR_PARAMS(-118, 51), "Links House Pot", RHT_POT_KOKIRI_FOREST, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_LINKS_HOUSE_POT)); - locationTable[RC_KF_TWINS_HOUSE_POT_2] = Location::Pot(RC_KF_TWINS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(35, 57), "Twins House Pot 2", RHT_POT_KOKIRI_FOREST, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_2)); - locationTable[RC_KF_TWINS_HOUSE_POT_1] = Location::Pot(RC_KF_TWINS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(33, -55), "Twins House Pot 1", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_1)); - locationTable[RC_KF_BROTHERS_HOUSE_POT_1] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-134, -29), "Brothers House Pot 1", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_1)); - locationTable[RC_KF_BROTHERS_HOUSE_POT_2] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-68, 114), "Brothers House Pot 2", RHT_POT_KOKIRI_FOREST, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_2)); - locationTable[RC_TH_BREAK_ROOM_FRONT_POT] = Location::Pot(RC_TH_BREAK_ROOM_FRONT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1438, -3629), "Break Room Front Pot", RHT_TH_BREAK_ROOM_FRONT_POT, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_BREAK_ROOM_FRONT_POT)); - locationTable[RC_TH_BREAK_ROOM_BACK_POT] = Location::Pot(RC_TH_BREAK_ROOM_BACK_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1403, -3679), "Break Room Back Pot", RHT_TH_BREAK_ROOM_BACK_POT, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_BREAK_ROOM_BACK_POT)); - locationTable[RC_TH_KITCHEN_POT_1] = Location::Pot(RC_TH_KITCHEN_POT_1, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1908, -789), "Kitchen Pot 1", RHT_TH_KITCHEN_POT_1, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_KITCHEN_POT_1)); - locationTable[RC_TH_KITCHEN_POT_2] = Location::Pot(RC_TH_KITCHEN_POT_2, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1951, -850), "Kitchen Pot 2", RHT_TH_KITCHEN_POT_2, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_KITCHEN_POT_2)); - locationTable[RC_TH_1_TORCH_CELL_RIGHT_POT] = Location::Pot(RC_TH_1_TORCH_CELL_RIGHT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(-475, -2622), "1 Torch Cell Right Pot", RHT_TH_1_TORCH_CELL_RIGHT_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_1_TORCH_CELL_RIGHT_POT)); - locationTable[RC_TH_1_TORCH_CELL_MID_POT] = Location::Pot(RC_TH_1_TORCH_CELL_MID_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(-512, -2621), "1 Torch Cell Middle Pot", RHT_TH_1_TORCH_CELL_MID_POT, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_1_TORCH_CELL_MID_POT)); - locationTable[RC_TH_1_TORCH_CELL_LEFT_POT] = Location::Pot(RC_TH_1_TORCH_CELL_LEFT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(-511, -2582), "1 Torch Cell Left Pot", RHT_TH_1_TORCH_CELL_LEFT_POT, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_1_TORCH_CELL_LEFT_POT)); - locationTable[RC_TH_STEEP_SLOPE_RIGHT_POT] = Location::Pot(RC_TH_STEEP_SLOPE_RIGHT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(67, -1975), "Steep Slope Right Pot", RHT_TH_STEEP_SLOPE_RIGHT_POT, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_STEEP_SLOPE_RIGHT_POT)); - locationTable[RC_TH_STEEP_SLOPE_LEFT_POT] = Location::Pot(RC_TH_STEEP_SLOPE_LEFT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(39, -1943), "Steep Slope Left Pot", RHT_TH_STEEP_SLOPE_LEFT_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_STEEP_SLOPE_LEFT_POT)); - locationTable[RC_TH_NEAR_DOUBLE_CELL_RIGHT_POT] = Location::Pot(RC_TH_NEAR_DOUBLE_CELL_RIGHT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(691, 48), "Double Cell Right Pot", RHT_TH_NEAR_DOUBLE_CELL_RIGHT_POT, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_NEAR_DOUBLE_CELL_RIGHT_POT)); - locationTable[RC_TH_NEAR_DOUBLE_CELL_MID_POT] = Location::Pot(RC_TH_NEAR_DOUBLE_CELL_MID_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(691, 16), "Double Cell Middle Pot", RHT_TH_NEAR_DOUBLE_CELL_MID_POT, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_NEAR_DOUBLE_CELL_MID_POT)); - locationTable[RC_TH_NEAR_DOUBLE_CELL_LEFT_POT] = Location::Pot(RC_TH_NEAR_DOUBLE_CELL_LEFT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(661, 16), "Double Cell Left Pot", RHT_TH_NEAR_DOUBLE_CELL_LEFT_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_NEAR_DOUBLE_CELL_LEFT_POT)); - locationTable[RC_TH_RIGHTMOST_JAILED_POT] = Location::Pot(RC_TH_RIGHTMOST_JAILED_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(26, 524), "Rightmost Jailed Pot", RHT_TH_RIGHTMOST_JAILED_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_RIGHTMOST_JAILED_POT)); - locationTable[RC_TH_RIGHT_MIDDLE_JAILED_POT] = Location::Pot(RC_TH_RIGHT_MIDDLE_JAILED_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(61, 549), "Right Middle Jailed Pot", RHT_TH_LEFT_MIDDLE_JAILED_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_RIGHT_MIDDLE_JAILED_POT)); - locationTable[RC_TH_LEFT_MIDDLE_JAILED_POT] = Location::Pot(RC_TH_LEFT_MIDDLE_JAILED_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(215, 549), "Left Middle Jailed Pot", RHT_TH_RIGHT_MIDDLE_JAILED_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_LEFT_MIDDLE_JAILED_POT)); - locationTable[RC_TH_LEFTMOST_JAILED_POT] = Location::Pot(RC_TH_LEFTMOST_JAILED_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(254, 529), "Leftmost Jailed Pot", RHT_TH_LEFTMOST_JAILED_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_LEFTMOST_JAILED_POT)); - locationTable[RC_WASTELAND_NEAR_GS_POT_1] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_1, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(488, -2424), "Near GS Pot 1", RHT_POT_WASTELAND, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_1)); - locationTable[RC_WASTELAND_NEAR_GS_POT_2] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_2, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(485, -2463), "Near GS Pot 2", RHT_POT_WASTELAND, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_2)); - locationTable[RC_WASTELAND_NEAR_GS_POT_3] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_3, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(806, -2426), "Near GS Pot 3", RHT_POT_WASTELAND, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_3)); - locationTable[RC_WASTELAND_NEAR_GS_POT_4] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_4, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(801, -2460), "Near GS Pot 4", RHT_POT_WASTELAND, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_4)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-60, 27), "Guard House Child Pot 1", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_1)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-89, 28), "Guard House Child Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_2)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-110, 6), "Guard House Child Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_3)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-58, -7), "Guard House Child Pot 4", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_4)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-80, -7), "Guard House Child Pot 5", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_5)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-65, -45), "Guard House Child Pot 6", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_6)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-85, -41), "Guard House Child Pot 7", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_7)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-107, -45), "Guard House Child Pot 8", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_8)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-66, -79), "Guard House Child Pot 9", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_9)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-88, -84), "Guard House Child Pot 10", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_10)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, 215), "Guard House Child Pot 11", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_11)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_12] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_12, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 148), "Guard House Child Pot 12", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_12)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_13] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_13, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(73, 117), "Guard House Child Pot 13", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_13)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_14] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_14, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 123), "Guard House Child Pot 14", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_14)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_15] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_15, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(43, 89), "Guard House Child Pot 15", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_15)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_16] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_16, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 81), "Guard House Child Pot 16", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_16)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_17] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_17, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(21, 73), "Guard House Child Pot 17", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_17)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_18] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_18, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(64, 45), "Guard House Child Pot 18", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_18)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_19] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_19, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(84, 31), "Guard House Child Pot 19", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_19)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_20] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_20, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, 26), "Guard House Child Pot 20", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_20)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_21] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_21, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(20, 34), "Guard House Child Pot 21", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_21)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_22] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_22, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(89, -2), "Guard House Child Pot 22", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_22)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_23] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_23, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -12), "Guard House Child Pot 23", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_23)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_24] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_24, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, -5), "Guard House Child Pot 24", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_24)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_25] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_25, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(16, -6), "Guard House Child Pot 25", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_25)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_26] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_26, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, -44), "Guard House Child Pot 26", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_26)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_27] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_27, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(37, -40), "Guard House Child Pot 27", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_27)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_28] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_28, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -80), "Guard House Child Pot 28", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_28)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_29] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_29, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(50, -74), "Guard House Child Pot 29", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_29)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_30] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_30, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(28, -79), "Guard House Child Pot 30", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_30)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_31] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_31, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(39, -111), "Guard House Child Pot 31", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_31)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_32] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_32, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(169, 216), "Guard House Child Pot 32", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_32)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_33] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_33, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 166), "Guard House Child Pot 33", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_33)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_34] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_34, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, 120), "Guard House Child Pot 34", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_34)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_35] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_35, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(177, 85), "Guard House Child Pot 35", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_35)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_36] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_36, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(155, 39), "Guard House Child Pot 36", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_36)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_37] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_37, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(184, 13), "Guard House Child Pot 37", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_37)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_38] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_38, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -1), "Guard House Child Pot 38", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_38)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_39] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_39, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(181, -33), "Guard House Child Pot 39", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_39)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_40] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_40, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -45), "Guard House Child Pot 40", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_40)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_41] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_41, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(172, -82), "Guard House Child Pot 41", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_41)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_42] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_42, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -120), "Guard House Child Pot 42", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_42)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_43] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_43, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -166), "Guard House Child Pot 43", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_43)); - locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_44] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_44, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -216), "Guard House Child Pot 44", RHT_POT_MARKET, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_44)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(61, 204), "Guard House Adult Pot 1", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_1)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, 132), "Guard House Adult Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_2)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(74, 23), "Guard House Adult Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_3)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 4), "Guard House Adult Pot 4", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_4)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, -22), "Guard House Adult Pot 5", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_5)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -151), "Guard House Adult Pot 6", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_6)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(79, -182), "Guard House Adult Pot 7", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_7)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -198), "Guard House Adult Pot 8", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_8)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 210), "Guard House Adult Pot 9", RHT_POT_MARKET, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_9)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -122), "Guard House Adult Pot 10", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_10)); - locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -210), "Guard House Adult Pot 11", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_11)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_1] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(100, 45), "Back Alley House Pot 1", RHT_POT_MARKET, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_1)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_2] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(12, -180), "Back Alley House Pot 2", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_2)); - locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_3] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(-54, -180), "Back Alley House Pot 3", RHT_POT_MARKET, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_3)); - locationTable[RC_KAK_NEAR_POTION_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(222, -377), "Near Potion Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_1)); - locationTable[RC_KAK_NEAR_POTION_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(255, -366), "Near Potion Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_2)); - locationTable[RC_KAK_NEAR_POTION_SHOP_POT_3] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(284, -356), "Near Potion Shop Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_3)); - locationTable[RC_KAK_NEAR_IMPAS_HOUSE_POT_1] = Location::Pot(RC_KAK_NEAR_IMPAS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-384, 1568), "Near Impas House Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_POT_1)); - locationTable[RC_KAK_NEAR_IMPAS_HOUSE_POT_2] = Location::Pot(RC_KAK_NEAR_IMPAS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-384, 1539), "Near Impas House Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_POT_2)); - locationTable[RC_KAK_NEAR_IMPAS_HOUSE_POT_3] = Location::Pot(RC_KAK_NEAR_IMPAS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-384, 1510), "Near Impas House Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_POT_3)); - locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_1] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-392, -870), "Near Guards House Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_1)); - locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_2] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-422, -883), "Near Guards House Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_2)); - locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_3] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-450, -895), "Near Guards House Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_3)); - locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(781, 89), "Near Medicine Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_1)); - locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(815, 89), "Near Medicine Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_2)); - locationTable[RC_GY_DAMPES_GRAVE_POT_1] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1542), "Dampes Grave Pot 1", RHT_POT_GRAVEYARD, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_1)); - locationTable[RC_GY_DAMPES_GRAVE_POT_2] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1600), "Dampes Grave Pot 2", RHT_POT_GRAVEYARD, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_2)); - locationTable[RC_GY_DAMPES_GRAVE_POT_3] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-364, -1571), "Dampes Grave Pot 3", RHT_POT_GRAVEYARD, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_3)); - locationTable[RC_GY_DAMPES_GRAVE_POT_4] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_4, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1540), "Dampes Grave Pot 4", RHT_POT_GRAVEYARD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_4)); - locationTable[RC_GY_DAMPES_GRAVE_POT_5] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_5, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1608), "Dampes Grave Pot 5", RHT_POT_GRAVEYARD, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_5)); - locationTable[RC_GY_DAMPES_GRAVE_POT_6] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_6, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(239, -1577), "Dampes Grave Pot 6", RHT_POT_GRAVEYARD, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_6)); - locationTable[RC_GC_LOWER_STAIRCASE_POT_1] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-189, 866), "Lower Staircase Pot 1", RHT_POT_GORON_CITY, RG_DEKU_STICK_1, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_1)); - locationTable[RC_GC_LOWER_STAIRCASE_POT_2] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-271, 825), "Lower Staircase Pot 2", RHT_POT_GORON_CITY, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_2)); - locationTable[RC_GC_UPPER_STAIRCASE_POT_1] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1170, 60), "Upper Staircase Pot 1", RHT_POT_GORON_CITY, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_1)); - locationTable[RC_GC_UPPER_STAIRCASE_POT_2] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1185, 95), "Upper Staircase Pot 2", RHT_POT_GORON_CITY, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_2)); - locationTable[RC_GC_UPPER_STAIRCASE_POT_3] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_3, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1200, 63), "Upper Staircase Pot 3", RHT_POT_GORON_CITY, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_3)); - locationTable[RC_GC_MEDIGORON_POT_1] = Location::Pot(RC_GC_MEDIGORON_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-694, 1196), "Medigoron Pot 1", RHT_POT_GORON_CITY, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MEDIGORON_POT_1)); - locationTable[RC_GC_DARUNIA_POT_1] = Location::Pot(RC_GC_DARUNIA_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(262, -1210), "Darunia Pot 1", RHT_POT_GORON_CITY, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_DARUNIA_POT_1)); - locationTable[RC_GC_DARUNIA_POT_2] = Location::Pot(RC_GC_DARUNIA_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(261, -1254), "Darunia Pot 2", RHT_POT_GORON_CITY, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_DARUNIA_POT_2)); - locationTable[RC_GC_DARUNIA_POT_3] = Location::Pot(RC_GC_DARUNIA_POT_3, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(262, -1386), "Darunia Pot 3", RHT_POT_GORON_CITY, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_DARUNIA_POT_3)); + // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check + locationTable[RC_KF_LINKS_HOUSE_POT] = Location::Pot(RC_KF_LINKS_HOUSE_POT, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_LINKS_HOUSE, TWO_ACTOR_PARAMS(-118, 51), "Links House Pot", RHT_POT_LINKS_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_LINKS_HOUSE_POT)); + locationTable[RC_KF_TWINS_HOUSE_POT_2] = Location::Pot(RC_KF_TWINS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(35, 57), "Twins House Pot 2", RHT_POT_TWINS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_2)); + locationTable[RC_KF_TWINS_HOUSE_POT_1] = Location::Pot(RC_KF_TWINS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_TWINS_HOUSE, TWO_ACTOR_PARAMS(33, -55), "Twins House Pot 1", RHT_POT_TWINS_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_TWINS_HOUSE_POT_1)); + locationTable[RC_KF_BROTHERS_HOUSE_POT_1] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-134, -29), "Brothers House Pot 1", RHT_POT_KNOW_IT_ALL, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_1)); + locationTable[RC_KF_BROTHERS_HOUSE_POT_2] = Location::Pot(RC_KF_BROTHERS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KOKIRI_FOREST, SCENE_KNOW_IT_ALL_BROS_HOUSE, TWO_ACTOR_PARAMS(-68, 114), "Brothers House Pot 2", RHT_POT_KNOW_IT_ALL, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KF_BROTHERS_HOUSE_POT_2)); + locationTable[RC_TH_BREAK_ROOM_FRONT_POT] = Location::Pot(RC_TH_BREAK_ROOM_FRONT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1438, -3629), "Break Room Front Pot", RHT_TH_BREAK_ROOM_FRONT_POT, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_BREAK_ROOM_FRONT_POT)); + locationTable[RC_TH_BREAK_ROOM_BACK_POT] = Location::Pot(RC_TH_BREAK_ROOM_BACK_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1403, -3679), "Break Room Back Pot", RHT_TH_BREAK_ROOM_BACK_POT, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_BREAK_ROOM_BACK_POT)); + locationTable[RC_TH_KITCHEN_POT_1] = Location::Pot(RC_TH_KITCHEN_POT_1, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1908, -789), "Kitchen Pot 1", RHT_TH_KITCHEN_POT_1, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_KITCHEN_POT_1)); + locationTable[RC_TH_KITCHEN_POT_2] = Location::Pot(RC_TH_KITCHEN_POT_2, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(1951, -850), "Kitchen Pot 2", RHT_TH_KITCHEN_POT_2, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_KITCHEN_POT_2)); + locationTable[RC_TH_1_TORCH_CELL_RIGHT_POT] = Location::Pot(RC_TH_1_TORCH_CELL_RIGHT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(-475, -2622), "1 Torch Cell Right Pot", RHT_TH_1_TORCH_CELL_RIGHT_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_1_TORCH_CELL_RIGHT_POT)); + locationTable[RC_TH_1_TORCH_CELL_MID_POT] = Location::Pot(RC_TH_1_TORCH_CELL_MID_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(-512, -2621), "1 Torch Cell Middle Pot", RHT_TH_1_TORCH_CELL_MID_POT, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_1_TORCH_CELL_MID_POT)); + locationTable[RC_TH_1_TORCH_CELL_LEFT_POT] = Location::Pot(RC_TH_1_TORCH_CELL_LEFT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(-511, -2582), "1 Torch Cell Left Pot", RHT_TH_1_TORCH_CELL_LEFT_POT, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_1_TORCH_CELL_LEFT_POT)); + locationTable[RC_TH_STEEP_SLOPE_RIGHT_POT] = Location::Pot(RC_TH_STEEP_SLOPE_RIGHT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(67, -1975), "Steep Slope Right Pot", RHT_TH_STEEP_SLOPE_RIGHT_POT, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_STEEP_SLOPE_RIGHT_POT)); + locationTable[RC_TH_STEEP_SLOPE_LEFT_POT] = Location::Pot(RC_TH_STEEP_SLOPE_LEFT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(39, -1943), "Steep Slope Left Pot", RHT_TH_STEEP_SLOPE_LEFT_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_STEEP_SLOPE_LEFT_POT)); + locationTable[RC_TH_NEAR_DOUBLE_CELL_RIGHT_POT] = Location::Pot(RC_TH_NEAR_DOUBLE_CELL_RIGHT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(691, 48), "Double Cell Right Pot", RHT_TH_NEAR_DOUBLE_CELL_RIGHT_POT, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_NEAR_DOUBLE_CELL_RIGHT_POT)); + locationTable[RC_TH_NEAR_DOUBLE_CELL_MID_POT] = Location::Pot(RC_TH_NEAR_DOUBLE_CELL_MID_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(691, 16), "Double Cell Middle Pot", RHT_TH_NEAR_DOUBLE_CELL_MID_POT, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_NEAR_DOUBLE_CELL_MID_POT)); + locationTable[RC_TH_NEAR_DOUBLE_CELL_LEFT_POT] = Location::Pot(RC_TH_NEAR_DOUBLE_CELL_LEFT_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(661, 16), "Double Cell Left Pot", RHT_TH_NEAR_DOUBLE_CELL_LEFT_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_NEAR_DOUBLE_CELL_LEFT_POT)); + locationTable[RC_TH_RIGHTMOST_JAILED_POT] = Location::Pot(RC_TH_RIGHTMOST_JAILED_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(26, 524), "Rightmost Jailed Pot", RHT_TH_RIGHTMOST_JAILED_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_RIGHTMOST_JAILED_POT)); + locationTable[RC_TH_RIGHT_MIDDLE_JAILED_POT] = Location::Pot(RC_TH_RIGHT_MIDDLE_JAILED_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(61, 549), "Right Middle Jailed Pot", RHT_TH_LEFT_MIDDLE_JAILED_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_RIGHT_MIDDLE_JAILED_POT)); + locationTable[RC_TH_LEFT_MIDDLE_JAILED_POT] = Location::Pot(RC_TH_LEFT_MIDDLE_JAILED_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(215, 549), "Left Middle Jailed Pot", RHT_TH_RIGHT_MIDDLE_JAILED_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_LEFT_MIDDLE_JAILED_POT)); + locationTable[RC_TH_LEFTMOST_JAILED_POT] = Location::Pot(RC_TH_LEFTMOST_JAILED_POT, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(254, 529), "Leftmost Jailed Pot", RHT_TH_LEFTMOST_JAILED_POT, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_TH_LEFTMOST_JAILED_POT)); + locationTable[RC_WASTELAND_NEAR_GS_POT_1] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_1, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(488, -2424), "Near GS Pot 1", RHT_POT_WASTELAND, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_1)); + locationTable[RC_WASTELAND_NEAR_GS_POT_2] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_2, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(485, -2463), "Near GS Pot 2", RHT_POT_WASTELAND, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_2)); + locationTable[RC_WASTELAND_NEAR_GS_POT_3] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_3, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(806, -2426), "Near GS Pot 3", RHT_POT_WASTELAND, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_3)); + locationTable[RC_WASTELAND_NEAR_GS_POT_4] = Location::Pot(RC_WASTELAND_NEAR_GS_POT_4, RCQUEST_BOTH, RCAREA_WASTELAND, SCENE_HAUNTED_WASTELAND, TWO_ACTOR_PARAMS(801, -2460), "Near GS Pot 4", RHT_POT_WASTELAND, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_WASTELAND_NEAR_GS_POT_4)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-60, 27), "Guard House Child Pot 1", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_1)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-89, 28), "Guard House Child Pot 2", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_2)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-110, 6), "Guard House Child Pot 3", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_3)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-58, -7), "Guard House Child Pot 4", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_4)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-80, -7), "Guard House Child Pot 5", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_5)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-65, -45), "Guard House Child Pot 6", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_6)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-85, -41), "Guard House Child Pot 7", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_7)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-107, -45), "Guard House Child Pot 8", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_8)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-66, -79), "Guard House Child Pot 9", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_9)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(-88, -84), "Guard House Child Pot 10", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_10)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, 215), "Guard House Child Pot 11", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_11)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_12] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_12, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 148), "Guard House Child Pot 12", RHT_POT_GUARD_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_12)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_13] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_13, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(73, 117), "Guard House Child Pot 13", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_13)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_14] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_14, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 123), "Guard House Child Pot 14", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_14)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_15] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_15, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(43, 89), "Guard House Child Pot 15", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_15)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_16] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_16, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, 81), "Guard House Child Pot 16", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_16)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_17] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_17, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(21, 73), "Guard House Child Pot 17", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_17)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_18] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_18, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(64, 45), "Guard House Child Pot 18", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_18)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_19] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_19, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(84, 31), "Guard House Child Pot 19", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_19)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_20] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_20, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, 26), "Guard House Child Pot 20", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_20)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_21] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_21, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(20, 34), "Guard House Child Pot 21", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_21)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_22] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_22, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(89, -2), "Guard House Child Pot 22", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_22)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_23] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_23, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -12), "Guard House Child Pot 23", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_23)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_24] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_24, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(42, -5), "Guard House Child Pot 24", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_24)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_25] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_25, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(16, -6), "Guard House Child Pot 25", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_25)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_26] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_26, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(68, -44), "Guard House Child Pot 26", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_26)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_27] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_27, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(37, -40), "Guard House Child Pot 27", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_27)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_28] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_28, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(70, -80), "Guard House Child Pot 28", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_28)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_29] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_29, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(50, -74), "Guard House Child Pot 29", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_29)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_30] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_30, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(28, -79), "Guard House Child Pot 30", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_30)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_31] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_31, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(39, -111), "Guard House Child Pot 31", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_31)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_32] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_32, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(169, 216), "Guard House Child Pot 32", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_32)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_33] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_33, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 166), "Guard House Child Pot 33", RHT_POT_GUARD_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_33)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_34] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_34, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, 120), "Guard House Child Pot 34", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_34)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_35] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_35, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(177, 85), "Guard House Child Pot 35", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_35)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_36] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_36, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(155, 39), "Guard House Child Pot 36", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_36)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_37] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_37, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(184, 13), "Guard House Child Pot 37", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_37)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_38] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_38, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -1), "Guard House Child Pot 38", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_38)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_39] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_39, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(181, -33), "Guard House Child Pot 39", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_39)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_40] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_40, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(156, -45), "Guard House Child Pot 40", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_40)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_41] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_41, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(172, -82), "Guard House Child Pot 41", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_41)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_42] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_42, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -120), "Guard House Child Pot 42", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_42)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_43] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_43, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -166), "Guard House Child Pot 43", RHT_POT_GUARD_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_43)); + locationTable[RC_MK_GUARD_HOUSE_CHILD_POT_44] = Location::Pot(RC_MK_GUARD_HOUSE_CHILD_POT_44, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(170, -216), "Guard House Child Pot 44", RHT_POT_GUARD_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_CHILD_POT_44)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_1] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(61, 204), "Guard House Adult Pot 1", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_1)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_2] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, 132), "Guard House Adult Pot 2", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_2)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_3] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(74, 23), "Guard House Adult Pot 3", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_3)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_4] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_4, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(40, 4), "Guard House Adult Pot 4", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_4)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_5] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_5, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(71, -22), "Guard House Adult Pot 5", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_5)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_6] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_6, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -151), "Guard House Adult Pot 6", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_6)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_7] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_7, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(79, -182), "Guard House Adult Pot 7", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_7)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_8] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_8, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(44, -198), "Guard House Adult Pot 8", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_8)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_9] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_9, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(168, 210), "Guard House Adult Pot 9", RHT_POT_POE_SHOP, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_9)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_10] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_10, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -122), "Guard House Adult Pot 10", RHT_POT_POE_SHOP, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_10)); + locationTable[RC_MK_GUARD_HOUSE_ADULT_POT_11] = Location::Pot(RC_MK_GUARD_HOUSE_ADULT_POT_11, RCQUEST_BOTH, RCAREA_MARKET, SCENE_MARKET_GUARD_HOUSE, TWO_ACTOR_PARAMS(167, -210), "Guard House Adult Pot 11", RHT_POT_POE_SHOP, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_GUARD_HOUSE_ADULT_POT_11)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_1] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(100, 45), "Back Alley House Pot 1", RHT_POT_ALLEY_HOUSE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_1)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_2] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(12, -180), "Back Alley House Pot 2", RHT_POT_ALLEY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_2)); + locationTable[RC_MK_BACK_ALLEY_HOUSE_POT_3] = Location::Pot(RC_MK_BACK_ALLEY_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_MARKET, SCENE_BACK_ALLEY_HOUSE, TWO_ACTOR_PARAMS(-54, -180), "Back Alley House Pot 3", RHT_POT_ALLEY_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_MK_BACK_ALLEY_HOUSE_POT_3)); + locationTable[RC_KAK_NEAR_POTION_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(222, -377), "Near Potion Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_1)); + locationTable[RC_KAK_NEAR_POTION_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(255, -366), "Near Potion Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_2)); + locationTable[RC_KAK_NEAR_POTION_SHOP_POT_3] = Location::Pot(RC_KAK_NEAR_POTION_SHOP_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(284, -356), "Near Potion Shop Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_POTION_SHOP_POT_3)); + locationTable[RC_KAK_NEAR_IMPAS_HOUSE_POT_1] = Location::Pot(RC_KAK_NEAR_IMPAS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-384, 1568), "Near Impas House Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_POT_1)); + locationTable[RC_KAK_NEAR_IMPAS_HOUSE_POT_2] = Location::Pot(RC_KAK_NEAR_IMPAS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-384, 1539), "Near Impas House Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_POT_2)); + locationTable[RC_KAK_NEAR_IMPAS_HOUSE_POT_3] = Location::Pot(RC_KAK_NEAR_IMPAS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-384, 1510), "Near Impas House Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_POT_3)); + locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_1] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-392, -870), "Near Guards House Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_1)); + locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_2] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-422, -883), "Near Guards House Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_2)); + locationTable[RC_KAK_NEAR_GUARDS_HOUSE_POT_3] = Location::Pot(RC_KAK_NEAR_GUARDS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-450, -895), "Near Guards House Pot 3", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GUARDS_HOUSE_POT_3)); + locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_1] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(781, 89), "Near Medicine Shop Pot 1", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_1)); + locationTable[RC_KAK_NEAR_MEDICINE_SHOP_POT_2] = Location::Pot(RC_KAK_NEAR_MEDICINE_SHOP_POT_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(815, 89), "Near Medicine Shop Pot 2", RHT_POT_KAKARIKO, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_MEDICINE_SHOP_POT_2)); + locationTable[RC_GY_DAMPES_GRAVE_POT_1] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_1, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1542), "Dampes Grave Pot 1", RHT_POT_DAMPE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_1)); + locationTable[RC_GY_DAMPES_GRAVE_POT_2] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_2, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-319, -1600), "Dampes Grave Pot 2", RHT_POT_DAMPE, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_2)); + locationTable[RC_GY_DAMPES_GRAVE_POT_3] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_3, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(-364, -1571), "Dampes Grave Pot 3", RHT_POT_DAMPE, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_3)); + locationTable[RC_GY_DAMPES_GRAVE_POT_4] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_4, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1540), "Dampes Grave Pot 4", RHT_POT_DAMPE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_4)); + locationTable[RC_GY_DAMPES_GRAVE_POT_5] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_5, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(198, -1608), "Dampes Grave Pot 5", RHT_POT_DAMPE, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_5)); + locationTable[RC_GY_DAMPES_GRAVE_POT_6] = Location::Pot(RC_GY_DAMPES_GRAVE_POT_6, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_WINDMILL_AND_DAMPES_GRAVE, TWO_ACTOR_PARAMS(239, -1577), "Dampes Grave Pot 6", RHT_POT_DAMPE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GY_DAMPES_GRAVE_POT_6)); + locationTable[RC_GC_LOWER_STAIRCASE_POT_1] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-189, 866), "Lower Staircase Pot 1", RHT_POT_GORON_CITY, RG_DEKU_STICK_1, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_1)); + locationTable[RC_GC_LOWER_STAIRCASE_POT_2] = Location::Pot(RC_GC_LOWER_STAIRCASE_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-271, 825), "Lower Staircase Pot 2", RHT_POT_GORON_CITY, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_LOWER_STAIRCASE_POT_2)); + locationTable[RC_GC_UPPER_STAIRCASE_POT_1] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1170, 60), "Upper Staircase Pot 1", RHT_POT_GORON_CITY, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_1)); + locationTable[RC_GC_UPPER_STAIRCASE_POT_2] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1185, 95), "Upper Staircase Pot 2", RHT_POT_GORON_CITY, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_2)); + locationTable[RC_GC_UPPER_STAIRCASE_POT_3] = Location::Pot(RC_GC_UPPER_STAIRCASE_POT_3, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-1200, 63), "Upper Staircase Pot 3", RHT_POT_GORON_CITY, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_UPPER_STAIRCASE_POT_3)); + locationTable[RC_GC_MEDIGORON_POT_1] = Location::Pot(RC_GC_MEDIGORON_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(-694, 1196), "Medigoron Pot 1", RHT_POT_GORON_CITY, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_MEDIGORON_POT_1)); + locationTable[RC_GC_DARUNIA_POT_1] = Location::Pot(RC_GC_DARUNIA_POT_1, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(262, -1210), "Darunia Pot 1", RHT_POT_GORON_CITY, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_DARUNIA_POT_1)); + locationTable[RC_GC_DARUNIA_POT_2] = Location::Pot(RC_GC_DARUNIA_POT_2, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(261, -1254), "Darunia Pot 2", RHT_POT_GORON_CITY, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_DARUNIA_POT_2)); + locationTable[RC_GC_DARUNIA_POT_3] = Location::Pot(RC_GC_DARUNIA_POT_3, RCQUEST_BOTH, RCAREA_GORON_CITY, SCENE_GORON_CITY, TWO_ACTOR_PARAMS(262, -1386), "Darunia Pot 3", RHT_POT_GORON_CITY, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GC_DARUNIA_POT_3)); locationTable[RC_DMC_NEAR_GC_POT_2] = Location::Pot(RC_DMC_NEAR_GC_POT_2, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, TWO_ACTOR_PARAMS(-1546, 141), "Near GC Pot 2", RHT_POT_DEATH_MOUNTAIN_CRATER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_NEAR_GC_POT_2)); locationTable[RC_DMC_NEAR_GC_POT_3] = Location::Pot(RC_DMC_NEAR_GC_POT_3, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, TWO_ACTOR_PARAMS(-1641, -127), "Near GC Pot 3", RHT_POT_DEATH_MOUNTAIN_CRATER, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_NEAR_GC_POT_3)); locationTable[RC_DMC_NEAR_GC_POT_1] = Location::Pot(RC_DMC_NEAR_GC_POT_1, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, TWO_ACTOR_PARAMS(-1590, 132), "Near GC Pot 1", RHT_POT_DEATH_MOUNTAIN_CRATER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_NEAR_GC_POT_1)); locationTable[RC_DMC_NEAR_GC_POT_4] = Location::Pot(RC_DMC_NEAR_GC_POT_4, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_CRATER, SCENE_DEATH_MOUNTAIN_CRATER, TWO_ACTOR_PARAMS(-1606, -166), "Near GC Pot 4", RHT_POT_DEATH_MOUNTAIN_CRATER, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMC_NEAR_GC_POT_4)); - locationTable[RC_ZD_NEAR_SHOP_POT_1] = Location::Pot(RC_ZD_NEAR_SHOP_POT_1, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(676, 377), "Near Shop Pot 1", RHT_POT_ZORAS_DOMAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_1)); - locationTable[RC_ZD_NEAR_SHOP_POT_2] = Location::Pot(RC_ZD_NEAR_SHOP_POT_2, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(614, 419), "Near Shop Pot 2", RHT_POT_ZORAS_DOMAIN, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_2)); - locationTable[RC_ZD_NEAR_SHOP_POT_3] = Location::Pot(RC_ZD_NEAR_SHOP_POT_3, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(289, 415), "Near Shop Pot 3", RHT_POT_ZORAS_DOMAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_3)); - locationTable[RC_ZD_NEAR_SHOP_POT_4] = Location::Pot(RC_ZD_NEAR_SHOP_POT_4, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(289, 289), "Near Shop Pot 4", RHT_POT_ZORAS_DOMAIN, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_4)); - locationTable[RC_ZD_NEAR_SHOP_POT_5] = Location::Pot(RC_ZD_NEAR_SHOP_POT_5, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(220, 384), "Near Shop Pot 5", RHT_POT_ZORAS_DOMAIN, RG_DEKU_STICK_1, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_5)); - locationTable[RC_ZF_HIDDEN_CAVE_POT_1] = Location::Pot(RC_ZF_HIDDEN_CAVE_POT_1, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(385, 2587), "Hidden Cave Pot 1", RHT_POT_ZORAS_FOUNTAIN, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_HIDDEN_CAVE_POT_1)); - locationTable[RC_ZF_HIDDEN_CAVE_POT_2] = Location::Pot(RC_ZF_HIDDEN_CAVE_POT_2, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(418, 2609), "Hidden Cave Pot 2", RHT_POT_ZORAS_FOUNTAIN, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_HIDDEN_CAVE_POT_2)); - locationTable[RC_ZF_HIDDEN_CAVE_POT_3] = Location::Pot(RC_ZF_HIDDEN_CAVE_POT_3, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(430, 2568), "Hidden Cave Pot 3", RHT_POT_ZORAS_FOUNTAIN, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_HIDDEN_CAVE_POT_3)); - locationTable[RC_ZF_NEAR_JABU_POT_1] = Location::Pot(RC_ZF_NEAR_JABU_POT_1, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(-1630, 170), "Near Jabu Pot 1", RHT_POT_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_NEAR_JABU_POT_1)); - locationTable[RC_ZF_NEAR_JABU_POT_2] = Location::Pot(RC_ZF_NEAR_JABU_POT_2, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(-1550, 170), "Near Jabu Pot 2", RHT_POT_ZORAS_FOUNTAIN, RG_DEKU_SEEDS_30, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_NEAR_JABU_POT_2)); - locationTable[RC_ZF_NEAR_JABU_POT_3] = Location::Pot(RC_ZF_NEAR_JABU_POT_3, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(-1630, -260), "Near Jabu Pot 3", RHT_POT_ZORAS_FOUNTAIN, RG_DEKU_SEEDS_30, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_NEAR_JABU_POT_3)); - locationTable[RC_ZF_NEAR_JABU_POT_4] = Location::Pot(RC_ZF_NEAR_JABU_POT_4, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(-1550, -260), "Near Jabu Pot 4", RHT_POT_ZORAS_FOUNTAIN, RG_DEKU_SEEDS_30, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_NEAR_JABU_POT_4)); - locationTable[RC_LLR_FRONT_POT_1] = Location::Pot(RC_LLR_FRONT_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(667, -3218), "Front Pot 1", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_FRONT_POT_1)); - locationTable[RC_LLR_FRONT_POT_2] = Location::Pot(RC_LLR_FRONT_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(667, -3186), "Front Pot 2", RHT_POT_LON_LON_RANCH, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_FRONT_POT_2)); - locationTable[RC_LLR_FRONT_POT_3] = Location::Pot(RC_LLR_FRONT_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(667, -3154), "Front Pot 3", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_FRONT_POT_3)); - locationTable[RC_LLR_FRONT_POT_4] = Location::Pot(RC_LLR_FRONT_POT_4, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(667, -3122), "Front Pot 4", RHT_POT_LON_LON_RANCH, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_FRONT_POT_4)); - locationTable[RC_LLR_RAIN_SHED_POT_1] = Location::Pot(RC_LLR_RAIN_SHED_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(852, 172), "Rain Shed Pot 1", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_1)); - locationTable[RC_LLR_RAIN_SHED_POT_2] = Location::Pot(RC_LLR_RAIN_SHED_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(840, 212), "Rain Shed Pot 2", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_2)); - locationTable[RC_LLR_RAIN_SHED_POT_3] = Location::Pot(RC_LLR_RAIN_SHED_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(872, 219), "Rain Shed Pot 3", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_3)); - locationTable[RC_LLR_TALONS_HOUSE_POT_1] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1255, 47), "Talons House Pot 1", RHT_POT_LON_LON_RANCH, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_1)); - locationTable[RC_LLR_TALONS_HOUSE_POT_2] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -51), "Talons House Pot 2", RHT_POT_LON_LON_RANCH, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_2)); - locationTable[RC_LLR_TALONS_HOUSE_POT_3] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -78), "Talons House Pot 3", RHT_POT_LON_LON_RANCH, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_3)); - locationTable[RC_HF_COW_GROTTO_POT_1] = Location::Pot(RC_HF_COW_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3410, -223), "Cow Grotto Pot 1", RHT_POT_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_1)); - locationTable[RC_HF_COW_GROTTO_POT_2] = Location::Pot(RC_HF_COW_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3390, -258), "Cow Grotto Pot 2", RHT_POT_HYRULE_FIELD, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_2)); - locationTable[RC_HC_STORMS_GROTTO_POT_1] = Location::Pot(RC_HC_STORMS_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1843, 1014), "Storms Grotto Pot 1", RHT_POT_HYRULE_CASTLE, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_1)); - locationTable[RC_HC_STORMS_GROTTO_POT_2] = Location::Pot(RC_HC_STORMS_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1769, 954), "Storms Grotto Pot 2", RHT_POT_HYRULE_CASTLE, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_2)); - locationTable[RC_HC_STORMS_GROTTO_POT_3] = Location::Pot(RC_HC_STORMS_GROTTO_POT_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1857, 897), "Storms Grotto Pot 3", RHT_POT_HYRULE_CASTLE, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_3)); - locationTable[RC_HC_STORMS_GROTTO_POT_4] = Location::Pot(RC_HC_STORMS_GROTTO_POT_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1764, 847), "Storms Grotto Pot 4", RHT_POT_HYRULE_CASTLE, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_4)); - + locationTable[RC_ZD_NEAR_SHOP_POT_1] = Location::Pot(RC_ZD_NEAR_SHOP_POT_1, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(676, 377), "Near Shop Pot 1", RHT_POT_ZORAS_DOMAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_1)); + locationTable[RC_ZD_NEAR_SHOP_POT_2] = Location::Pot(RC_ZD_NEAR_SHOP_POT_2, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(614, 419), "Near Shop Pot 2", RHT_POT_ZORAS_DOMAIN, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_2)); + locationTable[RC_ZD_NEAR_SHOP_POT_3] = Location::Pot(RC_ZD_NEAR_SHOP_POT_3, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(289, 415), "Near Shop Pot 3", RHT_POT_ZORAS_DOMAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_3)); + locationTable[RC_ZD_NEAR_SHOP_POT_4] = Location::Pot(RC_ZD_NEAR_SHOP_POT_4, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(289, 289), "Near Shop Pot 4", RHT_POT_ZORAS_DOMAIN, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_4)); + locationTable[RC_ZD_NEAR_SHOP_POT_5] = Location::Pot(RC_ZD_NEAR_SHOP_POT_5, RCQUEST_BOTH, RCAREA_ZORAS_DOMAIN, SCENE_ZORAS_DOMAIN, TWO_ACTOR_PARAMS(220, 384), "Near Shop Pot 5", RHT_POT_ZORAS_DOMAIN, RG_DEKU_STICK_1, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZD_NEAR_SHOP_POT_5)); + locationTable[RC_ZF_HIDDEN_CAVE_POT_1] = Location::Pot(RC_ZF_HIDDEN_CAVE_POT_1, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(385, 2587), "Hidden Cave Pot 1", RHT_POT_ZORAS_FOUNTAIN, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_HIDDEN_CAVE_POT_1)); + locationTable[RC_ZF_HIDDEN_CAVE_POT_2] = Location::Pot(RC_ZF_HIDDEN_CAVE_POT_2, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(418, 2609), "Hidden Cave Pot 2", RHT_POT_ZORAS_FOUNTAIN, RG_ARROWS_10, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_HIDDEN_CAVE_POT_2)); + locationTable[RC_ZF_HIDDEN_CAVE_POT_3] = Location::Pot(RC_ZF_HIDDEN_CAVE_POT_3, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(430, 2568), "Hidden Cave Pot 3", RHT_POT_ZORAS_FOUNTAIN, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_HIDDEN_CAVE_POT_3)); + locationTable[RC_ZF_NEAR_JABU_POT_1] = Location::Pot(RC_ZF_NEAR_JABU_POT_1, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(-1630, 170), "Near Jabu Pot 1", RHT_POT_ZORAS_FOUNTAIN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_NEAR_JABU_POT_1)); + locationTable[RC_ZF_NEAR_JABU_POT_2] = Location::Pot(RC_ZF_NEAR_JABU_POT_2, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(-1550, 170), "Near Jabu Pot 2", RHT_POT_ZORAS_FOUNTAIN, RG_DEKU_SEEDS_30, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_NEAR_JABU_POT_2)); + locationTable[RC_ZF_NEAR_JABU_POT_3] = Location::Pot(RC_ZF_NEAR_JABU_POT_3, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(-1630, -260), "Near Jabu Pot 3", RHT_POT_ZORAS_FOUNTAIN, RG_DEKU_SEEDS_30, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_NEAR_JABU_POT_3)); + locationTable[RC_ZF_NEAR_JABU_POT_4] = Location::Pot(RC_ZF_NEAR_JABU_POT_4, RCQUEST_BOTH, RCAREA_ZORAS_FOUNTAIN, SCENE_ZORAS_FOUNTAIN, TWO_ACTOR_PARAMS(-1550, -260), "Near Jabu Pot 4", RHT_POT_ZORAS_FOUNTAIN, RG_DEKU_SEEDS_30, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ZF_NEAR_JABU_POT_4)); + locationTable[RC_LLR_FRONT_POT_1] = Location::Pot(RC_LLR_FRONT_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(667, -3218), "Front Pot 1", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_FRONT_POT_1)); + locationTable[RC_LLR_FRONT_POT_2] = Location::Pot(RC_LLR_FRONT_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(667, -3186), "Front Pot 2", RHT_POT_LON_LON_RANCH, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_FRONT_POT_2)); + locationTable[RC_LLR_FRONT_POT_3] = Location::Pot(RC_LLR_FRONT_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(667, -3154), "Front Pot 3", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_FRONT_POT_3)); + locationTable[RC_LLR_FRONT_POT_4] = Location::Pot(RC_LLR_FRONT_POT_4, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(667, -3122), "Front Pot 4", RHT_POT_LON_LON_RANCH, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_FRONT_POT_4)); + locationTable[RC_LLR_RAIN_SHED_POT_1] = Location::Pot(RC_LLR_RAIN_SHED_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(852, 172), "Rain Shed Pot 1", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_1)); + locationTable[RC_LLR_RAIN_SHED_POT_2] = Location::Pot(RC_LLR_RAIN_SHED_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(840, 212), "Rain Shed Pot 2", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_2)); + locationTable[RC_LLR_RAIN_SHED_POT_3] = Location::Pot(RC_LLR_RAIN_SHED_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_RANCH, TWO_ACTOR_PARAMS(872, 219), "Rain Shed Pot 3", RHT_POT_LON_LON_RANCH, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_RAIN_SHED_POT_3)); + locationTable[RC_LLR_TALONS_HOUSE_POT_1] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_1, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1255, 47), "Talons House Pot 1", RHT_POT_TALONS_HOUSE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_1)); + locationTable[RC_LLR_TALONS_HOUSE_POT_2] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_2, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -51), "Talons House Pot 2", RHT_POT_TALONS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_2)); + locationTable[RC_LLR_TALONS_HOUSE_POT_3] = Location::Pot(RC_LLR_TALONS_HOUSE_POT_3, RCQUEST_BOTH, RCAREA_LON_LON_RANCH, SCENE_LON_LON_BUILDINGS, TWO_ACTOR_PARAMS(1256, -78), "Talons House Pot 3", RHT_POT_TALONS_HOUSE, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LLR_TALONS_HOUSE_POT_3)); + locationTable[RC_HF_COW_GROTTO_POT_1] = Location::Pot(RC_HF_COW_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3410, -223), "Cow Grotto Pot 1", RHT_POT_WEB_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_1)); + locationTable[RC_HF_COW_GROTTO_POT_2] = Location::Pot(RC_HF_COW_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_FIELD, SCENE_GROTTOS, TWO_ACTOR_PARAMS(3390, -258), "Cow Grotto Pot 2", RHT_POT_WEB_GROTTO, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HF_COW_GROTTO_POT_2)); + locationTable[RC_HC_STORMS_GROTTO_POT_1] = Location::Pot(RC_HC_STORMS_GROTTO_POT_1, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1843, 1014), "Storms Grotto Pot 1", RHT_POT_MUD_WALL_GROTTO, RG_RED_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_1)); + locationTable[RC_HC_STORMS_GROTTO_POT_2] = Location::Pot(RC_HC_STORMS_GROTTO_POT_2, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1769, 954), "Storms Grotto Pot 2", RHT_POT_MUD_WALL_GROTTO, RG_ARROWS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_2)); + locationTable[RC_HC_STORMS_GROTTO_POT_3] = Location::Pot(RC_HC_STORMS_GROTTO_POT_3, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1857, 897), "Storms Grotto Pot 3", RHT_POT_MUD_WALL_GROTTO, RG_BOMBS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_3)); + locationTable[RC_HC_STORMS_GROTTO_POT_4] = Location::Pot(RC_HC_STORMS_GROTTO_POT_4, RCQUEST_BOTH, RCAREA_HYRULE_CASTLE, SCENE_GROTTOS, TWO_ACTOR_PARAMS(1764, 847), "Storms Grotto Pot 4", RHT_POT_MUD_WALL_GROTTO, RG_DEKU_NUTS_5, SpoilerCollectionCheck::RandomizerInf(RAND_INF_HC_STORMS_GROTTO_POT_4)); + // Dungeon Pots // Randomizer Check Randomizer Check Quest Area Scene ID Params Short Name Hint Text Key Vanilla Spoiler Collection Check locationTable[RC_DODONGOS_CAVERN_LIZALFOS_POT_3] = Location::Pot(RC_DODONGOS_CAVERN_LIZALFOS_POT_3, RCQUEST_VANILLA, RCAREA_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(2673, -2060), "Lizalfos Pot 3", RHT_POT_DODONGOS_CAVERN, RG_RECOVERY_HEART, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_LIZALFOS_POT_3)); diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index b9cc0b10b..b17718b65 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -1,13 +1,17 @@ -#include #include "draw.h" -#include "z64.h" -#include "macros.h" -#include "functions.h" -#include "variables.h" #include "soh/OTRGlobals.h" #include "soh/cvar_prefixes.h" #include "randomizerTypes.h" #include +#include "soh_assets.h" +#include "soh/Enhancements/cosmetics/cosmeticsTypes.h" + +extern "C" { +#include "z64.h" +#include "macros.h" +#include "functions.h" +#include "variables.h" +#include "dungeon.h" #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" @@ -30,11 +34,6 @@ #include "overlays/ovl_Boss_Sst/ovl_Boss_Sst.h" #include "objects/object_tw/object_tw.h" #include "objects/object_ganon2/object_ganon2.h" -#include "soh_assets.h" -#include "dungeon.h" -#include "soh/Enhancements/cosmetics/cosmeticsTypes.h" - -extern "C" { extern PlayState* gPlayState; extern SaveContext gSaveContext; } diff --git a/soh/soh/Enhancements/randomizer/entrance.cpp b/soh/soh/Enhancements/randomizer/entrance.cpp index 00a7a5adb..1cd4160de 100644 --- a/soh/soh/Enhancements/randomizer/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/entrance.cpp @@ -45,8 +45,6 @@ std::string Entrance::GetName() const { } void Entrance::printAgeTimeAccess() { - // CitraPrint("Name: "); - // CitraPrint(name); auto message = "Child Day: " + std::to_string(CheckConditionAtAgeTime(logic->IsChild, logic->AtDay)) + "\t" "Child Night: " + @@ -57,7 +55,6 @@ void Entrance::printAgeTimeAccess() { "\t" "Adult Night: " + std::to_string(CheckConditionAtAgeTime(logic->IsAdult, logic->AtNight)); - // CitraPrint(message); } bool Entrance::ConditionsMet(bool allAgeTimes) const { @@ -276,8 +273,8 @@ void SetAllEntrancesData() { { EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } }, { { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE }, { EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } }, - { { EntranceType::Dungeon, RR_GF_OUTSIDE_GTG, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE }, - { EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GF_OUTSIDE_GTG, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } }, + { { EntranceType::Dungeon, RR_GF_TO_GTG, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE }, + { EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GF_EXITING_GTG, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } }, { { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE }, { EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } }, @@ -1214,15 +1211,6 @@ int EntranceShuffler::ShuffleAllEntrances() { if (ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES).Is(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL)) { entrancePools[EntranceType::Boss] = GetShuffleableEntrances(EntranceType::ChildBoss); AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::AdultBoss)); - // If forest is closed, ensure Ghoma is inside the Deku tree - // Deku tree being in its vanilla location is handled below - if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) && - !(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) { - FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance) { - return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY && - 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()); @@ -1231,14 +1219,6 @@ int EntranceShuffler::ShuffleAllEntrances() { } else { entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss); entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss); - // If forest is closed, ensure Ghoma is inside the Deku tree - if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) && - !(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) { - FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance) { - return entrance->GetParentRegionKey() == RR_DEKU_TREE_BOSS_ENTRYWAY && - 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()); @@ -1258,14 +1238,6 @@ int EntranceShuffler::ShuffleAllEntrances() { AddElementsToPool(entrancePools[EntranceType::Dungeon], GetShuffleableEntrances(EntranceType::GanonDungeon)); } - // If forest is closed don't allow a forest escape via spirit temple hands - if (ctx->GetOption(RSK_FOREST).Is(RO_CLOSED_FOREST_ON) && - !(ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES))) { - FilterAndEraseFromPool(entrancePools[EntranceType::Dungeon], [](const Entrance* entrance) { - return entrance->GetParentRegionKey() == RR_KF_OUTSIDE_DEKU_TREE && - entrance->GetConnectedRegionKey() == RR_DEKU_TREE_ENTRYWAY; - }); - } if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) { for (Entrance* entrance : entrancePools[EntranceType::Dungeon]) { entrancePools[EntranceType::DungeonReverse].push_back(entrance->GetReverse()); diff --git a/soh/soh/Enhancements/randomizer/hint.cpp b/soh/soh/Enhancements/randomizer/hint.cpp index c98ecea15..27ca4eb2a 100644 --- a/soh/soh/Enhancements/randomizer/hint.cpp +++ b/soh/soh/Enhancements/randomizer/hint.cpp @@ -299,6 +299,8 @@ const CustomMessage Hint::GetHintMessage(MessageFormat format, size_t id) const } else if (hintType == HINT_TYPE_ALTAR_CHILD) { if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { hintText = StaticData::hintTextTable[RHT_CHILD_ALTAR_STONES].GetHintMessage(); + } else { + hintText.SetTextBoxType(TEXTBOX_TYPE_BLUE); } if (ctx->GetOption(RSK_DOOR_OF_TIME).Is(RO_DOOROFTIME_OPEN)) { hintText += CustomMessage(StaticData::hintTextTable[RHT_CHILD_ALTAR_TEXT_END_DOTOPEN].GetHintMessage()); @@ -310,6 +312,8 @@ const CustomMessage Hint::GetHintMessage(MessageFormat format, size_t id) const } else if (hintType == HINT_TYPE_ALTAR_ADULT) { if (ctx->GetOption(RSK_TOT_ALTAR_HINT)) { hintText = StaticData::hintTextTable[RHT_ADULT_ALTAR_MEDALLIONS].GetHintMessage(); + } else { + hintText.SetTextBoxType(TEXTBOX_TYPE_BLUE); } hintText += GetBridgeReqsText() + GetGanonBossKeyText() + StaticData::hintTextTable[RHT_ADULT_ALTAR_TEXT_END].GetHintMessage(); diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 92d210300..d73cebca7 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -22,6 +22,7 @@ extern "C" { #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "soh/Enhancements/randomizer/randomizer_grotto.h" #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" +#include "src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.h" #include "src/overlays/actors/ovl_En_Si/z_en_si.h" #include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h" #include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" @@ -263,6 +264,14 @@ void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t Flags_SetRandomizerInf(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN); } + if (sceneNum == SCENE_SPIRIT_TEMPLE && flagType == FLAG_SCENE_SWITCH) { + bool isVanilla = + Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla(); + if (isVanilla && flag == 0x23) { + Flags_SetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON); + } + } + RandomizerCheck rc = GetRandomizerCheckFromSceneFlag(sceneNum, flagType, flag); if (rc == RC_UNKNOWN_CHECK) return; @@ -1783,7 +1792,7 @@ void RandomizerOnSceneInitHandler(int16_t sceneNum) { Entrance_OverrideSpawnScene(sceneNum, gPlayState->curSpawn); } - // LACs & Prelude checks + // LACS & Prelude checks static uint32_t updateHook = 0; if (updateHook) { @@ -1855,6 +1864,16 @@ void EnDns_RandomizerPurchase(EnDns* enDns) { void RandomizerOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); + if (actor->id == ACTOR_PLAYER) { + if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE) { + bool isVanilla = + Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla(); + if (isVanilla && Flags_GetRandomizerInf(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON)) { + Flags_SetSwitch(gPlayState, 0x23); + } + } + } + if (actor->id == ACTOR_EN_SI) { RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actor->id, gPlayState->sceneNum, actor->params); @@ -1986,6 +2005,15 @@ void RandomizerOnActorInitHandler(void* actorRef) { } } + if (actor->id == ACTOR_BG_JYA_BIGMIRROR && Flags_GetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED)) { + Flags_SetSwitch(gPlayState, 0x29); // destroy wall + auto jyaBigMirror = static_cast(actorRef); + jyaBigMirror->puzzleFlags |= + BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED | BIGMIR_PUZZLE_BOMBIWA_DESTROYED; + jyaBigMirror->cobraInfo[0].rotY = 0x4000; + jyaBigMirror->cobraInfo[1].rotY = 0x8000; + } + if (actor->id == ACTOR_DEMO_KEKKAI && actor->params == 0) { // 0 == KEKKAI_TOWER if (CompletedAllTrials()) { Actor_Kill(actor); @@ -2151,6 +2179,16 @@ void RandomizerOnActorUpdateHandler(void* refActor) { } } + if (actor->id == ACTOR_BG_JYA_BIGMIRROR) { + auto jyaBigMirror = reinterpret_cast(actor); + if ((jyaBigMirror->puzzleFlags & (BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED)) == + (BIGMIR_PUZZLE_COBRA1_SOLVED | BIGMIR_PUZZLE_COBRA2_SOLVED)) { + Flags_SetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED); + } else { + Flags_UnsetRandomizerInf(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED); + } + } + // In ER, override the warp song locations. Also removes the warp song cutscene if (RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES) && actor->id == ACTOR_DEMO_KANKYO && actor->params == 0x000F) { // Warp Song particles diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 3b75a0c95..71f9fff38 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -21,7 +21,8 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, 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_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), category(category_), 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_, @@ -36,10 +37,11 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, } Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const bool progressive_, - const uint16_t price_) + const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, + const GetItemCategory category_, const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), category(category_), progressive(progressive_), + price(price_) { } Item::~Item() = default; @@ -456,6 +458,10 @@ const HintText& Item::GetHint() const { return StaticData::hintTextTable[hintKey]; } +GetItemCategory Item::GetCategory() { + return category; +} + bool Item::operator==(const Item& right) const { return type == right.GetItemType() && getItemId == right.GetItemID(); } diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index da8632151..13a654d9c 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -35,7 +35,8 @@ class Item { 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_, - LogicVal logicVal_, RandomizerHintTextKey hintKey_, bool progressive_ = false, uint16_t price_ = 0); + LogicVal logicVal_, RandomizerHintTextKey hintKey_, GetItemCategory category_, bool progressive_ = false, + uint16_t price_ = 0); ~Item(); void ApplyEffect() const; @@ -58,6 +59,7 @@ class Item { bool IsMajorItem() const; RandomizerHintTextKey GetHintKey() const; const HintText& GetHint() const; + GetItemCategory GetCategory(); bool operator==(const Item& right) const; bool operator!=(const Item& right) const; @@ -69,6 +71,7 @@ class Item { bool advancement; LogicVal logicVal; RandomizerHintTextKey hintKey; + GetItemCategory category; bool progressive; uint16_t price; bool playthrough = false; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 786717c80..7f22fe83f 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -59,19 +59,19 @@ void Rando::StaticData::InitItemTable() { // Skulltula Token itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "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.)", "Fanghaken (prog.)" }, 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.)", "Stärke (prog.)" }, 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.)", "Bombentasche (prog.)" }, 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.)", "Bogen (prog.)" }, 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.)", "Schleuder (prog.)" }, 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.)", "Geldbörse (prog.)" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, true); - itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Zora-Schuppe (prog.)" }, 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.)", "Nuß-Kapazität (prog.)" }, 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.)", "Stab-Kapazität (prog.)" }, 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.)", "Krabbelminen (prog.)" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, true); - itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Magische Kraft (prog.)" }, 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.)", "Okarina (prog.)" }, 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.)", "Goronen-Schwert (prog.)" }, 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.)", "Fanghaken (prog.)" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Stärke (prog.)" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Bombentasche (prog.)" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Bogen (prog.)" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Schleuder (prog.)" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Geldbörse (prog.)" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Zora-Schuppe (prog.)" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Nuß-Kapazität (prog.)" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Stab-Kapazität (prog.)" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Krabbelminen (prog.)" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Magische Kraft (prog.)" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Okarina (prog.)" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, ITEM_CATEGORY_MAJOR, true); + itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Goronen-Schwert (prog.)" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, ITEM_CATEGORY_MAJOR, 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 (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); @@ -305,7 +305,7 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BUY_BOMBCHUS_10] = Item(RG_BUY_BOMBCHUS_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Krabbelminen kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 99); itemTable[RG_BUY_BOMBCHUS_20] = Item(RG_BUY_BOMBCHUS_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Krabbelminen kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_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-Kerne 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_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, ITEM_CATEGORY_JUNK, 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", "Kä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", "Irrlicht 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); @@ -372,8 +372,8 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "Sac de Noix Mojo", "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, ITEM_CATEGORY_MAJOR); + itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE, ITEM_CATEGORY_LESSER); // 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); diff --git a/soh/soh/Enhancements/randomizer/location.cpp b/soh/soh/Enhancements/randomizer/location.cpp index f474397aa..6c27e3aef 100644 --- a/soh/soh/Enhancements/randomizer/location.cpp +++ b/soh/soh/Enhancements/randomizer/location.cpp @@ -54,8 +54,9 @@ const std::string& Rando::Location::GetShortName() const { bool Rando::Location::IsDungeon() const { return (checkType != RCTYPE_SKULL_TOKEN && - (scene <= SCENE_GERUDO_TRAINING_GROUND || scene == SCENE_INSIDE_GANONS_CASTLE || - (scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_GANONDORF_BOSS))) || + (scene <= SCENE_GERUDO_TRAINING_GROUND || scene == SCENE_INSIDE_GANONS_CASTLE || + (scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_GANONDORF_BOSS)) || + (rc == RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST || rc == RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST)) || (checkType == RCTYPE_SKULL_TOKEN && scene <= SCENE_ICE_CAVERN); } diff --git a/soh/soh/Enhancements/randomizer/location_access.cpp b/soh/soh/Enhancements/randomizer/location_access.cpp index 2fb04dccd..e261b8d49 100644 --- a/soh/soh/Enhancements/randomizer/location_access.cpp +++ b/soh/soh/Enhancements/randomizer/location_access.cpp @@ -20,6 +20,18 @@ extern PlayState* gPlayState; // generic grotto event list std::vector grottoEvents; +bool EventAccess::CheckConditionAtAgeTime(bool& age, bool& time) { + logic->IsChild = false; + logic->IsAdult = false; + logic->AtDay = false; + logic->AtNight = false; + + time = true; + age = true; + + return ConditionsMet(); +} + // set the logic to be a specific age and time of day and see if the condition still holds bool LocationAccess::CheckConditionAtAgeTime(bool& age, bool& time) const { logic->IsChild = false; @@ -466,7 +478,7 @@ bool Region::UpdateEvents() { } void Region::AddExit(RandomizerRegion parentKey, RandomizerRegion newExitKey, ConditionFn condition) { - Rando::Entrance newExit = Rando::Entrance(newExitKey, { condition }); + Rando::Entrance newExit = Rando::Entrance(newExitKey, condition); newExit.SetParentRegion(parentKey); exits.push_front(newExit); } @@ -551,6 +563,110 @@ void Region::ResetVariables() { } } +/* + * This logic covers checks that exist in the shared areas of MQ spirit from a glitchless standpoint. + * This room has Quantum logic that I am currently handling with this function, however this is NOT suitable for + glitch logic as it relies on specific ages + * In this chunk there are 3 possibilities for passing a check, but first I have to talk about parallel universes. + + * In MQ Spirit key logic, we mostly care about 2 possibilities for how the player can spend keys, creating 2 + Parralel universes + * In the first universe, the player did not enter spirit as adult until after climbing as child, thus child spends + keys linearly, only needing 2 to reach statue room. + * In the second universe, the player went in as adult, possibly out of logic, and started wasting the keys to lock + child out. + * These Universes converge when the player has 7 keys (meaning adult can no longer lock child out) and adult is + known to be able to reach Statue room. This creates "Certain Access", which is tracked seperatly for each age. + * Child Certain Access is simple, if we have 7 keys and child access, it's Certain Access. + * Adult Certain Access is also simple, adult is not key locked, so if they make it to a location, it's Certain + Access. + * Things get complicated when we handle the overlap of the 2 universes, + * though an important detail is that if we have Certain Access as either age, we don't need to checked the overlap + because overlap logic is strictly stricter than either Certain Access. + + * In order to track the first universe, the logic allows technical child access with the minimum number of keys, + and then checks in this function for if we have 7 keys to determine if that is Certain or not. + * This is for technical reasons, as areas with no access at all will simply not be checked. + * Normally we would need to do similar shenanigans to track the second universe, however adult must have go through + statue room to waste keys, + * so can go back there and get new keys for Child to use if they do, and the navigation logic for shared MQ spirit + from Statue Room is very simple for Adult. + * Additionally, we don't need to know if adult can actually reach spirit temple or climb to statue room, because if + the player can't do that, then universe 2 can't happen anyway, + * and if the player does so out of logic, they can do it again, as the only consumable used sets a permanent flag. + + * The Adult Navigation logic is as such: + * - Broken Wall room is 6 key locked, because if the player tries to spend 6 keys in a way that would block adults + access, they would have to give child access instead. + * - The child side hammer switch for the time travelling chest is 7 key locked for adult + * - Reaching gauntlets hand is 7 key locked + * - Going back into big block room is complex, but the only check there is child only so not a concern + * - Everything else is possible with basic adult movement, or is impossible for child to reach glitchlessly + * Anything 7 key locked does not need to be checked as shared, as all child access is Certain and because of this + workaround we don't need to fake Adult access, meaning that is also Certain. + * All of this combined means that when checking if adult can reach a location in universe 2, we only have to ask if + it is a 6 key locked location or not. + + * Knowing all of this this, we can confirm things are logical in 3 different ways: + * - If we have Adult Access, we know it is Certain Access, so they can get checks alone. + * - If we have 7 keys, child has Certain Access as we know they cannot be locked out, so can get checks alone, + otherwise we check the logical overlap + * - If Child and Adult can get the check (ignoring actual adult access to the location), and the location is either + not 6 key locked or we have 6 keys, we can get the check with the overlap + */ +bool Region::MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge) { + // if we have Certain Access as child, we can check anyAge and if true, resolve a condition with Here as if + // adult is here it's also Certain Access + if (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) { + if (anyAge) { + return Here(condition); + } + return condition(); + // else, if we are here as adult, we have Certain Access from that and don't need special handling for + // checking adult + } else if (Adult() && logic->IsAdult) { + return condition(); + // if we do not have Certain Access, we need to check the overlap by seeing if we are both here as child and + // meet the adult universe's access condition We only need to do it as child, as only child access matters + // for this check, as adult access is assumed based on keys + } else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(RR_SPIRIT_TEMPLE, 6))) { + bool result = false; + // store current age variables + bool pastAdult = logic->IsAdult; + bool pastChild = logic->IsChild; + + // First check if the check is possible as child + logic->IsChild = true; + logic->IsAdult = false; + result = condition(); + // If so, check again as adult. both have to be true for result to be true + if (result) { + logic->IsChild = false; + logic->IsAdult = true; + result = condition(); + } + + // set back age variables + logic->IsChild = pastChild; + logic->IsAdult = pastAdult; + return result; + } + return false; +} + +void Region::printAgeTimeAccess() { + auto message = "Child Day: " + std::to_string(childDay) + + "\t" + "Child Night: " + + std::to_string(childNight) + + "\t" + "Adult Day: " + + std::to_string(adultDay) + + "\t" + "Adult Night: " + + std::to_string(adultNight); +} + std::array areaTable; bool Here(const RandomizerRegion region, ConditionFn condition) { @@ -692,11 +808,11 @@ void RegionTable_Init() { Entrance(RR_CHILD_SPAWN, []{return logic->IsChild;}), Entrance(RR_ADULT_SPAWN, []{return logic->IsAdult;}), Entrance(RR_MINUET_OF_FOREST_WARP, []{return logic->CanUse(RG_MINUET_OF_FOREST);}), - Entrance(RR_BOLERO_OF_FIRE_WARP, []{return logic->CanUse(RG_BOLERO_OF_FIRE) && logic->CanLeaveForest();}), - Entrance(RR_SERENADE_OF_WATER_WARP, []{return logic->CanUse(RG_SERENADE_OF_WATER) && logic->CanLeaveForest();}), - Entrance(RR_NOCTURNE_OF_SHADOW_WARP, []{return logic->CanUse(RG_NOCTURNE_OF_SHADOW) && logic->CanLeaveForest();}), - Entrance(RR_REQUIEM_OF_SPIRIT_WARP, []{return logic->CanUse(RG_REQUIEM_OF_SPIRIT) && logic->CanLeaveForest();}), - Entrance(RR_PRELUDE_OF_LIGHT_WARP, []{return logic->CanUse(RG_PRELUDE_OF_LIGHT) && logic->CanLeaveForest();}), + Entrance(RR_BOLERO_OF_FIRE_WARP, []{return logic->CanUse(RG_BOLERO_OF_FIRE);}), + Entrance(RR_SERENADE_OF_WATER_WARP, []{return logic->CanUse(RG_SERENADE_OF_WATER);}), + Entrance(RR_NOCTURNE_OF_SHADOW_WARP, []{return logic->CanUse(RG_NOCTURNE_OF_SHADOW);}), + Entrance(RR_REQUIEM_OF_SPIRIT_WARP, []{return logic->CanUse(RG_REQUIEM_OF_SPIRIT);}), + Entrance(RR_PRELUDE_OF_LIGHT_WARP, []{return logic->CanUse(RG_PRELUDE_OF_LIGHT);}), }); areaTable[RR_CHILD_SPAWN] = Region("Child Spawn", SCENE_ID_MAX, TIME_DOESNT_PASS, {RA_LINKS_POCKET}, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access.h b/soh/soh/Enhancements/randomizer/location_access.h index 547000ce5..5cbc84060 100644 --- a/soh/soh/Enhancements/randomizer/location_access.h +++ b/soh/soh/Enhancements/randomizer/location_access.h @@ -34,17 +34,7 @@ class EventAccess { return true; } - bool CheckConditionAtAgeTime(bool& age, bool& time) { - logic->IsChild = false; - logic->IsAdult = false; - logic->AtDay = false; - logic->AtNight = false; - - time = true; - age = true; - - return ConditionsMet(); - } + bool CheckConditionAtAgeTime(bool& age, bool& time); void EventOccurred() { *event = true; @@ -210,7 +200,7 @@ class Region { logic->IsChild = Child(); logic->IsAdult = Adult(); - // heck condition as well as having at least child or adult access + // check condition as well as having at least child or adult access bool hereVal = condition() && (logic->IsAdult || logic->IsChild); // set back age variables @@ -222,112 +212,11 @@ class Region { bool CanPlantBeanCheck() const; bool AllAccountedFor() const; + bool MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge = false); void ResetVariables(); - void printAgeTimeAccess() const { - auto message = "Child Day: " + std::to_string(childDay) + - "\t" - "Child Night: " + - std::to_string(childNight) + - "\t" - "Adult Day: " + - std::to_string(adultDay) + - "\t" - "Adult Night: " + - std::to_string(adultNight); - } - - /* - * This logic covers checks that exist in the shared areas of MQ spirit from a glitchless standpoint. - * This room has Quantum logic that I am currently handling with this function, however this is NOT suitable for - glitch logic as it relies on specific ages - * In this chunk there are 3 possibilities for passing a check, but first I have to talk about parallel universes. - - * In MQ Spirit key logic, we mostly care about 2 possibilities for how the player can spend keys, creating 2 - Parralel universes - * In the first universe, the player did not enter spirit as adult until after climbing as child, thus child spends - keys linearly, only needing 2 to reach statue room. - * In the second universe, the player went in as adult, possibly out of logic, and started wasting the keys to lock - child out. - * These Universes converge when the player has 7 keys (meaning adult can no longer lock child out) and adult is - known to be able to reach Statue room. This creates "Certain Access", which is tracked seperatly for each age. - * Child Certain Access is simple, if we have 7 keys and child access, it's Certain Access. - * Adult Certain Access is also simple, adult is not key locked, so if they make it to a location, it's Certain - Access. - * Things get complicated when we handle the overlap of the 2 universes, - * though an important detail is that if we have Certain Access as either age, we don't need to checked the overlap - because overlap logic is strictly stricter than either Certain Access. - - * In order to track the first universe, the logic allows technical child access with the minimum number of keys, - and then checks in this function for if we have 7 keys to determine if that is Certain or not. - * This is for technical reasons, as areas with no access at all will simply not be checked. - * Normally we would need to do similar shenanigans to track the second universe, however adult must have go through - statue room to waste keys, - * so can go back there and get new keys for Child to use if they do, and the navigation logic for shared MQ spirit - from Statue Room is very simple for Adult. - * Additionally, we don't need to know if adult can actually reach spirit temple or climb to statue room, because if - the player can't do that, then universe 2 can't happen anyway, - * and if the player does so out of logic, they can do it again, as the only consumable used sets a permanent flag. - - * The Adult Navigation logic is as such: - * - Broken Wall room is 6 key locked, because if the player tries to spend 6 keys in a way that would block adults - access, they would have to give child access instead. - * - The child side hammer switch for the time travelling chest is 7 key locked for adult - * - Reaching gauntlets hand is 7 key locked - * - Going back into big block room is complex, but the only check there is child only so not a concern - * - Everything else is possible with basic adult movement, or is impossible for child to reach glitchlessly - * Anything 7 key locked does not need to be checked as shared, as all child access is Certain and because of this - workaround we don't need to fake Adult access, meaning that is also Certain. - * All of this combined means that when checking if adult can reach a location in universe 2, we only have to ask if - it is a 6 key locked location or not. - - * Knowing all of this this, we can confirm things are logical in 3 different ways: - * - If we have Adult Access, we know it is Certain Access, so they can get checks alone. - * - If we have 7 keys, child has Certain Access as we know they cannot be locked out, so can get checks alone, - otherwise we check the logical overlap - * - If Child and Adult can get the check (ignoring actual adult access to the location), and the location is either - not 6 key locked or we have 6 keys, we can get the check with the overlap - */ - bool MQSpiritShared(ConditionFn condition, bool IsBrokenWall, bool anyAge = false) { - // if we have Certain Access as child, we can check anyAge and if true, resolve a condition with Here as if - // adult is here it's also Certain Access - if (logic->SmallKeys(RR_SPIRIT_TEMPLE, 7)) { - if (anyAge) { - return Here(condition); - } - return condition(); - // else, if we are here as adult, we have Certain Access from that and don't need special handling for - // checking adult - } else if (Adult() && logic->IsAdult) { - return condition(); - // if we do not have Certain Access, we need to check the overlap by seeing if we are both here as child and - // meet the adult universe's access condition We only need to do it as child, as only child access matters - // for this check, as adult access is assumed based on keys - } else if (Child() && logic->IsChild && (!IsBrokenWall || logic->SmallKeys(RR_SPIRIT_TEMPLE, 6))) { - bool result = false; - // store current age variables - bool pastAdult = logic->IsAdult; - bool pastChild = logic->IsChild; - - // First check if the check is possible as child - logic->IsChild = true; - logic->IsAdult = false; - result = condition(); - // If so, check again as adult. both have to be true for result to be true - if (result) { - logic->IsChild = false; - logic->IsAdult = true; - result = condition(); - } - - // set back age variables - logic->IsChild = pastChild; - logic->IsAdult = pastAdult; - return result; - } - return false; - } + void printAgeTimeAccess(); }; extern std::array areaTable; diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp index 2eb8764e1..6c891abc0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp @@ -11,7 +11,7 @@ void RegionTable_Init_GerudoTrainingGround() { //Exits Entrance(RR_GERUDO_TRAINING_GROUND_LOBBY, []{return ctx->GetDungeon(GERUDO_TRAINING_GROUND)->IsVanilla();}), Entrance(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, []{return ctx->GetDungeon(GERUDO_TRAINING_GROUND)->IsMQ();}), - Entrance(RR_GF_OUTSIDE_GTG, []{return true;}), + Entrance(RR_GF_EXITING_GTG, []{return true;}), }); #pragma region Vanilla diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp index c40ccf805..51e80fc0c 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/jabujabus_belly.cpp @@ -64,7 +64,7 @@ void RegionTable_Init_JabuJabusBelly() { //Exits Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return true;}), //there's tricks for getting here with bunny-jumps or just side-hops - Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_SOUTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), }); @@ -90,7 +90,7 @@ void RegionTable_Init_JabuJabusBelly() { }, { //Exits Entrance(RR_JABU_JABUS_BELLY_B1_NORTH, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE);}), - Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), + Entrance(RR_JABU_JABUS_BELLY_WATER_SWITCH_ROOM_LEDGE, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_JABU_JABUS_BELLY_MAIN, []{return logic->CanUseProjectile();}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index 2755fe453..e2a13ecc1 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -48,12 +48,12 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CHILD_CLIMB] = Region("Child Spirit Temple Climb", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || ((logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->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) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->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_NORTH_CHEST, logic->HasProjectile(HasProjectileAge::Both) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && 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, 2) && 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->TakeDamage() && (logic->CanJumpslashExceptHammer() || 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) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))), + (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->HasProjectile(HasProjectileAge::Adult) || (logic->TakeDamage() && logic->CanJumpslashExceptHammer())))), LOCATION(RC_SPIRIT_TEMPLE_CHILD_CLIMB_POT_1, logic->CanBreakPots()), }, { //Exits @@ -75,11 +75,11 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER] = Region("Spirit Temple Central Chamber", SCENE_SPIRIT_TEMPLE, {}, { //Locations - LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + LOCATION(RC_SPIRIT_TEMPLE_MAP_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_MAP_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && 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) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && (logic->CanUse(RG_DINS_FIRE) || ((logic->CanUse(RG_FIRE_ARROWS) || ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST)) && logic->CanUse(RG_FAIRY_BOW) && logic->CanUse(RG_STICKS) ))) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives() && logic->CanUse(RG_STICKS)) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) && (logic->CanUse(RG_FIRE_ARROWS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))) && logic->CanUse(RG_SILVER_GAUNTLETS))), @@ -87,20 +87,19 @@ void RegionTable_Init_SpiritTemple() { 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->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))), LOCATION(RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM, (logic->HasExplosives() && logic->CanUse(RG_BOOMERANG) && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_BOOMERANG) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 5) && logic->HasExplosives()) || - (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && - logic->CanUse(RG_BOOMERANG) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->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) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF))) && + (logic->CanUse(RG_HOOKSHOT) && logic->CanUse(RG_SILVER_GAUNTLETS) && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2))), + LOCATION(RC_SPIRIT_TEMPLE_GS_LOBBY, ((logic->HasExplosives() || logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)) && ctx->GetTrickOption(RT_SPIRIT_LOBBY_GS) && logic->CanUse(RG_BOOMERANG) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP))) || (ctx->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->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || ctx->GetTrickOption(RT_SPIRIT_LOBBY_JUMP)))), - LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), - LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && (logic->SmallKeys(RR_SPIRIT_TEMPLE, 3) || (logic->SmallKeys(RR_SPIRIT_TEMPLE, 2) && ctx->GetOption(RSK_BOMBCHU_BAG) && logic->BombchuRefill() && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).Is(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF)))), + LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_AFTER_SUN_BLOCK_POT_2, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_1, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_2, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_3, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_4, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_5, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), + LOCATION(RC_SPIRIT_TEMPLE_CENTRAL_CHAMBER_POT_6, logic->CanBreakPots() && logic->SmallKeys(RR_SPIRIT_TEMPLE, 2)), }, { //Exits Entrance(RR_SPIRIT_TEMPLE_OUTDOOR_HANDS, []{return logic->CanJumpslashExceptHammer() || logic->HasExplosives();}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp index e26e841f0..3929faf86 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_fortress.cpp @@ -49,15 +49,26 @@ void RegionTable_Init_GerudoFortress() { EventAccess(&logic->GtG_GateOpen, []{return (logic->IsAdult && logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->HasItem(RG_CHILD_WALLET));}), }, {}, { //Exits - Entrance(RR_GERUDO_TRAINING_GROUND_ENTRYWAY, []{return logic->GtG_GateOpen && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}), + Entrance(RR_GF_TO_GTG, []{return logic->GtG_GateOpen && (logic->IsAdult || ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES));}), //Jail + Entrance(RR_GF_JAIL_WINDOW, []{return logic->CanUse(RG_HOOKSHOT);}), + Entrance(RR_GF_OUTSKIRTS, []{return true;}), + Entrance(RR_GF_NEAR_GROTTO, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), + // RANDTODO: Add tricks for getting past the gerudo guarding the hba range + Entrance(RR_GF_ABOVE_GTG, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), + Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_GF_HBA_RANGE, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), + }); + + areaTable[RR_GF_TO_GTG] = Region("GF to GTG", SCENE_GERUDOS_FORTRESS, {}, {}, { + Entrance(RR_GERUDO_TRAINING_GROUND_ENTRYWAY, []{return true;}), + }); + + // Split out to handle adult being immediately captured without card + areaTable[RR_GF_EXITING_GTG] = Region("GF Exiting GTG", SCENE_GERUDOS_FORTRESS, {}, {}, { + Entrance(RR_GF_OUTSIDE_GTG, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), Entrance(RR_GF_JAIL_WINDOW, []{return logic->CanUse(RG_HOOKSHOT);}), Entrance(RR_GF_OUTSKIRTS, []{return true;}), - Entrance(RR_GF_NEAR_GROTTO, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), - // RANDTODO: Add tricks for getting past the gerudo guarding the hba range - Entrance(RR_GF_ABOVE_GTG, []{return logic->IsChild || logic->CanPassEnemy(RE_GERUDO_GUARD);}), - Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD) && logic->CanUse(RG_LONGSHOT);}), - Entrance(RR_GF_HBA_RANGE, []{return logic->IsChild || logic->HasItem(RG_GERUDO_MEMBERSHIP_CARD);}), }); #pragma endregion @@ -123,6 +134,7 @@ void RegionTable_Init_GerudoFortress() { Entrance(RR_GF_TOP_OF_LOWER_VINES, []{return true;}), Entrance(RR_GF_SLOPED_ROOF, []{return logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_GF_TOP_OF_UPPER_VINES, []{return true /* logic->CanClimb() */;}), + Entrance(RR_GF_TO_GTG, []{return logic->IsAdult && ctx->GetTrickOption(RT_GF_LEDGE_CLIP_INTO_GTG).Get();}), }); areaTable[RR_GF_TOP_OF_UPPER_VINES] = Region("GF Top of Upper Vines", SCENE_GERUDOS_FORTRESS, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp index 7027ab6c6..9d155c3a0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/goron_city.cpp @@ -63,7 +63,7 @@ void RegionTable_Init_GoronCity() { EventAccess(&logic->GCWoodsWarpOpen, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE);}), }, {}, { //Exits - Entrance(RR_GORON_CITY, []{return logic->CanLeaveForest() && logic->GCWoodsWarpOpen;}), + Entrance(RR_GORON_CITY, []{return logic->GCWoodsWarpOpen;}), Entrance(RR_THE_LOST_WOODS, []{return true;}), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index 763d12575..2fce0854f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -10,6 +10,7 @@ void RegionTable_Init_Graveyard() { EventAccess(&logic->ButterflyFairy, []{return logic->CanUse(RG_STICKS) && logic->AtDay;}), EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), EventAccess(&logic->BugRock, []{return true;}), + EventAccess(&logic->BorrowBunnyHood, []{return logic->IsChild && logic->AtDay && logic->BorrowSpookyMask && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && CanPlantBean(RR_THE_GRAVEYARD)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index 5bc3aeb26..3d850be58 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -8,6 +8,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HYRULE_FIELD] = Region("Hyrule Field", SCENE_HYRULE_FIELD, { //Events EventAccess(&logic->BigPoeKill, []{return logic->HasBottle() && logic->CanUse(RG_FAIRY_BOW) && (logic->CanUse(RG_EPONA) || ctx->GetTrickOption(RT_HF_BIG_POE_WITHOUT_EPONA));}), + EventAccess(&logic->BorrowRightMasks, []{return logic->IsChild && logic->BorrowBunnyHood && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_HF_OCARINA_OF_TIME_ITEM, logic->IsChild && logic->StoneCount() == 3 && logic->HasItem(RG_BRONZE_SCALE)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 13490c9a4..92bc9aa37 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -10,6 +10,8 @@ void RegionTable_Init_Kakariko() { EventAccess(&logic->BugRock, []{return true;}), //Open Gate setting is applied in RR_ROOT EventAccess(&logic->KakarikoVillageGateOpen, []{return logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER);}), + //Needs wallet to be able to get another mask after selling Keaton + EventAccess(&logic->BorrowSkullMask, []{return logic->IsChild && logic->CanBorrowMasks && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp index 525e22200..5d8ef11ec 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kokiri_forest.cpp @@ -13,7 +13,7 @@ void RegionTable_Init_KokiriForest() { }, { //Locations LOCATION(RC_KF_KOKIRI_SWORD_CHEST, logic->IsChild), - LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanAttack() && (/*TODO: HasNightStart ||*/ logic->CanLeaveForest() || logic->CanUse(RG_SUNS_SONG)) && logic->CanGetNightTimeGS()), + LOCATION(RC_KF_GS_KNOW_IT_ALL_HOUSE, logic->IsChild && logic->CanAttack() && logic->CanGetNightTimeGS()), LOCATION(RC_KF_GS_BEAN_PATCH, logic->CanSpawnSoilSkull() && logic->CanAttack()), LOCATION(RC_KF_GS_HOUSE_OF_TWINS, logic->IsAdult && (logic->HookshotOrBoomerang() || (ctx->GetTrickOption(RT_KF_ADULT_GS) && logic->CanUse(RG_HOVER_BOOTS))) && logic->CanGetNightTimeGS()), LOCATION(RC_KF_BEAN_SPROUT_FAIRY_1, logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index e949a7b1e..6c6bdb536 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -12,9 +12,10 @@ void RegionTable_Init_LostWoods() { areaTable[RR_THE_LOST_WOODS] = Region("Lost Woods", SCENE_LOST_WOODS, { //Events - EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), - EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), - EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}), + EventAccess(&logic->GossipStoneFairy, []{return logic->CallGossipFairyExceptSuns();}), + EventAccess(&logic->BeanPlantFairy, []{return logic->IsChild && logic->CanUse(RG_MAGIC_BEAN) && logic->CanUse(RG_SONG_OF_STORMS);}), + EventAccess(&logic->BugShrub, []{return logic->IsChild && logic->CanCutShrubs();}), + EventAccess(&logic->BorrowSpookyMask, []{return logic->IsChild && logic->BorrowSkullMask && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET);}), }, { //Locations LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), @@ -56,8 +57,8 @@ void RegionTable_Init_LostWoods() { //Exits Entrance(RR_LW_FOREST_EXIT, []{return true;}), Entrance(RR_GC_WOODS_WARP, []{return true;}), - Entrance(RR_LW_BRIDGE, []{return logic->CanLeaveForest() && ((logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT));}), - Entrance(RR_ZR_FROM_SHORTCUT, []{return logic->CanLeaveForest() && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash()));}), + Entrance(RR_LW_BRIDGE, []{return (logic->IsAdult && (CanPlantBean(RR_THE_LOST_WOODS) || ctx->GetTrickOption(RT_LW_BRIDGE))) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_LONGSHOT);}), + Entrance(RR_ZR_FROM_SHORTCUT, []{return logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LOST_WOOD_NAVI_DIVE) && logic->IsChild && logic->HasItem(RG_BRONZE_SCALE) && logic->CanJumpslash());}), Entrance(RR_LW_BEYOND_MIDO, []{return logic->IsChild || logic->CanUse(RG_SARIAS_SONG) || ctx->GetTrickOption(RT_LW_MIDO_BACKFLIP);}), Entrance(RR_LW_NEAR_SHORTCUTS_GROTTO, []{return Here(RR_THE_LOST_WOODS, []{return logic->BlastOrSmash();});}), }); @@ -110,8 +111,8 @@ void RegionTable_Init_LostWoods() { areaTable[RR_DEKU_THEATER] = Region("Deku Theater", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->SkullMask), - LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->MaskOfTruth), + LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->BorrowSkullMask), + LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->BorrowRightMasks), }, { //Exits Entrance(RR_LW_BEYOND_MIDO, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index 7d7655ef0..4f62d437f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -138,8 +138,14 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_MASK_SHOP] = Region("Market Mask Shop", SCENE_HAPPY_MASK_SHOP, { //Events - EventAccess(&logic->SkullMask, []{return logic->HasItem(RG_ZELDAS_LETTER) && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || ChildCanAccess(RR_KAKARIKO_VILLAGE));}), //RANDOTODO Complete mask quest does not need this location, so should be tied to link's pocket - EventAccess(&logic->MaskOfTruth, []{return logic->SkullMask && (ctx->GetOption(RSK_COMPLETE_MASK_QUEST) || (ChildCanAccess(RR_THE_LOST_WOODS) && logic->CanUse(RG_SARIAS_SONG) && RegionTable(RR_THE_GRAVEYARD)->childDay && ChildCanAccess(RR_HYRULE_FIELD) && logic->StoneCount() == 3));}), + //Currently, mask swap in menu doesn't need access to the mask shop + //If it is forced on/a setting, a copy of these events should be added to root + //it also doesn't need you to open kak gate, but that might be best treated as a bug + EventAccess(&logic->CanBorrowMasks, []{return logic->HasItem(RG_ZELDAS_LETTER) && logic->KakarikoVillageGateOpen;}), + EventAccess(&logic->BorrowSkullMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowSpookyMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowBunnyHood, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowRightMasks, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), }, { //Locations LOCATION(RC_MASK_SHOP_HINT, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp index cfd2125c1..e1062caf9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/zoras_fountain.cpp @@ -31,7 +31,7 @@ void RegionTable_Init_ZorasFountain() { //child can break the brown rock without lifting the silver rock and it stays gone for adult, but it's not intuitive and there's no reasonable case where it matters. Entrance(RR_ZF_HIDDEN_CAVE, []{return logic->CanUse(RG_SILVER_GAUNTLETS) && logic->BlastOrSmash();}), Entrance(RR_ZF_ROCK, []{return logic->IsAdult && logic->CanUse(RG_SCARECROW);}), - Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, []{return (logic->IsChild && logic->CanUse(RG_BOTTLE_WITH_FISH));}), + Entrance(RR_JABU_JABUS_BELLY_ENTRYWAY, []{return logic->IsChild && (ctx->GetOption(RSK_JABU_OPEN).Is(RO_JABU_OPEN) || logic->CanUse(RG_BOTTLE_WITH_FISH));}), Entrance(RR_ZF_GREAT_FAIRY_FOUNTAIN, []{return logic->HasExplosives() || (ctx->GetTrickOption(RT_ZF_GREAT_FAIRY_WITHOUT_EXPLOSIVES) && logic->CanUse(RG_MEGATON_HAMMER) && logic->CanUse(RG_SILVER_GAUNTLETS));}), }); @@ -41,7 +41,7 @@ void RegionTable_Init_ZorasFountain() { }, { //Exits //This hover is pretty tight, come at it with momentum and aim for the small corner polygon of the big iceburg while spamming roll - Entrance(RR_ZORAS_FOUNTAIN, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->HasItem(RG_HOVER_BOOTS);}), + Entrance(RR_ZORAS_FOUNTAIN, []{return logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOVER_BOOTS);}), Entrance(RR_ZF_LAKEBED, []{return logic->CanUse(RG_IRON_BOOTS);}), Entrance(RR_ZF_LEDGE, []{return true;}), }); diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 442f2b23b..eea79e92d 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -1177,11 +1177,6 @@ bool Logic::CanStunDeku() { return CanAttack() || CanUse(RG_NUTS) || CanReflectNuts(); } -bool Logic::CanLeaveForest() { - return ctx->GetOption(RSK_FOREST).IsNot(RO_CLOSED_FOREST_ON) || IsAdult || DekuTreeClear || - ctx->GetOption(RSK_SHUFFLE_INTERIOR_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_OVERWORLD_ENTRANCES); -} - bool Logic::CallGossipFairyExceptSuns() { return CanUse(RG_ZELDAS_LULLABY) || CanUse(RG_EPONAS_SONG) || CanUse(RG_SONG_OF_TIME); } @@ -2350,9 +2345,12 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { // AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE)*/ false; TODO: AmmoDrop setting - // Child item logic - SkullMask = false; - MaskOfTruth = false; + // Mask quest + CanBorrowMasks = false; + BorrowSkullMask = false; + BorrowSpookyMask = false; + BorrowBunnyHood = false; + BorrowRightMasks = false; // Adult logic FreedEpona = false; diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h index ba9ab60d0..2bfea75e9 100644 --- a/soh/soh/Enhancements/randomizer/logic.h +++ b/soh/soh/Enhancements/randomizer/logic.h @@ -30,9 +30,12 @@ class Logic { public: bool noVariable = false; - // Child item logic - bool SkullMask = false; - bool MaskOfTruth = false; + // Mask Quest + bool CanBorrowMasks = false; + bool BorrowSkullMask = false; + bool BorrowSpookyMask = false; + bool BorrowBunnyHood = false; + bool BorrowRightMasks = false; // Adult logic bool FreedEpona = false; @@ -228,7 +231,6 @@ class Logic { bool CanReflectNuts(); bool CanCutShrubs(); bool CanStunDeku(); - bool CanLeaveForest(); bool CallGossipFairy(); bool CallGossipFairyExceptSuns(); uint8_t EffectiveHealth(); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 16c89a1c4..50d11d9b2 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -42,6 +42,8 @@ void Settings::CreateOptionDescriptions() { "\n" "Open - Sleeping Waterfall is always open. " "Link may always enter Zora's Domain."; + mOptionDescriptions[RSK_JABU_OPEN] = "Closed - A fish is required to open Jabu-Jabu's mouth.\n\n" + "Open - Jabu-Jabu's mouth opens without the need for a fish."; mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS] = "Add locks to all wooden overworld doors, requiring specific small keys to open them"; mOptionDescriptions[RSK_STARTING_AGE] = diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index abfa8f3b6..2a2acd5c7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -472,26 +472,72 @@ std::unordered_map getItemIdToItemId = { #pragma GCC optimize("O0") #endif bool Randomizer::SpoilerFileExists(const char* spoilerFileName) { - if (strcmp(spoilerFileName, "") != 0) { - std::ifstream spoilerFileStream(SohUtils::Sanitize(spoilerFileName)); + static std::unordered_map existsCache; + static std::unordered_map lastModifiedCache; + + if (strcmp(spoilerFileName, "") == 0) { + return false; + } + + std::string sanitizedFileName = SohUtils::Sanitize(spoilerFileName); + + try { + // Check if file exists and get last modified time + std::filesystem::path filePath(sanitizedFileName); + if (!std::filesystem::exists(filePath)) { + // Cache and return false if file doesn't exist + existsCache[sanitizedFileName] = false; + lastModifiedCache.erase(sanitizedFileName); + return false; + } + + auto currentLastModified = std::filesystem::last_write_time(filePath); + + // Check cache first + auto existsCacheIt = existsCache.find(sanitizedFileName); + auto lastModifiedCacheIt = lastModifiedCache.find(sanitizedFileName); + + // If we have a valid cache entry and the file hasn't been modified + if (existsCacheIt != existsCache.end() && lastModifiedCacheIt != lastModifiedCache.end() && + lastModifiedCacheIt->second == currentLastModified) { + return existsCacheIt->second; + } + + // Cache miss or file modified - need to check contents + std::ifstream spoilerFileStream(sanitizedFileName); if (spoilerFileStream) { nlohmann::json contents; spoilerFileStream >> contents; spoilerFileStream.close(); - if (contents.contains("version") && - strcmp(std::string(contents["version"]).c_str(), (char*)gBuildVersion) == 0) { - return true; - } else { + + bool isValid = contents.contains("version") && + strcmp(std::string(contents["version"]).c_str(), (char*)gBuildVersion) == 0; + + if (!isValid) { SohGui::RegisterPopup( "Old Spoiler Version", "The spoiler file located at\n" + std::string(spoilerFileName) + "\nwas made by a version that doesn't match the currently running version.\n" + "Loading for this file has been cancelled."); } - } - } - return false; + // Update cache + existsCache[sanitizedFileName] = isValid; + lastModifiedCache[sanitizedFileName] = currentLastModified; + return isValid; + } + + // File couldn't be opened + existsCache[sanitizedFileName] = false; + lastModifiedCache.erase(sanitizedFileName); + return false; + + } catch (const std::filesystem::filesystem_error&) { + // Handle filesystem errors by invalidating cache + existsCache[sanitizedFileName] = false; + lastModifiedCache.erase(sanitizedFileName); + return false; + } } #ifdef _MSC_VER #pragma optimize("", on) @@ -3713,7 +3759,7 @@ std::thread randoThread; void GenerateRandomizerImgui(std::string seed = "") { CVarSetInteger(CVAR_GENERAL("RandoGenerating"), 1); - CVarSave(); + Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); auto ctx = Rando::Context::GetInstance(); // RANDOTODO proper UI for selecting if a spoiler loaded should be used for settings Rando::Settings::GetInstance()->SetAllToContext(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 8295eb6cd..15a2fbd37 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -421,6 +421,8 @@ typedef enum { RR_GF_OUTSKIRTS, RR_GF_NEAR_GROTTO, RR_GF_OUTSIDE_GTG, + RR_GF_TO_GTG, + RR_GF_EXITING_GTG, RR_GF_ABOVE_GTG, RR_GF_BOTTOM_OF_LOWER_VINES, RR_GF_TOP_OF_LOWER_VINES, @@ -3579,6 +3581,7 @@ typedef enum { RT_PASS_GUARDS_WITH_NOTHING, RT_GF_JUMP, RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, + RT_GF_LEDGE_CLIP_INTO_GTG, RT_HW_BUNNY_CROSSING, RT_HW_CROSSING, RT_LENS_HW, @@ -5415,7 +5418,9 @@ typedef enum { RHT_SKULLS_HINT, RHT_MASK_SHOP_HINT, // Shuffle Pots - RHT_POT_KOKIRI_FOREST, + RHT_POT_LINKS_HOUSE, + RHT_POT_TWINS_HOUSE, + RHT_POT_KNOW_IT_ALL, RHT_TH_BREAK_ROOM_FRONT_POT, RHT_TH_BREAK_ROOM_BACK_POT, RHT_TH_KITCHEN_POT_1, @@ -5433,16 +5438,19 @@ typedef enum { RHT_TH_LEFT_MIDDLE_JAILED_POT, RHT_TH_LEFTMOST_JAILED_POT, RHT_POT_WASTELAND, - RHT_POT_MARKET, + RHT_POT_GUARD_HOUSE, + RHT_POT_POE_SHOP, + RHT_POT_ALLEY_HOUSE, RHT_POT_KAKARIKO, - RHT_POT_GRAVEYARD, + RHT_POT_DAMPE, RHT_POT_GORON_CITY, RHT_POT_DEATH_MOUNTAIN_CRATER, RHT_POT_ZORAS_DOMAIN, RHT_POT_ZORAS_FOUNTAIN, RHT_POT_LON_LON_RANCH, - RHT_POT_HYRULE_FIELD, - RHT_POT_HYRULE_CASTLE, + RHT_POT_TALONS_HOUSE, + RHT_POT_WEB_GROTTO, + RHT_POT_MUD_WALL_GROTTO, RHT_POT_DODONGOS_CAVERN, RHT_POT_JABU_JABUS_BELLY, RHT_POT_FOREST_TEMPLE, @@ -5748,6 +5756,7 @@ typedef enum { RSK_DOOR_OF_TIME, RSK_ZORAS_FOUNTAIN, RSK_SLEEPING_WATERFALL, + RSK_JABU_OPEN, RSK_STARTING_AGE, RSK_SELECTED_STARTING_AGE, RSK_GERUDO_FORTRESS, @@ -5997,6 +6006,12 @@ typedef enum { RO_WATERFALL_OPEN, } RandoOptionSleepingWaterfall; +// Jabu-Jabu settings (closed, open) +typedef enum { + RO_JABU_CLOSED, + RO_JABU_OPEN, +} RandoOptionJabu; + // Starting Age settings (child, adult, random) typedef enum { RO_AGE_CHILD, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index d460c6daf..d6334b6a0 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -500,6 +500,9 @@ void SetShopSeen(uint32_t sceneNum, bool prices) { } void CheckTrackerLoadGame(int32_t fileNum) { + if (IS_BOSS_RUSH) { + return; + } LoadSettings(); TrySetAreas(); for (auto& entry : Rando::StaticData::GetLocationTable()) { @@ -592,7 +595,7 @@ void CheckTrackerLoadGame(int32_t fileNum) { Rando::Context::GetInstance()->GetEntranceShuffler()->ApplyEntranceOverrides(); } - RecalculateAvailableChecks(); + recalculateAvailable = true; } void CheckTrackerShopSlotChange(uint8_t cursorSlot, int16_t basePrice) { @@ -1005,6 +1008,11 @@ void CheckTrackerWindow::DrawElement() { return; } + if (recalculateAvailable) { + recalculateAvailable = false; + RecalculateAvailableChecks(); + } + SceneID sceneId = SCENE_ID_MAX; if (gPlayState != nullptr) { sceneId = (SceneID)gPlayState->sceneNum; @@ -1603,10 +1611,11 @@ bool IsCheckShuffled(RandomizerCheck rc) { bool IsVisibleInCheckTracker(RandomizerCheck rc) { auto loc = Rando::StaticData::GetLocation(rc); if (IS_RANDO) { - return IsCheckShuffled(rc) || - (alwaysShowGS && loc->GetRCType() == RCTYPE_SKULL_TOKEN && - OTRGlobals::Instance->gRandoContext->IsQuestOfLocationActive(rc)) || - (loc->GetRCType() == RCTYPE_SHOP && showShops && !hideShopUnshuffledChecks); + return !Rando::Context::GetInstance()->GetItemLocation(rc)->IsExcluded() && + (IsCheckShuffled(rc) || + (alwaysShowGS && loc->GetRCType() == RCTYPE_SKULL_TOKEN && + OTRGlobals::Instance->gRandoContext->IsQuestOfLocationActive(rc)) || + (loc->GetRCType() == RCTYPE_SHOP && showShops && !hideShopUnshuffledChecks)); } else { return loc->IsVanillaCompletion() && (!loc->IsDungeon() || (loc->IsDungeon() && loc->GetQuest() == gSaveContext.ship.quest.id)); @@ -2000,7 +2009,7 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName, } void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) { - if (!enableAvailableChecks) { + if (!enableAvailableChecks || !GameInteractor::IsSaveLoaded()) { return; } @@ -2072,10 +2081,6 @@ static std::unordered_map buttonStrings = { }; void CheckTrackerSettingsWindow::DrawElement() { - if (recalculateAvailable) { - recalculateAvailable = false; - RecalculateAvailableChecks(); - } ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 8.0f, 8.0f }); if (ImGui::BeginTable("CheckTrackerSettingsTable", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("General settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); @@ -2156,10 +2161,7 @@ void CheckTrackerSettingsWindow::DrawElement() { "with your current progress.") .Color(THEME_COLOR))) { enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0); - - if (GameInteractor::IsSaveLoaded(true)) { - RecalculateAvailableChecks(); - } + RecalculateAvailableChecks(); } ImGui::EndDisabled(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index cf2f83d3a..d42e14cb1 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -1091,6 +1091,8 @@ DEFINE_RAND_INF(RAND_INF_MARKET_TREASURE_CHEST_GAME_KEY_5) DEFINE_RAND_INF(RAND_INF_TH_ITEM_FROM_LEADER_OF_FORTRESS) DEFINE_RAND_INF(RAND_INF_GF_GTG_GATE_PERMANENTLY_OPEN) +DEFINE_RAND_INF(RAND_INF_SPIRIT_SUN_ON_FLOOR_ON) +DEFINE_RAND_INF(RAND_INF_SPIRIT_BIG_MIRROR_STATUE_TURNED) DEFINE_RAND_INF(RAND_INF_ZELDAS_LETTER) DEFINE_RAND_INF(RAND_INF_WEIRD_EGG) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 6284d7121..fcace1017 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -696,9 +696,9 @@ void DrawQuest(ItemTrackerItem item) { bool hasQuestItem = HasQuestItem(item); float iconSize = static_cast(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36)); ImGui::BeginGroup(); - ImGui::Image(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName( - hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), - ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); + ImGui::ImageWithBg(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) { DrawItemCount(item, false); @@ -1231,7 +1231,7 @@ void DrawItemsInACircle(std::vector items) { float radius = (iconSize + iconSpacing) * 2.0f; for (int i = 0; i < items.size(); i++) { - float angle = static_cast(i / items.size() * 2.0f * M_PI); + float angle = static_cast(i) / items.size() * 2.0f * M_PIf; 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(CVAR_TRACKER_ITEM("IconSize"), 36) - 8) / 2.0f, y + 4)); diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 05a10a2b3..51101f6fa 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -358,17 +358,6 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); } - // Now handled on the fly. - // int openForest = Randomizer_GetSettingValue(RSK_FOREST); - // switch (openForest) { - // case RO_CLOSED_FOREST_OFF: - // Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD); - // // Fallthrough - // case RO_CLOSED_FOREST_DEKU_ONLY: - // Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD); - // break; - // } - int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); switch (doorOfTime) { case RO_DOOROFTIME_OPEN: diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 52add036e..5f8c60ac0 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -120,6 +120,7 @@ void Settings::CreateOptions() { OPT_U8(RSK_DOOR_OF_TIME, "Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox); OPT_U8(RSK_ZORAS_FOUNTAIN, "Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]); OPT_U8(RSK_SLEEPING_WATERFALL, "Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]); + OPT_U8(RSK_JABU_OPEN, "Jabu-Jabu", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("JabuJabu"), mOptionDescriptions[RSK_JABU_OPEN]); OPT_BOOL(RSK_LOCK_OVERWORLD_DOORS, "Lock Overworld Doors", CVAR_RANDOMIZER_SETTING("LockOverworldDoors"), mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS]); OPT_U8(RSK_GERUDO_FORTRESS, "Fortress Carpenters", {"Normal", "Fast", "Free"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FortressCarpenters"), mOptionDescriptions[RSK_GERUDO_FORTRESS]); OPT_U8(RSK_RAINBOW_BRIDGE, "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); @@ -590,6 +591,9 @@ void Settings::CreateOptions() { OPT_TRICK(RT_GF_WARRIOR_WITH_DIFFICULT_WEAPON, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE }, "Gerudo\'s Fortress Warriors with Difficult Weapons", "Warriors can be defeated with Slingshot or Bombchus."); + OPT_TRICK(RT_GF_LEDGE_CLIP_INTO_GTG, RCQUEST_BOTH, RA_GERUDO_FORTRESS, { Tricks::Tag::NOVICE, Tricks::Tag::GLITCH }, + "Ledge Clip into Training Ground", + "Adult Link can use a ledge clip to enter Gerudo Training Ground without Gerudo Card."); // disabled for now, can't check for being able to use bunny hood & bunny hood speedup is currently completely // decoupled from rando OPT_TRICK(RT_HW_BUNNY_CROSSING, RCQUEST_BOTH, RA_HAUNTED_WASTELAND, {Tricks::Tag::NOVICE}, // "Wasteland Crossing with Bunny Hood", "You can beat the quicksand by using the increased speed of the Bunny Hood. @@ -1173,6 +1177,7 @@ void Settings::CreateOptions() { &mOptions[RSK_DOOR_OF_TIME], &mOptions[RSK_ZORAS_FOUNTAIN], &mOptions[RSK_SLEEPING_WATERFALL], + &mOptions[RSK_JABU_OPEN], &mOptions[RSK_LOCK_OVERWORLD_DOORS], }, WidgetContainerType::COLUMN); @@ -1427,6 +1432,7 @@ void Settings::CreateOptions() { &mOptions[RSK_DOOR_OF_TIME], &mOptions[RSK_ZORAS_FOUNTAIN], &mOptions[RSK_SLEEPING_WATERFALL], + &mOptions[RSK_JABU_OPEN], &mOptions[RSK_LOCK_OVERWORLD_DOORS], &mOptions[RSK_GERUDO_FORTRESS], &mOptions[RSK_RAINBOW_BRIDGE], @@ -1826,10 +1832,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(CVAR_RANDOMIZER_SETTING("ClosedForest"), RO_CLOSED_FOREST_ON) == RO_CLOSED_FOREST_ON || - (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 */ { + if (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 { @@ -2526,8 +2531,7 @@ void Context::FinalizeSettings(const std::set& excludedLocation } // With certain access settings, the seed is only beatable if Starting Age is set to Child. - if (mOptions[RSK_FOREST].Is(RO_CLOSED_FOREST_ON) || - (mOptions[RSK_DOOR_OF_TIME].Is(RO_DOOROFTIME_CLOSED) && !mOptions[RSK_SHUFFLE_OCARINA])) { + if (mOptions[RSK_DOOR_OF_TIME].Is(RO_DOOROFTIME_CLOSED) && !mOptions[RSK_SHUFFLE_OCARINA]) { mOptions[RSK_STARTING_AGE].Set(RO_AGE_CHILD); } @@ -2841,13 +2845,6 @@ void Context::FinalizeSettings(const std::set& excludedLocation mOptions[RSK_MIX_GROTTO_ENTRANCES].Set(RO_GENERIC_OFF); } - if (mOptions[RSK_FOREST].Is(RO_CLOSED_FOREST_ON) && - (mOptions[RSK_SHUFFLE_INTERIOR_ENTRANCES].Is(RO_INTERIOR_ENTRANCE_SHUFFLE_ALL) || - mOptions[RSK_SHUFFLE_OVERWORLD_ENTRANCES] || mOptions[RSK_SHUFFLE_OVERWORLD_SPAWNS] || - mOptions[RSK_DECOUPLED_ENTRANCES] || mOptions[RSK_MIXED_ENTRANCE_POOLS])) { - mOptions[RSK_FOREST].Set(RO_CLOSED_FOREST_DEKU_ONLY); - } - if (mOptions[RSK_STARTING_AGE].Is(RO_AGE_RANDOM)) { if (const uint32_t choice = Random(0, 2); choice == 0) { mOptions[RSK_SELECTED_STARTING_AGE].Set(RO_AGE_CHILD); diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index dd8185c1d..662c0d857 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -9,6 +9,7 @@ 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_Obj_Lightswitch/z_obj_lightswitch.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" @@ -25,11 +26,13 @@ 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_En_Jj/z_en_jj.h" #include "src/overlays/actors/ovl_En_Daiku/z_en_daiku.h" #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" #include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h" #include "src/overlays/actors/ovl_Bg_Spot06_Objects/z_bg_spot06_objects.h" #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" +#include "src/overlays/actors/ovl_Bg_Jya_Bombchuiwa/z_bg_jya_bombchuiwa.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" @@ -48,6 +51,10 @@ extern void EnGo2_CurledUp(EnGo2* enGo2, PlayState* play); extern void EnRu2_SetEncounterSwitchFlag(EnRu2* enRu2, PlayState* play); extern void EnDaiku_EscapeSuccess(EnDaiku* enDaiku, PlayState* play); + +extern void EnJj_WaitToOpenMouth(EnJj* enJj, PlayState* play); +extern void EnJj_WaitForFish(EnJj* enJj, PlayState* play); +extern void EnJj_SetupAction(EnJj* enJj, EnJjActionFunc actionFunc); } void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) { @@ -868,6 +875,8 @@ static uint32_t enMa1UpdateHook = 0; static uint32_t enMa1KillHook = 0; static uint32_t enFuUpdateHook = 0; static uint32_t enFuKillHook = 0; +static uint32_t enJjUpdateHook = 0; +static uint32_t enJjKillHook = 0; static uint32_t bgSpot02UpdateHook = 0; static uint32_t bgSpot02KillHook = 0; static uint32_t bgSpot03UpdateHook = 0; @@ -933,6 +942,39 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } + if (actor->id == ACTOR_EN_JJ && !IS_RANDO) { + enJjUpdateHook = + GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + + if (innerActor->id != ACTOR_EN_JJ || Flags_GetEventChkInf(EVENTCHKINF_OFFERED_FISH_TO_JABU_JABU)) { + return; + } + + bool shouldOpen = IS_RANDO ? RAND_GET_OPTION(RSK_JABU_OPEN) + : CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipJabuJabuFish"), 0); + if (!shouldOpen) { + return; + } + + EnJj* enJj = static_cast(innerActorRef); + if (enJj->actionFunc == EnJj_WaitForFish) { + EnJj_SetupAction(enJj, EnJj_WaitToOpenMouth); + GameInteractor::Instance->UnregisterGameHook(enJjUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enJjKillHook); + enJjUpdateHook = 0; + enJjKillHook = 0; + } + }); + enJjKillHook = + GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(enJjUpdateHook); + GameInteractor::Instance->UnregisterGameHook(enJjKillHook); + enJjUpdateHook = 0; + enJjKillHook = 0; + }); + } + if (actor->id == ACTOR_EN_OWL && gPlayState->sceneNum == SCENE_ZORAS_RIVER && CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), 0) == 2) { Actor_Kill(actor); @@ -1386,14 +1428,35 @@ void TimeSaverRegisterHooks() { }); } -void RegisterSkipWaterTempleGateDelay() { +void RegisterSkipTimerDelay() { + // Skip Water Temple gate delay COND_ID_HOOK(OnActorUpdate, ACTOR_BG_SPOT06_OBJECTS, CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) { - BgSpot06Objects* spot06 = static_cast(actor); + auto spot06 = static_cast(actor); if (spot06->dyna.actor.params == 0) { spot06->timer = 0; } - }) + }); + + // Skip Spirit Sun on Floor activation delay + COND_ID_HOOK(OnActorUpdate, ACTOR_BG_JYA_BOMBCHUIWA, + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) { + auto jya = static_cast(actor); + if (!(jya->drawFlags & 4) && jya->timer > 0 && jya->timer < 9) { + jya->timer = 9; + } + }); + + // Skip Spirit Sun on Floor & Sun on Block activation delay + COND_ID_HOOK(OnActorUpdate, ACTOR_OBJ_LIGHTSWITCH, + CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO), [](void* actor) { + if (gPlayState->sceneNum == SCENE_SPIRIT_TEMPLE && + (gPlayState->roomCtx.curRoom.num == 4 || gPlayState->roomCtx.curRoom.num == 8)) { + auto sun = static_cast(actor); + sun->toggleDelay = 0; + } + }); } -static RegisterShipInitFunc skipWaterTempleGateDelay(RegisterSkipWaterTempleGateDelay); +static RegisterShipInitFunc skipTimerDelay(RegisterSkipTimerDelay, + { CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), "IS_RANDO" }); diff --git a/soh/soh/Enhancements/timesplits/TimeSplits.cpp b/soh/soh/Enhancements/timesplits/TimeSplits.cpp index f08235970..047a6f502 100644 --- a/soh/soh/Enhancements/timesplits/TimeSplits.cpp +++ b/soh/soh/Enhancements/timesplits/TimeSplits.cpp @@ -1,12 +1,11 @@ +#include +#include +#include + #include "TimeSplits.h" #include "soh/Enhancements/gameplaystats.h" #include "soh/SaveManager.h" #include "soh/util.h" -#include -#include "include/z64item.h" - -#include -#include #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" @@ -17,6 +16,7 @@ #include "soh/SohGui/UIWidgets.hpp" extern "C" { +#include "z64item.h" extern SaveContext gSaveContext; extern PlayState* gPlayState; } diff --git a/soh/soh/Enhancements/timesplits/TimeSplits.h b/soh/soh/Enhancements/timesplits/TimeSplits.h index 8644d6010..2d4a4ba3f 100644 --- a/soh/soh/Enhancements/timesplits/TimeSplits.h +++ b/soh/soh/Enhancements/timesplits/TimeSplits.h @@ -3,17 +3,6 @@ #define TIMESPLITS_H #include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif // TIMESPLITS_H - #include #ifdef __cplusplus @@ -66,3 +55,5 @@ typedef struct { } SplitObject; #endif + +#endif // TIMESPLITS_H diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index 13dd9f183..1dc8a1ba6 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -370,9 +370,16 @@ void RegisterOnKaleidoscopeUpdateHook() { auto translation = GetParameritizedText("magic", TEXT_BANK_KALEIDO, arg); SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { - snprintf(arg, sizeof(arg), "%d", gSaveContext.rupees); - auto translation = GetParameritizedText("rupees", TEXT_BANK_KALEIDO, arg); - SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + if (gPlayState->sceneNum >= SCENE_FOREST_TEMPLE && gPlayState->sceneNum <= SCENE_INSIDE_GANONS_CASTLE) { + snprintf(arg, sizeof(arg), "%d", + std::max(gSaveContext.inventory.dungeonKeys[gPlayState->sceneNum], (s8)0)); + auto translation = GetParameritizedText("keys", TEXT_BANK_KALEIDO, arg); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + } else { + snprintf(arg, sizeof(arg), "%d", gSaveContext.rupees); + auto translation = GetParameritizedText("rupees", TEXT_BANK_KALEIDO, arg); + SpeechSynthesizer::Instance->Speak(translation.c_str(), GetLanguageCode()); + } } else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) { // TODO: announce timer? } diff --git a/soh/soh/Network/CrowdControl/CrowdControl.cpp b/soh/soh/Network/CrowdControl/CrowdControl.cpp index f706bed89..fd293d8ba 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.cpp +++ b/soh/soh/Network/CrowdControl/CrowdControl.cpp @@ -136,9 +136,11 @@ void CrowdControl::EmitMessage(uint32_t eventId, long timeRemaining, EffectResul CrowdControl::EffectResult CrowdControl::ExecuteEffect(Effect* effect) { GameInteractionEffectQueryResult giResult; if (effect->category == kEffectCatSpawnEnemy) { - giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1]); + giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->spawnParams[0], effect->spawnParams[1], + effect->viewerName); } else if (effect->category == kEffectCatSpawnActor) { - giResult = GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1]); + giResult = + GameInteractor::RawAction::SpawnActor(effect->spawnParams[0], effect->spawnParams[1], effect->viewerName); } else { giResult = GameInteractor::ApplyEffect(effect->giEffect); } @@ -185,6 +187,7 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { Effect* effect = new Effect(); effect->lastExecutionResult = EffectResult::Initiate; effect->id = dataReceived["id"]; + effect->viewerName = dataReceived["viewer"]; auto parameters = dataReceived["parameters"]; uint32_t receivedParameter = 0; auto effectName = dataReceived["code"].get(); @@ -301,13 +304,13 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { case kEffectIncreaseSpeed: effect->category = kEffectCatSpeed; effect->timeRemaining = 30000; - effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier(); + effect->giEffect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); dynamic_cast(effect->giEffect)->parameters[0] = 2; break; case kEffectDecreaseSpeed: effect->category = kEffectCatSpeed; effect->timeRemaining = 30000; - effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier(); + effect->giEffect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); dynamic_cast(effect->giEffect)->parameters[0] = -2; break; case kEffectLowGravity: @@ -620,147 +623,6 @@ CrowdControl::Effect* CrowdControl::ParseMessage(nlohmann::json dataReceived) { dynamic_cast(effect->giEffect)->parameters[0] = GI_TP_DEST_PRELUDE; break; - // Tunic Color (Bidding War) - case kEffectTunicRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectTunicGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectTunicBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectTunicOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectTunicYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectTunicPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectTunicPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectTunicBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectTunicBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_TUNICS; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - - // Navi Color (Bidding War) - case kEffectNaviRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectNaviGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectNaviBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectNaviOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectNaviYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectNaviPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectNaviPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectNaviBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectNaviBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_NAVI; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - - // Link's Hair Color (Bidding War) - case kEffectHairRed: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_RED; - break; - case kEffectHairGreen: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_GREEN; - break; - case kEffectHairBlue: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLUE; - break; - case kEffectHairOrange: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_ORANGE; - break; - case kEffectHairYellow: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_YELLOW; - break; - case kEffectHairPurple: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PURPLE; - break; - case kEffectHairPink: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_PINK; - break; - case kEffectHairBrown: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BROWN; - break; - case kEffectHairBlack: - effect->giEffect = new GameInteractionEffect::SetCosmeticsColor(); - dynamic_cast(effect->giEffect)->parameters[0] = GI_COSMETICS_HAIR; - dynamic_cast(effect->giEffect)->parameters[1] = GI_COLOR_BLACK; - break; - default: break; } diff --git a/soh/soh/Network/CrowdControl/CrowdControl.h b/soh/soh/Network/CrowdControl/CrowdControl.h index 8951e6cf1..f906961c3 100644 --- a/soh/soh/Network/CrowdControl/CrowdControl.h +++ b/soh/soh/Network/CrowdControl/CrowdControl.h @@ -56,6 +56,7 @@ class CrowdControl : public Network { uint32_t category = 0; long timeRemaining; GameInteractionEffectBase* giEffect; + std::string viewerName; // Metadata used while executing (only for timed effects) bool isPaused; diff --git a/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs b/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs index b1617435c..554e0d56b 100644 --- a/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs +++ b/soh/soh/Network/CrowdControl/ShipOfHarkinian.cs @@ -124,50 +124,5 @@ public class ShipOfHarkinian : SimpleTCPPack new("Requiem Destination", "tp_requiem") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to Desert Colossus." }, new("Nocturne Destination", "tp_nocturne") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Raveyard." }, new("Prelude Destination", "tp_prelude") { Category = "Teleport Player", Price = 100, Description = "Teleport the player to the Temple of Time." }, - - // Tunic Color (Bidding War) - new("Tunic Color", "tunic", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_tunic_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - }, - - // Navi Color (Bidding War) - new("Navi Color", "navi", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_navi_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - }, - - // Link's Hair Color (Bidding War) - new("Link's Hair Color", "hair", ItemKind.BidWar) - { - Parameters = new ParameterDef("Color", "color_hair_param", - new Parameter("Red", "red"), - new Parameter("Green", "green"), - new Parameter("Blue", "blue"), - new Parameter("Orange", "orange"), - new Parameter("Yellow", "yellow"), - new Parameter("Purple", "purple"), - new Parameter("Pink", "pink"), - new Parameter("Brown", "brown"), - new Parameter("Black", "black")) - } }; } diff --git a/soh/soh/Network/Sail/Sail.cpp b/soh/soh/Network/Sail/Sail.cpp index a5396777e..08f23fca5 100644 --- a/soh/soh/Network/Sail/Sail.cpp +++ b/soh/soh/Network/Sail/Sail.cpp @@ -242,8 +242,8 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) { effect->parameters[0] = payload["parameters"][0].get(); } return effect; - } else if (name == "ModifyRunSpeedModifier") { - auto effect = new GameInteractionEffect::ModifyRunSpeedModifier(); + } else if (name == "ModifyMovementSpeedMultiplier") { + auto effect = new GameInteractionEffect::ModifyMovementSpeedMultiplier(); if (payload.contains("parameters")) { effect->parameters[0] = payload["parameters"][0].get(); } @@ -282,13 +282,6 @@ GameInteractionEffectBase* Sail::EffectFromJson(nlohmann::json payload) { return effect; } else if (name == "SetCollisionViewer") { return new GameInteractionEffect::SetCollisionViewer(); - } else if (name == "SetCosmeticsColor") { - auto effect = new GameInteractionEffect::SetCosmeticsColor(); - if (payload.contains("parameters")) { - effect->parameters[0] = payload["parameters"][0].get(); - effect->parameters[1] = payload["parameters"][1].get(); - } - return effect; } else if (name == "RandomizeCosmetics") { return new GameInteractionEffect::RandomizeCosmetics(); } else if (name == "PressButton") { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 2bdcabfb5..bc9b3106e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2331,7 +2331,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } } else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar - messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() + messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage(MF_AUTO_FORMAT) : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); } else if (textId == TEXT_GANONDORF) { if (ctx->GetOption(RSK_GANONDORF_HINT)) { diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 2180f6d95..4b830f846 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -180,6 +180,9 @@ void SaveManager::LoadRandomizer() { // all ItemLocations is 0 anyway. randoContext->GetItemLocation(i)->SetCustomPrice(price); } + bool excluded = false; + SaveManager::Instance->LoadData("excluded", excluded, false); + randoContext->GetItemLocation(i)->SetExcludedOption(excluded); }); }); @@ -271,6 +274,9 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f randoContext->GetItemOverride(i).GetTrickName().GetFrench()); }); } + if (randoContext->GetItemLocation(i)->IsExcluded()) { + SaveManager::Instance->SaveData("excluded", true); + } if (randoContext->GetItemLocation(i)->HasCustomPrice()) { SaveManager::Instance->SaveData("price", randoContext->GetItemLocation(i)->GetPrice()); } diff --git a/soh/soh/SohGui/SohMenu.h b/soh/soh/SohGui/SohMenu.h index c3c3f4fd1..ec5f7705c 100644 --- a/soh/soh/SohGui/SohMenu.h +++ b/soh/soh/SohGui/SohMenu.h @@ -27,7 +27,6 @@ void disableBetaQuest(); #endif namespace SohGui { - static std::unordered_map languages = { { LANGUAGE_ENG, "English" }, { LANGUAGE_GER, "German" }, @@ -35,164 +34,6 @@ static std::unordered_map languages = { { LANGUAGE_JPN, "Japanese" }, }; -static const std::unordered_map menuThemeOptions = { - { UIWidgets::Colors::Red, "Red" }, - { UIWidgets::Colors::DarkRed, "Dark Red" }, - { UIWidgets::Colors::Orange, "Orange" }, - { UIWidgets::Colors::Green, "Green" }, - { UIWidgets::Colors::DarkGreen, "Dark Green" }, - { UIWidgets::Colors::LightBlue, "Light Blue" }, - { UIWidgets::Colors::Blue, "Blue" }, - { UIWidgets::Colors::DarkBlue, "Dark Blue" }, - { UIWidgets::Colors::Indigo, "Indigo" }, - { UIWidgets::Colors::Violet, "Violet" }, - { UIWidgets::Colors::Purple, "Purple" }, - { UIWidgets::Colors::Brown, "Brown" }, - { UIWidgets::Colors::Gray, "Gray" }, - { UIWidgets::Colors::DarkGray, "Dark Gray" }, -}; - -static const std::unordered_map textureFilteringMap = { - { Fast::FILTER_THREE_POINT, "Three-Point" }, - { Fast::FILTER_LINEAR, "Linear" }, - { Fast::FILTER_NONE, "None" }, -}; - -static const std::unordered_map logLevels = { - { DEBUG_LOG_TRACE, "Trace" }, { DEBUG_LOG_DEBUG, "Debug" }, { DEBUG_LOG_INFO, "Info" }, - { DEBUG_LOG_WARN, "Warn" }, { DEBUG_LOG_ERROR, "Error" }, { DEBUG_LOG_CRITICAL, "Critical" }, - { DEBUG_LOG_OFF, "Off" }, -}; - -static const std::unordered_map notificationPosition = { - { 0, "Top Left" }, { 1, "Top Right" }, { 2, "Bottom Left" }, { 3, "Bottom Right" }, { 4, "Hidden" }, -}; - -static const std::unordered_map dekuStickCheat = { - { DEKU_STICK_NORMAL, "Normal" }, - { DEKU_STICK_UNBREAKABLE, "Unbreakable" }, - { DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, "Unbreakable + Always on Fire" }, -}; - -static const std::unordered_map skipForcedDialogOptions = { - { FORCED_DIALOG_SKIP_NONE, "None" }, - { FORCED_DIALOG_SKIP_NAVI, "Navi" }, - { FORCED_DIALOG_SKIP_NPC, "NPCs" }, - { FORCED_DIALOG_SKIP_ALL, "All" }, -}; - -static const std::unordered_map skipGetItemAnimationOptions = { - { SGIA_DISABLED, "Disabled" }, - { SGIA_JUNK, "Junk Items" }, - { SGIA_ALL, "All Items" }, -}; - -static const std::unordered_map chestStyleMatchesContentsOptions = { - { CSMC_DISABLED, "Disabled" }, - { CSMC_BOTH, "Both" }, - { CSMC_TEXTURE, "Texture Only" }, - { CSMC_SIZE, "Size Only" }, -}; - -static const std::unordered_map timeTravelOptions = { - { TIME_TRAVEL_DISABLED, "Disabled" }, - { TIME_TRAVEL_OOT, "Ocarina of Time" }, - { TIME_TRAVEL_ANY, "Any Ocarina" }, -}; - -static const std::unordered_map sleepingWaterfallOptions = { - { WATERFALL_ALWAYS, "Always" }, - { WATERFALL_ONCE, "Once" }, - { WATERFALL_NEVER, "Never" }, -}; - -static const std::unordered_map allPowers = { - { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, - { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, - { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, - { DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" }, - { DAMAGE_OHKO, "OHKO (256x)" }, -}; - -static const std::unordered_map subPowers = { - { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, - { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, - { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, - { DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" }, -}; - -static const std::unordered_map subSubPowers = { - { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, - { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, - { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, - { DAMAGE_MERCILESS, "Merciless (64x)" }, -}; - -static const std::unordered_map bonkDamageValues = { - { BONK_DAMAGE_NONE, "No Damage" }, { BONK_DAMAGE_QUARTER_HEART, "0.25 Hearts" }, - { BONK_DAMAGE_HALF_HEART, "0.5 Hearts" }, { BONK_DAMAGE_1_HEART, "1 Heart" }, - { BONK_DAMAGE_2_HEARTS, "2 Hearts" }, { BONK_DAMAGE_4_HEARTS, "4 Hearts" }, - { BONK_DAMAGE_8_HEARTS, "8 Hearts" }, { BONK_DAMAGE_OHKO, "OHKO" }, -}; - -static const std::unordered_map dampeDropRates = { - { DAMPE_NONE, "None" }, - { DAMPE_NORMAL, "Vanilla" }, - { DAMPE_JALAPENO, "Jalapeño" }, - { DAMPE_CHIPOTLE, "Serrano" }, - { DAMPE_SCOTCH_BONNET, "Habanero" }, - { DAMPE_GHOST_PEPPER, "Ghost Pepper" }, - { DAMPE_INFERNO, "Dampe's Inferno" }, -}; - -static const std::unordered_map cursorAnywhereValues = { - { PAUSE_ANY_CURSOR_RANDO_ONLY, "Only in Rando" }, - { PAUSE_ANY_CURSOR_ALWAYS_ON, "Always" }, - { PAUSE_ANY_CURSOR_ALWAYS_OFF, "Never" }, -}; - -static const std::unordered_map swordToggleModes = { - { SWORD_TOGGLE_NONE, "None" }, - { SWORD_TOGGLE_CHILD, "Child Toggle" }, - { SWORD_TOGGLE_BOTH_AGES, "Both Ages" }, -}; - -static const std::unordered_map zFightingOptions = { - { ZFIGHT_FIX_DISABLED, "Disabled" }, - { ZFIGHT_FIX_CONSISTENT_VANISH, "Consistent Vanish" }, - { ZFIGHT_FIX_NO_VANISH, "No Vanish" }, -}; - -static const std::unordered_map mirroredWorldModes = { - { MIRRORED_WORLD_OFF, "Disabled" }, - { MIRRORED_WORLD_ALWAYS, "Always" }, - { MIRRORED_WORLD_RANDOM, "Random" }, - { MIRRORED_WORLD_RANDOM_SEEDED, "Random (Seeded)" }, - { MIRRORED_WORLD_DUNGEONS_ALL, "Dungeons" }, - { MIRRORED_WORLD_DUNGEONS_VANILLA, "Dungeons (Vanilla)" }, - { MIRRORED_WORLD_DUNGEONS_MQ, "Dungeons (MQ)" }, - { MIRRORED_WORLD_DUNGEONS_RANDOM, "Dungeons Random" }, - { MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED, "Dungeons Random (Seeded)" }, -}; - -static const std::unordered_map enemyRandomizerModes = { - { ENEMY_RANDOMIZER_OFF, "Disabled" }, - { ENEMY_RANDOMIZER_RANDOM, "Random" }, - { ENEMY_RANDOMIZER_RANDOM_SEEDED, "Random (Seeded)" }, -}; - -static const std::unordered_map debugSaveFileModes = { - { 0, "Off" }, - { 1, "Vanilla" }, - { 2, "Maxed" }, -}; - -static const std::unordered_map bootSequenceLabels = { - { BOOTSEQUENCE_DEFAULT, "Default" }, - { BOOTSEQUENCE_AUTHENTIC, "Authentic" }, - { BOOTSEQUENCE_FILESELECT, "File Select" }, -}; - class SohMenu : public Ship::Menu { public: SohMenu(const std::string& consoleVariable, const std::string& name); diff --git a/soh/soh/SohGui/SohMenuDevTools.cpp b/soh/soh/SohGui/SohMenuDevTools.cpp index 3e87af890..2a0fcd62a 100644 --- a/soh/soh/SohGui/SohMenuDevTools.cpp +++ b/soh/soh/SohGui/SohMenuDevTools.cpp @@ -5,6 +5,18 @@ namespace SohGui { extern std::shared_ptr mSohMenu; using namespace UIWidgets; +static const std::unordered_map logLevels = { + { DEBUG_LOG_TRACE, "Trace" }, { DEBUG_LOG_DEBUG, "Debug" }, { DEBUG_LOG_INFO, "Info" }, + { DEBUG_LOG_WARN, "Warn" }, { DEBUG_LOG_ERROR, "Error" }, { DEBUG_LOG_CRITICAL, "Critical" }, + { DEBUG_LOG_OFF, "Off" }, +}; + +static const std::unordered_map debugSaveFileModes = { + { 0, "Off" }, + { 1, "Vanilla" }, + { 2, "Maxed" }, +}; + void SohMenu::AddMenuDevTools() { // Add Dev Tools Menu AddMenuEntry("Dev Tools", CVAR_SETTING("Menu.DevToolsSidebarSection")); diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index c8d456923..eda3d85bb 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1,4 +1,4 @@ -#include "SohMenu.h" +#include "SohMenu.h" #include #include #include @@ -6,13 +6,12 @@ #include #include +#define CVAR_INT_SHIP_INIT(cvar, val) \ + CVarSetInteger(cvar, val); \ + ShipInit::Init(cvar); + static std::string comboboxTooltip = ""; bool isBetaQuestEnabled = false; -static std::unordered_map bunnyHoodEffectMap = { - { BUNNY_HOOD_VANILLA, "Vanilla" }, - { BUNNY_HOOD_FAST, "Faster Run" }, - { BUNNY_HOOD_FAST_AND_JUMP, "Faster + Longer Jump" }, -}; extern "C" { void enableBetaQuest() { @@ -28,6 +27,119 @@ namespace SohGui { extern std::shared_ptr mSohMenu; using namespace UIWidgets; +static std::unordered_map bunnyHoodEffectMap = { + { BUNNY_HOOD_VANILLA, "Vanilla" }, + { BUNNY_HOOD_FAST, "Faster Run" }, + { BUNNY_HOOD_FAST_AND_JUMP, "Faster + Longer Jump" }, +}; + +static const std::unordered_map dekuStickCheat = { + { DEKU_STICK_NORMAL, "Normal" }, + { DEKU_STICK_UNBREAKABLE, "Unbreakable" }, + { DEKU_STICK_UNBREAKABLE_AND_ALWAYS_ON_FIRE, "Unbreakable + Always on Fire" }, +}; + +static const std::unordered_map skipForcedDialogOptions = { + { FORCED_DIALOG_SKIP_NONE, "None" }, + { FORCED_DIALOG_SKIP_NAVI, "Navi" }, + { FORCED_DIALOG_SKIP_NPC, "NPCs" }, + { FORCED_DIALOG_SKIP_ALL, "All" }, +}; + +static const std::unordered_map chestStyleMatchesContentsOptions = { + { CSMC_DISABLED, "Disabled" }, + { CSMC_BOTH, "Both" }, + { CSMC_TEXTURE, "Texture Only" }, + { CSMC_SIZE, "Size Only" }, +}; + +static const std::unordered_map timeTravelOptions = { + { TIME_TRAVEL_DISABLED, "Disabled" }, + { TIME_TRAVEL_OOT, "Ocarina of Time" }, + { TIME_TRAVEL_ANY, "Any Ocarina" }, +}; + +static const std::unordered_map sleepingWaterfallOptions = { + { WATERFALL_ALWAYS, "Always" }, + { WATERFALL_ONCE, "Once" }, + { WATERFALL_NEVER, "Never" }, +}; + +static const std::unordered_map allPowers = { + { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, + { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, + { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, + { DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" }, + { DAMAGE_OHKO, "OHKO (256x)" }, +}; + +static const std::unordered_map subPowers = { + { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, + { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, + { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, + { DAMAGE_MERCILESS, "Merciless (64x)" }, { DAMAGE_TORTURE, "Pure Torture (128x)" }, +}; + +static const std::unordered_map subSubPowers = { + { DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" }, + { DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" }, + { DAMAGE_FOOLISH, "Foolish (16x)" }, { DAMAGE_RIDICULOUS, "Ridiculous (32x)" }, + { DAMAGE_MERCILESS, "Merciless (64x)" }, +}; + +static const std::unordered_map bonkDamageValues = { + { BONK_DAMAGE_NONE, "No Damage" }, { BONK_DAMAGE_QUARTER_HEART, "0.25 Hearts" }, + { BONK_DAMAGE_HALF_HEART, "0.5 Hearts" }, { BONK_DAMAGE_1_HEART, "1 Heart" }, + { BONK_DAMAGE_2_HEARTS, "2 Hearts" }, { BONK_DAMAGE_4_HEARTS, "4 Hearts" }, + { BONK_DAMAGE_8_HEARTS, "8 Hearts" }, { BONK_DAMAGE_OHKO, "OHKO" }, +}; + +static const std::unordered_map dampeDropRates = { + { DAMPE_NONE, "None" }, + { DAMPE_NORMAL, "Vanilla" }, + { DAMPE_JALAPENO, "Jalapeño" }, + { DAMPE_CHIPOTLE, "Serrano" }, + { DAMPE_SCOTCH_BONNET, "Habanero" }, + { DAMPE_GHOST_PEPPER, "Ghost Pepper" }, + { DAMPE_INFERNO, "Dampe's Inferno" }, +}; + +static const std::unordered_map cursorAnywhereValues = { + { PAUSE_ANY_CURSOR_RANDO_ONLY, "Only in Rando" }, + { PAUSE_ANY_CURSOR_ALWAYS_ON, "Always" }, + { PAUSE_ANY_CURSOR_ALWAYS_OFF, "Never" }, +}; + +static const std::unordered_map zFightingOptions = { + { ZFIGHT_FIX_DISABLED, "Disabled" }, + { ZFIGHT_FIX_CONSISTENT_VANISH, "Consistent Vanish" }, + { ZFIGHT_FIX_NO_VANISH, "No Vanish" }, +}; + +static const std::unordered_map swordToggleModes = { + { SWORD_TOGGLE_NONE, "None" }, + { SWORD_TOGGLE_CHILD, "Child Toggle" }, + { SWORD_TOGGLE_BOTH_AGES, "Both Ages" }, +}; + +static const std::unordered_map mirroredWorldModes = { + { MIRRORED_WORLD_OFF, "Disabled" }, + { MIRRORED_WORLD_ALWAYS, "Always" }, + { MIRRORED_WORLD_RANDOM, "Random" }, + { MIRRORED_WORLD_RANDOM_SEEDED, "Random (Seeded)" }, + { MIRRORED_WORLD_DUNGEONS_ALL, "Dungeons" }, + { MIRRORED_WORLD_DUNGEONS_VANILLA, "Dungeons (Vanilla)" }, + { MIRRORED_WORLD_DUNGEONS_MQ, "Dungeons (MQ)" }, + { MIRRORED_WORLD_DUNGEONS_RANDOM, "Dungeons Random" }, + { MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED, "Dungeons Random (Seeded)" }, +}; + +static const std::unordered_map enemyRandomizerModes = { + { ENEMY_RANDOMIZER_OFF, "Disabled" }, + { ENEMY_RANDOMIZER_RANDOM, "Random" }, + { ENEMY_RANDOMIZER_RANDOM_SEEDED, "Random (Seeded)" }, +}; + void SohMenu::AddMenuEnhancements() { // Add Enhancements Menu AddMenuEntry("Enhancements", CVAR_SETTING("Menu.EnhancementsSidebarSection")); @@ -217,6 +329,15 @@ void SohMenu::AddMenuEnhancements() { "open permanently.\n" "Never: Link never needs to play Zelda's Lullaby to open the waterfall. He only needs to have " "learned it and have an Ocarina.")); + AddWidget(path, "Skip Feeding Jabu-Jabu", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("TimeSavers.SkipJabuJabuFish")) + .PreFunc([](WidgetInfo& info) { + info.options->disabled = + IS_RANDO && OTRGlobals::Instance->gRandoContext->GetOption(RSK_JABU_OPEN).Is(RO_JABU_OPEN); + info.options->disabledTooltip = + "This setting is disabled because a randomizer savefile with \"Jabu-Jaby: Open\" is loaded."; + }) + .Options(CheckboxOptions().Tooltip("Allow Link to enter Jabu-Jabu without feeding him a fish.")); // Skips & Speed-ups path.sidebarName = "Skips & Speed-ups"; @@ -227,16 +348,16 @@ void SohMenu::AddMenuEnhancements() { AddWidget(path, "All##Skips", WIDGET_BUTTON) .Options(ButtonOptions().Size(Sizes::Inline)) .Callback([](WidgetInfo& info) { - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), true); - CVarSetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), true); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), true); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); }); @@ -244,16 +365,16 @@ void SohMenu::AddMenuEnhancements() { .SameLine(true) .Options(ButtonOptions().Size(Sizes::Inline)) .Callback([](WidgetInfo& info) { - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions")); - CVarClear(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard")); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Intro"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.LearnSong"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.BossIntro"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.QuickBossDeaths"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), false); + CVAR_INT_SHIP_INIT(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), false); Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); }); @@ -467,7 +588,7 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip( "Scales all of the Adult Equipment, as well as moving some a bit, to fit on Child Link better. May " "not work properly with some mods.")); - AddWidget(path, "Show Gauntlets in First Person", WIDGET_CVAR_CHECKBOX) + AddWidget(path, "Show Gauntlets in First-Person", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("FirstPersonGauntlets")) .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Renders Gauntlets when using the Bow and Hookshot like in OoT3D.")); diff --git a/soh/soh/SohGui/SohMenuNetwork.cpp b/soh/soh/SohGui/SohMenuNetwork.cpp index bb6004288..f2fba3ff1 100644 --- a/soh/soh/SohGui/SohMenuNetwork.cpp +++ b/soh/soh/SohGui/SohMenuNetwork.cpp @@ -96,21 +96,15 @@ void SohMenu::AddMenuNetwork() { AddSidebarEntry("Network", path.sidebarName, 3); path.column = SECTION_COLUMN_1; + AddWidget(path, "About Crowd Control", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Crowd Control is a platform that allows viewers to interact " "with a streamer's game in real time.\n" "\n" - "Click the question mark to copy the link to the Crowd Control " - "website to your clipboard.", + "Please head over to www.crowdcontrol.live for more information!", WIDGET_TEXT); - AddWidget(path, ICON_FA_CLIPBOARD "##CrowdControl", WIDGET_BUTTON) - .Callback([](WidgetInfo& info) { - ImGui::SetClipboardText("https://crowdcontrol.live"); - Notification::Emit({ - .message = "Copied to clipboard", - }); - }) - .Options(ButtonOptions().Tooltip("https://crowdcontrol.live")); + + AddWidget(path, "Connect to Crowd Control", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Host & Port", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { ImGui::BeginDisabled(CrowdControl::Instance->isEnabled || CVarGetInteger(CVAR_SETTING("DisableChanges"), 0)); ImGui::Text("%s", info.name.c_str()); @@ -155,14 +149,25 @@ void SohMenu::AddMenuNetwork() { CrowdControl::Instance->Enable(); } }); - AddWidget(path, "Connecting...##CrowdControl", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { + AddWidget(path, "Connecting...", WIDGET_TEXT).PreFunc([](WidgetInfo& info) { info.isHidden = !CrowdControl::Instance->isEnabled; if (CrowdControl::Instance->isConnected) { - info.name = "Connected##CrowdControl"; + info.name = "Connected"; } else { - info.name = "Connecting...##CrowdControl"; + info.name = "Connecting..."; } }); + AddWidget(path, "Additional Settings", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Enemy Name Tags", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_REMOTE_CROWD_CONTROL("EnemyNameTags")) + .RaceDisable(true) + .Options(CheckboxOptions().Tooltip( + "When viewers spawn enemies, the enemy will have a name tag above them with the viewer's name.")); + AddWidget(path, "Spawned Enemies Ignored Ingame", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame")) + .RaceDisable(true) + .Options(CheckboxOptions().Tooltip("Enemies spawned by CrowdControl won't be considered for \"clear enemy " + "rooms\", so they don't need to be killed to complete these rooms.")); } } // namespace SohGui diff --git a/soh/soh/SohGui/SohMenuRandomizer.cpp b/soh/soh/SohGui/SohMenuRandomizer.cpp index b95a8049c..47e651408 100644 --- a/soh/soh/SohGui/SohMenuRandomizer.cpp +++ b/soh/soh/SohGui/SohMenuRandomizer.cpp @@ -6,6 +6,12 @@ namespace SohGui { extern std::shared_ptr mSohMenu; using namespace UIWidgets; +static const std::unordered_map skipGetItemAnimationOptions = { + { SGIA_DISABLED, "Disabled" }, + { SGIA_JUNK, "Junk Items" }, + { SGIA_ALL, "All Items" }, +}; + void SohMenu::AddMenuRandomizer() { // Add Randomizer Menu AddMenuEntry("Randomizer", CVAR_SETTING("Menu.RandomizerSidebarSection")); diff --git a/soh/soh/SohGui/SohMenuSettings.cpp b/soh/soh/SohGui/SohMenuSettings.cpp index 0221ae3f7..bb7c82574 100644 --- a/soh/soh/SohGui/SohMenuSettings.cpp +++ b/soh/soh/SohGui/SohMenuSettings.cpp @@ -23,6 +23,39 @@ static std::unordered_map imguiScaleOptions = { { 3, "X-Large" }, }; +static const std::unordered_map menuThemeOptions = { + { UIWidgets::Colors::Red, "Red" }, + { UIWidgets::Colors::DarkRed, "Dark Red" }, + { UIWidgets::Colors::Orange, "Orange" }, + { UIWidgets::Colors::Green, "Green" }, + { UIWidgets::Colors::DarkGreen, "Dark Green" }, + { UIWidgets::Colors::LightBlue, "Light Blue" }, + { UIWidgets::Colors::Blue, "Blue" }, + { UIWidgets::Colors::DarkBlue, "Dark Blue" }, + { UIWidgets::Colors::Indigo, "Indigo" }, + { UIWidgets::Colors::Violet, "Violet" }, + { UIWidgets::Colors::Purple, "Purple" }, + { UIWidgets::Colors::Brown, "Brown" }, + { UIWidgets::Colors::Gray, "Gray" }, + { UIWidgets::Colors::DarkGray, "Dark Gray" }, +}; + +static const std::unordered_map textureFilteringMap = { + { Fast::FILTER_THREE_POINT, "Three-Point" }, + { Fast::FILTER_LINEAR, "Linear" }, + { Fast::FILTER_NONE, "None" }, +}; + +static const std::unordered_map notificationPosition = { + { 0, "Top Left" }, { 1, "Top Right" }, { 2, "Bottom Left" }, { 3, "Bottom Right" }, { 4, "Hidden" }, +}; + +static const std::unordered_map bootSequenceLabels = { + { BOOTSEQUENCE_DEFAULT, "Default" }, + { BOOTSEQUENCE_AUTHENTIC, "Authentic" }, + { BOOTSEQUENCE_FILESELECT, "File Select" }, +}; + const char* GetGameVersionString(uint32_t index) { uint32_t gameVersion = ResourceMgr_GetGameVersion(index); switch (gameVersion) { diff --git a/soh/soh/SohGui/UIWidgets.hpp b/soh/soh/SohGui/UIWidgets.hpp index caf2e912b..0ed88bade 100644 --- a/soh/soh/SohGui/UIWidgets.hpp +++ b/soh/soh/SohGui/UIWidgets.hpp @@ -115,10 +115,12 @@ struct WidgetOptions { tooltip = tooltip_; return *this; } + WidgetOptions& Disabled(bool disabled_) { disabled = disabled_; return *this; } + WidgetOptions& DisabledTooltip(const char* disabledTooltip_) { disabledTooltip = disabledTooltip_; return *this; @@ -143,14 +145,17 @@ struct ButtonOptions : WidgetOptions { size = size_; return *this; } + ButtonOptions& Padding(ImVec2 padding_) { padding = padding_; return *this; } + ButtonOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + ButtonOptions& Color(Colors color_) { color = color_; return *this; @@ -168,22 +173,27 @@ struct WindowButtonOptions : WidgetOptions { size = size_; return *this; } + WindowButtonOptions& Padding(ImVec2 padding_) { padding = padding_; return *this; } + WindowButtonOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + WindowButtonOptions& Color(Colors color_) { color = color_; return *this; } + WindowButtonOptions& ShowButton(bool showButton_) { showButton = showButton_; return *this; } + WindowButtonOptions& EmbedWindow(bool embedWindow_) { embedWindow = embedWindow_; return *this; @@ -201,26 +211,32 @@ struct CheckboxOptions : WidgetOptions { defaultValue = defaultValue_; return *this; } + CheckboxOptions& ComponentAlignment(ComponentAlignments alignment_) { alignment = alignment_; return *this; } + CheckboxOptions& LabelPosition(LabelPositions labelPosition_) { labelPosition = labelPosition_; return *this; } + CheckboxOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + CheckboxOptions& Color(Colors color_) { color = color_; return *this; } + CheckboxOptions& DisabledTooltip(const char* disabledTooltip_) { WidgetOptions::disabledTooltip = disabledTooltip_; return *this; } + CheckboxOptions& Padding(ImVec2 padding_) { padding = padding_; return *this; @@ -239,22 +255,27 @@ struct ComboboxOptions : WidgetOptions { comboMap = comboMap_; return *this; } + ComboboxOptions& DefaultIndex(uint32_t defaultIndex_) { defaultIndex = defaultIndex_; return *this; } + ComboboxOptions& ComponentAlignment(ComponentAlignments alignment_) { alignment = alignment_; return *this; } + ComboboxOptions& LabelPosition(LabelPositions labelPosition_) { labelPosition = labelPosition_; return *this; } + ComboboxOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + ComboboxOptions& Color(Colors color_) { color = color_; return *this; @@ -279,46 +300,57 @@ struct IntSliderOptions : WidgetOptions { showButtons = showButtons_; return *this; } + IntSliderOptions& Format(const char* format_) { format = format_; return *this; } + IntSliderOptions& Step(int32_t step_) { step = step_; return *this; } + IntSliderOptions& Min(int32_t min_) { min = min_; return *this; } + IntSliderOptions& Max(int32_t max_) { max = max_; return *this; } + IntSliderOptions& DefaultValue(int32_t defaultValue_) { defaultValue = defaultValue_; return *this; } + IntSliderOptions& ComponentAlignment(ComponentAlignments alignment_) { alignment = alignment_; return *this; } + IntSliderOptions& LabelPosition(LabelPositions labelPosition_) { labelPosition = labelPosition_; return *this; } + IntSliderOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + IntSliderOptions& Color(Colors color_) { color = color_; return *this; } + IntSliderOptions& Size(ImVec2 size_) { size = size_; return *this; } + IntSliderOptions& Clamp(bool clamp_) { clamp = clamp_; return *this; @@ -344,34 +376,42 @@ struct FloatSliderOptions : WidgetOptions { showButtons = showButtons_; return *this; } + FloatSliderOptions& Format(const char* format_) { format = format_; return *this; } + FloatSliderOptions& Step(float step_) { step = step_; return *this; } + FloatSliderOptions& Min(float min_) { min = min_; return *this; } + FloatSliderOptions& Max(float max_) { max = max_; return *this; } + FloatSliderOptions& DefaultValue(float defaultValue_) { defaultValue = defaultValue_; return *this; } + FloatSliderOptions& ComponentAlignment(ComponentAlignments alignment_) { alignment = alignment_; return *this; } + FloatSliderOptions& LabelPosition(LabelPositions labelPosition_) { labelPosition = labelPosition_; return *this; } + FloatSliderOptions& IsPercentage(bool isPercentage_ = true) { isPercentage = isPercentage_; format = "%.0f%%"; @@ -379,18 +419,22 @@ struct FloatSliderOptions : WidgetOptions { max = 1.0f; return *this; } + FloatSliderOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + FloatSliderOptions& Color(Colors color_) { color = color_; return *this; } + FloatSliderOptions& Size(ImVec2 size_) { size = size_; return *this; } + FloatSliderOptions& Clamp(bool clamp_) { clamp = clamp_; return *this; @@ -406,14 +450,17 @@ struct RadioButtonsOptions : WidgetOptions { buttonMap = buttonMap_; return *this; } + RadioButtonsOptions& Tooltip(const char* tooltip_) { WidgetOptions::tooltip = tooltip_; return *this; } + RadioButtonsOptions& Color(Colors color_) { color = color_; return *this; } + RadioButtonsOptions& DefaultIndex(int32_t defaultIndex_) { defaultIndex = defaultIndex_; return *this; @@ -437,10 +484,12 @@ struct InputOptions : WidgetOptions { WidgetOptions::tooltip = tooltip_; return *this; } + InputOptions& Color(Colors color_) { color = color_; return *this; } + InputOptions& Size(ImVec2 size_) { size = size_; return *this; diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 3933f263d..d8263f5de 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1284,8 +1284,16 @@ void Actor_UpdatePos(Actor* actor) { } void Actor_UpdateVelocityXZGravity(Actor* actor) { - actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ; - actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ; + Player* player = GET_PLAYER(gPlayState); + uint8_t inCutscene = player->stateFlags1 & PLAYER_STATE1_CLIMBING_LADDER || + player->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE || + player->stateFlags2 & PLAYER_STATE2_CRAWLING; + f32 speedModifier = 1.0f; + if (actor->id == ACTOR_PLAYER && !inCutscene) { + speedModifier = GameInteractor_MovementSpeedMultiplier(); + } + actor->velocity.x = Math_SinS(actor->world.rot.y) * actor->speedXZ * speedModifier; + actor->velocity.z = Math_CosS(actor->world.rot.y) * actor->speedXZ * speedModifier; actor->velocity.y += actor->gravity; if (actor->velocity.y < actor->minVelocityY) { @@ -5047,8 +5055,8 @@ void Flags_SetRandomizerInf(RandomizerInf flag) { */ s32 previouslyOff = !Flags_GetRandomizerInf(flag); - gSaveContext.ship.randomizerInf[flag >> 4] |= (1 << (flag & 0xF)); if (previouslyOff) { + gSaveContext.ship.randomizerInf[flag >> 4] |= (1 << (flag & 0xF)); LUSLOG_INFO("RandomizerInf Flag Set - %#x", flag); GameInteractor_ExecuteOnFlagSet(FLAG_RANDOMIZER_INF, flag); } @@ -5068,8 +5076,8 @@ void Flags_UnsetRandomizerInf(RandomizerInf flag) { */ s32 previouslyOn = Flags_GetRandomizerInf(flag); - gSaveContext.ship.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF)); if (previouslyOn) { + gSaveContext.ship.randomizerInf[flag >> 4] &= ~(1 << (flag & 0xF)); LUSLOG_INFO("RandomizerInf Flag Unset - %#x", flag); GameInteractor_ExecuteOnFlagUnset(FLAG_RANDOMIZER_INF, flag); } 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 a90764717..54e9768b4 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 @@ -813,7 +813,8 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SPIRIT_TEMPLE_BOSS) { - if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT), + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, + !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE), RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SPIRIT_TEMPLE); if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SPIRIT)) { @@ -831,7 +832,8 @@ void DoorWarp1_AdultWarpOut(DoorWarp1* this, PlayState* play) { gSaveContext.nextCutsceneIndex = 0; } } else if (play->sceneNum == SCENE_SHADOW_TEMPLE_BOSS) { - if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW), + if (GameInteractor_Should(VB_PLAY_BLUE_WARP_CS, + !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE), RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE)) { Flags_SetRandomizerInf(RAND_INF_DUNGEONS_DONE_SHADOW_TEMPLE); if (GameInteractor_Should(VB_GIVE_ITEM_FROM_BLUE_WARP, true, ITEM_MEDALLION_SHADOW)) { diff --git a/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c b/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c index aa455739e..70bd36a6b 100644 --- a/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c +++ b/soh/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c @@ -58,6 +58,11 @@ void EnAttackNiw_Init(Actor* thisx, PlayState* play) { this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; this->actor.shape.rot.y = this->actor.world.rot.y = (Rand_ZeroOne() - 0.5f) * 60000.0f; this->actionFunc = func_809B5670; + + if (CVarGetInteger("gCrowdControl", 0) && + CVarGetInteger(CVAR_REMOTE_CROWD_CONTROL("SpawnedEnemiesIgnoredIngame"), 0)) { + Actor_ChangeCategory(gPlayState, &gPlayState->actorCtx, this, ACTORCAT_NPC); + } } void EnAttackNiw_Destroy(Actor* thisx, PlayState* play) { 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 4ae6fb744..205079576 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -7124,15 +7124,6 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) { if (this->meleeWeaponState == 0) { float maxSpeed = R_RUN_SPEED_LIMIT / 100.0f; - int32_t giSpeedModifier = GameInteractor_RunSpeedModifier(); - if (giSpeedModifier != 0) { - if (giSpeedModifier > 0) { - maxSpeed *= giSpeedModifier; - } else { - maxSpeed /= abs(giSpeedModifier); - } - } - if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) == BUNNY_HOOD_FAST_AND_JUMP && this->currentMask == PLAYER_MASK_BUNNY) { maxSpeed *= 1.5f; @@ -8873,14 +8864,6 @@ void Player_Action_80842180(Player* this, PlayState* play) { Player_GetMovementSpeedAndYaw(this, &sp2C, &sp2A, SPEED_MODE_CURVED, play); if (!func_8083C484(this, &sp2C, &sp2A)) { - int32_t giSpeedModifier = GameInteractor_RunSpeedModifier(); - if (giSpeedModifier != 0) { - if (giSpeedModifier > 0) { - sp2C *= giSpeedModifier; - } else { - sp2C /= abs(giSpeedModifier); - } - } if (CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA && this->currentMask == PLAYER_MASK_BUNNY) { 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 17f1aa89e..78a072c6f 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 @@ -124,7 +124,17 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { s16 pad2; s16 phi_s0_2; s16 sp208[3]; - bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); + if (CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0)) { + if (CHECK_BTN_ALL(input->press.button, BTN_DLEFT)) { + pauseCtx->stickRelX = -35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DRIGHT)) { + pauseCtx->stickRelX = 35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) { + pauseCtx->stickRelY = -35; + } else if (CHECK_BTN_ALL(input->press.button, BTN_DUP)) { + pauseCtx->stickRelY = 35; + } + } OPEN_DISPS(gfxCtx); @@ -140,7 +150,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } else { phi_s3 = pauseCtx->cursorPoint[PAUSE_QUEST]; - if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { + if ((pauseCtx->stickRelX < -30)) { phi_s0 = D_8082A1AC[phi_s3][2]; if (phi_s0 == -3) { KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_LEFT); @@ -153,7 +163,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { phi_s0 = D_8082A1AC[phi_s0][2]; } } - } else if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { + } else if ((pauseCtx->stickRelX > 30)) { phi_s0 = D_8082A1AC[phi_s3][3]; if (phi_s0 == -2) { KaleidoScope_MoveCursorToSpecialPos(play, PAUSE_CURSOR_PAGE_RIGHT); @@ -168,7 +178,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } } - if ((pauseCtx->stickRelY < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DDOWN))) { + if ((pauseCtx->stickRelY < -30)) { phi_s0 = D_8082A1AC[phi_s3][1]; while (phi_s0 >= 0) { if ((s16)KaleidoScope_UpdateQuestStatusPoint(pauseCtx, phi_s0) != 0) { @@ -176,7 +186,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } phi_s0 = D_8082A1AC[phi_s0][1]; } - } else if ((pauseCtx->stickRelY > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) { + } else if ((pauseCtx->stickRelY > 30)) { phi_s0 = D_8082A1AC[phi_s3][0]; while (phi_s0 >= 0) { if ((s16)KaleidoScope_UpdateQuestStatusPoint(pauseCtx, phi_s0) != 0) { @@ -267,7 +277,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { } } } else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) { - if ((pauseCtx->stickRelX > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DRIGHT))) { + if ((pauseCtx->stickRelX > 30)) { pauseCtx->cursorPoint[PAUSE_QUEST] = 0x15; pauseCtx->nameDisplayTimer = 0; pauseCtx->cursorSpecialPos = 0; @@ -285,7 +295,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play, GraphicsContext* gfxCtx) { pauseCtx->cursorSlot[pauseCtx->pageIndex] = sp216; } } else { - if ((pauseCtx->stickRelX < -30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DLEFT))) { + if ((pauseCtx->stickRelX < -30)) { pauseCtx->cursorPoint[PAUSE_QUEST] = 0; pauseCtx->nameDisplayTimer = 0; pauseCtx->cursorSpecialPos = 0;