diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp
index c24b83fb6..3d494b87f 100644
--- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp
+++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp
@@ -20,6 +20,10 @@ static const std::unordered_map<std::string, std::string> percentColors = { { "w
                                                               { "b", QM_BLUE },   { "c", QM_LBLUE }, { "p", QM_PINK },
                                                               { "y", QM_YELLOW }, { "B", QM_BLACK } };
 
+static const std::unordered_map<std::string, std::string> colorToPercent = { { QM_WHITE, "%w" },  { QM_RED, "%r"},   { QM_GREEN, "%g" },
+                                                              { QM_BLUE, "%b" },   { QM_LBLUE, "%c"}, { QM_PINK, "%p" },
+                                                              { QM_YELLOW, "%y" }, { QM_BLACK, "%B" } };
+
 static const std::unordered_map<std::string, ItemID> altarIcons = {
     { "0", ITEM_KOKIRI_EMERALD },
     { "1", ITEM_GORON_RUBY },
@@ -147,6 +151,8 @@ void CustomMessage::ProcessMessageFormat(std::string& str, MessageFormat format)
         CleanString(str);
     } else if (format == MF_AUTO_FORMAT){
         AutoFormatString(str);
+    }else if (format == MF_ENCODE){
+        EncodeColors(str);
     }
 }
 
@@ -281,6 +287,12 @@ void CustomMessage::Clean() {
     }
 }
 
+void CustomMessage::Encode() {
+    for (std::string& str : messages) {
+        EncodeColors(str);
+    }
+}
+
 void CustomMessage::FormatString(std::string& str) const {
     std::replace(str.begin(), str.end(), '&', NEWLINE()[0]);
     std::replace(str.begin(), str.end(), '^', WAIT_FOR_INPUT()[0]);
@@ -506,7 +518,23 @@ const char* Interface_ReplaceSpecialCharacters(char text[]) {
     return textChar;
 }
 
+void CustomMessage::EncodeColors(std::string& str) const {
+    for (std::string color: colors) {
+        if (const size_t firstHashtag = str.find('#'); firstHashtag != std::string::npos) {
+            str.replace(firstHashtag, 1, colorToPercent.at(color));
+            if (const size_t secondHashtag = str.find('#', firstHashtag + 1); secondHashtag != std::string::npos) {
+                str.replace(secondHashtag, 1, "%w");
+            } else {
+                SPDLOG_DEBUG("non-matching hashtags in string: \"%s\"", str);
+            }
+        }
+    }
+    // Remove any remaining '#' characters.
+    std::erase(str, '#');
+}
+
 void CustomMessage::ReplaceColors(std::string& str) const {
+    EncodeColors(str);
     for (const auto& colorPair : percentColors) {
         std::string textToReplace = "%";
         textToReplace += colorPair.first;
@@ -516,18 +544,6 @@ void CustomMessage::ReplaceColors(std::string& str) const {
             start_pos += textToReplace.length();
         }
     }
-    for (auto color: colors) {
-        if (const size_t firstHashtag = str.find('#'); firstHashtag != std::string::npos) {
-            str.replace(firstHashtag, 1, COLOR(color));
-        if (const size_t secondHashtag = str.find('#', firstHashtag + 1); secondHashtag != std::string::npos) {
-            str.replace(secondHashtag, 1, COLOR(QM_WHITE));
-        } else {
-            SPDLOG_DEBUG("non-matching hashtags in string: \"%s\"", str);
-        }
-        }
-    }
-    // Remove any remaining '#' characters.
-    std::erase(str, '#');
 }
 
 void CustomMessage::ReplaceAltarIcons(std::string& str) const {
@@ -619,6 +635,8 @@ CustomMessage CustomMessageManager::RetrieveMessage(std::string tableID, uint16_
         message.AutoFormat();
     } else if (format == MF_CLEAN){
         message.Clean();
+    } else if (format == MF_ENCODE){
+        message.Encode();
     }
     
     return message;
diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h
index 130feda73..7f68f2fab 100644
--- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h
+++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h
@@ -26,7 +26,8 @@ typedef enum {
     MF_FORMATTED,
     MF_CLEAN,
     MF_RAW,
-    MF_AUTO_FORMAT
+    MF_AUTO_FORMAT,
+    MF_ENCODE,
 } MessageFormat;
 
 /**
@@ -108,6 +109,11 @@ class CustomMessage {
      */
     void ReplaceSpecialCharacters(std::string& str) const;
 
+    /**
+     * @brief Replaces hashtags with stored colors.
+     */
+    void EncodeColors(std::string& str) const;
+
     /**
      * @brief Replaces our color variable strings with the OoT control codes.
      */
@@ -160,6 +166,11 @@ class CustomMessage {
      */
     void Clean();
 
+    /**
+     * @brief Replaces variable characters with fixed ones to store the sata in string form
+     */
+    void Encode();
+
     /**
      * @brief Replaces various symbols with the control codes necessary to
      * display them in OoT's textboxes for a single string
diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
index a5126d32e..2a1cf9f49 100644
--- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
+++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp
@@ -1206,7 +1206,7 @@ void DrawQuestStatusTab() {
     ImGui::SameLine();
     DrawQuestItemButton(QUEST_GERUDO_CARD);
 
-    for (const SongMapEntry& entry : songMapping) {
+    for (const auto& [quest, entry] : songMapping) {
         if ((entry.id != QUEST_SONG_MINUET) && (entry.id != QUEST_SONG_LULLABY)) {
             ImGui::SameLine();
         }
diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
index ea082218e..14faa479b 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp
@@ -2253,6 +2253,118 @@ void StaticData::HintTable_Init() {
                                                /*german*/ "",
                                                /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
 
+    hintTextTable[RHT_JUNK_CREW_1] = HintText(CustomMessage("They say that %gGanondorf's Mom%w is going out with %ySqueak%w!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_2] = HintText(CustomMessage("They say that %gProxySaw%w is still fixing %yCaladius's Bugs%w...",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_3] = HintText(CustomMessage("They say that %gItsHeckinPat%w is still just %yEyeballing it%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_4] = HintText(CustomMessage("They say that %gCaladius%w is working on %yV2%w of something.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_5] = HintText(CustomMessage("They say that %gdice%w is a funny name for a %ytaco%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_6] = HintText(CustomMessage("They say %g2Ship Rando%w is still blocked by %yV3%w...",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_7] = HintText(CustomMessage("They say if you click your heels and say %gframebuffer%w 3 times, %yArchez%w appears!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_8] = HintText(CustomMessage("They say %gVB%w stands for %yVirtual Bananas%w... Probably.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_9] = HintText(CustomMessage("They say %gZeru%w is still routing his %yHundo%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_10] = HintText(CustomMessage("They say %gRaccoonCloud%w is still looking for his %yHover Boots%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_11] = HintText(CustomMessage("They say %gItsHeckinPat%w foreclosed on his %yHut%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_12] = HintText(CustomMessage("They say %gRaccoonCloud%w is part of the %yInner Circle%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_13] = HintText(CustomMessage("They say %gMoonlitxShadows%w is the %rleader%w of the %yDork Army%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_14] = HintText(CustomMessage("They say %gGanondorf%w hates the %yInternet%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_15] = HintText(CustomMessage("They say %gMido's House%w hoards %yTrash%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_16] = HintText(CustomMessage("They say %gSweettalking Ganondorf%w rewards %yHis Heart%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_17] = HintText(CustomMessage("They say %gaMannus%w said %yGo To Bed%w!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_18] = HintText(CustomMessage("They say %gCaladius%w is a %yPinhead%w!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_19] = HintText(CustomMessage("They say %gRaccoonCloud%w loves the %yIce Cavern%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_20] = HintText(CustomMessage("They say %gNo One%w should forget %yHover Scrub%w!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_21] = HintText(CustomMessage("They say %gMoonlitxShadows%w likes to %ySlide%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_23] = HintText(CustomMessage("They say that %gBackwalking%w should be %rBanned%w!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_24] = HintText(CustomMessage("They say that %gGorons%w should always have %yLong Necks%w!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_25] = HintText(CustomMessage("They say that %gCaladius%w has a %ytendency to lose his shirt%w!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_26] = HintText(CustomMessage("They say that if your %rSkip keeps Failing%w, you're probably an %yESS Off%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_27] = HintText(CustomMessage("They say that %gLogic%w is just a %ySuggestion%w.",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_28] = HintText(CustomMessage("They say there's %gAlways Logic%w in %yNo Logic%w...",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
+    hintTextTable[RHT_JUNK_CREW_29] = HintText(CustomMessage("They said that %rFredomato%w has just %yone more push up%w to do!",
+                                               /*german*/ "",
+                                               /*french*/ HINT_TEXT_NEEDS_TRANSLATION_FR));
+
     /*--------------------------
     |     DUNGEON HINT TEXT    |
     ---------------------------*/
diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp
index f72212301..9831c2d2b 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp
@@ -113,8 +113,8 @@ StaticHintInfo::StaticHintInfo(HintType _type, std::vector<RandomizerHintTextKey
 
 RandomizerHintTextKey GetRandomJunkHint(){ 
   //temp code to handle random junk hints now I work in keys instead of a vector of HintText
-  // Will be replaced with a better system once more customisable hint pools are added
-  uint32_t range = RHT_JUNK_SG_8 - RHT_JUNK02;
+  //Will be replaced with a better system once more customisable hint pools are added
+  uint32_t range = RHT_JUNK_CREW_29 - RHT_JUNK02;
   return (RandomizerHintTextKey)(Random(0, range) + RHT_JUNK02);
 }
 
diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.hpp b/soh/soh/Enhancements/randomizer/3drando/hints.hpp
index d111c78ca..9199c6c81 100644
--- a/soh/soh/Enhancements/randomizer/3drando/hints.hpp
+++ b/soh/soh/Enhancements/randomizer/3drando/hints.hpp
@@ -69,6 +69,8 @@ struct StaticHintInfo{
                  std::vector<RandomizerCheck> _hintChecks = {}, bool _yourPocket = false, int _num = 0);
 };
 
+RandomizerHintTextKey GetRandomJunkHint();
 extern void CreateAllHints();
 extern void CreateWarpSongTexts();
-void CreateStaticHints();
\ No newline at end of file
+void CreateStaticHints();
+RandomizerHintTextKey GetRandomJunkHint();
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/Plandomizer.cpp b/soh/soh/Enhancements/randomizer/Plandomizer.cpp
new file mode 100644
index 000000000..732ef700b
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/Plandomizer.cpp
@@ -0,0 +1,1109 @@
+#include "Plandomizer.h"
+#include "soh/UIWidgets.hpp"
+#include "soh/util.h"
+#include <vector>
+#include "soh/Notification/Notification.h"
+#include <soh_assets.h>
+#include "soh/Enhancements/randomizer/3drando/hints.hpp"
+
+#include <fstream>
+#include <filesystem>
+
+#include "soh/OTRGlobals.h"
+#include "soh/ImGuiUtils.h"
+#include "soh/Enhancements/randomizer/logic.h"
+#include "soh/Enhancements/randomizer/randomizer_check_objects.h"
+#include "soh/Enhancements/randomizer/rando_hash.h"
+#include "soh/Enhancements/randomizer/3drando/shops.hpp"
+
+extern "C" {
+    #include "include/z64item.h"
+    #include "objects/gameplay_keep/gameplay_keep.h"
+    extern SaveContext gSaveContext;
+    extern PlayState* gPlayState;
+}
+
+const std::string randomizeButton = ICON_FA_RANDOM;
+
+static int32_t correctedItemID = -1;
+static int32_t getTabID = TAB_HINTS;
+
+Rando::Item temporaryItem;
+std::string shortName = "";
+std::string logTemp = "";
+std::string lastLoadedSpoiler = "";
+int32_t temporaryItemIndex = -1;
+RandomizerCheckArea selectedArea = RCAREA_INVALID; 
+
+ImVec4 itemColor = ImVec4( 1.0f, 1.0f, 1.0f, 1.0f );
+ImTextureID textureID;
+ImVec2 imageSize = ImVec2(32.0f, 32.0f);
+float imagePadding = 2.0f;
+ImVec2 textureUV0 = ImVec2( 0, 0 );
+ImVec2 textureUV1 = ImVec2( 1, 1 );
+
+bool shouldPopup = false;
+bool shouldTrapPopup = false;
+bool shouldRemove = false;
+
+namespace fs = std::filesystem;
+std::vector<std::string> existingSeedList;
+
+std::vector<int32_t> spoilerHash;
+std::vector<int32_t> plandoHash;
+std::vector<SpoilerCheckObject> spoilerLogData;
+std::vector<SpoilerCheckObject> plandoLogData;
+std::vector<std::pair<Rando::Item, int32_t>> drawnItemsList;
+
+std::vector<SpoilerHintObject> spoilerHintData;
+std::vector<SpoilerHintObject> plandoHintData;
+
+extern std::map<RandomizerCheckArea, std::string> rcAreaNames;
+
+std::unordered_map<RandomizerGet, std::string> bossKeyShortNames = {
+    { RG_FOREST_TEMPLE_BOSS_KEY,     "Frst" },
+    { RG_FIRE_TEMPLE_BOSS_KEY,       "Fire" },
+    { RG_WATER_TEMPLE_BOSS_KEY,      "Watr" },
+    { RG_SPIRIT_TEMPLE_BOSS_KEY,     "Sprt" },
+    { RG_SHADOW_TEMPLE_BOSS_KEY,     "Shdw" },
+    { RG_GANONS_CASTLE_BOSS_KEY,     "Ganon" },
+};
+
+std::unordered_map<RandomizerGet, std::string> ocarinaButtonNames = {
+    { RG_OCARINA_A_BUTTON,          "A" },
+    { RG_OCARINA_C_UP_BUTTON,       "C-UP" },
+    { RG_OCARINA_C_DOWN_BUTTON,     "C-DWN" },
+    { RG_OCARINA_C_LEFT_BUTTON,     "C-LFT" },
+    { RG_OCARINA_C_RIGHT_BUTTON,    "C-RHT" },
+};
+
+std::map<RandomizerGet, ImVec4> bossSoulMapping = {
+    { RG_GOHMA_SOUL,          { 0.00f, 1.00f, 0.00f, 1.0f } },
+    { RG_KING_DODONGO_SOUL,   { 1.00f, 0.00f, 0.39f, 1.0f } },
+    { RG_BARINADE_SOUL,       { 0.20f, 1.00f, 1.00f, 1.0f } },
+    { RG_PHANTOM_GANON_SOUL,  { 0.02f, 0.76f, 0.18f, 1.0f } },
+    { RG_VOLVAGIA_SOUL,       { 0.93f, 0.37f, 0.37f, 1.0f } },
+    { RG_MORPHA_SOUL,         { 0.33f, 0.71f, 0.87f, 1.0f } },
+    { RG_BONGO_BONGO_SOUL,    { 0.49f, 0.06f, 0.69f, 1.0f } },
+    { RG_TWINROVA_SOUL,       { 0.87f, 0.62f, 0.18f, 1.0f } },
+    { RG_GANON_SOUL,          { 0.31f, 0.31f, 0.31f, 1.0f } }
+};
+
+
+std::vector<RandomizerGet> infiniteItemList = {
+    RG_GREEN_RUPEE, RG_BLUE_RUPEE, RG_RED_RUPEE, RG_PURPLE_RUPEE, RG_HUGE_RUPEE,
+    RG_ARROWS_5, RG_ARROWS_10, RG_ARROWS_30,
+    RG_DEKU_STICK_1, RG_DEKU_SEEDS_30, RG_DEKU_NUTS_5, RG_DEKU_NUTS_10,
+    RG_BOMBS_5, RG_BOMBS_10, RG_BOMBS_20, RG_BOMBCHU_5, RG_BOMBCHU_10, RG_BOMBCHU_20,
+    RG_RECOVERY_HEART, RG_ICE_TRAP, RG_SOLD_OUT
+};
+
+std::unordered_map<RandomizerGet, std::string> itemImageMap = {
+    { RG_NONE,                      		"ITEM_SOLD_OUT" },
+    { RG_KOKIRI_SWORD,              		"ITEM_SWORD_KOKIRI" },
+    { RG_GIANTS_KNIFE,              		"ITEM_SWORD_KNIFE" },
+    { RG_BIGGORON_SWORD,            		"ITEM_SWORD_BGS" },
+    { RG_DEKU_SHIELD,               		"ITEM_SHIELD_DEKU" },
+    { RG_HYLIAN_SHIELD,             		"ITEM_SHIELD_HYLIAN" },
+    { RG_MIRROR_SHIELD,             		"ITEM_SHIELD_MIRROR" },
+    { RG_GORON_TUNIC,               		"ITEM_TUNIC_GORON" },
+    { RG_ZORA_TUNIC,                		"ITEM_TUNIC_ZORA" },
+    { RG_IRON_BOOTS,                		"ITEM_BOOTS_IRON" },
+    { RG_HOVER_BOOTS,               		"ITEM_BOOTS_HOVER" },
+    { RG_BOOMERANG,                 		"ITEM_BOOMERANG" },
+    { RG_LENS_OF_TRUTH,             		"ITEM_LENS" },
+    { RG_MEGATON_HAMMER,            		"ITEM_HAMMER" },
+    { RG_STONE_OF_AGONY,            		"ITEM_STONE_OF_AGONY" },
+    { RG_DINS_FIRE,                 		"ITEM_DINS_FIRE" },
+    { RG_FARORES_WIND,              		"ITEM_FARORES_WIND" },
+    { RG_NAYRUS_LOVE,               		"ITEM_NAYRUS_LOVE" },
+    { RG_FIRE_ARROWS,               		"ITEM_ARROW_FIRE" },
+    { RG_ICE_ARROWS,                		"ITEM_ARROW_ICE" },
+    { RG_LIGHT_ARROWS,              		"ITEM_ARROW_LIGHT" },
+    { RG_GERUDO_MEMBERSHIP_CARD,    		"ITEM_GERUDO_CARD" },
+    { RG_MAGIC_BEAN,                		"ITEM_BEAN" },
+    { RG_MAGIC_BEAN_PACK,           		"ITEM_BEAN" },
+    { RG_DOUBLE_DEFENSE,            		"ITEM_HEART_CONTAINER" },
+    { RG_WEIRD_EGG,                 		"ITEM_WEIRD_EGG" },
+    { RG_ZELDAS_LETTER,             		"ITEM_LETTER_ZELDA" },
+    { RG_POCKET_EGG,                		"ITEM_POCKET_EGG" },
+    { RG_COJIRO,                    		"ITEM_COJIRO" },
+    { RG_ODD_MUSHROOM,              		"ITEM_ODD_MUSHROOM" },
+    { RG_ODD_POTION,                		"ITEM_ODD_POTION" },
+    { RG_POACHERS_SAW,              		"ITEM_SAW" },
+    { RG_BROKEN_SWORD,              		"ITEM_SWORD_BROKEN" },
+    { RG_PRESCRIPTION,              		"ITEM_PRESCRIPTION" },
+    { RG_EYEBALL_FROG,              		"ITEM_FROG" },
+    { RG_EYEDROPS,                  		"ITEM_EYEDROPS" },
+    { RG_CLAIM_CHECK,               		"ITEM_CLAIM_CHECK" },
+    { RG_GOLD_SKULLTULA_TOKEN,      		"ITEM_SKULL_TOKEN" },
+    { RG_PROGRESSIVE_HOOKSHOT,      		"ITEM_HOOKSHOT" },
+    { RG_PROGRESSIVE_STRENGTH,      		"ITEM_BRACELET" },
+    { RG_PROGRESSIVE_BOMB_BAG,      		"ITEM_BOMB_BAG_30" },
+    { RG_PROGRESSIVE_BOW,           		"ITEM_QUIVER_30" },
+    { RG_PROGRESSIVE_SLINGSHOT,     		"ITEM_SLINGSHOT" },
+    { RG_PROGRESSIVE_WALLET,        		"ITEM_WALLET_ADULT" },
+    { RG_PROGRESSIVE_SCALE,         		"ITEM_SCALE_SILVER" },
+    { RG_PROGRESSIVE_NUT_UPGRADE,   		"ITEM_NUT" },
+    { RG_PROGRESSIVE_STICK_UPGRADE, 		"ITEM_STICK" },
+    { RG_PROGRESSIVE_BOMBCHUS,      		"ITEM_BOMBCHU" },
+    { RG_PROGRESSIVE_MAGIC_METER,   		"ITEM_MAGIC_SMALL" },
+    { RG_MAGIC_SINGLE,              		"ITEM_MAGIC_SMALL" },
+    { RG_MAGIC_DOUBLE,              		"ITEM_MAGIC_LARGE" },
+    { RG_PROGRESSIVE_OCARINA,       		"ITEM_OCARINA_FAIRY" },
+    { RG_PROGRESSIVE_GORONSWORD,    		"ITEM_SWORD_BGS" },
+    { RG_EMPTY_BOTTLE,              		"ITEM_BOTTLE" },
+    { RG_BOTTLE_WITH_MILK,          		"ITEM_MILK_BOTTLE" },
+    { RG_BOTTLE_WITH_RED_POTION,    		"ITEM_POTION_RED" },
+    { RG_BOTTLE_WITH_GREEN_POTION,  		"ITEM_POTION_GREEN" },
+    { RG_BOTTLE_WITH_BLUE_POTION,   		"ITEM_POTION_BLUE" },
+    { RG_BOTTLE_WITH_FAIRY,         		"ITEM_FAIRY" },
+    { RG_BOTTLE_WITH_FISH,          		"ITEM_FISH" },
+    { RG_BOTTLE_WITH_BLUE_FIRE,     		"ITEM_BLUE_FIRE" },
+    { RG_BOTTLE_WITH_BUGS,          		"ITEM_BUG" },
+    { RG_BOTTLE_WITH_POE,           		"ITEM_POE" },
+    { RG_RUTOS_LETTER,              		"ITEM_LETTER_RUTO" },
+    { RG_BOTTLE_WITH_BIG_POE,       		"ITEM_BIG_POE" },
+    { RG_ZELDAS_LULLABY,            		"ITEM_SONG_LULLABY" },
+    { RG_EPONAS_SONG,               		"ITEM_SONG_EPONA" },
+    { RG_SARIAS_SONG,               		"ITEM_SONG_SARIA" },
+    { RG_SUNS_SONG,                 		"ITEM_SONG_SUN" },
+    { RG_SONG_OF_TIME,              		"ITEM_SONG_TIME" },
+    { RG_SONG_OF_STORMS,            		"ITEM_SONG_STORMS" },
+    { RG_MINUET_OF_FOREST,          		"ITEM_SONG_MINUET" },
+    { RG_BOLERO_OF_FIRE,            		"ITEM_SONG_BOLERO" },
+    { RG_SERENADE_OF_WATER,         		"ITEM_SONG_SERENADE" },
+    { RG_REQUIEM_OF_SPIRIT,         		"ITEM_SONG_REQUIEM" },
+    { RG_NOCTURNE_OF_SHADOW,        		"ITEM_SONG_NOCTURNE" },
+    { RG_PRELUDE_OF_LIGHT,          		"ITEM_SONG_PRELUDE" },
+    { RG_DEKU_TREE_MAP,             		"ITEM_DUNGEON_MAP" },
+    { RG_DODONGOS_CAVERN_MAP,       		"ITEM_DUNGEON_MAP" },
+    { RG_JABU_JABUS_BELLY_MAP,      		"ITEM_DUNGEON_MAP" },
+    { RG_FOREST_TEMPLE_MAP,         		"ITEM_DUNGEON_MAP" },
+    { RG_FIRE_TEMPLE_MAP,           		"ITEM_DUNGEON_MAP" },
+    { RG_WATER_TEMPLE_MAP,          		"ITEM_DUNGEON_MAP" },
+    { RG_SPIRIT_TEMPLE_MAP,         		"ITEM_DUNGEON_MAP" },
+    { RG_SHADOW_TEMPLE_MAP,         		"ITEM_DUNGEON_MAP" },
+    { RG_BOTTOM_OF_THE_WELL_MAP,    		"ITEM_DUNGEON_MAP" },
+    { RG_ICE_CAVERN_MAP,            		"ITEM_DUNGEON_MAP" },
+    { RG_DEKU_TREE_COMPASS,         		"ITEM_COMPASS" },
+    { RG_DODONGOS_CAVERN_COMPASS,   		"ITEM_COMPASS" },
+    { RG_JABU_JABUS_BELLY_COMPASS,  		"ITEM_COMPASS" },
+    { RG_FOREST_TEMPLE_COMPASS,     		"ITEM_COMPASS" },
+    { RG_FIRE_TEMPLE_COMPASS,       		"ITEM_COMPASS" },
+    { RG_WATER_TEMPLE_COMPASS,      		"ITEM_COMPASS" },
+    { RG_SPIRIT_TEMPLE_COMPASS,     		"ITEM_COMPASS" },
+    { RG_SHADOW_TEMPLE_COMPASS,     		"ITEM_COMPASS" },
+    { RG_BOTTOM_OF_THE_WELL_COMPASS,		"ITEM_COMPASS" },
+    { RG_ICE_CAVERN_COMPASS,        		"ITEM_COMPASS" },
+    { RG_FOREST_TEMPLE_BOSS_KEY,    		"ITEM_KEY_BOSS" },
+    { RG_FIRE_TEMPLE_BOSS_KEY,      		"ITEM_KEY_BOSS" },
+    { RG_WATER_TEMPLE_BOSS_KEY,     		"ITEM_KEY_BOSS" },
+    { RG_SPIRIT_TEMPLE_BOSS_KEY,    		"ITEM_KEY_BOSS" },
+    { RG_SHADOW_TEMPLE_BOSS_KEY,    		"ITEM_KEY_BOSS" },
+    { RG_GANONS_CASTLE_BOSS_KEY,    		"ITEM_KEY_BOSS" },
+    { RG_FOREST_TEMPLE_SMALL_KEY,   		"ITEM_KEY_SMALL" },
+    { RG_FIRE_TEMPLE_SMALL_KEY,     		"ITEM_KEY_SMALL" },
+    { RG_WATER_TEMPLE_SMALL_KEY,    		"ITEM_KEY_SMALL" },
+    { RG_SPIRIT_TEMPLE_SMALL_KEY,   		"ITEM_KEY_SMALL" },
+    { RG_SHADOW_TEMPLE_SMALL_KEY,   		"ITEM_KEY_SMALL" },
+    { RG_BOTTOM_OF_THE_WELL_SMALL_KEY, 		"ITEM_KEY_SMALL" },
+    { RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY, "ITEM_KEY_SMALL" },
+    { RG_GERUDO_FORTRESS_SMALL_KEY, 		"ITEM_KEY_SMALL" },
+    { RG_GANONS_CASTLE_SMALL_KEY,   		"ITEM_KEY_SMALL" },
+    { RG_TREASURE_GAME_SMALL_KEY,   		"ITEM_KEY_SMALL" },
+    { RG_KOKIRI_EMERALD,            		"ITEM_KOKIRI_EMERALD" },
+    { RG_GORON_RUBY,                		"ITEM_GORON_RUBY" },
+    { RG_ZORA_SAPPHIRE,             		"ITEM_ZORA_SAPPHIRE" },
+    { RG_FOREST_MEDALLION,          		"ITEM_MEDALLION_FOREST" },
+    { RG_FIRE_MEDALLION,            		"ITEM_MEDALLION_FIRE" },
+    { RG_WATER_MEDALLION,           		"ITEM_MEDALLION_WATER" },
+    { RG_SPIRIT_MEDALLION,          		"ITEM_MEDALLION_SPIRIT" },
+    { RG_SHADOW_MEDALLION,          		"ITEM_MEDALLION_SHADOW" },
+    { RG_LIGHT_MEDALLION,           		"ITEM_MEDALLION_LIGHT" },
+    { RG_RECOVERY_HEART,            		"ITEM_HEART_GRAYSCALE" },
+    { RG_GREEN_RUPEE,               		"ITEM_RUPEE_GRAYSCALE" },
+    { RG_GREG_RUPEE,                		"ITEM_RUPEE_GRAYSCALE" },
+    { RG_BLUE_RUPEE,                		"ITEM_RUPEE_GRAYSCALE" },
+    { RG_RED_RUPEE,                 		"ITEM_RUPEE_GRAYSCALE" },
+    { RG_PURPLE_RUPEE,              		"ITEM_RUPEE_GRAYSCALE" },
+    { RG_HUGE_RUPEE,                		"ITEM_RUPEE_GRAYSCALE" },
+    { RG_TREASURE_GAME_GREEN_RUPEE,         "ITEM_RUPEE_GRAYSCALE" },
+    { RG_PIECE_OF_HEART,            		"ITEM_HEART_PIECE" },
+    { RG_HEART_CONTAINER,           		"ITEM_HEART_CONTAINER" },
+    { RG_ICE_TRAP,                  		"ITEM_ICE_TRAP" },
+    { RG_MILK,                              "ITEM_MILK_BOTTLE"},
+    { RG_BOMBS_5,                   		"ITEM_BOMB" },
+    { RG_BOMBS_10,                  		"ITEM_BOMB" },
+    { RG_BOMBS_20,                  		"ITEM_BOMB" },
+    { RG_BUY_BOMBS_525,              		"ITEM_BOMB" },
+    { RG_BUY_BOMBS_535,              		"ITEM_BOMB" },
+    { RG_BUY_BOMBS_10,              		"ITEM_BOMB" },
+    { RG_BUY_BOMBS_20,              		"ITEM_BOMB" },
+    { RG_BUY_BOMBS_30,                      "ITEM_BOMB" },
+    { RG_DEKU_NUTS_5,               		"ITEM_NUT" },
+    { RG_DEKU_NUTS_10,              		"ITEM_NUT" },
+    { RG_BUY_DEKU_NUTS_5,           		"ITEM_NUT" },
+    { RG_BUY_DEKU_NUTS_10,               	"ITEM_NUT" },
+    { RG_BOMBCHU_5,                 		"ITEM_BOMBCHU" },
+    { RG_BOMBCHU_10,                		"ITEM_BOMBCHU" },
+    { RG_BOMBCHU_20,                		"ITEM_BOMBCHU" },
+    { RG_BUY_BOMBCHUS_20,                 	"ITEM_BOMBCHU" },
+    { RG_ARROWS_5,                  		"ITEM_ARROWS_SMALL" },
+    { RG_BUY_ARROWS_10,                  	"ITEM_ARROWS_SMALL" },
+    { RG_ARROWS_10,                 		"ITEM_ARROWS_MEDIUM" },
+    { RG_BUY_ARROWS_30,                 	"ITEM_ARROWS_MEDIUM" },
+    { RG_ARROWS_30,                 		"ITEM_ARROWS_LARGE" },
+    { RG_BUY_ARROWS_50,                 	"ITEM_ARROWS_LARGE" },
+    { RG_TREASURE_GAME_HEART,       		"ITEM_HEART_PIECE" },
+    { RG_DEKU_SEEDS_30,             		"ITEM_SEEDS" },
+    { RG_BUY_DEKU_SEEDS_30,             	"ITEM_SEEDS" },
+    { RG_BUY_HEART,                         "ITEM_HEART_GRAYSCALE" },
+    { RG_FISHING_POLE,             	        "ITEM_FISHING_POLE" },
+    { RG_SOLD_OUT,                  		"ITEM_SOLD_OUT" },
+    { RG_TRIFORCE_PIECE,                  	"TRIFORCE_PIECE" },
+    { RG_SKELETON_KEY,                      "ITEM_KEY_SMALL" }
+};
+
+Rando::Item plandomizerRandoRetrieveItem(RandomizerGet randoGetItem) {
+    auto randoGetItemEntry = Rando::StaticData::RetrieveItem(randoGetItem);
+    return randoGetItemEntry;
+}
+
+ImVec4 plandomizerGetItemColor(Rando::Item randoItem) {
+    itemColor = ImVec4( 1.0f, 1.0f, 1.0f, 1.0f );
+    if (randoItem.GetItemType() == ITEMTYPE_SMALLKEY || randoItem.GetItemType() == ITEMTYPE_FORTRESS_SMALLKEY
+        || randoItem.GetItemType() == ITEMTYPE_BOSSKEY) {
+        if (randoItem.GetRandomizerGet() == RG_FOREST_TEMPLE_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_FOREST_TEMPLE_KEY_RING) {
+            itemColor = ImVec4( 0.02f, 0.76f, 0.18f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_FIRE_TEMPLE_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_FIRE_TEMPLE_KEY_RING) {
+            itemColor = ImVec4( 0.93f, 0.37f, 0.37f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_WATER_TEMPLE_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_WATER_TEMPLE_KEY_RING) {
+            itemColor = ImVec4( 0.33f, 0.71f, 0.87f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_SPIRIT_TEMPLE_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_SPIRIT_TEMPLE_KEY_RING) {
+            itemColor = ImVec4( 0.87f, 0.62f, 0.18f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_SHADOW_TEMPLE_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_SHADOW_TEMPLE_KEY_RING) {
+            itemColor = ImVec4( 0.49f, 0.06f, 0.69f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_BOTTOM_OF_THE_WELL_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_BOTTOM_OF_THE_WELL_KEY_RING) {
+            itemColor = ImVec4( 0.89f, 0.43f, 1.0f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_GERUDO_TRAINING_GROUNDS_KEY_RING) {
+            itemColor = ImVec4( 1.0f, 1.0f, 0, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_GERUDO_FORTRESS_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_GERUDO_FORTRESS_KEY_RING) {
+            itemColor = ImVec4( 1.0f, 1.0f, 1.0f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_GANONS_CASTLE_SMALL_KEY || 
+            randoItem.GetRandomizerGet() == RG_GANONS_CASTLE_KEY_RING) {
+            itemColor = ImVec4( 0.5f, 0.5f, 0.5f, 1.0f );
+        }
+        return itemColor;
+    }
+    if (randoItem.GetItemType() == ITEMTYPE_SONG) {
+        uint32_t questID = Rando::Logic::RandoGetToQuestItem[randoItem.GetRandomizerGet()];
+        textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(songMapping.at((QuestItem)questID).name);
+        itemColor = songMapping.at((QuestItem)questID).color;
+        imageSize = ImVec2(24.0f, 32.0f);
+        imagePadding = 6.0f;
+        return itemColor;
+    }
+    if (randoItem.GetRandomizerGet() >= RG_GREEN_RUPEE && randoItem.GetRandomizerGet() <= RG_HUGE_RUPEE) {
+        if (randoItem.GetRandomizerGet() == RG_GREG_RUPEE || randoItem.GetRandomizerGet() == RG_GREEN_RUPEE 
+            || randoItem.GetRandomizerGet() == RG_TREASURE_GAME_GREEN_RUPEE) {
+            itemColor = ImVec4( 0.02f, 0.76f, 0.18f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_BLUE_RUPEE) {
+            itemColor = ImVec4( 0.33f, 0.71f, 0.87f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_RED_RUPEE) {
+            itemColor = ImVec4( 0.93f, 0.37f, 0.37f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_PURPLE_RUPEE) {
+            itemColor = ImVec4( 0.89f, 0.43f, 1.0f, 1.0f );
+        } else if (randoItem.GetRandomizerGet() == RG_HUGE_RUPEE) {
+            itemColor = ImVec4( 1.0f, 1.0f, 0, 1.0f );
+        }
+        return itemColor;
+    }
+
+    if (randoItem.GetRandomizerGet() >= RG_GOHMA_SOUL && randoItem.GetRandomizerGet() <= RG_GANON_SOUL) {
+        itemColor = bossSoulMapping.at(randoItem.GetRandomizerGet());
+    }
+    
+    return itemColor;
+}
+
+std::string plandomizerHintsTooltip() {
+    std::string hintTootip;
+    hintTootip = 
+        "The following options are available:\n"
+        "- Use \\n to create New Lines.\n"
+        "- Use %g to change the text color to Green,\n"
+        " - %r for Red, %y for Yellow, and %w for White\n"
+        "   can also be used as color examples.";
+
+    return hintTootip;
+}
+
+std::string extractNumberInParentheses(const std::string& text) {
+    size_t start = text.find('(');
+    size_t end = text.find(')');
+
+    if (start != std::string::npos && end != std::string::npos && start < end) {
+        return text.substr(start + 1, end - start - 1);
+    }
+    return "";
+}
+
+void PlandomizerPopulateSeedList() {
+    existingSeedList.clear();
+    auto spoilerPath = Ship::Context::GetPathRelativeToAppDirectory("Randomizer");
+
+    for (const auto& entry : std::filesystem::directory_iterator(spoilerPath)) {
+        if (entry.is_regular_file() && entry.path().extension() == ".json") {
+            existingSeedList.push_back(entry.path().stem().string());
+        }
+    }
+}
+
+void PlandomizerItemImageCorrection(Rando::Item randoItem) {
+    textureID = 0;
+    imageSize = ImVec2( 32.0f, 32.0f );
+    imagePadding = 2.0f;
+    textureUV0 = ImVec2( 0, 0 );
+    textureUV1 = ImVec2( 1, 1 );
+    
+
+    itemColor = plandomizerGetItemColor(randoItem);
+
+    if (randoItem.GetItemType() == ITEMTYPE_SMALLKEY || randoItem.GetItemType() == ITEMTYPE_FORTRESS_SMALLKEY) {
+        textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ITEM_KEY_SMALL");
+        return;
+    }
+    if (randoItem.GetItemType() == ITEMTYPE_BOSSKEY) {
+        textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ITEM_KEY_BOSS");
+        return;
+    }
+
+    for (auto& map : itemImageMap) {
+        if (map.first == randoItem.GetRandomizerGet()) {
+            textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(map.second.c_str());
+            if (map.second.find("ITEM_ARROWS") != std::string::npos) {
+                textureUV0 = ImVec2( 0, 1 );
+                textureUV1 = ImVec2( 1, 0 );
+            }
+            if (map.second == "ITEM_TRIFORCE" || map.first == RG_SKELETON_KEY) {
+                textureUV0 = ImVec2( 1, 1 );
+                textureUV1 = ImVec2( 0, 0 );
+            }
+            break;
+        }
+    }
+
+    if (randoItem.GetRandomizerGet() >= RG_GOHMA_SOUL && randoItem.GetRandomizerGet() <= RG_GANON_SOUL) {
+        textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("BOSS_SOUL");
+    }
+
+    if (randoItem.GetRandomizerGet() >= RG_OCARINA_A_BUTTON && randoItem.GetRandomizerGet() <= RG_OCARINA_C_RIGHT_BUTTON) {
+        textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("ITEM_OCARINA_TIME");
+    }
+
+    if (textureID == 0) {
+        textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(itemMapping[randoItem.GetGIEntry()->itemId].name);
+    }
+}
+
+void PlandomizerRandomizeHint(int32_t status, int32_t index) {
+    if (status == HINT_SINGLE) {
+        plandoHintData[index].hintText = Rando::StaticData::hintTextTable[GetRandomJunkHint()].GetHintMessage().GetForCurrentLanguage(MF_ENCODE);
+    } else {
+        for (auto& hint : plandoHintData) {
+            hint.hintText = Rando::StaticData::hintTextTable[GetRandomJunkHint()].GetHintMessage().GetForCurrentLanguage(MF_ENCODE);
+        }
+    }
+}
+
+void PlandomizerRemoveAllHints() {
+    if (plandoHintData.size() > 0) {
+        for (auto& remove : plandoHintData) {
+            remove.hintText.clear();
+        }
+    }
+}
+
+void PlandomizerSortDrawnItems() {
+    std::sort(drawnItemsList.begin(), drawnItemsList.end(),
+      [](const auto& a, const auto& b) {
+        auto typeA = a.first.GetItemType();
+        auto typeB = b.first.GetItemType();
+        if (typeA != typeB){
+          return typeA < typeB;
+        }
+        return a.first.GetRandomizerGet() < b.first.GetRandomizerGet();
+      });
+}
+
+void PlandomizerRemoveAllItems() {
+    if (drawnItemsList.size() == 1) {
+        drawnItemsList.clear();
+    }
+    for (auto& remove : plandoLogData) {
+        if (std::find(infiniteItemList.begin(), infiniteItemList.end(), remove.checkRewardItem.GetRandomizerGet()) == infiniteItemList.end()) {
+            bool itemExists = false;
+            for (auto& itemToCheck : drawnItemsList) {
+                if (itemToCheck.first.GetRandomizerGet() == remove.checkRewardItem.GetRandomizerGet()) {
+                    itemToCheck.second += 1;
+                    itemExists = true;
+                    break;
+                }
+            }
+            if (!itemExists) {
+                drawnItemsList.push_back(std::make_pair(remove.checkRewardItem, 1));
+            }
+        }
+        remove.checkRewardItem = plandomizerRandoRetrieveItem(RG_SOLD_OUT);
+    }
+    PlandomizerSortDrawnItems();
+}
+
+void PlandomizerRemoveFromItemList(Rando::Item randoItem) {
+    if (std::find(infiniteItemList.begin(), infiniteItemList.end(), randoItem.GetRandomizerGet()) == infiniteItemList.end()) {
+        uint32_t index = 0;
+        for (auto& itemToCheck : drawnItemsList) {
+            if (itemToCheck.first.GetRandomizerGet() == randoItem.GetRandomizerGet()) {
+                if (shouldRemove) {
+                    drawnItemsList.erase(drawnItemsList.begin() + index);
+                    break;
+                } else {
+                    itemToCheck.second -= 1;
+                }
+            }
+            index++;
+        }
+        shouldRemove = false;
+    }
+    PlandomizerSortDrawnItems();
+}
+
+void PlandomizerAddToItemList(Rando::Item randoItem) {
+    if (std::find(infiniteItemList.begin(), infiniteItemList.end(), randoItem.GetRandomizerGet()) == infiniteItemList.end()) {
+        bool itemExists = false;
+        for (auto& itemToCheck : drawnItemsList) {
+            if (itemToCheck.first.GetRandomizerGet() == randoItem.GetRandomizerGet()) {
+                itemToCheck.second += 1;
+                itemExists = true;
+                break;
+            }
+        }
+        
+        if (!itemExists) {
+            drawnItemsList.push_back(std::make_pair(randoItem, 1));
+        }
+    }
+    PlandomizerSortDrawnItems();
+}
+
+void PlandomizerSaveSpoilerLog() {
+    nlohmann::json spoilerSave;
+    std::string filename = lastLoadedSpoiler;
+
+    std::ifstream inputFile(filename);
+    if (inputFile.is_open()) {
+        inputFile >> spoilerSave;
+        inputFile.close();
+    }
+
+    spoilerSave["file_hash"] = {
+        plandoHash[0], plandoHash[1], plandoHash[2], plandoHash[3], plandoHash[4]
+    };
+
+    for (auto& import : plandoHintData) {
+        spoilerSave["Gossip Stone Hints"][import.hintName] = {
+            { "type", import.hintType.c_str() },
+            { "message", import.hintText.c_str() }
+        };
+    }
+    
+    for (auto& import : plandoLogData) {
+        if (import.checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) {
+            spoilerSave["locations"][import.checkName] = {
+                { "item", import.checkRewardItem.GetName().english },
+                { "model", import.iceTrapModel.GetName().english },
+                { "trickName", import.iceTrapName.c_str() }
+            };
+            if (import.shopPrice > -1) {
+                spoilerSave["locations"][import.checkName]["price"] = import.shopPrice;
+            }
+        } else if (import.shopPrice > -1) {
+            spoilerSave["locations"][import.checkName] = {
+                { "item", import.checkRewardItem.GetName().english },
+                { "price", import.shopPrice }
+            };
+        } else {
+            spoilerSave["locations"][import.checkName] = import.checkRewardItem.GetName().english;
+        }
+    }
+
+    std::ofstream outputFile(filename);
+    if (outputFile.is_open()) {
+        outputFile << spoilerSave.dump(4);
+        outputFile.close();
+    }    
+}
+
+void PlandomizerLoadSpoilerLog(std::string logFile) {
+    spoilerHash.clear();
+    plandoHash.clear();
+    spoilerLogData.clear();
+    plandoLogData.clear();
+    spoilerHintData.clear();
+    plandoHintData.clear();
+    drawnItemsList.clear();
+
+    nlohmann::json spoilerLogInput;
+    auto spoilerPath = Ship::Context::GetPathRelativeToAppDirectory("Randomizer");
+    std::string spoilerStr = spoilerPath + "/" + logFile.c_str() + ".json";
+
+    if (!std::filesystem::exists(spoilerStr)) {
+        return;
+    }
+
+    std::ifstream file(spoilerStr);
+
+    if (file.is_open()) {
+        try {
+            file >> spoilerLogInput;
+            file.close();
+
+            if (spoilerLogInput.contains("file_hash")) {
+                auto hash = spoilerLogInput["file_hash"];
+                for (auto& load : hash) {
+                    spoilerHash.push_back(load);
+                    plandoHash.push_back(load);
+                }
+            }
+
+            if (spoilerLogInput.contains("Gossip Stone Hints")) {
+                auto hints = spoilerLogInput["Gossip Stone Hints"];
+                for (auto& [key, value] : hints.items()) {
+                    SpoilerHintObject hintObject;
+                    hintObject.hintName = key.c_str();
+                    hintObject.hintType = "Hardcoded Message";
+                    hintObject.hintText = value["message"];
+
+                    spoilerHintData.push_back(hintObject);
+                    plandoHintData.push_back(hintObject);
+                }
+            }
+
+            if (spoilerLogInput.contains("locations")) {
+                auto locations = spoilerLogInput["locations"];
+                for (auto& [key, value] : locations.items()) {
+                    if (key == "Ganon" || key == "Completed Triforce") {
+                        continue;
+                    }
+                    SpoilerCheckObject checkObject;
+                    checkObject.checkName = key;
+                    auto type = value;
+                    if (value.is_object()) {
+                        checkObject.checkRewardItem = plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value["item"]]);
+                        if (value["price"].is_number()) {
+                            checkObject.shopPrice = value["price"];
+                        } else {
+                            checkObject.shopPrice = -1;
+                        }
+                        if (checkObject.checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) {
+                            checkObject.iceTrapModel = plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value["model"]]);
+                            checkObject.iceTrapName = value["trickName"];
+                        }
+                    } else {
+                        checkObject.checkRewardItem = plandomizerRandoRetrieveItem(Rando::StaticData::itemNameToEnum[value.get<std::string>()]);
+                        checkObject.shopPrice = -1;
+                        if (checkObject.shopPrice == -1 
+                            && checkObject.checkRewardItem.GetName().english.find("Buy") != std::string::npos) {
+                            checkObject.shopPrice = checkObject.checkRewardItem.GetPrice();
+                        }
+                    }
+                    spoilerLogData.push_back(checkObject);
+                    plandoLogData.push_back(checkObject);
+                    PlandomizerAddToItemList(plandomizerRandoRetrieveItem(RG_SOLD_OUT));
+                }
+            }
+        } catch (nlohmann::json::parse_error& e) {
+            Notification::Emit({ .message = "Invalid Spoiler Log Format", .remainingTime = 10.0f });
+        }
+    }
+    lastLoadedSpoiler = spoilerStr;
+}
+
+void PlandomizerOverlayText(std::pair<Rando::Item, uint32_t> drawObject ) {
+    // Overlay the item count text on the existing button
+    ImVec2 imageMin = ImGui::GetItemRectMin();
+    ImVec2 imageMax = ImGui::GetItemRectMax();
+    ImVec2 textPos = ImVec2(imageMax.x - ImGui::CalcTextSize(std::to_string(drawObject.second).c_str()).x - 2,
+                            imageMax.y - ImGui::CalcTextSize(std::to_string(drawObject.second).c_str()).y - 2);
+
+    ImGui::SetCursorScreenPos(textPos);
+    ImGui::Text(std::to_string(drawObject.second).c_str());
+
+    // Overlay item info
+    if (drawObject.first.GetRandomizerGet() >= RG_PROGRESSIVE_HOOKSHOT && 
+        drawObject.first.GetRandomizerGet() <= RG_PROGRESSIVE_GORONSWORD) {
+        textPos = ImVec2(imageMin.x + 2, imageMin.y + 2);
+
+        ImGui::SetCursorScreenPos(textPos);
+        ImGui::Text("+");
+    }
+    if (extractNumberInParentheses(drawObject.first.GetName().english.c_str()) != "" && 
+        extractNumberInParentheses(drawObject.first.GetName().english.c_str()) != "WINNER" && 
+        extractNumberInParentheses(drawObject.first.GetName().english.c_str()) != "LOSER") {
+        textPos = ImVec2(imageMin.x + 2, imageMin.y + 2);
+
+        ImGui::SetCursorScreenPos(textPos);
+        std::string overlayText = "+";
+        overlayText += extractNumberInParentheses(drawObject.first.GetName().english.c_str());
+        ImGui::Text(overlayText.c_str());
+    }
+    if (drawObject.first.GetRandomizerGet() >= RG_FOREST_TEMPLE_BOSS_KEY && 
+        drawObject.first.GetRandomizerGet() <= RG_GANONS_CASTLE_BOSS_KEY) {
+        textPos = ImVec2(imageMin.x + 1, imageMin.y + 1);
+        ImGui::SetCursorScreenPos(textPos);
+        shortName = "";
+        for (auto& name : bossKeyShortNames) {
+            if (name.first == drawObject.first.GetRandomizerGet()) {
+                shortName = name.second;
+                break;
+            }
+        }
+        ImGui::Text(shortName.c_str());
+    }
+    if (drawObject.first.GetRandomizerGet() >= RG_OCARINA_A_BUTTON &&
+        drawObject.first.GetRandomizerGet() <= RG_OCARINA_C_RIGHT_BUTTON) {
+        textPos = ImVec2(imageMin.x + 1, imageMin.y + 1);
+        ImGui::SetCursorScreenPos(textPos);
+        shortName = "";
+        for (auto& name : ocarinaButtonNames) {
+            if (name.first == drawObject.first.GetRandomizerGet()) {
+                shortName = name.second;
+                break;
+            }
+        }
+        ImGui::Text(shortName.c_str());
+    }
+}
+
+void PlandomizerDrawItemPopup(uint32_t index) {
+    if (shouldPopup && ImGui::BeginPopup("ItemList")) {
+        ImGui::SeparatorText("Resources");
+        ImGui::BeginTable("Infinite Item Table", 7);
+        for (auto& item : infiniteItemList) {
+            ImGui::PushID(item);
+            ImGui::TableNextColumn();
+            PlandomizerItemImageCorrection(plandomizerRandoRetrieveItem(item));
+            if (ImGui::ImageButton(textureID,
+                    imageSize, textureUV0, textureUV1, imagePadding, ImVec4(0, 0, 0, 0), itemColor)) {
+                if (std::find(infiniteItemList.begin(), infiniteItemList.end(), plandoLogData[index].checkRewardItem.GetRandomizerGet()) == infiniteItemList.end()) {
+                    PlandomizerAddToItemList(plandoLogData[index].checkRewardItem);
+                }
+                plandoLogData[index].checkRewardItem = plandomizerRandoRetrieveItem(item);
+                ImGui::CloseCurrentPopup();
+            }
+            UIWidgets::Tooltip(plandomizerRandoRetrieveItem(item).GetName().english.c_str());
+            PlandomizerOverlayText(std::make_pair(plandomizerRandoRetrieveItem(item), 1));
+            ImGui::PopID();
+        }
+        
+        
+        ImGui::EndTable();
+        ImGui::SeparatorText("Spoiler Log Rewards");
+        ImGui::BeginTable("Item Button Table", 8);
+        uint32_t itemIndex = 0;
+
+        bool isClicked = false;
+        for (auto& drawSlots : drawnItemsList) {
+            ImGui::TableNextColumn();
+            ImGui::BeginGroup();
+            ImGui::PushID(itemIndex);
+            auto itemToDraw = drawSlots.first;
+            PlandomizerItemImageCorrection(drawSlots.first);
+            if (ImGui::ImageButton(textureID,
+                    imageSize, textureUV0, textureUV1, imagePadding, ImVec4(0, 0, 0, 0), itemColor)) {
+                if (itemToDraw.GetRandomizerGet() >= RG_PROGRESSIVE_HOOKSHOT && 
+                    itemToDraw.GetRandomizerGet() <= RG_PROGRESSIVE_GORONSWORD) {
+                    plandoLogData[index].checkRewardItem = drawSlots.first;
+                } else {
+                    plandoLogData[index].checkRewardItem = itemToDraw;
+                }
+                temporaryItemIndex = itemIndex;
+                if (drawSlots.second == 1) {
+                    shouldRemove = true;
+                }
+                isClicked = true;
+                ImGui::CloseCurrentPopup();
+            }
+            if (!isClicked) {
+                UIWidgets::Tooltip(drawSlots.first.GetName().english.c_str());
+            }
+            ImGui::PopID();
+
+            PlandomizerOverlayText(drawSlots);
+
+            ImGui::EndGroup();
+            itemIndex++;
+        }
+        if (isClicked) {
+            PlandomizerRemoveFromItemList(drawnItemsList[temporaryItemIndex].first);
+            PlandomizerAddToItemList(temporaryItem);
+        }
+        ImGui::EndTable();
+        ImGui::EndPopup();
+    }
+}
+
+void PlandomizerDrawIceTrapPopUp(uint32_t index) {
+    if (shouldTrapPopup && ImGui::BeginPopup("TrapList")) {
+        ImGui::BeginTable("Ice Trap Table", 8);
+        for (auto& items : itemImageMap) {
+            if (items.first == RG_ICE_TRAP) {
+                continue;
+            }
+            ImGui::TableNextColumn();
+            ImGui::PushID(items.first);
+            PlandomizerItemImageCorrection(Rando::StaticData::RetrieveItem(items.first));
+            if (ImGui::ImageButton(textureID, imageSize, textureUV0, textureUV1, imagePadding, ImVec4(0, 0, 0, 0), itemColor)) {
+                plandoLogData[index].iceTrapModel = Rando::StaticData::RetrieveItem(items.first);
+                ImGui::CloseCurrentPopup();
+            };
+            UIWidgets::Tooltip(Rando::StaticData::RetrieveItem(items.first).GetName().english.c_str());
+
+            auto itemObject = Rando::StaticData::RetrieveItem(items.first);
+            PlandomizerOverlayText(std::make_pair(itemObject, 1));
+
+            ImGui::PopID();
+        }
+        ImGui::EndTable();
+        ImGui::EndPopup();
+    }
+}
+
+void PlandomizerDrawItemSlots(uint32_t index) {
+    ImGui::PushID(index);
+    PlandomizerItemImageCorrection(plandoLogData[index].checkRewardItem);
+    if (ImGui::ImageButton(textureID, imageSize, textureUV0, textureUV1, imagePadding, ImVec4(0, 0, 0, 0), itemColor)) {
+        shouldPopup = true;
+        temporaryItem = plandoLogData[index].checkRewardItem;
+        ImGui::OpenPopup("ItemList");
+    };
+    UIWidgets::Tooltip(plandoLogData[index].checkRewardItem.GetName().english.c_str());
+    PlandomizerOverlayText(std::make_pair(plandoLogData[index].checkRewardItem, 1));
+    PlandomizerDrawItemPopup(index);
+    ImGui::PopID();
+}
+
+void PlandomizerDrawShopSlider(uint32_t index) {
+    ImGui::PushID(index);
+    ImGui::Text("Price:");
+    ImGui::SameLine();
+    ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - 20.0f);
+    ImGui::SliderInt("", &plandoLogData[index].shopPrice, 0, 999, "%d Rupees");
+    ImGui::PopItemWidth();
+    ImGui::PopID();
+}
+
+void PlandomizerDrawIceTrapSetup(uint32_t index) {
+    std::string trapTextInput = plandoLogData[index].iceTrapName.c_str();
+
+    ImGui::PushID(index);
+    ImGui::BeginTable("IceTrap", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInner);
+    ImGui::TableSetupColumn("Model", ImGuiTableColumnFlags_WidthFixed, 36.0f);
+    ImGui::TableSetupColumn("Trap Options");
+    ImGui::TableHeadersRow();
+
+    ImGui::TableNextColumn();
+    PlandomizerItemImageCorrection(plandoLogData[index].iceTrapModel);
+    if (ImGui::ImageButton(textureID, imageSize, textureUV0, textureUV1, imagePadding, ImVec4(0, 0, 0, 0), itemColor)) {
+        shouldTrapPopup = true;
+        ImGui::OpenPopup("TrapList");
+    };
+    UIWidgets::Tooltip(plandoLogData[index].iceTrapModel.GetName().english.c_str());
+    PlandomizerDrawIceTrapPopUp(index);
+    ImGui::SameLine();
+    ImGui::TableNextColumn();
+    ImGui::Text("Name: ");
+    ImGui::SameLine();
+    if (plandoLogData[index].iceTrapModel.GetRandomizerGet() != RG_NONE && 
+        plandoLogData[index].iceTrapModel.GetRandomizerGet() != RG_SOLD_OUT) {
+        if (ImGui::Button(randomizeButton.c_str())) {
+            plandoLogData[index].iceTrapName = 
+                GetIceTrapName(plandoLogData[index].iceTrapModel.GetRandomizerGet()).GetForLanguage(CVarGetInteger(CVAR_SETTING("Languages"), 0)).c_str();
+        }
+        ImGui::SameLine();
+    }
+    if (UIWidgets::InputString("##TrapName", &trapTextInput)) {
+            plandoLogData[index].iceTrapName = trapTextInput.c_str();
+        }
+    
+    if (plandoLogData[index].shopPrice > -1) {
+        PlandomizerDrawShopSlider(index);
+    }
+    ImGui::EndTable();
+    
+    ImGui::PopID();
+}
+
+void PlandomizerDrawOptions() {
+    ImGui::BeginTable("LoadSpoiler", 2);
+    ImGui::TableNextColumn();
+    ImGui::SeparatorText("Load/Save Spoiler Log");
+    PlandomizerPopulateSeedList();
+    static int32_t selectedList = 0;
+    if (existingSeedList.size() != 0) {
+        if (ImGui::BeginCombo("##JsonFiles", existingSeedList[selectedList].c_str())) {
+            for (size_t i = 0; i < existingSeedList.size(); i++) {
+                bool isSelected = (selectedList == i);
+                if (ImGui::Selectable(existingSeedList[i].c_str(), isSelected)) {
+                    selectedList = i;
+                }
+                if (isSelected) {
+                    ImGui::SetItemDefaultFocus();
+                }
+            }
+            ImGui::EndCombo();
+        }
+    } else {
+        ImGui::Text("No Spoiler Logs found.");
+    }
+
+    if (ImGui::Button("Load")) {
+        logTemp = existingSeedList[selectedList].c_str();
+        PlandomizerLoadSpoilerLog(logTemp.c_str());
+    }
+    ImGui::SameLine();
+    if (ImGui::Button("Save")) {
+        PlandomizerSaveSpoilerLog();
+    }
+
+    ImGui::TableNextColumn();
+    ImGui::SeparatorText("Current Seed Hash");
+    ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (ImGui::GetContentRegionAvail().x * 0.5f) - (34.0f * 5.0f));
+    if (spoilerLogData.size() > 0) {
+        ImGui::BeginTable("HashIcons", 5);
+        ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
+        ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f));
+        ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.1f));
+        for (int i = 0; i < 5; i++) {
+            ImGui::TableSetupColumn("Icon", ImGuiTableColumnFlags_WidthFixed, 34.0f);
+        }
+        ImGui::TableNextColumn();
+    
+        int32_t index = 0;
+        for (auto& hash : plandoHash) {
+            ImGui::PushID(index);
+            textureID = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(gSeedTextures[hash].tex);
+            if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("HASH_ARROW_UP"), 
+                ImVec2(35.0f, 18.0f), ImVec2(1, 1), ImVec2(0, 0), 2.0f, ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1))) {
+                if (hash + 1 >= gSeedTextures.size()) {
+                    hash = 0;
+                } else {
+                    hash++;
+                }
+            }
+            ImGui::Image(textureID, ImVec2(35.0f, 35.0f));
+            if (ImGui::ImageButton(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName("HASH_ARROW_DWN"), 
+                ImVec2(35.0f, 18.0f), ImVec2(0, 0), ImVec2(1, 1), 2.0f, ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1))) {
+                if (hash == 0) {
+                    hash = gSeedTextures.size() - 1;
+                } else {
+                    hash--;
+                }
+            }
+            if (index != spoilerHash.size() - 1) {
+                ImGui::TableNextColumn();
+            }
+            ImGui::PopID();
+            index++;
+        }
+        ImGui::PopStyleColor(3);
+        ImGui::EndTable();
+    } else {
+        ImGui::Text("No Spoiler Log Loaded");
+    }
+    ImGui::EndTable();
+    
+    ImGui::SeparatorText("Options");
+    if (plandoLogData.size() == 0) {
+        ImGui::Text("Please Load Spoiler Data...");
+        return;
+    }
+
+    if (getTabID == TAB_HINTS) {
+        if (ImGui::Button("Clear All Hints")) {
+            PlandomizerRemoveAllHints();
+        }
+        ImGui::SameLine();
+        if (ImGui::Button("Randomize All Hints")) {
+            PlandomizerRandomizeHint(HINT_ALL, 0);
+        }
+    }
+    if (getTabID == TAB_LOCATIONS) {
+        if (plandoLogData.size() > 0) {
+            const char* comboLabel = rcAreaNames[selectedArea].c_str();
+            if (selectedArea == RCAREA_INVALID) {
+                comboLabel = "All";
+            }
+            ImGui::Text("Filter by Area:");
+            ImGui::SameLine();
+            ImGui::PushItemWidth(300.0f);
+            if (ImGui::BeginCombo("##AreaFilter", comboLabel)) {
+                for (const auto& [area, name] : rcAreaNames) {
+                    bool isSelected = (selectedArea == area);
+
+                    const char* displayName = name.c_str();
+                    if (area == RCAREA_INVALID) {
+                        displayName = "All";
+                    }
+                    if (ImGui::Selectable(displayName, isSelected)) {
+                        selectedArea = area;
+                    }
+                    if (isSelected) {
+                        ImGui::SetItemDefaultFocus();
+                    }
+                }
+                ImGui::EndCombo();
+            }
+            ImGui::PopItemWidth();
+    
+            ImGui::SameLine();
+            if (ImGui::Button("Empty All Rewards")) {
+                PlandomizerRemoveAllItems();
+            }
+        }
+    }
+}
+
+void PlandomizerDrawHintsWindow() {
+    uint32_t index = 0;
+    std::string hintInputText;
+
+    ImGui::BeginChild("Hints");
+    ImGui::BeginTable("Hints Window", 1, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY);
+    ImGui::TableSetupColumn("Hint Entries");
+    ImGui::TableSetupScrollFreeze(0, 1);
+    ImGui::TableHeadersRow();
+    
+    for (auto& hintData : spoilerHintData) {
+        ImGui::PushID(index);
+        ImGui::TableNextColumn();
+        ImGui::SeparatorText(hintData.hintName.c_str());
+        ImGui::Text("Current Hint: ");
+        ImGui::SameLine();
+        ImGui::TextWrapped(hintData.hintText.c_str());
+
+        if (spoilerHintData.size() > 0) {
+            hintInputText = plandoHintData[index].hintText.c_str();
+        }
+        ImGui::Text("New Hint:     ");
+        ImGui::SameLine();
+        if (ImGui::Button(randomizeButton.c_str())) {
+            PlandomizerRandomizeHint(HINT_SINGLE, index);
+        }
+        UIWidgets::Tooltip("Randomize Hint");
+        ImGui::SameLine();
+        ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 10);
+        if (UIWidgets::InputString("##HintMessage", &hintInputText)) {
+            plandoHintData[index].hintText = hintInputText.c_str();
+        }
+        UIWidgets::Tooltip(plandomizerHintsTooltip().c_str());
+        index++;
+        ImGui::PopID();
+    }
+
+    ImGui::EndTable();
+    ImGui::EndChild();
+}
+
+void PlandomizerDrawLocationsWindow(RandomizerCheckArea rcArea) {
+    uint32_t index = 0;
+    ImGui::BeginChild("Locations");
+    ImGui::BeginTable("Locations Window", 4, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_ScrollY);
+    ImGui::TableSetupColumn("Spoiler Log Check Name", ImGuiTableColumnFlags_WidthFixed, 250.0f);
+    ImGui::TableSetupColumn("Spoiler Log Reward", ImGuiTableColumnFlags_WidthFixed, 190.0f);
+    ImGui::TableSetupColumn("New Reward", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHeaderLabel, 34.0f);
+    ImGui::TableSetupColumn("Additional Options");
+    ImGui::TableSetupScrollFreeze(0, 1);
+    ImGui::TableHeadersRow();
+    ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
+    ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 1.0f, 1.0f, 0.2f));
+    ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.0f, 1.0f, 1.0f, 0.1f));
+
+    for (auto& spoilerData : spoilerLogData) {
+        auto checkID = Rando::StaticData::locationNameToEnum[spoilerData.checkName];
+        auto randoArea = Rando::StaticData::GetLocation(checkID)->GetArea();
+        if (rcArea == RCAREA_INVALID || rcArea == randoArea) {
+            ImGui::TableNextColumn();
+            ImGui::TextWrapped(spoilerData.checkName.c_str());
+            ImGui::TableNextColumn();
+            ImGui::TextWrapped(spoilerData.checkRewardItem.GetName().english.c_str());
+            ImGui::TableNextColumn();
+            PlandomizerDrawItemSlots(index);
+            if (plandoLogData[index].checkRewardItem.GetRandomizerGet() == RG_ICE_TRAP) {
+                ImGui::TableNextColumn();
+                PlandomizerDrawIceTrapSetup(index);
+            } else if (spoilerData.shopPrice != -1) {
+                ImGui::TableNextColumn();
+                ImGui::BeginTable("Shops", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInner);
+                ImGui::TableSetupColumn("Shop Price");
+                ImGui::TableHeadersRow();
+                ImGui::TableNextColumn();
+                PlandomizerDrawShopSlider(index);
+                ImGui::EndTable();
+            } else {
+                ImGui::TableNextColumn();
+            }
+        }
+        index++;
+    }
+    ImGui::PopStyleColor(3);
+    ImGui::EndTable();
+    ImGui::EndChild();
+}
+
+void PlandomizerDrawSpoilerTable() {
+    ImGui::BeginChild("Main");
+    if (ImGui::BeginTabBar("Check Tabs")) {
+        if (ImGui::BeginTabItem("Gossip Stones")) {
+            getTabID = TAB_HINTS;
+            PlandomizerDrawHintsWindow();
+            ImGui::EndTabItem();
+        }
+        if (ImGui::BeginTabItem("Locations")) {
+            getTabID = TAB_LOCATIONS;
+            PlandomizerDrawLocationsWindow(selectedArea);
+            ImGui::EndTabItem();
+        }
+    }
+    ImGui::EndTabBar();
+    ImGui::EndChild();
+}
+
+void PlandomizerWindow::DrawElement() {
+    PlandomizerDrawOptions();
+    UIWidgets::PaddedSeparator();
+    PlandomizerDrawSpoilerTable();
+}
+
+void PlandomizerWindow::InitElement() {
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_RUPEE_GRAYSCALE", gRupeeCounterIconTex, ImVec4(1, 1, 1, 1));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_HEART_GRAYSCALE", gHeartFullTex, ImVec4(0.87f, 0.10f, 0.10f, 1));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_SEEDS", gItemIconDekuSeedsTex, ImVec4( 1, 1, 1, 1 ));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_SMALL", gDropArrows1Tex, ImVec4( 1, 1, 1, 1 ));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_MEDIUM", gDropArrows2Tex, ImVec4( 1, 1, 1, 1 ));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ARROWS_LARGE", gDropArrows3Tex, ImVec4( 1, 1, 1, 1 ));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("ITEM_ICE_TRAP", gMagicArrowEquipEffectTex, ImVec4( 1, 1, 1, 1 ));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("HASH_ARROW_UP", gEmptyCDownArrowTex, ImVec4( 1, 1, 1, 1 ));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("HASH_ARROW_DWN", gEmptyCDownArrowTex, ImVec4( 1, 1, 1, 1 ));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("BOSS_SOUL", gBossSoulTex, ImVec4(1, 1, 1, 1));
+    Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture("TRIFORCE_PIECE", gTriforcePieceTex, ImVec4(1, 1, 1, 1));
+}
diff --git a/soh/soh/Enhancements/randomizer/Plandomizer.h b/soh/soh/Enhancements/randomizer/Plandomizer.h
new file mode 100644
index 000000000..d337e4da6
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/Plandomizer.h
@@ -0,0 +1,52 @@
+#pragma once
+#ifndef PLANDOMIZER_H
+#define PLANDOMIZER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PLANDOMIZER_H
+
+#include <libultraship/libultraship.h>
+#include "soh/Enhancements/randomizer/item.h"
+
+#ifdef __cplusplus
+class PlandomizerWindow : public Ship::GuiWindow {
+  public:
+    using GuiWindow::GuiWindow;
+
+    void InitElement() override;
+    void DrawElement() override;
+    void UpdateElement() override{};
+};
+
+typedef struct {
+    std::string checkName;
+    Rando::Item checkRewardItem;
+    int32_t shopPrice;
+    Rando::Item iceTrapModel;
+    std::string iceTrapName;
+} SpoilerCheckObject;
+
+typedef struct {
+    std::string hintName;
+    std::string hintType;
+    std::string hintText;
+} SpoilerHintObject;
+
+typedef enum {
+    TAB_HINTS,
+    TAB_LOCATIONS
+};
+
+typedef enum {
+    HINT_SINGLE,
+    HINT_ALL,
+};
+
+#endif
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/rando_hash.h b/soh/soh/Enhancements/randomizer/rando_hash.h
index 76c3ce0a3..3fdcd205e 100644
--- a/soh/soh/Enhancements/randomizer/rando_hash.h
+++ b/soh/soh/Enhancements/randomizer/rando_hash.h
@@ -10,7 +10,7 @@
 #include <textures/icon_item_static/icon_item_static.h>
 #include <textures/icon_item_24_static/icon_item_24_static.h>
 
-std::array<Sprite, 100> gSeedTextures = { {
+inline std::array<Sprite, 100> gSeedTextures = { {
     { dgItemIconDekuNutTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 0 },
     { dgItemIconDekuStickTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 1 },
     { dgItemIconBombTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b, 2 },
diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h
index 4cda80c37..fe8910c6d 100644
--- a/soh/soh/Enhancements/randomizer/randomizerTypes.h
+++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h
@@ -2627,6 +2627,35 @@ typedef enum {
     RHT_JUNK_SG_6,
     RHT_JUNK_SG_7,
     RHT_JUNK_SG_8,
+    RHT_JUNK_CREW_1,
+    RHT_JUNK_CREW_2,
+    RHT_JUNK_CREW_3,
+    RHT_JUNK_CREW_4,
+    RHT_JUNK_CREW_5,
+    RHT_JUNK_CREW_6,
+    RHT_JUNK_CREW_7,
+    RHT_JUNK_CREW_8,
+    RHT_JUNK_CREW_9,
+    RHT_JUNK_CREW_10,
+    RHT_JUNK_CREW_11,
+    RHT_JUNK_CREW_12,
+    RHT_JUNK_CREW_13,
+    RHT_JUNK_CREW_14,
+    RHT_JUNK_CREW_15,
+    RHT_JUNK_CREW_16,
+    RHT_JUNK_CREW_17,
+    RHT_JUNK_CREW_18,
+    RHT_JUNK_CREW_19,
+    RHT_JUNK_CREW_20,
+    RHT_JUNK_CREW_21,
+    RHT_JUNK_CREW_22,
+    RHT_JUNK_CREW_23,
+    RHT_JUNK_CREW_24,
+    RHT_JUNK_CREW_25,
+    RHT_JUNK_CREW_26,
+    RHT_JUNK_CREW_27,
+    RHT_JUNK_CREW_28,
+    RHT_JUNK_CREW_29,
     // Locations
     RHT_LINKS_POCKET,
     RHT_QUEEN_GOHMA,
diff --git a/soh/soh/ImGuiUtils.cpp b/soh/soh/ImGuiUtils.cpp
index 11ad464e8..bfe1293d5 100644
--- a/soh/soh/ImGuiUtils.cpp
+++ b/soh/soh/ImGuiUtils.cpp
@@ -1,6 +1,7 @@
 #include "ImGuiUtils.h"
 #include <Context.h>
 #include "assets/soh_assets.h"
+#include "soh/Enhancements/randomizer/rando_hash.h"
 
 std::map<uint32_t, ItemMapEntry> itemMapping = {
     ITEM_MAP_ENTRY(ITEM_STICK),
@@ -150,7 +151,7 @@ std::map<uint32_t, QuestMapEntry> questMapping = {
     QUEST_MAP_ENTRY(QUEST_SKULL_TOKEN, dgQuestIconGoldSkulltulaTex),
 };
 
-std::array<SongMapEntry, 12> songMapping = { {
+std::map<QuestItem, SongMapEntry> songMapping = {
     SONG_MAP_ENTRY(QUEST_SONG_LULLABY,  224, 107, 255),
     SONG_MAP_ENTRY(QUEST_SONG_EPONA,    255, 195, 60),
     SONG_MAP_ENTRY(QUEST_SONG_SARIA,    127, 255, 137),
@@ -163,7 +164,7 @@ std::array<SongMapEntry, 12> songMapping = { {
     SONG_MAP_ENTRY(QUEST_SONG_REQUIEM,  255, 160, 0),
     SONG_MAP_ENTRY(QUEST_SONG_NOCTURNE, 255, 100, 255),
     SONG_MAP_ENTRY(QUEST_SONG_PRELUDE,  255, 240, 100),
-} };
+};
 
 std::array<SongMapEntry, 12> vanillaSongMapping = { {
     VANILLA_SONG_MAP_ENTRY(QUEST_SONG_LULLABY,  255, 255, 255),
@@ -212,7 +213,7 @@ void RegisterImGuiItemIcons() {
         Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, ImVec4(1, 1, 1, 0.3f));
     }
 
-    for (const auto& entry : songMapping) {
+    for (const auto& [quest, entry] : songMapping) {
         Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.name, gSongNoteTex, entry.color);
         ImVec4 fadedCol = entry.color;
         fadedCol.w = 0.3f;
@@ -225,4 +226,8 @@ void RegisterImGuiItemIcons() {
         fadedCol.w = 0.3f;
         Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.nameFaded, gSongNoteTex, fadedCol);
     }
+
+    for (const auto& entry : gSeedTextures) {
+        Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadGuiTexture(entry.tex, entry.tex, ImVec4(1, 1, 1, 1));
+    }
 }
\ No newline at end of file
diff --git a/soh/soh/ImGuiUtils.h b/soh/soh/ImGuiUtils.h
index c5545ba74..ed735713a 100644
--- a/soh/soh/ImGuiUtils.h
+++ b/soh/soh/ImGuiUtils.h
@@ -67,11 +67,11 @@ typedef struct {
 
 #define SONG_MAP_ENTRY(id, r, g, b) \
     {                               \
-            id, #id, #id "_Faded", ImVec4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f) \
+            id, { id, #id, #id "_Faded", ImVec4(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f) } \
     }
 
 // Maps song ids to info for use in ImGui
-extern std::array<SongMapEntry, 12> songMapping;
+extern std::map<QuestItem, SongMapEntry> songMapping;
 
 #define VANILLA_SONG_MAP_ENTRY(id, r, g, b) \
     {                                       \
diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp
index c70f544b0..19b8639de 100644
--- a/soh/soh/SohGui.cpp
+++ b/soh/soh/SohGui.cpp
@@ -131,6 +131,7 @@ namespace SohGui {
     std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
     std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
     std::shared_ptr<TimeSplitWindow> mTimeSplitWindow;
+    std::shared_ptr<PlandomizerWindow> mPlandomizerWindow;
     std::shared_ptr<RandomizerSettingsWindow> mRandomizerSettingsWindow;
     std::shared_ptr<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow> mAdvancedResolutionSettingsWindow;
     std::shared_ptr<SohModalWindow> mModalWindow;
@@ -210,6 +211,8 @@ namespace SohGui {
         gui->AddGuiWindow(mRandomizerSettingsWindow);
         mTimeSplitWindow = std::make_shared<TimeSplitWindow>(CVAR_WINDOW("TimeSplitEnabled"), "Time Splits", ImVec2(450, 660));
         gui->AddGuiWindow(mTimeSplitWindow);
+        mPlandomizerWindow = std::make_shared<PlandomizerWindow>(CVAR_WINDOW("PlandomizerWindow"), "Plandomizer Editor", ImVec2(850, 760));
+        gui->AddGuiWindow(mPlandomizerWindow);
         mAdvancedResolutionSettingsWindow = std::make_shared<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow>(CVAR_WINDOW("AdvancedResolutionEditor"), "Advanced Resolution Settings", ImVec2(497, 599));
         gui->AddGuiWindow(mAdvancedResolutionSettingsWindow);
         mModalWindow = std::make_shared<SohModalWindow>(CVAR_WINDOW("ModalWindow"), "Modal Window");
@@ -252,6 +255,7 @@ namespace SohGui {
         mInputViewer = nullptr;
         mInputViewerSettings = nullptr;
         mTimeSplitWindow = nullptr;
+        mPlandomizerWindow = nullptr;
     }
 
     void RegisterPopup(std::string title, std::string message, std::string button1, std::string button2, std::function<void()> button1callback, std::function<void()> button2callback) {
diff --git a/soh/soh/SohGui.hpp b/soh/soh/SohGui.hpp
index 1c8eecb79..5502b6757 100644
--- a/soh/soh/SohGui.hpp
+++ b/soh/soh/SohGui.hpp
@@ -25,6 +25,7 @@
 #include "Enhancements/randomizer/randomizer_item_tracker.h"
 #include "Enhancements/randomizer/randomizer_settings_window.h"
 #include "Enhancements/timesplits/TimeSplits.h"
+#include "Enhancements/randomizer/Plandomizer.h"
 #include "SohModals.h"
 
 #ifdef __cplusplus
diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp
index 71336671b..beadebfae 100644
--- a/soh/soh/SohMenuBar.cpp
+++ b/soh/soh/SohMenuBar.cpp
@@ -41,6 +41,7 @@
 #include "Enhancements/resolution-editor/ResolutionEditor.h"
 #include "Enhancements/enemyrandomizer.h"
 #include "Enhancements/timesplits/TimeSplits.h"
+#include "Enhancements/randomizer/Plandomizer.h"
 
 // FA icons are kind of wonky, if they worked how I expected them to the "+ 2.0f" wouldn't be needed, but
 // they don't work how I expect them to so I added that because it looked good when I eyeballed it
@@ -2046,6 +2047,7 @@ extern std::shared_ptr<EntranceTrackerWindow> mEntranceTrackerWindow;
 extern std::shared_ptr<EntranceTrackerSettingsWindow> mEntranceTrackerSettingsWindow;
 extern std::shared_ptr<CheckTracker::CheckTrackerWindow> mCheckTrackerWindow;
 extern std::shared_ptr<CheckTracker::CheckTrackerSettingsWindow> mCheckTrackerSettingsWindow;
+extern std::shared_ptr<PlandomizerWindow> mPlandomizerWindow;
 extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey);
 
 void DrawRandomizerMenu() {
@@ -2075,6 +2077,14 @@ void DrawRandomizerMenu() {
         static float separationToOptionsButton = 5.0f;
     #endif
 
+        if (mPlandomizerWindow) {
+            if (ImGui::Button(GetWindowButtonText("Plandomizer Editor", CVarGetInteger(CVAR_WINDOW("PlandomizerWindow"), 0)).c_str(), buttonSize)) {
+                mPlandomizerWindow->ToggleVisibility();
+            }
+        }
+
+        UIWidgets::Spacer(0);
+
         if (mRandomizerSettingsWindow) {
             if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVarGetInteger(CVAR_WINDOW("RandomizerSettings"), 0)).c_str(), buttonSize)) {
                 mRandomizerSettingsWindow->ToggleVisibility();