From b43f77cabafb21934ed4e600513a49d2645d0a1e Mon Sep 17 00:00:00 2001 From: aMannus Date: Fri, 26 Aug 2022 09:56:34 +0200 Subject: [PATCH 01/52] Columns in childs & code style changes --- .../Enhancements/randomizer/randomizer.cpp | 737 ++++++++++-------- 1 file changed, 414 insertions(+), 323 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 2e73b3ed0..25b7ab873 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3185,7 +3185,7 @@ void DrawRandoEditor(bool& open) { "Timer", "Zelda Gasp (Adult)" }; - ImGui::SetNextWindowSize(ImVec2(830, 600), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(920, 563), ImGuiCond_FirstUseEver); if (!ImGui::Begin("Randomizer Editor", &open, ImGuiWindowFlags_NoFocusOnAppearing)) { ImGui::End(); return; @@ -3232,294 +3232,339 @@ void DrawRandoEditor(bool& open) { // COLUMN 1 - OPEN SETTINGS ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildOpenSettings", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); - if (CVar_GetS32("gRandomizeAllOpenSettings", 0) != 1) { - // Forest - ImGui::Text(Settings::OpenForest.GetName().c_str()); - InsertHelpHoverText("Closed - Kokiri sword & shield are required to access " - "the Deku Tree, and completing the Deku Tree is required to " - "access the Hyrule Field exit.\n" - "\n" - "Closed Deku - Kokiri boy no longer blocks the path to Hyrule " - "Field but Mido still requires the Kokiri sword and Deku shield " - "to access the tree.\n" - "\n" - "Open - Mido no longer blocks the path to the Deku Tree. Kokiri " - "boy no longer blocks the path out of the forest."); - SohImGui::EnhancementCombobox("gRandomizeForest", randoForest, 3, 0); - PaddedSeparator(); - // Kakariko Gate - ImGui::Text(Settings::OpenKakariko.GetName().c_str()); - InsertHelpHoverText("Closed - The gate will remain closed until Zelda's letter " - "is shown to the guard.\n" - "\n" - "Open - The gate is always open. The happy mask shop " - "will open immediately after obtaining Zelda's letter."); - SohImGui::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 0); - PaddedSeparator(); + // Forest + ImGui::Text(Settings::OpenForest.GetName().c_str()); + InsertHelpHoverText( + "Closed - Kokiri sword & shield are required to access " + "the Deku Tree, and completing the Deku Tree is required to " + "access the Hyrule Field exit.\n" + "\n" + "Closed Deku - Kokiri boy no longer blocks the path to Hyrule " + "Field but Mido still requires the Kokiri sword and Deku shield " + "to access the tree.\n" + "\n" + "Open - Mido no longer blocks the path to the Deku Tree. Kokiri " + "boy no longer blocks the path out of the forest." + ); + SohImGui::EnhancementCombobox("gRandomizeForest", randoForest, 3, 0); - // Door of Time - ImGui::Text(Settings::OpenDoorOfTime.GetName().c_str()); - InsertHelpHoverText("Closed - The Ocarina of Time, the Song of Time and all " - "three spiritual stones are required to open the Door of Time.\n" - "\n" - "Song only - Play the Song of Time in front of the Door of " - "Time to open it.\n" - "\n" - "Open - The Door of Time is permanently open with no requirements."); - SohImGui::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); - PaddedSeparator(); + PaddedSeparator(); - // Zora's Fountain - ImGui::Text(Settings::ZorasFountain.GetName().c_str()); - InsertHelpHoverText("Closed - King Zora obstructs the way to Zora's Fountain. " - "Ruto's letter must be shown as child Link in order to move " - "him in both time periods.\n" - "\n" - "Closed as child - Ruto's Letter is only required to move King Zora " - "as child Link. Zora's Fountain starts open as adult.\n" - "\n" - "Open - King Zora has already mweeped out of the way in both " - "time periods. Ruto's Letter is removed from the item pool."); - SohImGui::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); - PaddedSeparator(); + // Kakariko Gate + ImGui::Text(Settings::OpenKakariko.GetName().c_str()); + InsertHelpHoverText( + "Closed - The gate will remain closed until Zelda's letter " + "is shown to the guard.\n" + "\n" + "Open - The gate is always open. The happy mask shop " + "will open immediately after obtaining Zelda's letter." + ); + SohImGui::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 0); - // Gerudo Fortress - ImGui::Text(Settings::GerudoFortress.GetName().c_str()); - InsertHelpHoverText("Sets the amount of carpenters required to repair the bridge " - "in Gerudo Valley.\n" - "\n" - "Normal - All 4 carpenters are required to be saved.\n" - "\n" - "Fast - Only the bottom left carpenter requires rescuing.\n" - "\n" - "Open - The bridge is repaired from the start."); - SohImGui::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 0); - PaddedSeparator(); + PaddedSeparator(); - // Rainbow Bridge - ImGui::Text(Settings::Bridge.GetName().c_str()); - InsertHelpHoverText("Alters the requirements to open the bridge to Ganon's Castle.\n" - "\n" - "Vanilla - Obtain the Shadow Medallion, Spirit Medallion and Light Arrows.\n" - "\n" - "Always open - No requirements.\n" - "\n" - "Stones - Obtain the specified amount of spiritual stones.\n" - "\n" - "Medallions - Obtain the specified amount of medallions.\n" - "\n" - "Dungeon rewards - Obtain the specified total sum of spiritual " - "stones or medallions.\n" - "\n" - "Dungeons - Complete the specified amount of dungeons. Dungeons " - "are considered complete after stepping in to the blue warp after " - "the boss.\n" - "\n" - "Tokens - Obtain the specified amount of Skulltula tokens."); - SohImGui::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 0); - ImGui::PopItemWidth(); - switch (CVar_GetS32("gRandomizeRainbowBridge", 0)) { - case 0: - break; - case 1: - break; - case 2: - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", - "gRandomizeStoneCount", 1, 3, "", 3, true); - break; - case 3: - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", - "gRandomizeMedallionCount", 1, 6, "", 6, true); - break; - case 4: - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", - "gRandomizeRewardCount", 1, 9, "", 9, true); - break; - case 5: - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", - "gRandomizeDungeonCount", 1, 8, "", 8, true); - break; - case 6: - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", - "gRandomizeTokenCount", 1, 100, "", 100, true); - break; - } - PaddedSeparator(); + // Door of Time + ImGui::Text(Settings::OpenDoorOfTime.GetName().c_str()); + InsertHelpHoverText( + "Closed - The Ocarina of Time, the Song of Time and all " + "three spiritual stones are required to open the Door of Time.\n" + "\n" + "Song only - Play the Song of Time in front of the Door of " + "Time to open it.\n" + "\n" + "Open - The Door of Time is permanently open with no requirements." + ); + SohImGui::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); - // Random Ganon's Trials - /* - ImGui::Text("Random Ganon's Trials"); - InsertHelpHoverText("Sets a random number or required trials to enter\nGanon's Tower."); - SohImGui::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 2, 0); - if (CVar_GetS32("gRandomizeGanonTrial", 0) == 0) { - ImGui::PopItemWidth(); - SohImGui::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", - "gRandomizeGanonTrialCount", 0, 6, "", 6); - InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); - RANDTODO: Switch back to slider when pre-completing some of Ganon's Trials is properly implemnted. - } - */ - SohImGui::EnhancementCheckbox("Skip Ganon's Trials", "gRandomizeGanonTrialCount"); - InsertHelpHoverText( - "Sets whether or not Ganon's Castle Trials are required to enter Ganon's Tower."); + PaddedSeparator(); + + // Zora's Fountain + ImGui::Text(Settings::ZorasFountain.GetName().c_str()); + InsertHelpHoverText( + "Closed - King Zora obstructs the way to Zora's Fountain. " + "Ruto's letter must be shown as child Link in order to move " + "him in both time periods.\n" + "\n" + "Closed as child - Ruto's Letter is only required to move King Zora " + "as child Link. Zora's Fountain starts open as adult.\n" + "\n" + "Open - King Zora has already mweeped out of the way in both " + "time periods. Ruto's Letter is removed from the item pool." + ); + SohImGui::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); + + PaddedSeparator(); + + // Gerudo Fortress + ImGui::Text(Settings::GerudoFortress.GetName().c_str()); + InsertHelpHoverText( + "Sets the amount of carpenters required to repair the bridge " + "in Gerudo Valley.\n" + "\n" + "Normal - All 4 carpenters are required to be saved.\n" + "\n" + "Fast - Only the bottom left carpenter requires rescuing.\n" + "\n" + "Open - The bridge is repaired from the start." + ); + SohImGui::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 0); + + PaddedSeparator(); + + // Rainbow Bridge + ImGui::Text(Settings::Bridge.GetName().c_str()); + InsertHelpHoverText( + "Alters the requirements to open the bridge to Ganon's Castle.\n" + "\n" + "Vanilla - Obtain the Shadow Medallion, Spirit Medallion and Light Arrows.\n" + "\n" + "Always open - No requirements.\n" + "\n" + "Stones - Obtain the specified amount of spiritual stones.\n" + "\n" + "Medallions - Obtain the specified amount of medallions.\n" + "\n" + "Dungeon rewards - Obtain the specified total sum of spiritual " + "stones or medallions.\n" + "\n" + "Dungeons - Complete the specified amount of dungeons. Dungeons " + "are considered complete after stepping in to the blue warp after " + "the boss.\n" + "\n" + "Tokens - Obtain the specified amount of Skulltula tokens." + ); + + SohImGui::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 0); + ImGui::PopItemWidth(); + switch (CVar_GetS32("gRandomizeRainbowBridge", 0)) { + case 0: + break; + case 1: + break; + case 2: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + SohImGui::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", + "gRandomizeStoneCount", 1, 3, "", 3, true); + break; + case 3: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + SohImGui::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", + "gRandomizeMedallionCount", 1, 6, "", 6, true); + break; + case 4: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + SohImGui::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", + "gRandomizeRewardCount", 1, 9, "", 9, true); + break; + case 5: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + SohImGui::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", + "gRandomizeDungeonCount", 1, 8, "", 8, true); + break; + case 6: + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + SohImGui::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", + "gRandomizeTokenCount", 1, 100, "", 100, true); + break; } + PaddedSeparator(); + + // Random Ganon's Trials + /* + ImGui::Text("Random Ganon's Trials"); + InsertHelpHoverText("Sets a random number or required trials to enter\nGanon's Tower."); + SohImGui::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 2, 0); + if (CVar_GetS32("gRandomizeGanonTrial", 0) == 0) { + ImGui::PopItemWidth(); + SohImGui::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", + "gRandomizeGanonTrialCount", 0, 6, "", 6); + InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); + RANDTODO: Switch back to slider when pre-completing some of Ganon's Trials is properly implemnted. + } + */ + + SohImGui::EnhancementCheckbox("Skip Ganon's Trials", "gRandomizeGanonTrialCount"); + InsertHelpHoverText( + "Sets whether or not Ganon's Castle Trials are required to enter Ganon's Tower." + ); + + ImGui::EndChild(); + // COLUMN 2 - Shuffle Settings ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildShuffleSettings", ImVec2(0,-8)); ImGui::PushItemWidth(-FLT_MIN); - if (CVar_GetS32("gRandomizeAllShuffleSettings", 0) != 1) { - // Shuffle Songs - ImGui::Text(Settings::ShuffleSongs.GetName().c_str()); + // Shuffle Songs + ImGui::Text(Settings::ShuffleSongs.GetName().c_str()); + InsertHelpHoverText( + "Song locations - Songs will only appear at locations that normally teach songs.\n" + "\n" + "Dungeon rewards - Songs appear after beating a major dungeon boss.\n" + "The 4 remaining songs are located at:\n" + " - Zelda's lullaby location\n" + " - Ice Cavern's Serenade of Water location\n" + " - Bottom of the Well Lens of Truth location\n" + " - Gerudo Training Ground's Ice Arrows location\n" + "\n" + "Anywhere - Songs can appear at any location."); + + SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); + + PaddedSeparator(); + + // Shuffle Scrubs + ImGui::Text(Settings::Scrubsanity.GetName().c_str()); + InsertHelpHoverText( + "Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game (PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n" + "\n" + "Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n" + "\n" + "Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n" + "\n" + "Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n" + ); + SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0); + + PaddedSeparator(); + + // Shuffle Tokens + ImGui::Text(Settings::Tokensanity.GetName().c_str()); + InsertHelpHoverText( + "Shuffles Golden Skulltula Tokens into the item pool. This means " + "Golden Skulltulas can contain other items as well.\n" + "\n" + "Off - GS tokens will not be shuffled.\n" + "\n" + "Dungeons - Only shuffle GS tokens that are within dungeons.\n" + "\n" + "Overworld - Only shuffle GS tokens that are outside of dungeons.\n" + "\n" + "All Tokens - Shuffle all 100 GS tokens." + ); + SohImGui::EnhancementCombobox("gRandomizeShuffleTokens", randoShuffleTokens, 4, 0); + + PaddedSeparator(); + + SohImGui::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong"); + InsertHelpHoverText( + "All Golden Skulltulas that require nighttime to appear will only be " + "expected to be collected after getting Sun's Song." + ); + + PaddedSeparator(); + + // Shuffle Cows + SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); + InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); + PaddedSeparator(); + + // Shuffle Adult Trade Quest + SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), + "gRandomizeShuffleAdultTrade"); + InsertHelpHoverText( + "Adds all of the adult trade quest items into the pool, each of which " + "can be traded for a unique reward.\n" + "\n" + "You will be able to choose which of your owned adult trade items is visible " + "in the inventory by selecting the item with A and using the control stick or " + "D-pad.\n" + "\n" + "If disabled, only the Claim Check will be found in the pool." + ); + + PaddedSeparator(); + + if (CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { + // Shuffle Kokiri Sword + SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), + "gRandomizeShuffleKokiriSword"); InsertHelpHoverText( - "Song locations - Songs will only appear at locations that normally teach songs.\n" + "Shuffles the Kokiri Sword into the item pool.\n" "\n" - "Dungeon rewards - Songs appear after beating a major dungeon boss.\n" - "The 4 remaining songs are located at:\n" - " - Zelda's lullaby location\n" - " - Ice Cavern's Serenade of Water location\n" - " - Bottom of the Well Lens of Truth location\n" - " - Gerudo Training Ground's Ice Arrows location\n" - "\n" - "Anywhere - Songs can appear at any location."); - - SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); - PaddedSeparator(); - - // Shuffle Scrubs - ImGui::Text(Settings::Scrubsanity.GetName().c_str()); - InsertHelpHoverText( - "Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game (PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n" - "\n" - "Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n" - "\n" - "Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n" - "\n" - "Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n" + "This will require the use of sticks until the Kokiri Sword is found." ); - SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0); PaddedSeparator(); - - // Shuffle Tokens - ImGui::Text(Settings::Tokensanity.GetName().c_str()); - InsertHelpHoverText("Shuffles Golden Skulltula Tokens into the item pool. This means " - "Golden Skulltulas can contain other items as well.\n" - "\n" - "Off - GS tokens will not be shuffled.\n" - "\n" - "Dungeons - Only shuffle GS tokens that are within dungeons.\n" - "\n" - "Overworld - Only shuffle GS tokens that are outside of dungeons.\n" - "\n" - "All Tokens - Shuffle all 100 GS tokens."); - SohImGui::EnhancementCombobox("gRandomizeShuffleTokens", randoShuffleTokens, 4, 0); - PaddedSeparator(); - - SohImGui::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong"); - InsertHelpHoverText("All Golden Skulltulas that require nighttime to appear will only be " - "expected to be collected after getting Sun's Song."); - PaddedSeparator(); - - - // Shuffle Cows - SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); - InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); - PaddedSeparator(); - - // Shuffle Adult Trade Quest - SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), - "gRandomizeShuffleAdultTrade"); - InsertHelpHoverText("Adds all of the adult trade quest items into the pool, each of which " - "can be traded for a unique reward.\n" - "\n" - "You will be able to choose which of your owned adult trade items is visible " - "in the inventory by selecting the item with A and using the control stick or " - "D-pad.\n" - "\n" - "If disabled, only the Claim Check will be found in the pool."); - PaddedSeparator(); - - if (CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { - // Shuffle Kokiri Sword - SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), - "gRandomizeShuffleKokiriSword"); - InsertHelpHoverText("Shuffles the Kokiri Sword into the item pool.\n" - "\n" - "This will require the use of sticks until the Kokiri Sword is found."); - PaddedSeparator(); - } - - if (CVar_GetS32("gRandomizeStartingOcarina", 0) == 0) { - // Shuffle Ocarinas - SohImGui::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), - "gRandomizeShuffleOcarinas"); - InsertHelpHoverText( - "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" - "\n" - "This will require finding an Ocarina before being able to play songs."); - PaddedSeparator(); - } - - // Shuffle Weird Egg - // Disabled when Skip Child Zelda is active - if (!disableEditingRandoSettings) { - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, CVar_GetS32("gRandomizeSkipChildZelda", 0)); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, - ImGui::GetStyle().Alpha * - (CVar_GetS32("gRandomizeSkipChildZelda", 0) ? 0.5f : 1.0f)); - } - SohImGui::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), - "gRandomizeShuffleWeirdEgg"); - if (!disableEditingRandoSettings) { - ImGui::PopStyleVar(); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && - CVar_GetS32("gRandomizeSkipChildZelda", 0)) { - ImGui::SetTooltip("%s", "This option is disabled because \"Skip Child Zelda\" is enabled"); - } - ImGui::PopItemFlag(); - } - InsertHelpHoverText("Shuffles the Weird Egg from Malon in to the item pool. Enabling " - "\"Skip Child Zelda\" disables this feature.\n" - "\n" - "The Weird Egg is required to unlock several events:\n" - " - Zelda's Lullaby from Impa\n" - " - Saria's song in Sacred Forest Meadow\n" - " - Epona's song and chicken minigame at Lon Lon Ranch\n" - " - Zelda's letter for Kakariko gate (if set to closed)\n" - " - Happy Mask Shop sidequest\n"); - PaddedSeparator(); - - // Shuffle Gerudo Membership Card - SohImGui::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), - "gRandomizeShuffleGerudoToken"); - InsertHelpHoverText("Shuffles the Gerudo Membership Card into the item pool.\n" - "\n" - "The Gerudo Card is required to enter the Gerudo Training Grounds, opening " - "the gate to Haunted Wasteland and the Horseback Archery minigame."); - PaddedSeparator(); - - // Shuffle Frog Song Rupees - SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), - "gRandomizeShuffleFrogSongRupees"); - InsertHelpHoverText("Shuffles 5 Purple Rupees into to the item pool, and allows\n" - "you to earn items by playing songs at the Frog Choir.\n" - "\n" - "This setting does not effect the item earned from playing\n" - "the Song of Storms and the frog song minigame."); } + + if (CVar_GetS32("gRandomizeStartingOcarina", 0) == 0) { + // Shuffle Ocarinas + SohImGui::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), + "gRandomizeShuffleOcarinas"); + InsertHelpHoverText( + "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" + "\n" + "This will require finding an Ocarina before being able to play songs."); + PaddedSeparator(); + } + + // Shuffle Weird Egg + // Disabled when Skip Child Zelda is active + if (!disableEditingRandoSettings) { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, CVar_GetS32("gRandomizeSkipChildZelda", 0)); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, + ImGui::GetStyle().Alpha * + (CVar_GetS32("gRandomizeSkipChildZelda", 0) ? 0.5f : 1.0f)); + } + SohImGui::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), + "gRandomizeShuffleWeirdEgg"); + if (!disableEditingRandoSettings) { + ImGui::PopStyleVar(); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && + CVar_GetS32("gRandomizeSkipChildZelda", 0)) { + ImGui::SetTooltip("%s", "This option is disabled because \"Skip Child Zelda\" is enabled"); + } + ImGui::PopItemFlag(); + } + InsertHelpHoverText( + "Shuffles the Weird Egg from Malon in to the item pool. Enabling " + "\"Skip Child Zelda\" disables this feature.\n" + "\n" + "The Weird Egg is required to unlock several events:\n" + " - Zelda's Lullaby from Impa\n" + " - Saria's song in Sacred Forest Meadow\n" + " - Epona's song and chicken minigame at Lon Lon Ranch\n" + " - Zelda's letter for Kakariko gate (if set to closed)\n" + " - Happy Mask Shop sidequest\n" + ); + + PaddedSeparator(); + + // Shuffle Gerudo Membership Card + SohImGui::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), + "gRandomizeShuffleGerudoToken"); + InsertHelpHoverText( + "Shuffles the Gerudo Membership Card into the item pool.\n" + "\n" + "The Gerudo Card is required to enter the Gerudo Training Grounds, opening " + "the gate to Haunted Wasteland and the Horseback Archery minigame." + ); + + PaddedSeparator(); + + // Shuffle Frog Song Rupees + SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), + "gRandomizeShuffleFrogSongRupees"); + InsertHelpHoverText( + "Shuffles 5 Purple Rupees into to the item pool, and allows\n" + "you to earn items by playing songs at the Frog Choir.\n" + "\n" + "This setting does not effect the item earned from playing\n" + "the Song of Storms and the frog song minigame." + ); + ImGui::PopItemWidth(); + ImGui::EndChild(); // COLUMN 3 - Shuffle Dungeon Items ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildShuffleDungeonItems", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); // Shuffle Dungeon Rewards @@ -3536,84 +3581,100 @@ void DrawRandoEditor(bool& open) { "\n" "Anywhere - Spiritual stones and medallions can appear anywhere."); SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); + PaddedSeparator(); // Maps & Compasses ImGui::Text(Settings::MapsAndCompasses.GetName().c_str()); - InsertHelpHoverText("Start with - You will start with Maps & Compasses from all dungeons.\n" - "\n" - "Vanilla - Maps & Compasses will appear in their vanilla locations.\n" - "\n" - "Own dungeon - Maps & Compasses can only appear in their respective dungeon.\n" - "\n" - "Any dungeon - Maps & Compasses can only appear inside of any dungon.\n" - "\n" - "Overworld - Maps & Compasses can only appear outside of dungeons.\n" - "\n" - "Anywhere - Maps & Compasses can appear anywhere in the world."); + InsertHelpHoverText( + "Start with - You will start with Maps & Compasses from all dungeons.\n" + "\n" + "Vanilla - Maps & Compasses will appear in their vanilla locations.\n" + "\n" + "Own dungeon - Maps & Compasses can only appear in their respective dungeon.\n" + "\n" + "Any dungeon - Maps & Compasses can only appear inside of any dungon.\n" + "\n" + "Overworld - Maps & Compasses can only appear outside of dungeons.\n" + "\n" + "Anywhere - Maps & Compasses can appear anywhere in the world." + ); SohImGui::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2); + PaddedSeparator(); // Keysanity ImGui::Text(Settings::Keysanity.GetName().c_str()); - InsertHelpHoverText("Start with - You will start with all Small Keys from all dungeons.\n" - "\n" - "Vanilla - Small Keys will appear in their vanilla locations.\n" - "\n" - "Own dungeon - Small Keys can only appear in their respective dungeon.\n" - "\n" - "Any dungeon - Small Keys can only appear inside of any dungon.\n" - "\n" - "Overworld - Small Keys can only appear outside of dungeons.\n" - "\n" - "Anywhere - Small Keys can appear anywhere in the world."); + InsertHelpHoverText( + "Start with - You will start with all Small Keys from all dungeons.\n" + "\n" + "Vanilla - Small Keys will appear in their vanilla locations.\n" + "\n" + "Own dungeon - Small Keys can only appear in their respective dungeon.\n" + "\n" + "Any dungeon - Small Keys can only appear inside of any dungon.\n" + "\n" + "Overworld - Small Keys can only appear outside of dungeons.\n" + "\n" + "Anywhere - Small Keys can appear anywhere in the world." + ); SohImGui::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, 2); + PaddedSeparator(); // Gerudo Keys ImGui::Text(Settings::GerudoKeys.GetName().c_str()); - InsertHelpHoverText("Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n" - "\n" - "Any dungeon - Thieve's Hideout Keys can only appear inside of any dungon.\n" - "\n" - "Overworld - Thieve's Hideout Keys can only appear outside of dungeons.\n" - "\n" - "Anywhere - Thieve's Hideout Keys can appear anywhere in the world."); + InsertHelpHoverText( + "Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n" + "\n" + "Any dungeon - Thieve's Hideout Keys can only appear inside of any dungon.\n" + "\n" + "Overworld - Thieve's Hideout Keys can only appear outside of dungeons.\n" + "\n" + "Anywhere - Thieve's Hideout Keys can appear anywhere in the world." + ); SohImGui::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, 0); + PaddedSeparator(); // Boss Keysanity ImGui::Text(Settings::BossKeysanity.GetName().c_str()); - InsertHelpHoverText("Start with - You will start with Boss keys from all dungeons.\n" - "\n" - "Vanilla - Boss Keys will appear in their vanilla locations.\n" - "\n" - "Own dungeon - Boss Keys can only appear in their respective dungeon.\n" - "\n" - "Any dungeon - Boss Keys can only appear inside of any dungon.\n" - "\n" - "Overworld - Boss Keys can only appear outside of dungeons.\n" - "\n" - "Anywhere - Boss Keys can appear anywhere in the world."); + InsertHelpHoverText( + "Start with - You will start with Boss keys from all dungeons.\n" + "\n" + "Vanilla - Boss Keys will appear in their vanilla locations.\n" + "\n" + "Own dungeon - Boss Keys can only appear in their respective dungeon.\n" + "\n" + "Any dungeon - Boss Keys can only appear inside of any dungon.\n" + "\n" + "Overworld - Boss Keys can only appear outside of dungeons.\n" + "\n" + "Anywhere - Boss Keys can appear anywhere in the world." + ); SohImGui::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2); + PaddedSeparator(); // Ganon's Boss Key ImGui::Text(Settings::GanonsBossKey.GetName().c_str()); - InsertHelpHoverText("Vanilla - Ganon's Boss Key will appear in the vanilla location.\n" - "\n" - "Own dungeon - Ganon's Boss Key can appear anywhere inside Ganon's Castle.\n" - "\n" - "Start with - Places Ganon's Boss Key in your starting inventory." - "\n" - "Any dungeon - Ganon's Boss Key Key can only appear inside of any dungon.\n" - "\n" - "Overworld - Ganon's Boss Key Key can only appear outside of dungeons.\n" - "\n" - "Anywhere - Ganon's Boss Key Key can appear anywhere in the world."); + InsertHelpHoverText( + "Vanilla - Ganon's Boss Key will appear in the vanilla location.\n" + "\n" + "Own dungeon - Ganon's Boss Key can appear anywhere inside Ganon's Castle.\n" + "\n" + "Start with - Places Ganon's Boss Key in your starting inventory." + "\n" + "Any dungeon - Ganon's Boss Key Key can only appear inside of any dungon.\n" + "\n" + "Overworld - Ganon's Boss Key Key can only appear outside of dungeons.\n" + "\n" + "Anywhere - Ganon's Boss Key Key can appear anywhere in the world." + ); SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1); ImGui::PopItemWidth(); + ImGui::EndChild(); ImGui::EndTable(); } ImGui::PopStyleVar(1); @@ -3634,17 +3695,20 @@ void DrawRandoEditor(bool& open) { // COLUMN 1 - TIME SAVERS ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildTimeSavers", ImVec2(0, -8)); // Cuccos to return SohImGui::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", "gRandomizeCuccosToReturn", 0, 7, "", 7, true); InsertHelpHoverText("The amount of cuccos needed to claim the reward from Anju the cucco lady"); + PaddedSeparator(); // Big Poe Target Count SohImGui::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", "gRandomizeBigPoeTargetCount", 1, 10, "", 10, true); InsertHelpHoverText("The Poe collector will give a reward for turning in this many Big Poes."); + PaddedSeparator(); // Skip child stealth @@ -3697,17 +3761,23 @@ void DrawRandoEditor(bool& open) { "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise."); + ImGui::EndChild(); + // COLUMN 2 - WORLD SETTINGS ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildWorldSettings", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); + ImGui::Text("Coming soon"); ImGui::PopItemWidth(); + ImGui::EndChild(); // COLUMN 3 - ITEM POOL & HINT SETTINGS ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildItemPoolHintSettings", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); ImGui::Text(Settings::ItemPoolValue.GetName().c_str()); @@ -3791,6 +3861,7 @@ void DrawRandoEditor(bool& open) { } ImGui::PopItemWidth(); + ImGui::EndChild(); ImGui::EndTable(); } ImGui::PopStyleVar(1); @@ -3924,31 +3995,40 @@ void DrawRandoEditor(bool& open) { ImGui::TableNextColumn(); ImGui::PushItemWidth(170.0); ImGui::Text("Logic Rules"); - InsertHelpHoverText("Glitchless - No glitches are required, but may require some minor tricks.\n" - "\n" - "No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT."); + InsertHelpHoverText( + "Glitchless - No glitches are required, but may require some minor tricks.\n" + "\n" + "No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT." + ); SohImGui::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, 2, 0); ImGui::PopItemWidth(); ImGui::EndTable(); } if (ImGui::BeginTable("tableRandoTricksGlitches", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { - ImGui::TableSetupColumn("Enable Tricks", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Enable Glitches", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Disabled", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Enabled", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::TableHeadersRow(); ImGui::PopItemFlag(); ImGui::TableNextRow(); - // COLUMN 1 - ENABLE TRICKS + // COLUMN 1 - DISABLED TRICKS AND GLITCHES ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildTricksGlitchesDisabled", ImVec2(0, -8)); + ImGui::Text("Coming soon"); - // COLUMN 2 - ENABLE GLITCHES + ImGui::EndChild(); + + // COLUMN 2 - ENABLED TRICKS AND GLITCHES ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildTricksGlitchesEnabled", ImVec2(0, -8)); + ImGui::Text("Coming soon"); + ImGui::EndChild(); ImGui::EndTable(); } ImGui::PopStyleVar(1); @@ -3970,15 +4050,21 @@ void DrawRandoEditor(bool& open) { // COLUMN 1 - STARTING EQUIPMENT ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildStartingEquipment", ImVec2(0, -8)); + SohImGui::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), "gRandomizeStartingKokiriSword"); PaddedSeparator(); SohImGui::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), "gRandomizeStartingDekuShield"); + ImGui::EndChild(); + // COLUMN 2 - STARTING ITEMS ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildStartingItems", ImVec2(0, -8)); + SohImGui::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), "gRandomizeStartingOcarina"); PaddedSeparator(); SohImGui::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), @@ -3987,11 +4073,16 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); + ImGui::EndChild(); + // COLUMN 3 - STARTING SONGS ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildStartingSongs", ImVec2(0, -8)); + ImGui::Text("Coming soon"); + ImGui::EndChild(); ImGui::EndTable(); } ImGui::PopStyleVar(1); From 9e6d61d7ec8c9439668345cfdb965165e6dca42e Mon Sep 17 00:00:00 2001 From: aMannus Date: Fri, 26 Aug 2022 11:13:11 +0200 Subject: [PATCH 02/52] Incompatible checkboxes --- .../Enhancements/randomizer/randomizer.cpp | 92 ++++++++----------- 1 file changed, 37 insertions(+), 55 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 25b7ab873..21757949a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3196,7 +3196,7 @@ void DrawRandoEditor(bool& open) { ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * (disableEditingRandoSettings ? 0.5f : 1.0f)); SohImGui::EnhancementCheckbox("Enable Randomizer", "gRandomizer"); - if (CVar_GetS32("gRandomizer", 0) == 1) { + if (CVar_GetS32("gRandomizer", 0)) { ImGui::Dummy(ImVec2(0.0f, 0.0f)); if (ImGui::Button("Generate Seed")) { if (CVar_GetS32("gRandoGenerating", 0) == 0) { @@ -3216,7 +3216,7 @@ void DrawRandoEditor(bool& open) { ImGuiWindow* window = ImGui::GetCurrentWindow(); static ImVec2 cellPadding(8.0f, 8.0f); - if (CVar_GetS32("gRandomizer", 0) == 1 && + if (CVar_GetS32("gRandomizer", 0) && ImGui::BeginTabBar("Randomizer Settings", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { if (ImGui::BeginTabItem("Main Rules")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); @@ -3462,6 +3462,7 @@ void DrawRandoEditor(bool& open) { // Shuffle Cows SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); + PaddedSeparator(); // Shuffle Adult Trade Quest @@ -3480,47 +3481,41 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); - if (CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { - // Shuffle Kokiri Sword - SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), - "gRandomizeShuffleKokiriSword"); - InsertHelpHoverText( - "Shuffles the Kokiri Sword into the item pool.\n" - "\n" - "This will require the use of sticks until the Kokiri Sword is found." - ); - PaddedSeparator(); - } + // Shuffle Kokiri Sword + // Disabled when Start with Kokiri Sword is active + bool disableShuffleKokiriSword = CVar_GetS32("gRandomizeStartingKokiriSword", 0); + const char* disableShuffleKokiriSwordText = "This option is disabled because \"Start with Kokiri Sword\" is enabled."; + SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), + "gRandomizeShuffleKokiriSword", disableShuffleKokiriSword, + disableShuffleKokiriSwordText); + InsertHelpHoverText( + "Shuffles the Kokiri Sword into the item pool.\n" + "\n" + "This will require the use of sticks until the Kokiri Sword is found." + ); - if (CVar_GetS32("gRandomizeStartingOcarina", 0) == 0) { - // Shuffle Ocarinas - SohImGui::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), - "gRandomizeShuffleOcarinas"); - InsertHelpHoverText( - "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" - "\n" - "This will require finding an Ocarina before being able to play songs."); - PaddedSeparator(); - } + PaddedSeparator(); + + // Shuffle Ocarinas + // Disabled when Start with Ocarina is active + bool disableShuffleOcarinas = CVar_GetS32("gRandomizeStartingOcarina", 0); + const char* disableShuffleOcarinasText = "This option is disabled because \"Start with Fairy Ocarina\" is enabled."; + SohImGui::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), "gRandomizeShuffleOcarinas", + disableShuffleOcarinas, disableShuffleOcarinasText); + InsertHelpHoverText( + "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" + "\n" + "This will require finding an Ocarina before being able to play songs." + ); + + PaddedSeparator(); // Shuffle Weird Egg // Disabled when Skip Child Zelda is active - if (!disableEditingRandoSettings) { - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, CVar_GetS32("gRandomizeSkipChildZelda", 0)); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, - ImGui::GetStyle().Alpha * - (CVar_GetS32("gRandomizeSkipChildZelda", 0) ? 0.5f : 1.0f)); - } - SohImGui::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), - "gRandomizeShuffleWeirdEgg"); - if (!disableEditingRandoSettings) { - ImGui::PopStyleVar(); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && - CVar_GetS32("gRandomizeSkipChildZelda", 0)) { - ImGui::SetTooltip("%s", "This option is disabled because \"Skip Child Zelda\" is enabled"); - } - ImGui::PopItemFlag(); - } + bool disableShuffleWeirdEgg = CVar_GetS32("gRandomizeSkipChildZelda", 0); + const char* disableShuffleWeirdEggText = "This option is disabled because \"Skip Child Zelda\" is enabled."; + SohImGui::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), "gRandomizeShuffleWeirdEgg", + disableShuffleWeirdEgg, disableShuffleWeirdEggText); InsertHelpHoverText( "Shuffles the Weird Egg from Malon in to the item pool. Enabling " "\"Skip Child Zelda\" disables this feature.\n" @@ -3713,22 +3708,9 @@ void DrawRandoEditor(bool& open) { // Skip child stealth // Disabled when Skip Child Zelda is active - if (!disableEditingRandoSettings) { - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, CVar_GetS32("gRandomizeSkipChildZelda", 0)); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, - ImGui::GetStyle().Alpha * - (CVar_GetS32("gRandomizeSkipChildZelda", 0) ? 0.5f : 1.0f)); - } - SohImGui::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), - "gRandomizeSkipChildStealth"); - if (!disableEditingRandoSettings) { - ImGui::PopStyleVar(); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && - CVar_GetS32("gRandomizeSkipChildZelda", 0)) { - ImGui::SetTooltip("%s", "This option is disabled because \"Skip Child Zelda\" is enabled"); - } - ImGui::PopItemFlag(); - } + bool disableChildStealth = CVar_GetS32("gRandomizeSkipChildZelda", 0); + const char* disableChildStealthText = "This option is disabled because \"Skip Child Zelda\" is enabled"; + SohImGui::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), "gRandomizeSkipChildStealth", disableChildStealth, disableChildStealthText); InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); PaddedSeparator(); From 4ebcc83161143a81081d887c2edd3a7fa11711c3 Mon Sep 17 00:00:00 2001 From: aMannus Date: Fri, 26 Aug 2022 15:13:34 +0200 Subject: [PATCH 03/52] Code styling --- soh/soh/Enhancements/randomizer/randomizer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 21757949a..5e4dee5ef 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3211,6 +3211,7 @@ void DrawRandoEditor(bool& open) { // std::string presetfilepath = CVar_GetString("gLoadedPreset", ""); // ImGui::Text("Settings File: %s", presetfilepath.c_str()); } + PaddedSeparator(); ImGuiWindow* window = ImGui::GetCurrentWindow(); @@ -3412,8 +3413,8 @@ void DrawRandoEditor(bool& open) { " - Bottom of the Well Lens of Truth location\n" " - Gerudo Training Ground's Ice Arrows location\n" "\n" - "Anywhere - Songs can appear at any location."); - + "Anywhere - Songs can appear at any location." + ); SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); PaddedSeparator(); @@ -3485,9 +3486,8 @@ void DrawRandoEditor(bool& open) { // Disabled when Start with Kokiri Sword is active bool disableShuffleKokiriSword = CVar_GetS32("gRandomizeStartingKokiriSword", 0); const char* disableShuffleKokiriSwordText = "This option is disabled because \"Start with Kokiri Sword\" is enabled."; - SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), - "gRandomizeShuffleKokiriSword", disableShuffleKokiriSword, - disableShuffleKokiriSwordText); + SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword", + disableShuffleKokiriSword, disableShuffleKokiriSwordText); InsertHelpHoverText( "Shuffles the Kokiri Sword into the item pool.\n" "\n" From 637f089485398a5a13510a033706cd1fe16611e5 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 27 Aug 2022 00:42:54 +0200 Subject: [PATCH 04/52] some stuff --- .../Enhancements/randomizer/randomizer.cpp | 147 +++++++++--------- 1 file changed, 76 insertions(+), 71 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5e4dee5ef..31f38b378 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3219,12 +3219,12 @@ void DrawRandoEditor(bool& open) { if (CVar_GetS32("gRandomizer", 0) && ImGui::BeginTabBar("Randomizer Settings", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { - if (ImGui::BeginTabItem("Main Rules")) { + if (ImGui::BeginTabItem("World")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); - if (ImGui::BeginTable("tableRandoMainRules", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { + if (ImGui::BeginTable("tableRandoWorld", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("Open Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Shuffle Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Shuffle Dungeon Items", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Misc World Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Entrance Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::TableHeadersRow(); ImGui::PopItemFlag(); @@ -3676,12 +3676,12 @@ void DrawRandoEditor(bool& open) { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Other")) { + if (ImGui::BeginTabItem("Misc")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); - if (ImGui::BeginTable("tableRandoOther", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { + if (ImGui::BeginTable("tableRandoMisc", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("Timesavers", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("World Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Item Pool & Hint Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Hint Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Item Pool Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::TableHeadersRow(); ImGui::PopItemFlag(); @@ -3745,54 +3745,12 @@ void DrawRandoEditor(bool& open) { ImGui::EndChild(); - // COLUMN 2 - WORLD SETTINGS + // COLUMN 2 - HINT SETTINGS ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildWorldSettings", ImVec2(0, -8)); + ImGui::BeginChild("ChildHintSettings", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); - ImGui::Text("Coming soon"); - - ImGui::PopItemWidth(); - ImGui::EndChild(); - - // COLUMN 3 - ITEM POOL & HINT SETTINGS - ImGui::TableNextColumn(); - window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildItemPoolHintSettings", ImVec2(0, -8)); - ImGui::PushItemWidth(-FLT_MIN); - - ImGui::Text(Settings::ItemPoolValue.GetName().c_str()); - InsertHelpHoverText("Sets how many major items appear in the item pool.\n" - "\n" - "Plentiful - Extra major items are added to the pool.\n" - "\n" - "Balanced - Original item pool.\n" - "\n" - "Scarce - Some excess items are removed, including health upgrades.\n" - "\n" - "Minimal - Most excess items are removed."); - SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); - PaddedSeparator(); - - // Ice Traps - ImGui::Text(Settings::IceTrapValue.GetName().c_str()); - InsertHelpHoverText("Sets how many items are replaced by ice traps.\n" - "\n" - "Off - No ice traps.\n" - "\n" - "Normal - Only Ice Traps from the base item pool are shuffled in.\n" - "\n" - "Extra - Chance to replace added junk items with additional ice traps.\n" - "\n" - "Mayhem - All added junk items will be Ice Traps.\n" - "\n" - "Onslaught - All junk items will be replaced by Ice Traps, even those " - "in the base pool."); - SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); - - PaddedSeparator(); - // Gossip Stone Hints ImGui::Text(Settings::GossipStoneHints.GetName().c_str()); InsertHelpHoverText( @@ -3814,33 +3772,80 @@ void DrawRandoEditor(bool& open) { ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Indent(); ImGui::Text(Settings::ClearerHints.GetName().c_str()); - InsertHelpHoverText("Sets the difficulty of hints.\n" - "\n" - "Obscure - Hints are unique for each item, but the writing may be cryptic.\n" - "Ex: Kokiri Sword > a butter knife\n" - "\n" - "Ambiguous - Hints are clearly written, but may refer to more than one item.\n" - "Ex: Kokiri Sword > a sword\n" - "\n" - "Clear - Hints are clearly written and are unique for each item.\n" - "Ex: Kokiri Sword > the Kokiri Sword"); + InsertHelpHoverText( + "Sets the difficulty of hints.\n" + "\n" + "Obscure - Hints are unique for each item, but the writing may be cryptic.\n" + "Ex: Kokiri Sword > a butter knife\n" + "\n" + "Ambiguous - Hints are clearly written, but may refer to more than one item.\n" + "Ex: Kokiri Sword > a sword\n" + "\n" + "Clear - Hints are clearly written and are unique for each item.\n" + "Ex: Kokiri Sword > the Kokiri Sword" + ); SohImGui::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); // Hint Distribution ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Text(Settings::HintDistribution.GetName().c_str()); - InsertHelpHoverText("Sets how many hints will be useful.\n" - "\n" - "Useless - Only junk hints.\n" - "\n" - "Balanced - Recommended hint spread.\n" - "\n" - "Strong - More useful hints.\n" - "\n" - "Very Strong - Many powerful hints."); + InsertHelpHoverText( + "Sets how many hints will be useful.\n" + "\n" + "Useless - Only junk hints.\n" + "\n" + "Balanced - Recommended hint spread.\n" + "\n" + "Strong - More useful hints.\n" + "\n" + "Very Strong - Many powerful hints." + ); SohImGui::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); ImGui::Unindent(); } + + ImGui::PopItemWidth(); + ImGui::EndChild(); + + // COLUMN 3 - ITEM POOL SETTINGS + ImGui::TableNextColumn(); + window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildItemPoolSettings", ImVec2(0, -8)); + ImGui::PushItemWidth(-FLT_MIN); + + // Item Pool Settings + ImGui::Text(Settings::ItemPoolValue.GetName().c_str()); + InsertHelpHoverText( + "Sets how many major items appear in the item pool.\n" + "\n" + "Plentiful - Extra major items are added to the pool.\n" + "\n" + "Balanced - Original item pool.\n" + "\n" + "Scarce - Some excess items are removed, including health upgrades.\n" + "\n" + "Minimal - Most excess items are removed." + ); + SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); + PaddedSeparator(); + + // Ice Traps + ImGui::Text(Settings::IceTrapValue.GetName().c_str()); + InsertHelpHoverText( + "Sets how many items are replaced by ice traps.\n" + "\n" + "Off - No ice traps.\n" + "\n" + "Normal - Only Ice Traps from the base item pool are shuffled in.\n" + "\n" + "Extra - Chance to replace added junk items with additional ice traps.\n" + "\n" + "Mayhem - All added junk items will be Ice Traps.\n" + "\n" + "Onslaught - All junk items will be replaced by Ice Traps, even those " + "in the base pool." + ); + SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); ImGui::PopItemWidth(); ImGui::EndChild(); From 77f44729026b25095e8dd7379adb4821e088a648 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sun, 28 Aug 2022 19:40:46 +0200 Subject: [PATCH 05/52] Redone layout tabs/columns --- .../Enhancements/randomizer/randomizer.cpp | 252 ++++++++++++------ 1 file changed, 166 insertions(+), 86 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 31f38b378..9c093d2a9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3219,12 +3219,12 @@ void DrawRandoEditor(bool& open) { if (CVar_GetS32("gRandomizer", 0) && ImGui::BeginTabBar("Randomizer Settings", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { - if (ImGui::BeginTabItem("World")) { + if (ImGui::BeginTabItem("World Settings")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoWorld", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("Open Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::TableSetupColumn("Misc World Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Entrance Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Shuffle Entrances", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::TableHeadersRow(); ImGui::PopItemFlag(); @@ -3299,8 +3299,16 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); + ImGui::EndChild(); + + // COLUMN 2 - Shuffle Settings + ImGui::TableNextColumn(); + window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildShuffleSettings", ImVec2(0,-8)); + ImGui::PushItemWidth(-FLT_MIN); + // Gerudo Fortress - ImGui::Text(Settings::GerudoFortress.GetName().c_str()); + ImGui::Text("Gerudo Fortress Carpenters"); InsertHelpHoverText( "Sets the amount of carpenters required to repair the bridge " "in Gerudo Valley.\n" @@ -3316,7 +3324,7 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); // Rainbow Bridge - ImGui::Text(Settings::Bridge.GetName().c_str()); + ImGui::Text("Rainbow Bridge Requirements"); InsertHelpHoverText( "Alters the requirements to open the bridge to Ganon's Castle.\n" "\n" @@ -3393,12 +3401,45 @@ void DrawRandoEditor(bool& open) { "Sets whether or not Ganon's Castle Trials are required to enter Ganon's Tower." ); + PaddedSeparator(); + + ImGui::PopItemWidth(); ImGui::EndChild(); - // COLUMN 2 - Shuffle Settings + // COLUMN 3 - Shuffle Dungeon Items ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildShuffleSettings", ImVec2(0,-8)); + ImGui::BeginChild("ChildShuffleDungeonItems", ImVec2(0, -8)); + ImGui::PushItemWidth(-FLT_MIN); + + ImGui::Text("Coming soon"); + + PaddedSeparator(); + + ImGui::PopItemWidth(); + ImGui::EndChild(); + ImGui::EndTable(); + } + ImGui::PopStyleVar(1); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("Shuffle Items")) { + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); + if (ImGui::BeginTable("tableRandoStartingInventory", 3, + ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { + ImGui::TableSetupColumn("Shuffle Items", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Shuffle NPCs & Merchants", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Shuffle Dungeon Items", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::TableHeadersRow(); + ImGui::PopItemFlag(); + ImGui::TableNextRow(); + + // COLUMN 1 - STARTING EQUIPMENT + ImGui::TableNextColumn(); + window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildStartingEquipment", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); // Shuffle Songs @@ -3419,21 +3460,6 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); - // Shuffle Scrubs - ImGui::Text(Settings::Scrubsanity.GetName().c_str()); - InsertHelpHoverText( - "Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game (PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n" - "\n" - "Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n" - "\n" - "Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n" - "\n" - "Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n" - ); - SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0); - - PaddedSeparator(); - // Shuffle Tokens ImGui::Text(Settings::Tokensanity.GetName().c_str()); InsertHelpHoverText( @@ -3450,7 +3476,7 @@ void DrawRandoEditor(bool& open) { ); SohImGui::EnhancementCombobox("gRandomizeShuffleTokens", randoShuffleTokens, 4, 0); - PaddedSeparator(); + ImGui::Dummy(ImVec2(0,0)); SohImGui::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong"); InsertHelpHoverText( @@ -3460,28 +3486,6 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); - // Shuffle Cows - SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); - InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); - - PaddedSeparator(); - - // Shuffle Adult Trade Quest - SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), - "gRandomizeShuffleAdultTrade"); - InsertHelpHoverText( - "Adds all of the adult trade quest items into the pool, each of which " - "can be traded for a unique reward.\n" - "\n" - "You will be able to choose which of your owned adult trade items is visible " - "in the inventory by selecting the item with A and using the control stick or " - "D-pad.\n" - "\n" - "If disabled, only the Claim Check will be found in the pool." - ); - - PaddedSeparator(); - // Shuffle Kokiri Sword // Disabled when Start with Kokiri Sword is active bool disableShuffleKokiriSword = CVar_GetS32("gRandomizeStartingKokiriSword", 0); @@ -3542,9 +3546,38 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); + ImGui::PopItemWidth(); + ImGui::EndChild(); + + // COLUMN 2 - STARTING ITEMS + ImGui::TableNextColumn(); + window->DC.CurrLineTextBaseOffset = 0.0f; + ImGui::BeginChild("ChildStartingItems", ImVec2(0, -8)); + ImGui::PushItemWidth(-FLT_MIN); + + // Shuffle Scrubs + ImGui::Text(Settings::Scrubsanity.GetName().c_str()); + InsertHelpHoverText( + "Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game " + "(PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n" + "\n" + "Affordable - Scrubs will be shuffled and their item will cost 10 rupees.\n" + "\n" + "Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n" + "\n" + "Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n"); + SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0); + + PaddedSeparator(); + + // Shuffle Cows + SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); + InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); + + PaddedSeparator(); + // Shuffle Frog Song Rupees - SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), - "gRandomizeShuffleFrogSongRupees"); + SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees"); InsertHelpHoverText( "Shuffles 5 Purple Rupees into to the item pool, and allows\n" "you to earn items by playing songs at the Frog Choir.\n" @@ -3553,13 +3586,31 @@ void DrawRandoEditor(bool& open) { "the Song of Storms and the frog song minigame." ); + PaddedSeparator(); + + // Shuffle Adult Trade Quest + SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), + "gRandomizeShuffleAdultTrade"); + InsertHelpHoverText( + "Adds all of the adult trade quest items into the pool, each of which " + "can be traded for a unique reward.\n" + "\n" + "You will be able to choose which of your owned adult trade items is visible " + "in the inventory by selecting the item with A and using the control stick or " + "D-pad.\n" + "\n" + "If disabled, only the Claim Check will be found in the pool." + ); + + PaddedSeparator(); + ImGui::PopItemWidth(); ImGui::EndChild(); - // COLUMN 3 - Shuffle Dungeon Items + // COLUMN 3 - STARTING SONGS ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildShuffleDungeonItems", ImVec2(0, -8)); + ImGui::BeginChild("ChildStartingSongs", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); // Shuffle Dungeon Rewards @@ -3668,6 +3719,8 @@ void DrawRandoEditor(bool& open) { ); SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1); + PaddedSeparator(); + ImGui::PopItemWidth(); ImGui::EndChild(); ImGui::EndTable(); @@ -3676,12 +3729,12 @@ void DrawRandoEditor(bool& open) { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Misc")) { + if (ImGui::BeginTabItem("Misc Settings")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoMisc", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("Timesavers", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Hint Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Item Pool Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Item Pool & Hint Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Additional Features", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::TableHeadersRow(); ImGui::PopItemFlag(); @@ -3741,7 +3794,10 @@ void DrawRandoEditor(bool& open) { "gRandomizeEnableGlitchCutscenes"); InsertHelpHoverText( "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " - "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise."); + "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise." + ); + + PaddedSeparator(); ImGui::EndChild(); @@ -3751,6 +3807,42 @@ void DrawRandoEditor(bool& open) { ImGui::BeginChild("ChildHintSettings", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); + // Item Pool Settings + ImGui::Text(Settings::ItemPoolValue.GetName().c_str()); + InsertHelpHoverText( + "Sets how many major items appear in the item pool.\n" + "\n" + "Plentiful - Extra major items are added to the pool.\n" + "\n" + "Balanced - Original item pool.\n" + "\n" + "Scarce - Some excess items are removed, including health upgrades.\n" + "\n" + "Minimal - Most excess items are removed." + ); + SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); + PaddedSeparator(); + + // Ice Traps + ImGui::Text(Settings::IceTrapValue.GetName().c_str()); + InsertHelpHoverText( + "Sets how many items are replaced by ice traps.\n" + "\n" + "Off - No ice traps.\n" + "\n" + "Normal - Only Ice Traps from the base item pool are shuffled in.\n" + "\n" + "Extra - Chance to replace added junk items with additional ice traps.\n" + "\n" + "Mayhem - All added junk items will be Ice Traps.\n" + "\n" + "Onslaught - All junk items will be replaced by Ice Traps, even those " + "in the base pool." + ); + SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); + + PaddedSeparator(); + // Gossip Stone Hints ImGui::Text(Settings::GossipStoneHints.GetName().c_str()); InsertHelpHoverText( @@ -3765,7 +3857,6 @@ void DrawRandoEditor(bool& open) { "Need Stone of Agony - Hints are only available after obtaining the Stone of Agony.\n" "\n" "Need Mask of Truth - Hints are only available whilst wearing the Mask of Truth.\n"); - SohImGui::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); if (CVar_GetS32("gRandomizeGossipStoneHints", 1) != 0) { // Hint Clarity @@ -3803,7 +3894,9 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); ImGui::Unindent(); } - + + PaddedSeparator(); + ImGui::PopItemWidth(); ImGui::EndChild(); @@ -3813,39 +3906,24 @@ void DrawRandoEditor(bool& open) { ImGui::BeginChild("ChildItemPoolSettings", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); - // Item Pool Settings - ImGui::Text(Settings::ItemPoolValue.GetName().c_str()); - InsertHelpHoverText( - "Sets how many major items appear in the item pool.\n" - "\n" - "Plentiful - Extra major items are added to the pool.\n" - "\n" - "Balanced - Original item pool.\n" - "\n" - "Scarce - Some excess items are removed, including health upgrades.\n" - "\n" - "Minimal - Most excess items are removed." - ); - SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); + SohImGui::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); + InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); + PaddedSeparator(); - // Ice Traps - ImGui::Text(Settings::IceTrapValue.GetName().c_str()); + SohImGui::EnhancementCheckbox("WIP - Blue Ice Arrows", "gRandomizeBlueIceArrows", true, "In development"); InsertHelpHoverText( - "Sets how many items are replaced by ice traps.\n" - "\n" - "Off - No ice traps.\n" - "\n" - "Normal - Only Ice Traps from the base item pool are shuffled in.\n" - "\n" - "Extra - Chance to replace added junk items with additional ice traps.\n" - "\n" - "Mayhem - All added junk items will be Ice Traps.\n" - "\n" - "Onslaught - All junk items will be replaced by Ice Traps, even those " - "in the base pool." - ); - SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); + "Ice Arrows act like Blue Fire, making them able to melt red ice. " + "Item placement logic will respect this option, so it might be required to use this to progress."); + + PaddedSeparator(); + + SohImGui::EnhancementCheckbox("WIP - Sunlight Arrows", "gRandomizeSunlightArrows", true, "In development"); + InsertHelpHoverText( + "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " + "Item placement logic will respect this option, so it might be required to use this to progress."); + + PaddedSeparator(); ImGui::PopItemWidth(); ImGui::EndChild(); @@ -4045,6 +4123,8 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), "gRandomizeStartingDekuShield"); + PaddedSeparator(); + ImGui::EndChild(); // COLUMN 2 - STARTING ITEMS @@ -4057,8 +4137,6 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), "gRandomizeStartingConsumables"); PaddedSeparator(); - SohImGui::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); - InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); ImGui::EndChild(); @@ -4069,6 +4147,8 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Coming soon"); + PaddedSeparator(); + ImGui::EndChild(); ImGui::EndTable(); } From 2456473f49264a1a26efa43eeda1f0408ad3cbd0 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sun, 28 Aug 2022 20:21:32 +0200 Subject: [PATCH 06/52] Merge fix --- soh/soh/Enhancements/randomizer/randomizer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ec4323530..2dc778218 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3618,6 +3618,14 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); + SohImGui::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), "gRandomizeShuffleBeans"); + InsertHelpHoverText( + "Enabling this adds a pack of 10 beans to the item pool and changes the Magic Bean " + "Salesman to sell a random item at a price of 60 rupees." + ); + + PaddedSeparator(); + // Shuffle Frog Song Rupees SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees"); InsertHelpHoverText( From fdc0aa9ab475e752cff0c726e55965498359b1ab Mon Sep 17 00:00:00 2001 From: aMannus Date: Sun, 28 Aug 2022 21:07:18 +0200 Subject: [PATCH 07/52] Code Cleanup --- .../Enhancements/randomizer/randomizer.cpp | 223 +++--------------- 1 file changed, 38 insertions(+), 185 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 2dc778218..899b0e914 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3042,19 +3042,10 @@ void DrawRandoEditor(bool& open) { const char* randoShuffleDungeonRewards[4] = { "End of dungeons", "Any dungeon", "Overworld", "Anywhere" }; const char* randoLinksPocket[4] = { "Dungeon Reward", "Advancement", "Anything", "Nothing" }; const char* randoShuffleSongs[3] = { "Song Locations", "Dungeon Rewards", "Anywhere" }; - const char* randoShuffleTokens[4] = { "Off", "Dungeons", "Overworld", "All Tokens" }; const char* randoShopsanity[7] = { "Off", "0", "1", "2", "3", "4", "Random" }; const char* randoTokensanity[4] = { "Off", "Dungeons", "Overworld", "All Tokens" }; const char* randoShuffleScrubs[4] = { "Off", "Affordable", "Expensive", "Random Prices" }; - const char* randoShuffleCows[2] = { "Off", "On" }; - const char* randoShuffleKokiriSword[2] = { "Off", "On" }; - const char* randoShuffleOcarinas[2] = { "Off", "On" }; - const char* randoShuffleWeirdEgg[2] = { "Off", "On" }; - const char* randoShuffleGerudoToken[2] = { "Off", "On" }; - const char* randoShuffleMagicBeans[2] = { "Off", "On" }; const char* randoShuffleMerchants[3] = { "Off", "On (no hints)", "On (with hints)" }; - const char* randoShuffleFrogSongRupees[2] = { "Off", "On" }; - const char* randoShuffleAdultTrade[2] = { "Off", "On" }; // Shuffle Dungeon Items Settings const char* randoShuffleMapsAndCompasses[6] = { "Start With", "Vanilla", "Own Dungeon", @@ -3067,169 +3058,18 @@ void DrawRandoEditor(bool& open) { const char* randoShuffleGanonsBossKey[6] = { "Vanilla", "Own dungeon", "Start with", "Any Dungeon", "Overworld", "Anywhere" }; - // Timesaver Settings - const char* randoSkipSongReplays[3] = { "Don't skip", "Skip (no SFX)", "Skip (Keep SFX)" }; - // Misc Settings const char* randoGossipStoneHints[4] = { "No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony" }; const char* randoHintClarity[3] = { "Obscure", "Ambiguous", "Clear" }; const char* randoHintDistribution[4] = { "Useless", "Balanced", "Strong", "Very Strong" }; - const char* randoDamageMultiplier[7] = { "x1", "x2", "x4", "x8", "x16", "OHKO", "x1/2" }; const char* randoStartingTime[2] = { "Day", "Night" }; - const char* randoChestAnimations[2] = { "Always Fast", "Match contents" }; const char* randoChestSizeAndColor[2] = { "Vanilla", "Match contents" }; - const char* randoOpenInfoMenuWith[6] = { "Select", "Start", "D-Pad Up", "D-Pad Down", "D-Pad Right", "D-Pad Left" }; const char* randoRandomTrapDamage[3] = { "Basic", "Advanced", "Off" }; // Item Pool Settings const char* randoItemPool[4] = { "Plentiful", "Balanced", "Scarce", "Minimal" }; const char* randoIceTraps[5] = { "Off", "Normal", "Extra", "Mayhem", "Onslaught" }; - // SFX Settings - const char* randoSFXBackgroundMusic[3] = { "Normal", "No Music", "Random" }; - const char* randoSFXFanfares[3] = { "Normal", "No Fanfares", "Random" }; - const char* randoSFXLowHP[29] = { "Default", - "Completely Random", - "Random Ear-Safe", - "None", - "Bark", - "Bomb Bounce", - "Bongo Bongo Low", - "Business Scrub", - "Carrot Refill", - "Cluck", - "Drawbridge Set", - "Guay", - "HP Recover", - "Horse Trot", - "Iront Boots", - "Moo", - "Mweep!", - "Navi \"Hey!\"", - "Navi Random", - "Notification", - "Pot Shattering", - "Ribbit", - "Rupee (Silver)", - "Soft Beep", - "Switch", - "Sword Bonk", - "Tambourine", - "Timer", - "Zelda Gasp (Adult)" }; - const char* randoSFXHorse[13] = { - "Default", "Completely Random", "Random Ear-Safe", "Random Choice", "None", - "Armos", "Child Scream", "Great Fairy", "Moo", "Mweep!", - "Redead Scream", "Ruto Wiggle", "Stalchild Attack" - }; - const char* randoSFXNightfall[13] = { - "Default", "Completely Random", "Random Ear-Safe", "Random Choice", "None", - "Cockadoodiedoo", "Gold Skulltula Token", "Great Fairy", "Moo", "Mweep!", - "Redead Moan", "Talon Snore", "Thunder" - }; - const char* randoSFXHoverBoots[11] = { - "Default", "Completely Random", "Random Ear-Safe", "Random Choice", "None", "Bark", - "Cartoon Fall", "Flare Dancer Laugh", "Mweep!", "Shabom Pop", "Tambourine" - }; - const char* randoSFXOcarina[7] = { "Dafault", "Random Choice", "Flute", "Harp", "Whistle", "Malon", "Grind Organ" }; - const char* randoSFXMenu[65] = { "Default", - "Completely Random", - "Random Ear-Safe", - "Random Choise", - "None", - "Bark", - "Bomb Bounce", - "Bongo Bongo High", - "Bongo Bongo Low", - "Bottle Cork", - "Bow Twang", - "Bubble Laugh", - "Carrot Refill", - "Change Item", - "Child Pant", - "Cluck", - "Deku Baba", - "Drawbridge Set", - "Dusk Howl", - "Fanfare (Light)", - "Fanfare (Mediaum)", - "Field Shrub", - "Flare Dancer Startled", - "Ganondorf \"Teh!\"", - "Gohma Larva Croak", - "Gold Skulltula Token", - "Goron Wake", - "Guay", - "Gunshot", - "HP Low", - "HP Recover", - "Hammer Bonk", - "Horse Trot", - "Iron Boots", - "Iron Knuckle", - "Moo", - "Mweep!", - "Notification", - "Phantom Ganon Laugh", - "Plant Explode", - "Pot Shattering", - "Redead Moan", - "Ribbit", - "Rupee", - "Rupee (Silver)", - "Ruto Crash", - "Ruto Lift", - "Ruto Thrown", - "Scrub Emerge", - "Shabom Bounce", - "Shabom Pop", - "Shellblade", - "Skulltula", - "Soft Beep", - "Spit Nut", - "Switch", - "Sword Bonk", - "Talon \"Hmmm\"", - "Talon Snore", - "Talon Surprised", - "Tambourine", - "Target Ennemy", - "Target Neutral", - "Timer", - "Zelda Gasp (Adult)" }; - const char* randoSFXNavi[32] = { "Default", - "Completely Random", - "Random Ear-Safe", - "Random Choice", - "None", - "Bark", - "Business Scrub", - "Carrot Refill", - "Click", - "Dusk Howl", - "Exploding Crate", - "Explosion", - "Great Fairy", - "Guay", - "HP Low", - "HP Recover", - "Horse Neigh", - "Ice Shattering", - "Moo", - "Mweep!", - "Navi \"Hello!\"", - "Notification", - "Poe", - "Pot Shattering", - "Redead Scream", - "Ribit", - "Ruto Giggle", - "Skulltula", - "Soft Beep", - "Tambourine", - "Timer", - "Zelda Gasp (Adult)" }; - ImGui::SetNextWindowSize(ImVec2(920, 563), ImGuiCond_FirstUseEver); if (!ImGui::Begin("Randomizer Editor", &open, ImGuiWindowFlags_NoFocusOnAppearing)) { ImGui::End(); @@ -3275,7 +3115,7 @@ void DrawRandoEditor(bool& open) { ImGui::PopItemFlag(); ImGui::TableNextRow(); - // COLUMN 1 - OPEN SETTINGS + // COLUMN 1 - Open Settings ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildOpenSettings", ImVec2(0, -8)); @@ -3346,10 +3186,10 @@ void DrawRandoEditor(bool& open) { ImGui::EndChild(); - // COLUMN 2 - Shuffle Settings + // COLUMN 2 - Misc World Settings ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildShuffleSettings", ImVec2(0,-8)); + ImGui::BeginChild("ChildMiscWorldSettings", ImVec2(0,-8)); ImGui::PushItemWidth(-FLT_MIN); // Gerudo Fortress @@ -3427,31 +3267,36 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); - // Random Ganon's Trials + // Ganon's Trials + ImGui::PushItemWidth(-FLT_MIN); ImGui::Text("Ganon's Trials"); InsertHelpHoverText( - "Sets the number of Ganon's Trials required to dispel the barrier\n\n" - "Skip - No Trials are required and the barrier is already dispelled.\n\n" + "Sets the number of Ganon's Trials required to dispel the barrier.\n" + "\n" + "Skip - No Trials are required and the barrier is already dispelled.\n" + "\n" "Set Number - Select a number of trials that will be required from the" - "slider below. Which specific trials you need to complete will be random.\n\n" + "slider below. Which specific trials you need to complete will be random.\n" + "\n" "Random Number - A Random number and set of trials will be required." ); SohImGui::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 3, 0); + ImGui::PopItemWidth(); if (CVar_GetS32("gRandomizeGanonTrial", 0) == 1) { + ImGui::Dummy(ImVec2(0.0f, 0.0f)); SohImGui::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", - "gRandomizeGanonTrialCount", 1, 6, "", 6); + "gRandomizeGanonTrialCount", 1, 6, "", 6, true); InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); } PaddedSeparator(); - ImGui::PopItemWidth(); ImGui::EndChild(); - // COLUMN 3 - Shuffle Dungeon Items + // COLUMN 3 - Shuffle Entrances ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildShuffleDungeonItems", ImVec2(0, -8)); + ImGui::BeginChild("ChildShuffleEntrances", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); ImGui::Text("Coming soon"); @@ -3478,10 +3323,10 @@ void DrawRandoEditor(bool& open) { ImGui::PopItemFlag(); ImGui::TableNextRow(); - // COLUMN 1 - STARTING EQUIPMENT + // COLUMN 1 - Shuffle Items ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildStartingEquipment", ImVec2(0, -8)); + ImGui::BeginChild("ChildShuffleItems", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); // Shuffle Songs @@ -3516,7 +3361,7 @@ void DrawRandoEditor(bool& open) { "\n" "All Tokens - Shuffle all 100 GS tokens." ); - SohImGui::EnhancementCombobox("gRandomizeShuffleTokens", randoShuffleTokens, 4, 0); + SohImGui::EnhancementCombobox("gRandomizeShuffleTokens", randoTokensanity, 4, 0); ImGui::Dummy(ImVec2(0,0)); @@ -3591,10 +3436,10 @@ void DrawRandoEditor(bool& open) { ImGui::PopItemWidth(); ImGui::EndChild(); - // COLUMN 2 - STARTING ITEMS + // COLUMN 2 - Shuffle NPCs & Merchants ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildStartingItems", ImVec2(0, -8)); + ImGui::BeginChild("ChildShuffleNpcs", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); // Shuffle Scrubs @@ -3657,10 +3502,10 @@ void DrawRandoEditor(bool& open) { ImGui::PopItemWidth(); ImGui::EndChild(); - // COLUMN 3 - STARTING SONGS + // COLUMN 3 - Shuffle Dungeon Items ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildStartingSongs", ImVec2(0, -8)); + ImGui::BeginChild("ChildShuffleDungeonItems", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); // Shuffle Dungeon Rewards @@ -3675,7 +3520,8 @@ void DrawRandoEditor(bool& open) { "\n" "Overworld - Spiritual stones and medallions can only be found outside of dungeons.\n" "\n" - "Anywhere - Spiritual stones and medallions can appear anywhere."); + "Anywhere - Spiritual stones and medallions can appear anywhere." + ); SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); PaddedSeparator(); @@ -3815,28 +3661,33 @@ void DrawRandoEditor(bool& open) { const char* disableChildStealthText = "This option is disabled because \"Skip Child Zelda\" is enabled"; SohImGui::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), "gRandomizeSkipChildStealth", disableChildStealth, disableChildStealthText); InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); + PaddedSeparator(); // Skip child zelda SohImGui::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); InsertHelpHoverText("Start with Zelda's Letter in your inventory and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg."); + PaddedSeparator(); // Skip Epona race SohImGui::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), "gRandomizeSkipEponaRace"); InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); + PaddedSeparator(); // Skip tower escape SohImGui::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), "gRandomizeSkipTowerEscape"); InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); + PaddedSeparator(); // Complete mask quest SohImGui::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), "gRandomizeCompleteMaskQuest"); InsertHelpHoverText("Once the happy mask shop is opened, all masks will be available to be borrowed."); + PaddedSeparator(); // Enable Glitch-Useful Cutscenes @@ -3851,10 +3702,10 @@ void DrawRandoEditor(bool& open) { ImGui::EndChild(); - // COLUMN 2 - HINT SETTINGS + // COLUMN 2 - Item Pool & Hint Settings ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildHintSettings", ImVec2(0, -8)); + ImGui::BeginChild("ChildItemPoolHintSettings", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); // Item Pool Settings @@ -3950,10 +3801,10 @@ void DrawRandoEditor(bool& open) { ImGui::PopItemWidth(); ImGui::EndChild(); - // COLUMN 3 - ITEM POOL SETTINGS + // COLUMN 3 - Additional Features ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; - ImGui::BeginChild("ChildItemPoolSettings", ImVec2(0, -8)); + ImGui::BeginChild("ChildAdditionalFeatures", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); SohImGui::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); @@ -3964,14 +3815,16 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCheckbox("WIP - Blue Ice Arrows", "gRandomizeBlueIceArrows", true, "In development"); InsertHelpHoverText( "Ice Arrows act like Blue Fire, making them able to melt red ice. " - "Item placement logic will respect this option, so it might be required to use this to progress."); + "Item placement logic will respect this option, so it might be required to use this to progress." + ); PaddedSeparator(); SohImGui::EnhancementCheckbox("WIP - Sunlight Arrows", "gRandomizeSunlightArrows", true, "In development"); InsertHelpHoverText( "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " - "Item placement logic will respect this option, so it might be required to use this to progress."); + "Item placement logic will respect this option, so it might be required to use this to progress." + ); PaddedSeparator(); From 5961c33ba9ac80c152ea4f266500f6ace43bcc7a Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 29 Aug 2022 15:26:27 -0500 Subject: [PATCH 08/52] Rename GetItemFromGet and move obtainability checks to a separate function --- soh/include/functions.h | 1 + .../Enhancements/randomizer/randomizer.cpp | 731 +++++++++++++----- soh/soh/Enhancements/randomizer/randomizer.h | 3 +- .../Enhancements/randomizer/randomizerTypes.h | 8 + soh/src/code/z_parameter.c | 16 + 5 files changed, 552 insertions(+), 207 deletions(-) diff --git a/soh/include/functions.h b/soh/include/functions.h index 9047b6d3f..ca9fa7678 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -1063,6 +1063,7 @@ u8 Item_CheckObtainability(u8 item); void Inventory_DeleteItem(u16 item, u16 invSlot); s32 Inventory_ReplaceItem(GlobalContext* globalCtx, u16 oldItem, u16 newItem); s32 Inventory_HasEmptyBottle(void); +bool Inventory_HasEmptyBottleSlot(void); s32 Inventory_HasSpecificBottle(u8 bottleItem); void Inventory_UpdateBottleItem(GlobalContext* globalCtx, u8 item, u8 cButton); s32 Inventory_ConsumeFairy(GlobalContext* globalCtx); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 8f4ef7d3b..2ceb0d7e6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1191,81 +1191,541 @@ s16 Randomizer::GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams } s16 Randomizer::GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId) { - return GetItemFromGet(this->itemLocations[GetCheckFromActor(sceneNum, actorId, actorParams)], ogItemId); + return GetItemIDFromRandomizerGet(this->itemLocations[GetCheckFromActor(sceneNum, actorId, actorParams)], ogItemId); } -s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) { +CanObtainResult Randomizer::CanObtainRandomizerGet(RandomizerGet randoGet) { + switch (randoGet) { + case RG_NONE: + case RG_TRIFORCE: + case RG_HINT: + case RG_MAX: + case RG_SOLD_OUT: + // TODO: Implement key rings + case RG_FOREST_TEMPLE_KEY_RING: + case RG_FIRE_TEMPLE_KEY_RING: + case RG_WATER_TEMPLE_KEY_RING: + case RG_SPIRIT_TEMPLE_KEY_RING: + case RG_SHADOW_TEMPLE_KEY_RING: + case RG_BOTTOM_OF_THE_WELL_KEY_RING: + case RG_GERUDO_TRAINING_GROUNDS_KEY_RING: + case RG_GERUDO_FORTRESS_KEY_RING: + case RG_GANONS_CASTLE_KEY_RING: + return CANT_OBTAIN_MISC; + + // Equipment + case RG_KOKIRI_SWORD: + return !CHECK_OWNED_EQUIP(EQUIP_SWORD, 0) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + // TODO + // case RG_PROGRESSIVE_GORONSWORD: + // case RG_GIANTS_KNIFE: + // case RG_BIGGORON_SWORD: + case RG_DEKU_SHIELD: + case RG_BUY_DEKU_SHIELD: + return !CHECK_OWNED_EQUIP(EQUIP_SHIELD, 0) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_HYLIAN_SHIELD: + case RG_BUY_HYLIAN_SHIELD: + return !CHECK_OWNED_EQUIP(EQUIP_SHIELD, 1) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_MIRROR_SHIELD: + return !CHECK_OWNED_EQUIP(EQUIP_SHIELD, 2) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_GORON_TUNIC: + case RG_BUY_GORON_TUNIC: + return !CHECK_OWNED_EQUIP(EQUIP_TUNIC, 1) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_ZORA_TUNIC: + case RG_BUY_ZORA_TUNIC: + return !CHECK_OWNED_EQUIP(EQUIP_TUNIC, 2) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_IRON_BOOTS: + return !CHECK_OWNED_EQUIP(EQUIP_BOOTS, 1) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_HOVER_BOOTS: + return !CHECK_OWNED_EQUIP(EQUIP_BOOTS, 2) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + + // Inventory Items + case RG_PROGRESSIVE_STICK_UPGRADE: + return CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_PROGRESSIVE_NUT_UPGRADE: + return CUR_UPG_VALUE(UPG_NUTS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_PROGRESSIVE_BOMB_BAG: + return CUR_UPG_VALUE(UPG_BOMB_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_BOMBS_5: + case RG_BOMBS_10: + case RG_BOMBS_20: + case RG_BUY_BOMBS_525: + case RG_BUY_BOMBS_535: + case RG_BUY_BOMBS_10: + case RG_BUY_BOMBS_20: + case RG_BUY_BOMBS_30: + return CUR_UPG_VALUE(UPG_BOMB_BAG) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; + case RG_PROGRESSIVE_BOW: + return CUR_UPG_VALUE(UPG_QUIVER) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_ARROWS_5: + case RG_ARROWS_10: + case RG_ARROWS_30: + case RG_BUY_ARROWS_10: + case RG_BUY_ARROWS_30: + case RG_BUY_ARROWS_50: + return CUR_UPG_VALUE(UPG_QUIVER) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; + case RG_PROGRESSIVE_SLINGSHOT: + return CUR_UPG_VALUE(UPG_BULLET_BAG) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_DEKU_SEEDS_30: + case RG_BUY_DEKU_SEEDS_30: + return CUR_UPG_VALUE(UPG_BULLET_BAG) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; + case RG_PROGRESSIVE_OCARINA: + switch (INV_CONTENT(ITEM_OCARINA_FAIRY)) { + case ITEM_NONE: + case ITEM_OCARINA_FAIRY: + return CAN_OBTAIN; + case ITEM_OCARINA_TIME: + default: + return CANT_OBTAIN_ALREADY_HAVE; + } + case RG_PROGRESSIVE_BOMBCHUS: + return INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_BOMBCHU_5: + case RG_BOMBCHU_10: + case RG_BOMBCHU_20: + case RG_BOMBCHU_DROP: + case RG_BUY_BOMBCHU_10: + case RG_BUY_BOMBCHU_20: + case RG_BUY_BOMBCHU_5: + return INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; + case RG_PROGRESSIVE_HOOKSHOT: + switch (INV_CONTENT(ITEM_HOOKSHOT)) { + case ITEM_NONE: + case ITEM_HOOKSHOT: + return CAN_OBTAIN; + case ITEM_LONGSHOT: + default: + return CANT_OBTAIN_ALREADY_HAVE; + } + case RG_BOOMERANG: + return INV_CONTENT(ITEM_BOOMERANG) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_LENS_OF_TRUTH: + return INV_CONTENT(ITEM_LENS) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_MAGIC_BEAN: + case RG_MAGIC_BEAN_PACK: + return BEANS_BOUGHT < 10 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_MEGATON_HAMMER: + return INV_CONTENT(ITEM_HAMMER) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FIRE_ARROWS: + return INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_ICE_ARROWS: + return INV_CONTENT(ITEM_ARROW_ICE) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_LIGHT_ARROWS: + return INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_DINS_FIRE: + return INV_CONTENT(ITEM_DINS_FIRE) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FARORES_WIND: + return INV_CONTENT(ITEM_FARORES_WIND) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_NAYRUS_LOVE: + return INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + + // Bottles + case RG_EMPTY_BOTTLE: + case RG_BOTTLE_WITH_MILK: + case RG_BOTTLE_WITH_RED_POTION: + case RG_BOTTLE_WITH_GREEN_POTION: + case RG_BOTTLE_WITH_BLUE_POTION: + case RG_BOTTLE_WITH_FAIRY: + case RG_BOTTLE_WITH_FISH: + case RG_BOTTLE_WITH_BLUE_FIRE: + case RG_BOTTLE_WITH_BUGS: + case RG_BOTTLE_WITH_POE: + case RG_RUTOS_LETTER: + case RG_BOTTLE_WITH_BIG_POE: + return Inventory_HasEmptyBottleSlot() ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + + // Bottle Refills + case RG_MILK: + case RG_RED_POTION_REFILL: + case RG_GREEN_POTION_REFILL: + case RG_BLUE_POTION_REFILL: + case RG_BUY_FISH: + case RG_BUY_RED_POTION_30: + case RG_BUY_GREEN_POTION: + case RG_BUY_BLUE_POTION: + case RG_BUY_BLUE_FIRE: + case RG_BUY_BOTTLE_BUG: + case RG_BUY_POE: + case RG_BUY_FAIRYS_SPIRIT: + case RG_BUY_RED_POTION_40: + case RG_BUY_RED_POTION_50: + return Inventory_HasEmptyBottle() ? CAN_OBTAIN : CANT_OBTAIN_NEED_EMPTY_BOTTLE; + + // Trade Items + // TODO: Do we want to be strict about any of this? + // case RG_WEIRD_EGG: + // case RG_ZELDAS_LETTER: + // case RG_POCKET_EGG: + // case RG_COJIRO: + // case RG_ODD_MUSHROOM: + // case RG_ODD_POTION: + // case RG_POACHERS_SAW: + // case RG_BROKEN_SWORD: + // case RG_PRESCRIPTION: + // case RG_EYEBALL_FROG: + // case RG_EYEDROPS: + // case RG_CLAIM_CHECK: + + // Misc Items + case RG_STONE_OF_AGONY: + return !CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_GERUDO_MEMBERSHIP_CARD: + return !CHECK_QUEST_ITEM(QUEST_GERUDO_CARD) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_DOUBLE_DEFENSE: + return !gSaveContext.doubleDefense ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_GOLD_SKULLTULA_TOKEN: + return gSaveContext.inventory.gsTokens < 100 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_PROGRESSIVE_STRENGTH: + return CUR_UPG_VALUE(UPG_STRENGTH) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_PROGRESSIVE_WALLET: + return CUR_UPG_VALUE(UPG_WALLET) < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_PROGRESSIVE_SCALE: + return CUR_UPG_VALUE(UPG_SCALE) < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_PROGRESSIVE_MAGIC_METER: + case RG_MAGIC_SINGLE: + case RG_MAGIC_DOUBLE: + return gSaveContext.magicLevel < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + + // Songs + case RG_ZELDAS_LULLABY: + return !CHECK_QUEST_ITEM(QUEST_SONG_LULLABY) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_EPONAS_SONG: + return !CHECK_QUEST_ITEM(QUEST_SONG_EPONA) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SARIAS_SONG: + return !CHECK_QUEST_ITEM(QUEST_SONG_SARIA) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SUNS_SONG: + return !CHECK_QUEST_ITEM(QUEST_SONG_SUN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SONG_OF_TIME: + return !CHECK_QUEST_ITEM(QUEST_SONG_TIME) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SONG_OF_STORMS: + return !CHECK_QUEST_ITEM(QUEST_SONG_STORMS) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_MINUET_OF_FOREST: + return !CHECK_QUEST_ITEM(QUEST_SONG_MINUET) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_BOLERO_OF_FIRE: + return !CHECK_QUEST_ITEM(QUEST_SONG_BOLERO) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SERENADE_OF_WATER: + return !CHECK_QUEST_ITEM(QUEST_SONG_SERENADE) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_REQUIEM_OF_SPIRIT: + return !CHECK_QUEST_ITEM(QUEST_SONG_REQUIEM) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_NOCTURNE_OF_SHADOW: + return !CHECK_QUEST_ITEM(QUEST_SONG_NOCTURNE) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_PRELUDE_OF_LIGHT: + return !CHECK_QUEST_ITEM(QUEST_SONG_PRELUDE) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + + // Dungeon Items + case RG_DEKU_TREE_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_YDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_DODONGOS_CAVERN_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_DDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_JABU_JABUS_BELLY_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_BDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FOREST_TEMPLE_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_BMORI1) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FIRE_TEMPLE_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_HIDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_WATER_TEMPLE_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_MIZUSIN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SPIRIT_TEMPLE_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_JYASINZOU) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SHADOW_TEMPLE_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_HAKADAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_BOTTOM_OF_THE_WELL_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_HAKADANCH) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_ICE_CAVERN_MAP: + return !CHECK_DUNGEON_ITEM(DUNGEON_MAP, SCENE_ICE_DOUKUTO) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_DEKU_TREE_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_YDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_DODONGOS_CAVERN_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_DDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_JABU_JABUS_BELLY_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_BDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FOREST_TEMPLE_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_BMORI1) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FIRE_TEMPLE_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_HIDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_WATER_TEMPLE_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_MIZUSIN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SPIRIT_TEMPLE_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_JYASINZOU) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SHADOW_TEMPLE_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_HAKADAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_BOTTOM_OF_THE_WELL_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_HAKADANCH) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_ICE_CAVERN_COMPASS: + return !CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, SCENE_ICE_DOUKUTO) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FOREST_TEMPLE_BOSS_KEY: + return !CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_BMORI1) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FIRE_TEMPLE_BOSS_KEY: + return !CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_HIDAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_WATER_TEMPLE_BOSS_KEY: + return !CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_MIZUSIN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SPIRIT_TEMPLE_BOSS_KEY: + return !CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_JYASINZOU) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SHADOW_TEMPLE_BOSS_KEY: + return !CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_HAKADAN) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_GANONS_CASTLE_BOSS_KEY: + return !CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANON) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + // TODO: Handle MQ key counts + case RG_FOREST_TEMPLE_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] < 5 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FIRE_TEMPLE_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] < 8 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_WATER_TEMPLE_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] < 6 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SPIRIT_TEMPLE_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] < 5 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SHADOW_TEMPLE_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] < 5 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_MEN] < 9 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_GERUDO_FORTRESS_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_GERUDOWAY] < 4 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_GANONS_CASTLE_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] < 2 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_TREASURE_GAME_SMALL_KEY: + return gSaveContext.inventory.dungeonKeys[SCENE_TAKARAYA] < 6 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + + // Dungeon Rewards + case RG_KOKIRI_EMERALD: + return !CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_GORON_RUBY: + return !CHECK_QUEST_ITEM(QUEST_GORON_RUBY) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_ZORA_SAPPHIRE: + return !CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FOREST_MEDALLION: + return !CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_FIRE_MEDALLION: + return !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_WATER_MEDALLION: + return !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SPIRIT_MEDALLION: + return !CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_SHADOW_MEDALLION: + return !CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + case RG_LIGHT_MEDALLION: + return !CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + + case RG_RECOVERY_HEART: + case RG_GREEN_RUPEE: + case RG_BLUE_RUPEE: + case RG_RED_RUPEE: + case RG_PURPLE_RUPEE: + case RG_HUGE_RUPEE: + case RG_PIECE_OF_HEART: + case RG_HEART_CONTAINER: + case RG_ICE_TRAP: + case RG_DEKU_NUTS_5: + case RG_DEKU_NUTS_10: + case RG_DEKU_STICK_1: + case RG_TREASURE_GAME_HEART: + case RG_TREASURE_GAME_GREEN_RUPEE: + case RG_BUY_DEKU_NUT_5: + case RG_BUY_DEKU_NUT_10: + case RG_BUY_DEKU_STICK_1: + case RG_BUY_HEART: + default: + return CAN_OBTAIN; + } +} + +GetItemID Randomizer::GetItemIDFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId) { + CanObtainResult canObtain = Randomizer::CanObtainRandomizerGet(randoGet); + + if (canObtain !== CAN_OBTAIN) { + return GI_RUPEE_BLUE; + } + switch (randoGet) { case RG_NONE: return ogItemId; + case RG_TRIFORCE: + case RG_HINT: + case RG_MAX: + case RG_SOLD_OUT: + return GI_NONE; + // Equipment case RG_KOKIRI_SWORD: - return !CHECK_OWNED_EQUIP(EQUIP_SWORD, 0) ? GI_SWORD_KOKIRI : GI_RUPEE_BLUE; - case RG_GIANTS_KNIFE: - return GI_SWORD_KNIFE; - case RG_BIGGORON_SWORD: - return !gSaveContext.bgsFlag ? GI_SWORD_BGS : GI_RUPEE_BLUE; - + return GI_SWORD_KOKIRI; + // TODO Progressive? + case RG_PROGRESSIVE_GORONSWORD: + return GI_SWORD_BGS; + // case RG_GIANTS_KNIFE: + // case RG_BIGGORON_SWORD: case RG_DEKU_SHIELD: + case RG_BUY_DEKU_SHIELD: return GI_SHIELD_DEKU; case RG_HYLIAN_SHIELD: + case RG_BUY_HYLIAN_SHIELD: return GI_SHIELD_HYLIAN; case RG_MIRROR_SHIELD: - return !CHECK_OWNED_EQUIP(EQUIP_SHIELD, 2) ? GI_SHIELD_MIRROR : GI_RUPEE_BLUE; - + return GI_SHIELD_MIRROR; case RG_GORON_TUNIC: + case RG_BUY_GORON_TUNIC: return GI_TUNIC_GORON; case RG_ZORA_TUNIC: + case RG_BUY_ZORA_TUNIC: return GI_TUNIC_ZORA; - case RG_IRON_BOOTS: - return !CHECK_OWNED_EQUIP(EQUIP_BOOTS, 1) ? GI_BOOTS_IRON : GI_RUPEE_BLUE; + return GI_BOOTS_IRON; case RG_HOVER_BOOTS: - return !CHECK_OWNED_EQUIP(EQUIP_BOOTS, 2) ? GI_BOOTS_HOVER : GI_RUPEE_BLUE; + return GI_BOOTS_HOVER; + // Inventory Items + case RG_PROGRESSIVE_STICK_UPGRADE: + switch (CUR_UPG_VALUE(UPG_STICKS)) { + case 0: + case 1: + return GI_STICK_UPGRADE_20; + case 2: + return GI_STICK_UPGRADE_30; + } + case RG_PROGRESSIVE_NUT_UPGRADE: + switch (CUR_UPG_VALUE(UPG_NUTS)) { + case 0: + case 1: + return GI_NUT_UPGRADE_30; + case 2: + return GI_NUT_UPGRADE_40; + } + case RG_PROGRESSIVE_BOMB_BAG: + switch (CUR_UPG_VALUE(UPG_BOMB_BAG)) { + case 0: + return GI_BOMB_BAG_20; + case 1: + return GI_BOMB_BAG_30; + case 2: + return GI_BOMB_BAG_40; + } + case RG_BOMBS_5: + case RG_BUY_BOMBS_525: + case RG_BUY_BOMBS_535: + return GI_BOMBS_5; + case RG_BOMBS_10: + case RG_BUY_BOMBS_10: + return GI_BOMBS_10; + case RG_BOMBS_20: + case RG_BUY_BOMBS_20: + return GI_BOMBS_20; + case RG_BUY_BOMBS_30: + return GI_BOMBS_30; + case RG_PROGRESSIVE_BOW: + switch (CUR_UPG_VALUE(UPG_QUIVER)) { + case 0: + return GI_BOW; + case 1: + return GI_QUIVER_40; + case 2: + return GI_QUIVER_50; + } + case RG_ARROWS_5: + case RG_BUY_ARROWS_10: + return GI_ARROWS_SMALL; + case RG_ARROWS_10: + case RG_BUY_ARROWS_30: + return GI_ARROWS_MEDIUM; + case RG_ARROWS_30: + case RG_BUY_ARROWS_50: + return GI_ARROWS_LARGE; + case RG_PROGRESSIVE_SLINGSHOT: + switch (CUR_UPG_VALUE(UPG_BULLET_BAG)) { + case 0: + return GI_SLINGSHOT; + case 1: + return GI_BULLET_BAG_40; + case 2: + return GI_BULLET_BAG_50; + } + case RG_DEKU_SEEDS_30: + case RG_BUY_DEKU_SEEDS_30: + return GI_SEEDS_30; + case RG_PROGRESSIVE_OCARINA: + switch (INV_CONTENT(ITEM_OCARINA_FAIRY)) { + case ITEM_NONE: + return GI_OCARINA_FAIRY; + case ITEM_OCARINA_FAIRY: + return GI_OCARINA_OOT; + } + case RG_PROGRESSIVE_BOMBCHUS: + return GI_BOMBCHUS_20; + case RG_BOMBCHU_5: + case RG_BUY_BOMBCHU_5: + case RG_BOMBCHU_DROP: + return GI_BOMBCHUS_5; + case RG_BOMBCHU_10: + case RG_BUY_BOMBCHU_10: + return GI_BOMBCHUS_10; + case RG_BOMBCHU_20: + case RG_BUY_BOMBCHU_20: + return GI_BOMBCHUS_20; + case RG_PROGRESSIVE_HOOKSHOT: + switch (INV_CONTENT(ITEM_HOOKSHOT)) { + case ITEM_NONE: + return GI_HOOKSHOT; + case ITEM_HOOKSHOT: + return GI_LONGSHOT; + } case RG_BOOMERANG: - return INV_CONTENT(ITEM_BOOMERANG) == ITEM_NONE ? GI_BOOMERANG : GI_RUPEE_BLUE; - + return GI_BOOMERANG; case RG_LENS_OF_TRUTH: - return INV_CONTENT(ITEM_LENS) == ITEM_NONE ? GI_LENS : GI_RUPEE_BLUE; - - case RG_MEGATON_HAMMER: - return INV_CONTENT(ITEM_HAMMER) == ITEM_NONE ? GI_HAMMER : GI_RUPEE_BLUE; - - case RG_STONE_OF_AGONY: - return GI_STONE_OF_AGONY; - - case RG_DINS_FIRE: - return INV_CONTENT(ITEM_DINS_FIRE) == ITEM_NONE ? GI_DINS_FIRE : GI_RUPEE_BLUE; - case RG_FARORES_WIND: - return INV_CONTENT(ITEM_FARORES_WIND) == ITEM_NONE ? GI_FARORES_WIND : GI_RUPEE_BLUE; - case RG_NAYRUS_LOVE: - return INV_CONTENT(ITEM_NAYRUS_LOVE) == ITEM_NONE ? GI_NAYRUS_LOVE : GI_RUPEE_BLUE; - - case RG_FIRE_ARROWS: - return INV_CONTENT(ITEM_ARROW_FIRE) == ITEM_NONE ? GI_ARROW_FIRE : GI_RUPEE_BLUE; - case RG_ICE_ARROWS: - return INV_CONTENT(ITEM_ARROW_ICE) == ITEM_NONE ? GI_ARROW_ICE : GI_RUPEE_BLUE; - case RG_LIGHT_ARROWS: - return INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_NONE ? GI_ARROW_LIGHT : GI_RUPEE_BLUE; - - case RG_DOUBLE_DEFENSE: - return !gSaveContext.doubleDefense ? (GetItemID)RG_DOUBLE_DEFENSE : GI_RUPEE_BLUE; - - case RG_GERUDO_MEMBERSHIP_CARD: - return GI_GERUDO_CARD; - + return GI_LENS; case RG_MAGIC_BEAN: return GI_BEAN; + case RG_MEGATON_HAMMER: + return GI_HAMMER; + case RG_FIRE_ARROWS: + return GI_ARROW_FIRE; + case RG_ICE_ARROWS: + return GI_ARROW_ICE; + case RG_LIGHT_ARROWS: + return GI_ARROW_LIGHT; + case RG_DINS_FIRE: + return GI_DINS_FIRE; + case RG_FARORES_WIND: + return GI_FARORES_WIND; + case RG_NAYRUS_LOVE: + return GI_NAYRUS_LOVE; - case RG_WEIRD_EGG: - return GI_WEIRD_EGG; - - case RG_ZELDAS_LETTER: - return GI_LETTER_ZELDA; + // Bottles + case RG_EMPTY_BOTTLE: + return GI_BOTTLE; + case RG_BOTTLE_WITH_MILK: + return GI_MILK_BOTTLE; case RG_RUTOS_LETTER: return GI_LETTER_RUTO; + // Bottle Refills + case RG_MILK: + return GI_MILK; + case RG_RED_POTION_REFILL: + case RG_BUY_RED_POTION_30: + case RG_BUY_RED_POTION_40: + case RG_BUY_RED_POTION_50: + return GI_POTION_RED; + case RG_GREEN_POTION_REFILL: + case RG_BUY_GREEN_POTION: + return GI_POTION_GREEN; + case RG_BLUE_POTION_REFILL: + case RG_BUY_BLUE_POTION: + return GI_POTION_BLUE; + case RG_BUY_FISH: + return GI_FISH; + case RG_BUY_BLUE_FIRE: + return GI_BLUE_FIRE; + case RG_BUY_BOTTLE_BUG: + return GI_BUGS; + case RG_BUY_POE: + return GI_POE; + case RG_BUY_FAIRYS_SPIRIT: + return GI_FAIRY; + + // Trade Items + case RG_WEIRD_EGG: + return GI_WEIRD_EGG; + case RG_ZELDAS_LETTER: + return GI_LETTER_ZELDA; case RG_POCKET_EGG: return GI_POCKET_EGG; case RG_COJIRO: @@ -1286,19 +1746,14 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) { return GI_EYEDROPS; case RG_CLAIM_CHECK: return GI_CLAIM_CHECK; - + + // Misc Items + case RG_STONE_OF_AGONY: + return GI_STONE_OF_AGONY; + case RG_GERUDO_MEMBERSHIP_CARD: + return GI_GERUDO_CARD; case RG_GOLD_SKULLTULA_TOKEN: return GI_SKULL_TOKEN; - - case RG_PROGRESSIVE_HOOKSHOT: - switch (gSaveContext.inventory.items[SLOT_HOOKSHOT]) { - case ITEM_NONE: - return GI_HOOKSHOT; - case ITEM_HOOKSHOT: - return GI_LONGSHOT; - } - return GI_RUPEE_BLUE; - case RG_PROGRESSIVE_STRENGTH: switch (CUR_UPG_VALUE(UPG_STRENGTH)) { case 0: @@ -1308,41 +1763,6 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) { case 2: return GI_GAUNTLETS_GOLD; } - return GI_RUPEE_BLUE; - - case RG_PROGRESSIVE_BOMB_BAG: - switch (CUR_UPG_VALUE(UPG_BOMB_BAG)) { - case 0: - return GI_BOMB_BAG_20; - case 1: - return GI_BOMB_BAG_30; - case 2: - return GI_BOMB_BAG_40; - } - return GI_RUPEE_BLUE; - - case RG_PROGRESSIVE_BOW: - switch (CUR_UPG_VALUE(UPG_QUIVER)) { - case 0: - return GI_BOW; - case 1: - return GI_QUIVER_40; - case 2: - return GI_QUIVER_50; - } - return GI_RUPEE_BLUE; - - case RG_PROGRESSIVE_SLINGSHOT: - switch (CUR_UPG_VALUE(UPG_BULLET_BAG)) { - case 0: - return GI_SLINGSHOT; - case 1: - return GI_BULLET_BAG_40; - case 2: - return GI_BULLET_BAG_50; - } - return GI_RUPEE_BLUE; - case RG_PROGRESSIVE_WALLET: switch (CUR_UPG_VALUE(UPG_WALLET)) { case 0: @@ -1350,8 +1770,6 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) { case 1: return GI_WALLET_GIANT; } - return GI_RUPEE_BLUE; - case RG_PROGRESSIVE_SCALE: switch (CUR_UPG_VALUE(UPG_SCALE)) { case 0: @@ -1359,31 +1777,6 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) { case 1: return GI_SCALE_GOLD; } - return GI_RUPEE_BLUE; - - case RG_PROGRESSIVE_NUT_UPGRADE: - switch (CUR_UPG_VALUE(UPG_NUTS)) { - case 0: - case 1: - return GI_NUT_UPGRADE_30; - case 2: - return GI_NUT_UPGRADE_40; - } - return GI_RUPEE_BLUE; - - case RG_PROGRESSIVE_STICK_UPGRADE: - switch (CUR_UPG_VALUE(UPG_STICKS)) { - case 0: - case 1: - return GI_STICK_UPGRADE_20; - case 2: - return GI_STICK_UPGRADE_30; - } - return GI_RUPEE_BLUE; - - case RG_PROGRESSIVE_BOMBCHUS: - return GI_BOMBCHUS_20; //todo progressive? - case RG_PROGRESSIVE_MAGIC_METER: switch (gSaveContext.magicLevel) { case 0: @@ -1391,44 +1784,10 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) { case 1: return (GetItemID)RG_MAGIC_DOUBLE; } - return GI_RUPEE_BLUE; - - case RG_PROGRESSIVE_OCARINA: - switch (INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_NONE) { - case 1: - return GI_OCARINA_FAIRY; - case 0: - return GI_OCARINA_OOT; - } - return GI_RUPEE_BLUE; - - case RG_PROGRESSIVE_GORONSWORD: - return GI_SWORD_BGS; //todo progressive? - - case RG_EMPTY_BOTTLE: - return GI_BOTTLE; - case RG_BOTTLE_WITH_MILK: - return GI_MILK_BOTTLE; - - // todo test this with keys in own dungeon - case RG_TREASURE_GAME_SMALL_KEY: - return GI_DOOR_KEY; - - // todo keyrings - case RG_FOREST_TEMPLE_KEY_RING: - case RG_FIRE_TEMPLE_KEY_RING: - case RG_WATER_TEMPLE_KEY_RING: - case RG_SPIRIT_TEMPLE_KEY_RING: - case RG_SHADOW_TEMPLE_KEY_RING: - case RG_BOTTOM_OF_THE_WELL_KEY_RING: - case RG_GERUDO_TRAINING_GROUNDS_KEY_RING: - case RG_GERUDO_FORTRESS_KEY_RING: - case RG_GANONS_CASTLE_KEY_RING: - return GI_RUPEE_BLUE; case RG_RECOVERY_HEART: + case RG_BUY_HEART: return GI_HEART; - case RG_GREEN_RUPEE: return GI_RUPEE_GREEN; case RG_BLUE_RUPEE: @@ -1439,73 +1798,33 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) { return GI_RUPEE_PURPLE; case RG_HUGE_RUPEE: return GI_RUPEE_GOLD; - case RG_PIECE_OF_HEART: return GI_HEART_PIECE; case RG_HEART_CONTAINER: - // todo figure out what GI_HEART_CONTAINER_2 is return GI_HEART_CONTAINER; - case RG_MILK: - return GI_MILK; //todo logic around needing a bottle? - - case RG_BOMBS_5: - return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_5 : GI_RUPEE_BLUE; - case RG_BOMBS_10: - return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_10 : GI_RUPEE_BLUE; - case RG_BOMBS_20: - return CUR_UPG_VALUE(UPG_BOMB_BAG) ? GI_BOMBS_20 : GI_RUPEE_BLUE; - - case RG_BOMBCHU_5: - return GI_BOMBCHUS_5; - case RG_BOMBCHU_10: - return GI_BOMBCHUS_10; - case RG_BOMBCHU_20: - return GI_BOMBCHUS_20; - case RG_BOMBCHU_DROP: - return GI_BOMBCHUS_5; //todo figure out what we want to do for chu drops - - case RG_ARROWS_5: - return CUR_UPG_VALUE(UPG_QUIVER) ? GI_ARROWS_SMALL : GI_RUPEE_BLUE; - case RG_ARROWS_10: - return CUR_UPG_VALUE(UPG_QUIVER) ? GI_ARROWS_MEDIUM : GI_RUPEE_BLUE; - case RG_ARROWS_30: - return CUR_UPG_VALUE(UPG_QUIVER) ? GI_ARROWS_LARGE : GI_RUPEE_BLUE; - + case RG_DEKU_NUTS_5: + case RG_BUY_DEKU_NUT_5: return GI_NUTS_5; case RG_DEKU_NUTS_10: + case RG_BUY_DEKU_NUT_10: return GI_NUTS_10; - - case RG_DEKU_SEEDS_30: - return CUR_UPG_VALUE(UPG_BULLET_BAG) ? GI_SEEDS_30 : GI_RUPEE_BLUE; - case RG_DEKU_STICK_1: + case RG_BUY_DEKU_STICK_1: return GI_STICKS_1; - - // RANDOTODO these won't be used until we implement shopsanity/scrub shuffle - case RG_RED_POTION_REFILL: - case RG_GREEN_POTION_REFILL: - case RG_BLUE_POTION_REFILL: - return GI_NONE; - + case RG_TREASURE_GAME_SMALL_KEY: + return GI_DOOR_KEY; case RG_TREASURE_GAME_HEART: return GI_HEART_PIECE_WIN; case RG_TREASURE_GAME_GREEN_RUPEE: - return GI_RUPEE_GREEN_LOSE; //todo figure out how this works outside of the game - - case RG_TRIFORCE: - return GI_RUPEE_BLUE; //todo figure out what this is/does - - case RG_HINT: - return GI_RUPEE_BLUE; //todo - + return GI_RUPEE_GREEN_LOSE; default: if (!IsItemVanilla(randoGet)) { - return randoGet; + return (GetItemID)randoGet; } return ogItemId; - } } +} bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { switch (randoGet) { @@ -1925,7 +2244,7 @@ u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) { } s16 Randomizer::GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId) { - return GetItemFromGet(this->itemLocations[randomizerCheck], ogId); + return GetItemIDFromRandomizerGet(this->itemLocations[randomizerCheck], ogId); } RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams) { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 2c87a5b03..7ab29cfc8 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -21,7 +21,8 @@ class Randomizer { std::string ganonText; std::unordered_map randoSettings; std::unordered_map randomizerMerchantPrices; - s16 GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId); + CanObtainResult CanObtainRandomizerGet(RandomizerGet randoGet); + GetItemID GetItemIDFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId); s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId); void ParseRandomizerSettingsFile(const char* spoilerFileName); void ParseHintLocationsFile(const char* spoilerFileName); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 6d410df7c..406e25b8a 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1020,6 +1020,14 @@ typedef enum { RSK_SHUFFLE_MAGIC_BEANS } RandomizerSettingKey; +typedef enum { + CAN_OBTAIN, + CANT_OBTAIN_MISC, + CANT_OBTAIN_ALREADY_HAVE, + CANT_OBTAIN_NEED_UPGRADE, + CANT_OBTAIN_NEED_EMPTY_BOTTLE, +} CanObtainResult; + typedef struct ScrubIdentity { RandomizerInf randomizerInf; RandomizerCheck randomizerCheck; diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 73044df27..164fd95a4 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2534,6 +2534,22 @@ s32 Inventory_HasEmptyBottle(void) { } } +bool Inventory_HasEmptyBottleSlot(void) { + u8* items = gSaveContext.inventory.items; + + if (items[SLOT_BOTTLE_1] == ITEM_NONE) { + return true; + } else if (items[SLOT_BOTTLE_2] == ITEM_NONE) { + return true; + } else if (items[SLOT_BOTTLE_3] == ITEM_NONE) { + return true; + } else if (items[SLOT_BOTTLE_4] == ITEM_NONE) { + return true; + } else { + return false; + } +} + s32 Inventory_HasSpecificBottle(u8 bottleItem) { u8* items = gSaveContext.inventory.items; From ded7ccab3f616c42f734040fcaed2e0375d33064 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 29 Aug 2022 15:35:37 -0500 Subject: [PATCH 09/52] Minor fixes --- soh/soh/Enhancements/randomizer/randomizer.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 2ceb0d7e6..ce3d1424d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1533,7 +1533,7 @@ CanObtainResult Randomizer::CanObtainRandomizerGet(RandomizerGet randoGet) { GetItemID Randomizer::GetItemIDFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId) { CanObtainResult canObtain = Randomizer::CanObtainRandomizerGet(randoGet); - if (canObtain !== CAN_OBTAIN) { + if (canObtain != CAN_OBTAIN) { return GI_RUPEE_BLUE; } @@ -1549,11 +1549,12 @@ GetItemID Randomizer::GetItemIDFromRandomizerGet(RandomizerGet randoGet, GetItem // Equipment case RG_KOKIRI_SWORD: return GI_SWORD_KOKIRI; - // TODO Progressive? - case RG_PROGRESSIVE_GORONSWORD: + case RG_PROGRESSIVE_GORONSWORD: //todo progressive? + return GI_SWORD_BGS; + case RG_GIANTS_KNIFE: + return GI_SWORD_KNIFE; + case RG_BIGGORON_SWORD: return GI_SWORD_BGS; - // case RG_GIANTS_KNIFE: - // case RG_BIGGORON_SWORD: case RG_DEKU_SHIELD: case RG_BUY_DEKU_SHIELD: return GI_SHIELD_DEKU; From 8c6774fa35e10005e65740e69c449b3427098a7b Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 29 Aug 2022 16:00:47 -0500 Subject: [PATCH 10/52] More small changes --- soh/soh/Enhancements/randomizer/randomizer.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ce3d1424d..3e911bfee 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1216,10 +1216,8 @@ CanObtainResult Randomizer::CanObtainRandomizerGet(RandomizerGet randoGet) { // Equipment case RG_KOKIRI_SWORD: return !CHECK_OWNED_EQUIP(EQUIP_SWORD, 0) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; - // TODO - // case RG_PROGRESSIVE_GORONSWORD: - // case RG_GIANTS_KNIFE: - // case RG_BIGGORON_SWORD: + case RG_BIGGORON_SWORD: + return !gSaveContext.bgsFlag ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_DEKU_SHIELD: case RG_BUY_DEKU_SHIELD: return !CHECK_OWNED_EQUIP(EQUIP_SHIELD, 0) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; @@ -1287,6 +1285,7 @@ CanObtainResult Randomizer::CanObtainRandomizerGet(RandomizerGet randoGet) { case RG_BUY_BOMBCHU_10: case RG_BUY_BOMBCHU_20: case RG_BUY_BOMBCHU_5: + // TODO: We'll need to account for GetRandoSettingValue(RSK_BOMBCHUS_IN_LOGIC) whenever that's added return INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_HOOKSHOT: switch (INV_CONTENT(ITEM_HOOKSHOT)) { @@ -1365,6 +1364,8 @@ CanObtainResult Randomizer::CanObtainRandomizerGet(RandomizerGet randoGet) { // case RG_EYEBALL_FROG: // case RG_EYEDROPS: // case RG_CLAIM_CHECK: + // case RG_PROGRESSIVE_GORONSWORD: + // case RG_GIANTS_KNIFE: // Misc Items case RG_STONE_OF_AGONY: From c7207d2e0ac082082228c17fae942c7a8e9701d7 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 29 Aug 2022 17:42:48 -0500 Subject: [PATCH 11/52] Move obtainability check up higher --- soh/soh/Enhancements/randomizer/randomizer.cpp | 10 ++-------- soh/soh/Enhancements/randomizer/randomizer.h | 2 +- soh/soh/OTRGlobals.cpp | 16 ++++++++++++++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3e911bfee..c696f7a15 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1194,8 +1194,8 @@ s16 Randomizer::GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, Get return GetItemIDFromRandomizerGet(this->itemLocations[GetCheckFromActor(sceneNum, actorId, actorParams)], ogItemId); } -CanObtainResult Randomizer::CanObtainRandomizerGet(RandomizerGet randoGet) { - switch (randoGet) { +CanObtainResult Randomizer::GetCanObtainFromRandomizerCheck(RandomizerCheck randomizerCheck) { + switch (this->itemLocations[randomizerCheck]) { case RG_NONE: case RG_TRIFORCE: case RG_HINT: @@ -1532,12 +1532,6 @@ CanObtainResult Randomizer::CanObtainRandomizerGet(RandomizerGet randoGet) { } GetItemID Randomizer::GetItemIDFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId) { - CanObtainResult canObtain = Randomizer::CanObtainRandomizerGet(randoGet); - - if (canObtain != CAN_OBTAIN) { - return GI_RUPEE_BLUE; - } - switch (randoGet) { case RG_NONE: return ogItemId; diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 7ab29cfc8..4d46fc210 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -21,7 +21,6 @@ class Randomizer { std::string ganonText; std::unordered_map randoSettings; std::unordered_map randomizerMerchantPrices; - CanObtainResult CanObtainRandomizerGet(RandomizerGet randoGet); GetItemID GetItemIDFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId); s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId); void ParseRandomizerSettingsFile(const char* spoilerFileName); @@ -59,6 +58,7 @@ class Randomizer { ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData); s16 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); s16 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); + CanObtainResult GetCanObtainFromRandomizerCheck(RandomizerCheck randomizerCheck); static void CreateCustomMessages(); static std::string RandomizeRupeeName(std::string message, int language); static CustomMessageEntry GetRupeeMessage(u16 rupeeTextId); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7d7a86268..14801addd 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1631,13 +1631,19 @@ extern "C" GetItemEntry ItemTable_RetrieveEntry(s16 tableID, s16 getItemID) { extern "C" GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) { s16 getItemModIndex; - if (OTRGlobals::Instance->gRandomizer->CheckContainsVanillaItem( - OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams))) { + RandomizerCheck randomizerCheck = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams); + if (OTRGlobals::Instance->gRandomizer->CheckContainsVanillaItem(randomizerCheck)) { getItemModIndex = MOD_NONE; } else { getItemModIndex = MOD_RANDOMIZER; } s16 itemID = OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, actorId, actorParams, sceneNum); + + // This feels awkward, maybe in the future each mod will have it's own obtainability check + if (OTRGlobals::Instance->gRandomizer->GetCanObtainFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { + return ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); + } + return ItemTable_RetrieveEntry(getItemModIndex, itemID); } @@ -1649,6 +1655,12 @@ extern "C" GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomi getItemModIndex = MOD_RANDOMIZER; } s16 itemID = OTRGlobals::Instance->gRandomizer->GetRandomizedItemIdFromKnownCheck(randomizerCheck, ogId); + + // This feels awkward, maybe in the future each mod will have it's own obtainability check + if (OTRGlobals::Instance->gRandomizer->GetCanObtainFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { + return ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); + } + return ItemTable_RetrieveEntry(getItemModIndex, itemID); } From f4e53c54b5bdd56c4abd2f3632c88c1747c9cb94 Mon Sep 17 00:00:00 2001 From: Sarge-117 Date: Mon, 29 Aug 2022 18:17:23 -0700 Subject: [PATCH 12/52] Correct German spellings, add 2 more hints --- .../Enhancements/randomizer/randomizer.cpp | 20 +++++++++++++------ soh/soh/Enhancements/randomizer/randomizer.h | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 8f4ef7d3b..d12db3552 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4189,7 +4189,7 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = { "%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." }, { "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?", - "%cWusstest du, dass du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", + "%cWußtest du, daß du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", "%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables mouvants%c?" }, { "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!", @@ -4197,15 +4197,15 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = { "%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec une&%rcocotte%c!" }, { "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?", - "%cDie %yGeister-Prüfung %cin %pGanons&Schloss %chat irgendwo eine&%wversteckte Kiste%c. Weißt du schon&wo?", + "%cDie %yGeister-Prüfung %cin %pGanons&Schloß %chat irgendwo eine&%wversteckte Kiste%c. Weißt du schon&wo?", "%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu le savais&déjà?" }, { "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is junk!", - "%cKennst du die %wMinenbowlingbahn%c?&Ich habe gehört dass sich nur &%wzwei der Preise%c lohnen. Der Rest&ist Krimskrams!", + "%cKennst du die %wMinenbowlingbahn%c?&Ich habe gehört daß sich nur &%wzwei der Preise%c lohnen. Der Rest&ist Krimskrams!", "%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont intéréssant?" }, { "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!", - "%cBenutzt du auch genügend %wDeku&Nüsse%c? Ich habe mal gesehen dass&man damit %rKrabbelminen %cdetonieren&kann!", + "%cBenutzt du auch genügend %wDeku&Nüsse%c? Ich habe mal gesehen daß&man damit %rKrabbelminen %cdetonieren&kann!", "%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" }, { "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your safety!", @@ -4221,7 +4221,7 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = { "%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" }, { "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?", - "%cIch habe gehört dass der&%rFlammenderwisch %ceine Schwäche für&das %wMasterschwert %caufweist. Hast du&es schonmal versucht einzusetzen?", + "%cIch habe gehört daß der&%rFlammenderwisch %ceine Schwäche für&das %wMasterschwert %caufweist. Hast du&es schonmal versucht einzusetzen?", "%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as essayé?" }, { "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!", @@ -4229,8 +4229,16 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = { "%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une %wjarre&%cà la figure?" }, { "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!", - "%cIch habe gehört dass die Stelle&%wfeuchten Bodens %cim %bZora-Fluss %cals&einzige keine %rSkulltula %cbeherbergt.", + "%cIch habe gehört daß die Stelle&%wfeuchten Bodens %cim %bZora-Fluß %cals&einzige keine %rSkulltula %cbeherbergt.", "%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne contienne pas&d'%raraignée%c." }, + + { "%cThe people of Hyrule sometimes&have %witems %cfor you, but they won't&like it if you're %wwearing a mask%c!", + "%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür dich, aber Sie mögen&es nicht wenn du %wMasken trägst%c!", + "%cF16" }, + + { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&reset%c!", + "%cSolltest du irgendwo eingeschloßen&sein, mußt du vielleicht dein %wSpiel&speichern %cund neustarten!", + "%cF17" }, }; void CreateNaviRandoMessages() { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 2c87a5b03..a9087933c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -8,7 +8,7 @@ #include #include -#define NUM_NAVI_MESSAGES 15 +#define NUM_NAVI_MESSAGES 17 class Randomizer { private: From b803c77f58c590ee401a896dcae0c972bfa0d748 Mon Sep 17 00:00:00 2001 From: Sarge-117 Date: Tue, 30 Aug 2022 14:22:02 -0700 Subject: [PATCH 13/52] Add French translation Thanks to PurpleHato --- soh/soh/Enhancements/randomizer/randomizer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index d12db3552..50863b459 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4234,11 +4234,11 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = { { "%cThe people of Hyrule sometimes&have %witems %cfor you, but they won't&like it if you're %wwearing a mask%c!", "%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür dich, aber Sie mögen&es nicht wenn du %wMasken trägst%c!", - "%cF16" }, + "%cIl se peut que les habitants d'Hyrule&aient des %wobjets %cpour toi. Par contre,&ils risquent de ne pas trop apprécier&le fait que tu %wportes un masque%c!" }, - { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&reset%c!", - "%cSolltest du irgendwo eingeschloßen&sein, mußt du vielleicht dein %wSpiel&speichern %cund neustarten!", - "%cF17" }, + { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&%wreset%c!", + "%cSolltest du irgendwo eingeschloßen&sein, mußt du vielleicht dein %wSpiel&speichern %cund %wneustarten%c!", + "%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" }, }; void CreateNaviRandoMessages() { From 55fa913c782cc052145694fb4f550f74b6ec5fa6 Mon Sep 17 00:00:00 2001 From: Sarge-117 Date: Tue, 30 Aug 2022 15:24:44 -0700 Subject: [PATCH 14/52] Couple more Just need German for these Co-Authored-By: PurpleHato <47987542+PurpleHato@users.noreply.github.com> --- soh/soh/Enhancements/randomizer/randomizer.cpp | 8 ++++++++ soh/soh/Enhancements/randomizer/randomizer.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 0933fccc7..2dfaf97a9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4368,6 +4368,14 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = { { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&%wreset%c!", "%cSolltest du irgendwo eingeschloßen&sein, mußt du vielleicht dein %wSpiel&speichern %cund %wneustarten%c!", "%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" }, + + { "%cSheik will meet you in a %rburning&village %conce you have %gForest%c,&%rFire%c, and %bWater %cMedallions!", + "%cG18", + "%cSheik t'attendra dans un %rvillage&en feu %clorsque tu auras récupéré&les médaillons de la %gForêt%c, du %rFeu&%cet de l'%bEau%c!" }, + + { "%cIf you don't have a %wsword %cas a&child, try buying %wDeku Sticks%c!&They're effective against your foes!", + "%cG19", + "%cSi tu n'as pas d'%wépée %cen tant&qu'enfant, pourquoi n'irais-tu pas&acheter quelques %wBâtons Mojo%c? Ils&sont efficaces contre tes ennemis!" } }; void CreateNaviRandoMessages() { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index a9087933c..17fd39f3d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -8,7 +8,7 @@ #include #include -#define NUM_NAVI_MESSAGES 17 +#define NUM_NAVI_MESSAGES 19 class Randomizer { private: From 3502cea4220b2f4e4ae3fb3916fef68cb3b71a38 Mon Sep 17 00:00:00 2001 From: aMannus Date: Wed, 31 Aug 2022 10:10:28 +0200 Subject: [PATCH 15/52] Renamed tabs --- soh/soh/Enhancements/randomizer/randomizer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 2d5b493ab..f8340fbd5 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3233,7 +3233,7 @@ void DrawRandoEditor(bool& open) { if (CVar_GetS32("gRandomizer", 0) && ImGui::BeginTabBar("Randomizer Settings", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { - if (ImGui::BeginTabItem("World Settings")) { + if (ImGui::BeginTabItem("World")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoWorld", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("Open Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); @@ -3440,7 +3440,7 @@ void DrawRandoEditor(bool& open) { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Shuffle Items")) { + if (ImGui::BeginTabItem("Items")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoStartingInventory", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { @@ -3754,7 +3754,7 @@ void DrawRandoEditor(bool& open) { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Misc Settings")) { + if (ImGui::BeginTabItem("Misc")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoMisc", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("Timesavers", ImGuiTableColumnFlags_WidthStretch, 200.0f); From 75e5330263d1e250a562de414ea81a7214cdf9b2 Mon Sep 17 00:00:00 2001 From: Sarge-117 Date: Wed, 31 Aug 2022 17:23:16 -0700 Subject: [PATCH 16/52] Add German --- soh/soh/Enhancements/randomizer/randomizer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 2dfaf97a9..605cfc374 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4370,11 +4370,11 @@ CustomMessageMinimal NaviMessages[NUM_NAVI_MESSAGES] = { "%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" }, { "%cSheik will meet you in a %rburning&village %conce you have %gForest%c,&%rFire%c, and %bWater %cMedallions!", - "%cG18", + "%cSheik wird dich in einem %rbrennenden&Dorf %ctreffen sobald du das Amulett&des %gWaldes%c, %rFeuers %cund %bWassers&%cbesitzt.", "%cSheik t'attendra dans un %rvillage&en feu %clorsque tu auras récupéré&les médaillons de la %gForêt%c, du %rFeu&%cet de l'%bEau%c!" }, { "%cIf you don't have a %wsword %cas a&child, try buying %wDeku Sticks%c!&They're effective against your foes!", - "%cG19", + "%cSolltest du als Kind kein %wSchwert&%cbesitzen, empfehle ich %wDeku Stäbe&%czu kaufen! Diese sind effektiv gegen&Widersacher!", "%cSi tu n'as pas d'%wépée %cen tant&qu'enfant, pourquoi n'irais-tu pas&acheter quelques %wBâtons Mojo%c? Ils&sont efficaces contre tes ennemis!" } }; From 38dca43b3f561fd7ee3d0ae9f76e621973fb60b9 Mon Sep 17 00:00:00 2001 From: aMannus Date: Thu, 1 Sep 2022 20:25:10 +0200 Subject: [PATCH 17/52] Name changes and small layout changes --- .../Enhancements/randomizer/randomizer.cpp | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index f8340fbd5..de7997e9a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3236,15 +3236,15 @@ void DrawRandoEditor(bool& open) { if (ImGui::BeginTabItem("World")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); if (ImGui::BeginTable("tableRandoWorld", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { - ImGui::TableSetupColumn("Open Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Misc World Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Area Access", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("World Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::TableSetupColumn("Shuffle Entrances", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::TableHeadersRow(); ImGui::PopItemFlag(); ImGui::TableNextRow(); - // COLUMN 1 - Open Settings + // COLUMN 1 - Area Access ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildOpenSettings", ImVec2(0, -8)); @@ -3315,7 +3315,7 @@ void DrawRandoEditor(bool& open) { ImGui::EndChild(); - // COLUMN 2 - Misc World Settings + // COLUMN 2 - World Settings ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildMiscWorldSettings", ImVec2(0,-8)); @@ -3754,11 +3754,11 @@ void DrawRandoEditor(bool& open) { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Misc")) { + if (ImGui::BeginTabItem("Gameplay")) { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cellPadding); - if (ImGui::BeginTable("tableRandoMisc", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { + if (ImGui::BeginTable("tableRandoGameplay", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("Timesavers", ImGuiTableColumnFlags_WidthStretch, 200.0f); - ImGui::TableSetupColumn("Item Pool & Hint Settings", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Item Pool & Hints", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::TableSetupColumn("Additional Features", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); ImGui::TableHeadersRow(); @@ -3795,7 +3795,7 @@ void DrawRandoEditor(bool& open) { // Skip child zelda SohImGui::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); - InsertHelpHoverText("Start with Zelda's Letter in your inventory and skip the sequence up " + InsertHelpHoverText("Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg."); PaddedSeparator(); @@ -3819,16 +3819,6 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); - // Enable Glitch-Useful Cutscenes - SohImGui::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), - "gRandomizeEnableGlitchCutscenes"); - InsertHelpHoverText( - "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " - "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise." - ); - - PaddedSeparator(); - ImGui::EndChild(); // COLUMN 2 - Item Pool & Hint Settings @@ -3941,7 +3931,7 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); - SohImGui::EnhancementCheckbox("WIP - Blue Ice Arrows", "gRandomizeBlueIceArrows", true, "In development"); + SohImGui::EnhancementCheckbox("WIP - Blue Fire Arrows", "gRandomizeBlueIceArrows", true, "In development"); InsertHelpHoverText( "Ice Arrows act like Blue Fire, making them able to melt red ice. " "Item placement logic will respect this option, so it might be required to use this to progress." @@ -4098,6 +4088,16 @@ void DrawRandoEditor(bool& open) { "No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT." ); SohImGui::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, 2, 0); + + PaddedSeparator(); + + // Enable Glitch-Useful Cutscenes + SohImGui::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), + "gRandomizeEnableGlitchCutscenes"); + InsertHelpHoverText( + "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " + "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise."); + ImGui::PopItemWidth(); ImGui::EndTable(); } From c7a7059db4a8c8e805987d541352e11bea834832 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 2 Sep 2022 09:38:41 -0500 Subject: [PATCH 18/52] Minor adjustments from feedback and rename CanObtain to ItemObtainability --- soh/soh/Enhancements/randomizer/randomizer.cpp | 16 +++++++++++----- soh/soh/Enhancements/randomizer/randomizer.h | 2 +- .../Enhancements/randomizer/randomizerTypes.h | 2 +- soh/soh/OTRGlobals.cpp | 4 ++-- soh/src/code/z_parameter.c | 17 ++++++----------- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 1171dd7e1..5ba6912c2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1212,7 +1212,7 @@ s16 Randomizer::GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, Get return GetItemIDFromRandomizerGet(this->itemLocations[GetCheckFromActor(sceneNum, actorId, actorParams)], ogItemId); } -CanObtainResult Randomizer::GetCanObtainFromRandomizerCheck(RandomizerCheck randomizerCheck) { +ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck) { switch (this->itemLocations[randomizerCheck]) { case RG_NONE: case RG_TRIFORCE: @@ -1294,16 +1294,22 @@ CanObtainResult Randomizer::GetCanObtainFromRandomizerCheck(RandomizerCheck rand default: return CANT_OBTAIN_ALREADY_HAVE; } - case RG_PROGRESSIVE_BOMBCHUS: - return INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; case RG_BOMBCHU_5: case RG_BOMBCHU_10: case RG_BOMBCHU_20: - case RG_BOMBCHU_DROP: + case RG_PROGRESSIVE_BOMBCHUS: + return CAN_OBTAIN; case RG_BUY_BOMBCHU_10: case RG_BUY_BOMBCHU_20: case RG_BUY_BOMBCHU_5: - // TODO: We'll need to account for GetRandoSettingValue(RSK_BOMBCHUS_IN_LOGIC) whenever that's added + // If Bombchus aren't in logic, you need a bomb bag to purchase them + // If they are in logic, you need to have already obtained them somewhere else + if (GetRandoSettingValue(RSK_BOMBCHUS_IN_LOGIC)) { + return INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; + } else { + return CUR_UPG_VALUE(UPG_BOMB_BAG) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; + } + case RG_BOMBCHU_DROP: return INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_HOOKSHOT: switch (INV_CONTENT(ITEM_HOOKSHOT)) { diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 4d46fc210..17d89cad2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -58,7 +58,7 @@ class Randomizer { ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData); s16 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); s16 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); - CanObtainResult GetCanObtainFromRandomizerCheck(RandomizerCheck randomizerCheck); + ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); static void CreateCustomMessages(); static std::string RandomizeRupeeName(std::string message, int language); static CustomMessageEntry GetRupeeMessage(u16 rupeeTextId); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 83564b5b9..bd7e25a46 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1027,7 +1027,7 @@ typedef enum { CANT_OBTAIN_ALREADY_HAVE, CANT_OBTAIN_NEED_UPGRADE, CANT_OBTAIN_NEED_EMPTY_BOTTLE, -} CanObtainResult; +} ItemObtainability; typedef struct ScrubIdentity { RandomizerInf randomizerInf; diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index ad46024d4..d812e8824 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1640,7 +1640,7 @@ extern "C" GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId s16 itemID = OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, actorId, actorParams, sceneNum); // This feels awkward, maybe in the future each mod will have it's own obtainability check - if (OTRGlobals::Instance->gRandomizer->GetCanObtainFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { + if (OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { return ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); } @@ -1657,7 +1657,7 @@ extern "C" GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomi s16 itemID = OTRGlobals::Instance->gRandomizer->GetRandomizedItemIdFromKnownCheck(randomizerCheck, ogId); // This feels awkward, maybe in the future each mod will have it's own obtainability check - if (OTRGlobals::Instance->gRandomizer->GetCanObtainFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { + if (OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { return ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index a61669269..ac751cca3 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2559,17 +2559,12 @@ s32 Inventory_HasEmptyBottle(void) { bool Inventory_HasEmptyBottleSlot(void) { u8* items = gSaveContext.inventory.items; - if (items[SLOT_BOTTLE_1] == ITEM_NONE) { - return true; - } else if (items[SLOT_BOTTLE_2] == ITEM_NONE) { - return true; - } else if (items[SLOT_BOTTLE_3] == ITEM_NONE) { - return true; - } else if (items[SLOT_BOTTLE_4] == ITEM_NONE) { - return true; - } else { - return false; - } + return ( + items[SLOT_BOTTLE_1] == ITEM_NONE || + items[SLOT_BOTTLE_2] == ITEM_NONE || + items[SLOT_BOTTLE_3] == ITEM_NONE || + items[SLOT_BOTTLE_4] == ITEM_NONE + ); } s32 Inventory_HasSpecificBottle(u8 bottleItem) { From ee2f38ad910a7c50e21326ca1938f5db16da4a08 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 2 Sep 2022 10:34:20 -0500 Subject: [PATCH 19/52] Renaming of some randomizer item/check/get methods --- .../Enhancements/randomizer/randomizer.cpp | 21 +++++++++++-------- soh/soh/Enhancements/randomizer/randomizer.h | 12 ++++++----- soh/soh/OTRGlobals.cpp | 14 ++++++------- soh/soh/OTRGlobals.h | 4 ++-- soh/src/code/z_en_item00.c | 10 ++++----- .../ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c | 2 +- .../actors/ovl_Door_Warp1/z_door_warp1.c | 2 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 2 +- soh/src/overlays/actors/ovl_En_Si/z_en_si.c | 4 ++-- .../actors/ovl_Item_B_Heart/z_item_b_heart.c | 6 +++--- 10 files changed, 41 insertions(+), 36 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5ba6912c2..3039250c8 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1203,13 +1203,16 @@ bool Randomizer::IsTrialRequired(RandomizerInf trial) { return this->trialsRequired.contains(trial); } -s16 Randomizer::GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) { - s16 itemId = GetItemFromActor(actorId, actorParams, sceneNum, ogId); - return itemId; +RandomizerGet Randomizer::GetRandomizerGetFromActor(s16 actorId, s16 sceneNum, s16 actorParams) { + return this->itemLocations[GetCheckFromActor(actorId, sceneNum, actorParams)]; } -s16 Randomizer::GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId) { - return GetItemIDFromRandomizerGet(this->itemLocations[GetCheckFromActor(sceneNum, actorId, actorParams)], ogItemId); +RandomizerGet Randomizer::GetRandomizerGetFromKnownCheck(RandomizerCheck randomizerCheck) { + return this->itemLocations[randomizerCheck]; +} + +GetItemID Randomizer::GetItemIdFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId) { + return GetItemIdFromRandomizerGet(GetRandomizerGetFromActor(actorId, sceneNum, actorParams), ogItemId); } ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck) { @@ -1555,7 +1558,7 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerCheck(Randomizer } } -GetItemID Randomizer::GetItemIDFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId) { +GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId) { switch (randoGet) { case RG_NONE: return ogItemId; @@ -2382,11 +2385,11 @@ u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) { return this->randoSettings[randoSettingKey]; } -s16 Randomizer::GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId) { - return GetItemIDFromRandomizerGet(this->itemLocations[randomizerCheck], ogId); +GetItemID Randomizer::GetItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId) { + return GetItemIdFromRandomizerGet(this->itemLocations[randomizerCheck], ogItemId); } -RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams) { +RandomizerCheck Randomizer::GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams) { if (!gSaveContext.n64ddFlag) { return RC_UNKNOWN_CHECK; } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 17d89cad2..36b5ac4f0 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -21,8 +21,6 @@ class Randomizer { std::string ganonText; std::unordered_map randoSettings; std::unordered_map randomizerMerchantPrices; - GetItemID GetItemIDFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId); - s16 GetItemFromActor(s16 actorId, s16 actorParams, s16 sceneNum, GetItemID ogItemId); void ParseRandomizerSettingsFile(const char* spoilerFileName); void ParseHintLocationsFile(const char* spoilerFileName); void ParseRequiredTrialsFile(const char* spoilerFileName); @@ -50,15 +48,19 @@ class Randomizer { void LoadItemLocations(const char* spoilerFileName,bool silent); bool IsTrialRequired(RandomizerInf trial); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); - RandomizerCheck GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams); + RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); + RandomizerGet GetRandomizerGetFromActor(s16 actorId, s16 sceneNum, s16 actorParams); + RandomizerGet GetRandomizerGetFromKnownCheck(RandomizerCheck randomizerCheck); std::string GetChildAltarText() const; std::string GetAdultAltarText() const; std::string GetGanonText() const; std::string GetGanonHintText() const; ScrubIdentity IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData); - s16 GetRandomizedItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); - s16 GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); + GetItemID GetItemIdFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId); + GetItemID GetItemIdFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId); + GetItemID GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItemID ogItemId); ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); + ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); static void CreateCustomMessages(); static std::string RandomizeRupeeName(std::string message, int language); static CustomMessageEntry GetRupeeMessage(u16 rupeeTextId); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index d812e8824..d7273fedf 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1582,8 +1582,8 @@ extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey) { return OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(randoSettingKey); } -extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 sceneNum, s16 actorId, s16 actorParams) { - return OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams); +extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams) { + return OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actorId, sceneNum, actorParams); } extern "C" ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData) { @@ -1629,15 +1629,15 @@ extern "C" GetItemEntry ItemTable_RetrieveEntry(s16 tableID, s16 getItemID) { return ItemTableManager::Instance->RetrieveItemEntry(tableID, getItemID); } -extern "C" GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum) { +extern "C" GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId) { s16 getItemModIndex; - RandomizerCheck randomizerCheck = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(sceneNum, actorId, actorParams); + RandomizerCheck randomizerCheck = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actorId, sceneNum, actorParams); if (OTRGlobals::Instance->gRandomizer->CheckContainsVanillaItem(randomizerCheck)) { getItemModIndex = MOD_NONE; } else { getItemModIndex = MOD_RANDOMIZER; } - s16 itemID = OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, actorId, actorParams, sceneNum); + s16 itemID = OTRGlobals::Instance->gRandomizer->GetItemIdFromActor(actorId, sceneNum, actorParams, ogId); // This feels awkward, maybe in the future each mod will have it's own obtainability check if (OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { @@ -1654,7 +1654,7 @@ extern "C" GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomi } else { getItemModIndex = MOD_RANDOMIZER; } - s16 itemID = OTRGlobals::Instance->gRandomizer->GetRandomizedItemIdFromKnownCheck(randomizerCheck, ogId); + s16 itemID = OTRGlobals::Instance->gRandomizer->GetItemIdFromKnownCheck(randomizerCheck, ogId); // This feels awkward, maybe in the future each mod will have it's own obtainability check if (OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { @@ -1719,7 +1719,7 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) { } RandomizerCheck hintCheck = - Randomizer_GetCheckFromActor(globalCtx->sceneNum, msgCtx->talkActor->id, actorParams); + Randomizer_GetCheckFromActor(msgCtx->talkActor->id, globalCtx->sceneNum, actorParams); messageEntry = Randomizer_GetHintFromCheck(hintCheck); } else if (textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index e1541f0a8..e157db72e 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -97,13 +97,13 @@ void* getN64WeirdFrame(s32 i); Sprite* GetSeedTexture(uint8_t index); void Randomizer_LoadSettings(const char* spoilerFileName); u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey); -RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 actorParams, s16 sceneNum); +RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); ScrubIdentity Randomizer_IdentifyScrub(s32 sceneNum, s32 actorParams, s32 respawnData); void Randomizer_LoadHintLocations(const char* spoilerFileName); void Randomizer_LoadRequiredTrials(const char* spoilerFileName); void Randomizer_LoadItemLocations(const char* spoilerFileName, bool silent); bool Randomizer_IsTrialRequired(RandomizerInf trial); -GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId, s16 actorParams, s16 sceneNum); +GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId); bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor); bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId); diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 95375ea48..1ceff9f0d 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -520,7 +520,7 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) { func_8002F554(&this->actor, globalCtx, getItemId); } } else { - getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId); GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } } @@ -686,7 +686,7 @@ void func_8001E5C8(EnItem00* this, GlobalContext* globalCtx) { func_8002F434(&this->actor, globalCtx, this->getItemId, 50.0f, 80.0f); } else { GetItemEntry getItemEntry = - Randomizer_GetRandomizedItem(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, this->getItemId); GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 50.0f, 80.0f); } this->unk_15A++; @@ -911,7 +911,7 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) { if (!gSaveContext.n64ddFlag) { func_8002F554(&this->actor, globalCtx, getItemId); } else { - getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId); getItemId = getItem.getItemId; GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } @@ -1380,7 +1380,7 @@ void EnItem00_DrawCollectible(EnItem00* this, GlobalContext* globalCtx) { f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItemEntry randoGetItemEntry = - Randomizer_GetRandomizedItem(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, this->getItemId); EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry); GetItemEntry_Draw(globalCtx, randoGetItemEntry); } else { @@ -1442,7 +1442,7 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) { f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItemEntry randoGetItemEntry = - Randomizer_GetRandomizedItem(GI_HEART_PIECE, this->actor.id, this->ogParams, globalCtx->sceneNum); + Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, GI_HEART_PIECE); EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry); GetItemEntry_Draw(globalCtx, randoGetItemEntry); } else { diff --git a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c index e04755a34..33adac2cf 100644 --- a/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c +++ b/soh/src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.c @@ -70,7 +70,7 @@ const ActorInit Bg_Dy_Yoseizo_InitVars = { void GivePlayerRandoRewardGreatFairy(BgDyYoseizo* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_NONE, this->actor.id, this->fountainType + 1, globalCtx->sceneNum); + GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->fountainType + 1, GI_NONE); if (this->actor.parent == GET_PLAYER(globalCtx) && !Flags_GetTreasure(globalCtx, this->fountainType + 1) && !Player_InBlockingCsMode(globalCtx, GET_PLAYER(globalCtx))) { 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 e372d3291..39b754fb8 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 @@ -462,7 +462,7 @@ s32 DoorWarp1_PlayerInRange(DoorWarp1* this, GlobalContext* globalCtx) { } void GivePlayerRandoReward(DoorWarp1* this, Player* player, GlobalContext* globalCtx, u8 ruto, u8 adult) { - GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_NONE, this->actor.id, this->actor.params, globalCtx->sceneNum); + GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_NONE); if (this->actor.parent != NULL && this->actor.parent->id == GET_PLAYER(globalCtx)->actor.id && !Flags_GetTreasure(globalCtx, 0x1F)) { diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 3e78982a3..26d29b6d4 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -446,7 +446,7 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) { func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos); if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f && Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) { - sItem = Randomizer_GetRandomizedItem(this->dyna.actor.params >> 5 & 0x7F, this->dyna.actor.id, this->dyna.actor.params, globalCtx->sceneNum); + sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, globalCtx->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F); GetItemEntry blueRupee = ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); // RANDOTODO treasure chest game rando diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 39e1195f5..b955eda0e 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -187,7 +187,7 @@ void EnSi_Draw(Actor* thisx, GlobalContext* globalCtx) { if (!gSaveContext.n64ddFlag) { GetItem_Draw(globalCtx, GID_SKULL_TOKEN_2); } else { - getItem = Randomizer_GetRandomizedItem(GI_SKULL_TOKEN, this->actor.id, this->actor.params, globalCtx->sceneNum); + getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_SKULL_TOKEN); EnItem00_CustomItemsParticles(&this->actor, globalCtx, getItem); if (getItem.itemId != ITEM_SKULL_TOKEN) { f32 mtxScale = 1.5f; @@ -202,7 +202,7 @@ void EnSi_Draw(Actor* thisx, GlobalContext* globalCtx) { void Randomizer_UpdateSkullReward(EnSi* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - getItem = Randomizer_GetRandomizedItem(GI_SKULL_TOKEN, this->actor.id, this->actor.params, globalCtx->sceneNum); + getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_SKULL_TOKEN); getItemId = getItem.getItemId; if (getItemId == RG_ICE_TRAP) { player->pendingIceTrap = true; diff --git a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c index f4181146a..b785d35fa 100644 --- a/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c +++ b/soh/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c @@ -62,7 +62,7 @@ void ItemBHeart_Update(Actor* thisx, GlobalContext* globalCtx) { if (!gSaveContext.n64ddFlag) { func_8002F434(&this->actor, globalCtx, GI_HEART_CONTAINER_2, 30.0f, 40.0f); } else { - GetItemEntry getItemEntry = Randomizer_GetRandomizedItem(GI_HEART_CONTAINER_2, this->actor.id, this->actor.params, globalCtx->sceneNum); + GetItemEntry getItemEntry = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->actor.params, GI_HEART_CONTAINER_2); GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 30.0f, 40.0f); } } @@ -99,8 +99,8 @@ void ItemBHeart_Draw(Actor* thisx, GlobalContext* globalCtx) { } if (gSaveContext.n64ddFlag) { - GetItemEntry_Draw(globalCtx, Randomizer_GetRandomizedItem(GI_HEART_CONTAINER_2, - this->actor.id,this->actor.params, globalCtx->sceneNum)); + GetItemEntry_Draw(globalCtx, Randomizer_GetItemFromActor(this->actor.id, + globalCtx->sceneNum,this->actor.params, GI_HEART_CONTAINER_2)); } else { if (flag) { func_80093D84(globalCtx->state.gfxCtx); From 64aca784507fdcebd81e216ea3489739550d6a1a Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Fri, 2 Sep 2022 13:19:12 -0400 Subject: [PATCH 20/52] Fixes Switch/Wii U crashes with Wonder Rupees and Bottleable Entities (#1360) * Reorders switch statement to prevent some code that shouldn't execute. * Potentially fixes bottleable entities crash * Solves lack of ItemEntry for GI_MAX * Adds comment clarifying new GetItemEntry --- soh/soh/OTRGlobals.cpp | 3 ++- soh/soh/OTRGlobals.h | 1 - soh/soh/z_play_otr.cpp | 1 - soh/src/code/z_en_item00.c | 10 +++++----- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index cdab324d4..66aa22868 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -289,6 +289,7 @@ extern "C" void VanillaItemTable_Init() { GET_ITEM(ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG_50, 0x6C, 0x80, CHEST_ANIM_LONG, MOD_NONE, GI_BULLET_BAG_50), GET_ITEM_NONE, GET_ITEM_NONE, + GET_ITEM_NONE // GI_MAX - if you need to add to this table insert it before this entry. }; ItemTableManager::Instance->AddItemTable(MOD_NONE); for (uint8_t i = 0; i < ARRAY_COUNT(getItemTable); i++) { @@ -1613,7 +1614,7 @@ extern "C" CustomMessageEntry Randomizer_GetHintFromCheck(RandomizerCheck check) } extern "C" GetItemEntry ItemTable_Retrieve(int16_t getItemID) { - GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(OTRGlobals::Instance->getItemModIndex, getItemID); + GetItemEntry giEntry = ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, getItemID); return giEntry; } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 089394e33..4858c41b2 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -21,7 +21,6 @@ public: std::shared_ptr context; std::shared_ptr gSaveStateMgr; std::shared_ptr gRandomizer; - uint16_t getItemModIndex; OTRGlobals(); ~OTRGlobals(); diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index d0137644c..1a07ceb7e 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -60,7 +60,6 @@ void OTRGameplay_InitScene(GlobalContext* globalCtx, s32 spawn) { globalCtx->cUpElfMsgs = nullptr; globalCtx->setupPathList = nullptr; globalCtx->numSetupActors = 0; - OTRGlobals::Instance->getItemModIndex = MOD_NONE; Object_InitBank(globalCtx, &globalCtx->objectCtx); LightContext_Init(globalCtx, &globalCtx->lightCtx); TransitionActor_InitContext(&globalCtx->state, &globalCtx->transiActorCtx); diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 54beafdab..899984b89 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -515,13 +515,13 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) { } if (!Actor_HasParent(&this->actor, globalCtx)) { - if (!gSaveContext.n64ddFlag) { - if (getItemId != GI_NONE) { + if (getItemId != GI_NONE) { + if (!gSaveContext.n64ddFlag) { func_8002F554(&this->actor, globalCtx, getItemId); + } else { + getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } - } else { - getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); - GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } } From 1659f1f3869cc9b5ec843d34840d502f9b154714 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 2 Sep 2022 14:00:10 -0500 Subject: [PATCH 21/52] Re-add GetItemObtainabilityFromRandomizerCheck --- soh/soh/Enhancements/randomizer/randomizer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3039250c8..fe503694c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1216,7 +1216,11 @@ GetItemID Randomizer::GetItemIdFromActor(s16 actorId, s16 sceneNum, s16 actorPar } ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck) { - switch (this->itemLocations[randomizerCheck]) { + return GetItemObtainabilityFromRandomizerGet(GetRandomizerGetFromKnownCheck(randomizerCheck)); +} + +ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGet randoGet) { + switch (randoGet) { case RG_NONE: case RG_TRIFORCE: case RG_HINT: From 1aa33a794035d386a0e16c30d3262836d647cdd4 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 2 Sep 2022 14:17:45 -0500 Subject: [PATCH 22/52] Remove comments in OTRGlobals --- soh/soh/OTRGlobals.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index d812e8824..72d08b4e8 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1639,7 +1639,6 @@ extern "C" GetItemEntry Randomizer_GetRandomizedItem(GetItemID ogId, s16 actorId } s16 itemID = OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, actorId, actorParams, sceneNum); - // This feels awkward, maybe in the future each mod will have it's own obtainability check if (OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { return ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); } @@ -1656,7 +1655,6 @@ extern "C" GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomi } s16 itemID = OTRGlobals::Instance->gRandomizer->GetRandomizedItemIdFromKnownCheck(randomizerCheck, ogId); - // This feels awkward, maybe in the future each mod will have it's own obtainability check if (OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerCheck(randomizerCheck) != CAN_OBTAIN) { return ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE); } From 0cdcc27e53c01889577b3c307611e272d98dd76b Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Fri, 2 Sep 2022 15:45:55 -0400 Subject: [PATCH 23/52] Fixes Ganon's Boss Key shuffled while regular boss Keys aren't. --- soh/soh/Enhancements/randomizer/randomizer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 9bf46e430..115d10697 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1471,12 +1471,17 @@ s16 Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) { case RG_WATER_TEMPLE_BOSS_KEY: case RG_SPIRIT_TEMPLE_BOSS_KEY: case RG_SHADOW_TEMPLE_BOSS_KEY: - case RG_GANONS_CASTLE_BOSS_KEY: if (GetRandoSettingValue(RSK_BOSS_KEYSANITY) < 3) { return GI_KEY_BOSS; } else { return randoGet; } + case RG_GANONS_CASTLE_BOSS_KEY: + if (GetRandoSettingValue(RSK_GANONS_BOSS_KEY) < 3) { + return GI_KEY_BOSS; + } else { + return randoGet; + } case RG_FOREST_TEMPLE_SMALL_KEY: case RG_FIRE_TEMPLE_SMALL_KEY: From f6fd116adbbad06cd9e1415fcd5122a76e4327a8 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 2 Sep 2022 20:19:28 -0500 Subject: [PATCH 24/52] Cast randoGet for ganons boss key --- soh/soh/Enhancements/randomizer/randomizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b6693a8e2..b8442e241 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1858,7 +1858,7 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem if (GetRandoSettingValue(RSK_GANONS_BOSS_KEY) < 3) { return GI_KEY_BOSS; } else { - return randoGet; + return (GetItemID)randoGet; } case RG_FOREST_TEMPLE_SMALL_KEY: From 0ce0ab1260dd24ac6168d1cdd28d60f21554cd86 Mon Sep 17 00:00:00 2001 From: David Chavez Date: Sat, 3 Sep 2022 06:00:04 +0200 Subject: [PATCH 25/52] Phase 1: Separate ImGui Drawing From LUS (#1310) * Update LUS imported paths * Introduce GameMenuBar * Fix imports after LUS import paths change * Move Randomizer * Replace needs_save * Migrate Developer Tools * Migrate Cheats * Migrate Enhancements * Separate UIWidgets * Add missing Hooks.cpp file * Migrate Settings * Remove UI methods from LUS * Cleanup imports and exposed properties * Cleanup more methods * Fix project generation * Fix CI compilation * Remove resolved TODO --- libultraship/libultraship/CMakeLists.txt | 1 + libultraship/libultraship/GameOverlay.cpp | 18 +- libultraship/libultraship/ImGuiImpl.cpp | 2119 ++--------------- libultraship/libultraship/ImGuiImpl.h | 87 +- .../include/spdlog/sinks/sohconsole_sink.h | 6 +- libultraship/libultraship/Window.cpp | 2 +- soh/CMakeLists.txt | 14 +- soh/include/global.h | 2 +- soh/include/macros.h | 2 +- soh/include/z64.h | 2 +- soh/include/z64audio.h | 6 +- soh/include/z64effect.h | 2 +- soh/include/z64light.h | 2 +- soh/include/z64transition.h | 2 +- .../controls/GameControlEditor.cpp | 50 +- .../cosmetics/CosmeticsEditor.cpp | 201 +- .../Enhancements/cosmetics/CosmeticsEditor.h | 4 +- soh/soh/Enhancements/debugconsole.cpp | 108 +- .../Enhancements/debugger/ImGuiHelpers.cpp | 22 - soh/soh/Enhancements/debugger/ImGuiHelpers.h | 8 - soh/soh/Enhancements/debugger/actorViewer.cpp | 16 +- soh/soh/Enhancements/debugger/colViewer.cpp | 50 +- .../Enhancements/debugger/debugSaveEditor.cpp | 158 +- soh/soh/Enhancements/gameconsole.h | 4 +- .../randomizer/3drando/entrance.cpp | 2 +- .../Enhancements/randomizer/3drando/fill.cpp | 2 +- .../Enhancements/randomizer/3drando/hints.cpp | 2 +- .../randomizer/3drando/item_location.cpp | 4 +- .../randomizer/3drando/item_pool.cpp | 2 +- .../Enhancements/randomizer/3drando/menu.cpp | 6 +- .../randomizer/3drando/rando_main.cpp | 8 +- .../randomizer/3drando/spoiler_log.cpp | 6 +- .../Enhancements/randomizer/randomizer.cpp | 222 +- .../randomizer/randomizer_item_tracker.cpp | 33 +- soh/soh/Enhancements/savestates.cpp | 14 +- soh/soh/GameMenuBar.cpp | 1367 +++++++++++ soh/soh/GameMenuBar.hpp | 27 + soh/soh/OTRGlobals.cpp | 52 +- soh/soh/OTRGlobals.h | 2 +- soh/soh/SaveManager.cpp | 4 +- soh/soh/SaveManager.h | 2 +- soh/soh/UIWidgets.cpp | 523 ++++ soh/soh/UIWidgets.hpp | 49 + soh/soh/frame_interpolation.cpp | 2 +- soh/soh/z_message_OTR.cpp | 12 +- soh/soh/z_play_otr.cpp | 12 +- soh/soh/z_scene_otr.cpp | 20 +- soh/src/code/audio_playback.c | 2 +- soh/src/code/audio_synthesis.c | 2 +- soh/src/code/code_800F9280.c | 4 +- soh/src/code/z_play.c | 2 +- .../overlays/gamestates/ovl_title/z_title.c | 2 +- 52 files changed, 2719 insertions(+), 2552 deletions(-) delete mode 100644 soh/soh/Enhancements/debugger/ImGuiHelpers.cpp delete mode 100644 soh/soh/Enhancements/debugger/ImGuiHelpers.h create mode 100644 soh/soh/GameMenuBar.cpp create mode 100644 soh/soh/GameMenuBar.hpp create mode 100644 soh/soh/UIWidgets.cpp create mode 100644 soh/soh/UIWidgets.hpp diff --git a/libultraship/libultraship/CMakeLists.txt b/libultraship/libultraship/CMakeLists.txt index aec229bfb..d2b35a1f8 100644 --- a/libultraship/libultraship/CMakeLists.txt +++ b/libultraship/libultraship/CMakeLists.txt @@ -121,6 +121,7 @@ set(Source_Files__CustomImpl source_group("Source Files\\CustomImpl" FILES ${Source_Files__CustomImpl}) set(Source_Files__CustomImpl__Hooks + "Hooks.cpp" "Hooks.h" ) source_group("Source Files\\CustomImpl\\Hooks" FILES ${Source_Files__CustomImpl__Hooks}) diff --git a/libultraship/libultraship/GameOverlay.cpp b/libultraship/libultraship/GameOverlay.cpp index b5225e22e..a331c5cf6 100644 --- a/libultraship/libultraship/GameOverlay.cpp +++ b/libultraship/libultraship/GameOverlay.cpp @@ -16,28 +16,28 @@ namespace Ship { if (CVar_Get(args[2].c_str()) != nullptr) { const char* key = args[2].c_str(); - GameOverlay* overlay = SohImGui::overlay; + GameOverlay* overlay = SohImGui::GetGameOverlay(); if (args[1] == "add") { if (!overlay->RegisteredOverlays.contains(key)) { overlay->RegisteredOverlays[key] = new Overlay({ OverlayType::TEXT, ImStrdup(key), -1.0f }); - SohImGui::console->SendInfoMessage("Added overlay: %s", key); + SohImGui::GetConsole()->SendInfoMessage("Added overlay: %s", key); } else { - SohImGui::console->SendErrorMessage("Overlay already exists: %s", key); + SohImGui::GetConsole()->SendErrorMessage("Overlay already exists: %s", key); } } else if (args[1] == "remove") { if (overlay->RegisteredOverlays.contains(key)) { overlay->RegisteredOverlays.erase(key); - SohImGui::console->SendInfoMessage("Removed overlay: %s", key); + SohImGui::GetConsole()->SendInfoMessage("Removed overlay: %s", key); } else { - SohImGui::console->SendErrorMessage("Overlay not found: %s", key); + SohImGui::GetConsole()->SendErrorMessage("Overlay not found: %s", key); } } } else { - SohImGui::console->SendErrorMessage("CVar {} does not exist", args[2].c_str()); + SohImGui::GetConsole()->SendErrorMessage("CVar {} does not exist", args[2].c_str()); } return CMD_SUCCESS; @@ -124,7 +124,7 @@ namespace Ship { else text_display_end = text_end; - GameOverlay* overlay = SohImGui::overlay; + GameOverlay* overlay = SohImGui::GetGameOverlay(); ImFont* font = overlay->CurrentFont == "Default" ? g.Font : overlay->Fonts[overlay->CurrentFont]; const float font_size = font->FontSize; @@ -157,7 +157,7 @@ namespace Ship { } } - SohImGui::console->AddCommand("overlay", { OverlayCommand, "Draw an overlay using a cvar value" }); + SohImGui::GetConsole()->AddCommand("overlay", { OverlayCommand, "Draw an overlay using a cvar value" }); } void GameOverlay::DrawSettings() { @@ -167,7 +167,7 @@ namespace Ship { if (ImGui::Selectable(name.c_str(), name == this->CurrentFont)) { this->CurrentFont = name; CVar_SetString("gOverlayFont", ImStrdup(name.c_str())); - SohImGui::needs_save = true; + SohImGui::RequestCvarSaveOnNextTick(); } } diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index ed3287a5c..a8901b5a6 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -7,13 +7,6 @@ #include #include -#include -#include -#include -#include -#include -#include "../../soh/include/z64audio.h" -#include "Archive.h" #include "Console.h" #include "Hooks.h" #define IMGUI_DEFINE_MATH_OPERATORS @@ -27,7 +20,6 @@ #include "Lib/stb/stb_image.h" #include "Lib/Fast3D/gfx_rendering_api.h" #include "Lib/spdlog/include/spdlog/common.h" -#include "UltraController.h" #ifdef __WIIU__ #include // GX2SetViewport / GX2SetScissor @@ -69,12 +61,8 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPAR using namespace Ship; bool oldCursorState = true; -#define EXPERIMENTAL() \ - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ - InsertPadding(3.0f); \ - ImGui::Text("Experimental"); \ - ImGui::PopStyleColor(); \ - PaddedSeparator(false, true); +#define BindButton(btn, status) ImGui::Image(GetTextureByID(DefaultAssets[btn]->textureId), ImVec2(16.0f * scale, 16.0f * scale), ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, (status) ? 255 : 0)); + #define TOGGLE_BTN ImGuiKey_F1 #define TOGGLE_PAD_BTN ImGuiKey_GamepadBack #define HOOK(b) if(b) needs_save = true; @@ -83,21 +71,6 @@ OSContPad* pads; std::map DefaultAssets; std::vector emptyArgs; -bool isBetaQuestEnabled = false; - -enum SeqPlayers { - /* 0 */ SEQ_BGM_MAIN, - /* 1 */ SEQ_FANFARE, - /* 2 */ SEQ_SFX, - /* 3 */ SEQ_BGM_SUB, - /* 4 */ SEQ_MAX -}; - -extern "C" { - void enableBetaQuest() { isBetaQuestEnabled = true; } - void disableBetaQuest() { isBetaQuestEnabled = false; } -} - namespace SohImGui { WindowImpl impl; @@ -106,7 +79,10 @@ namespace SohImGui { GameOverlay* overlay = new GameOverlay; InputEditor* controller = new InputEditor; static ImVector s_GroupPanelLabelStack; - bool p_open = false; + + std::function clientDrawMenu; + std::function clientSetupHooks; + bool needs_save = false; int lastBackendID = 0; bool statsWindowOpen; @@ -132,32 +108,12 @@ namespace SohImGui { #endif }; - - const char* powers[9] = { - "Vanilla (1x)", - "Double (2x)", - "Quadruple (4x)", - "Octuple (8x)", - "Hexadecuple (16x)", - "Duotrigintuple (32x)", - "Quattuorsexagintuple (64x)", - "Octoviginticentuple (128x)", - "Hexaquinquagintiducentuple (256x)" - }; - std::map> hiddenwindowCategories; std::map> windowCategories; std::map customWindows; - void UpdateAudio() { - Audio_SetGameVolume(SEQ_BGM_MAIN, CVar_GetFloat("gMainMusicVolume", 1)); - Audio_SetGameVolume(SEQ_BGM_SUB, CVar_GetFloat("gSubMusicVolume", 1)); - Audio_SetGameVolume(SEQ_FANFARE, CVar_GetFloat("gSFXMusicVolume", 1)); - Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1)); - } - void InitSettings() { - Ship::RegisterHook(UpdateAudio); + clientSetupHooks(); Ship::RegisterHook([] { gfx_get_current_rendering_api()->set_texture_filter((FilteringMode)CVar_GetS32("gTextureFilter", FILTER_THREE_POINT)); if (CVar_GetS32("gConsoleEnabled", 0)) { @@ -171,8 +127,6 @@ namespace SohImGui { } else { controller->Close(); } - - UpdateAudio(); }); } @@ -191,16 +145,6 @@ namespace SohImGui { return 0; } - int ClampFloatToInt(float value, int min, int max) { - return fmin(fmax(value, min), max); - } - - void Tooltip(const char* text) { - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("%s", BreakTooltip(text, 60).c_str()); - } - } - void ImGuiWMInit() { switch (impl.backend) { #ifdef __WIIU__ @@ -352,26 +296,6 @@ namespace SohImGui { } } - void ShowCursor(bool hide, Dialogues d) { - if (d == Dialogues::dLoadSettings) { - Window::GetInstance()->ShowCursor(hide); - return; - } - - if (d == Dialogues::dConsole && CVar_GetS32("gOpenMenuBar", 0)) { - return; - } - if (!Window::GetInstance()->IsFullscreen()) { - oldCursorState = false; - return; - } - - if (oldCursorState != hide) { - oldCursorState = hide; - Window::GetInstance()->ShowCursor(hide); - } - } - void LoadTexture(const std::string& name, const std::string& path) { GfxRenderingAPI* api = gfx_get_current_rendering_api(); const auto res = Window::GetInstance()->GetResourceManager()->LoadFile(path); @@ -392,65 +316,7 @@ namespace SohImGui { stbi_image_free(img_data); } - void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha) - { - Color_RGBA8 defaultColors; - defaultColors.r = default_colors.x; - defaultColors.g = default_colors.y; - defaultColors.b = default_colors.z; - defaultColors.a = default_colors.w; - - Color_RGBA8 cvarColor = CVar_GetRGBA(cvarname, defaultColors); - - ColorArray.x = cvarColor.r / 255.0; - ColorArray.y = cvarColor.g / 255.0; - ColorArray.z = cvarColor.b / 255.0; - ColorArray.w = cvarColor.a / 255.0; - } - - void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) { - GfxRenderingAPI* api = gfx_get_current_rendering_api(); - const auto res = static_cast(Window::GetInstance()->GetResourceManager()->LoadResource(path).get()); - - std::vector texBuffer; - texBuffer.reserve(res->width * res->height * 4); - - switch (res->texType) { - case Ship::TextureType::RGBA32bpp: - texBuffer.assign(res->imageData, res->imageData + (res->width * res->height * 4)); - break; - case Ship::TextureType::GrayscaleAlpha8bpp: - for (int32_t i = 0; i < res->width * res->height; i++) { - uint8_t ia = res->imageData[i]; - uint8_t color = ((ia >> 4) & 0xF) * 255 / 15; - uint8_t alpha = (ia & 0xF) * 255 / 15; - texBuffer.push_back(color); - texBuffer.push_back(color); - texBuffer.push_back(color); - texBuffer.push_back(alpha); - } - break; - default: - // TODO convert other image types - SPDLOG_WARN("SohImGui::LoadResource: Attempting to load unsupporting image type %s", path.c_str()); - return; - } - - for (size_t pixel = 0; pixel < texBuffer.size() / 4; pixel++) { - texBuffer[pixel * 4 + 0] *= tint.x; - texBuffer[pixel * 4 + 1] *= tint.y; - texBuffer[pixel * 4 + 2] *= tint.z; - texBuffer[pixel * 4 + 3] *= tint.w; - } - - const auto asset = new GameAsset{ api->new_texture() }; - - api->select_texture(0, asset->textureId); - api->set_sampler_parameters(0, false, 0, 0); - api->upload_texture(texBuffer.data(), res->width, res->height); - - DefaultAssets[name] = asset; - } + // MARK: - Public API void Init(WindowImpl window_impl) { CVar_Load(); @@ -549,427 +415,6 @@ namespace SohImGui { ImGuiProcessEvent(event); } -#define BindButton(btn, status) ImGui::Image(GetTextureByID(DefaultAssets[btn]->textureId), ImVec2(16.0f * scale, 16.0f * scale), ImVec2(0, 0), ImVec2(1.0f, 1.0f), ImVec4(255, 255, 255, (status) ? 255 : 0)); - - void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId) - { - float value = CVar_GetFloat(key, defaultValue); - - ImGui::Text(name, static_cast(100 * value)); - if (ImGui::SliderFloat((std::string("##") + key).c_str(), &value, 0.0f, 1.0f, "")) { - const float volume = floorf(value * 100) / 100; - CVar_SetFloat(key, volume); - needs_save = true; - Audio_SetGameVolume(playerId, volume); - } - } - - void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue = 0) { - if (FirstTimeValue <= 0) { - FirstTimeValue = 0; - } - uint8_t selected = CVar_GetS32(name, FirstTimeValue); - uint8_t DefaultValue = selected; - std::string comboName = std::string("##") + std::string(name); - if (ImGui::BeginCombo(comboName.c_str(), ComboArray[DefaultValue])) { - for (uint8_t i = 0; i < arraySize; i++) { - if (strlen(ComboArray[i]) > 1) { - if (ImGui::Selectable(ComboArray[i], i == selected)) { - CVar_SetS32(name, i); - selected = i; - needs_save = true; - } - } - } - ImGui::EndCombo(); - } - } - - void EnhancementRadioButton(const char* text, const char* cvarName, int id) { - /*Usage : - EnhancementRadioButton("My Visible Name","gMyCVarName", MyID); - First arg is the visible name of the Radio button - Second is the cvar name where MyID will be saved. - Note: the CVar name should be the same to each Buddies. - Example : - EnhancementRadioButton("English", "gLanguages", 0); - EnhancementRadioButton("German", "gLanguages", 1); - EnhancementRadioButton("French", "gLanguages", 2); - */ - std::string make_invisible = "##"; - make_invisible += text; - make_invisible += cvarName; - - int val = CVar_GetS32(cvarName, 0); - if (ImGui::RadioButton(make_invisible.c_str(), id == val)) { - CVar_SetS32(cvarName, id); - needs_save = true; - } - ImGui::SameLine(); - ImGui::Text("%s", text); - } - - void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) - { - float thickness = ImMax(sz / 5.0f, 1.0f); - sz -= thickness * 0.5f; - pos += ImVec2(thickness * 0.25f, thickness * 0.25f); - - draw_list->PathLineTo(ImVec2(pos.x, pos.y)); - draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y + sz)); - draw_list->PathStroke(col, 0, thickness); - - draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y)); - draw_list->PathLineTo(ImVec2(pos.x, pos.y + sz)); - draw_list->PathStroke(col, 0, thickness); - } - - bool CustomCheckbox(const char* label, bool* v, bool disabled, ImGuiCheckboxGraphics disabledGraphic) { - ImGuiWindow* window = ImGui::GetCurrentWindow(); - if (window->SkipItems) - return false; - - ImGuiContext& g = *GImGui; - const ImGuiStyle& style = g.Style; - const ImGuiID id = window->GetID(label); - const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); - - const float square_sz = ImGui::GetFrameHeight(); - const ImVec2 pos = window->DC.CursorPos; - const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); - ImGui::ItemSize(total_bb, style.FramePadding.y); - if (!ImGui::ItemAdd(total_bb, id)) - { - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); - return false; - } - - bool hovered, held; - bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held); - if (pressed) - { - *v = !(*v); - ImGui::MarkItemEdited(id); - } - - const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); - ImGui::RenderNavHighlight(total_bb, id); - ImGui::RenderFrame(check_bb.Min, check_bb.Max, ImGui::GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); - ImU32 check_col = ImGui::GetColorU32(ImGuiCol_CheckMark); - ImU32 cross_col = ImGui::GetColorU32(ImVec4(0.50f, 0.50f, 0.50f, 1.00f)); - bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0; - if (mixed_value) - { - // Undocumented tristate/mixed/indeterminate checkbox (#2644) - // This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox) - ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f))); - window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); - } - else if ((!disabled && *v) || (disabled && disabledGraphic == ImGuiCheckboxGraphics::Checkmark)) - { - const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); - ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); - } - else if (disabled && disabledGraphic == ImGuiCheckboxGraphics::Cross) { - const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); - RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f); - } - - ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); - if (g.LogEnabled) - ImGui::LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); - if (label_size.x > 0.0f) - ImGui::RenderText(label_pos, label); - - IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); - return pressed; - } - - void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, ImGuiCheckboxGraphics disabledGraphic) - { - if (disabled) { - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); - } - bool val = (bool)CVar_GetS32(cvarName, 0); - if (CustomCheckbox(text, &val, disabled, disabledGraphic)) { - CVar_SetS32(cvarName, val); - needs_save = true; - } - - if (disabled) { - ImGui::PopStyleVar(1); - if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && disabledTooltipText != "") { - ImGui::SetTooltip("%s", disabledTooltipText); - } - ImGui::PopItemFlag(); - } - } - - void EnhancementButton(const char* text, const char* cvarName) - { - bool val = (bool)CVar_GetS32(cvarName, 0); - if (ImGui::Button(text)) { - CVar_SetS32(cvarName, !val); - CVar_SetS32(cvarName, !val); - needs_save = true; - } - } - - void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton) - { - int val = CVar_GetS32(cvarName, defaultValue); - ImGui::Text(text, val); - if(PlusMinusButton) { - std::string MinusBTNName = " - ##"; - MinusBTNName += cvarName; - if (ImGui::Button(MinusBTNName.c_str())) { - val--; - CVar_SetS32(cvarName, val); - needs_save = true; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - } - - if (ImGui::SliderInt(id, &val, min, max, format)) - { - CVar_SetS32(cvarName, val); - needs_save = true; - } - - if(PlusMinusButton) { - std::string PlusBTNName = " + ##"; - PlusBTNName += cvarName; - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(PlusBTNName.c_str())) { - val++; - CVar_SetS32(cvarName, val); - needs_save = true; - } - } - - if (val < min) - { - val = min; - CVar_SetS32(cvarName, val); - needs_save = true; - } - - if (val > max) - { - val = max; - CVar_SetS32(cvarName, val); - needs_save = true; - } - } - - void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton) - { - float val = CVar_GetFloat(cvarName, defaultValue); - - if (!isPercentage) - ImGui::Text(text, val); - else - ImGui::Text(text, static_cast(100 * val)); - - InsertPadding(); - - if(PlusMinusButton) { - std::string MinusBTNName = " - ##"; - MinusBTNName += cvarName; - if (ImGui::Button(MinusBTNName.c_str())) { - if (!isPercentage) - val -= 0.1f; - else - val -= 0.01f; - CVar_SetFloat(cvarName, val); - needs_save = true; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - } - if (PlusMinusButton) { - #ifdef __WIIU__ - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2); - #else - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); - #endif - } - if (ImGui::SliderFloat(id, &val, min, max, format)) - { - CVar_SetFloat(cvarName, val); - needs_save = true; - } - if (PlusMinusButton) { - ImGui::PopItemWidth(); - } - if(PlusMinusButton) { - std::string PlusBTNName = " + ##"; - PlusBTNName += cvarName; - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(PlusBTNName.c_str())) { - if (!isPercentage) - val += 0.1f; - else - val += 0.01f; - CVar_SetFloat(cvarName, val); - needs_save = true; - } - } - - if (val < min) - { - val = min; - CVar_SetFloat(cvarName, val); - needs_save = true; - } - - if (val > max) - { - val = max; - CVar_SetFloat(cvarName, val); - needs_save = true; - } - } - - void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue) { - - if (ImGui::BeginCombo(name.c_str(), items[static_cast(CVar_GetS32(cvarName, defaultValue))].c_str())) { - for (int settingIndex = 0; settingIndex < (int) items.size(); settingIndex++) { - if (ImGui::Selectable(items[settingIndex].c_str())) { - CVar_SetS32(cvarName, settingIndex); - needs_save = true; - - } - } - ImGui::EndCombo(); - } - } - - void RandomizeColor(const char* cvarName, ImVec4* colors) { - Color_RGBA8 NewColors = {0,0,0,255}; - std::string Cvar_RBM = cvarName; - Cvar_RBM += "RBM"; - std::string MakeInvisible = "##"; - MakeInvisible += cvarName; - MakeInvisible += "Random"; - std::string FullName = "Random"; - FullName += MakeInvisible; - if (ImGui::Button(FullName.c_str())) { - s16 RND_R = rand() % (255 - 0); - s16 RND_G = rand() % (255 - 0); - s16 RND_B = rand() % (255 - 0); - colors->x = (float)RND_R / 255; - colors->y = (float)RND_G / 255; - colors->z = (float)RND_B / 255; - NewColors.r = ClampFloatToInt(colors->x * 255, 0, 255); - NewColors.g = ClampFloatToInt(colors->y * 255, 0, 255); - NewColors.b = ClampFloatToInt(colors->z * 255, 0, 255); - CVar_SetRGBA(cvarName, NewColors); - CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. - needs_save = true; - } - Tooltip("Chooses a random color\nOverwrites previously chosen color"); - } - - void RainbowColor(const char* cvarName, ImVec4* colors) { - std::string Cvar_RBM = cvarName; - Cvar_RBM += "RBM"; - std::string MakeInvisible = "Rainbow"; - MakeInvisible += "##"; - MakeInvisible += cvarName; - MakeInvisible += "Rainbow"; - - EnhancementCheckbox(MakeInvisible.c_str(), Cvar_RBM.c_str()); - Tooltip("Cycles through colors on a timer\nOverwrites previously chosen color"); - } - - void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha) { - std::string Cvar_RBM = cvarName; - Cvar_RBM += "RBM"; - std::string MakeInvisible = "Reset"; - MakeInvisible += "##"; - MakeInvisible += cvarName; - MakeInvisible += "Reset"; - if (ImGui::Button(MakeInvisible.c_str())) { - colors->x = defaultcolors.x; - colors->y = defaultcolors.y; - colors->z = defaultcolors.z; - if (has_alpha) { colors->w = defaultcolors.w; }; - - Color_RGBA8 colorsRGBA; - colorsRGBA.r = defaultcolors.x; - colorsRGBA.g = defaultcolors.y; - colorsRGBA.b = defaultcolors.z; - if (has_alpha) { colorsRGBA.a = defaultcolors.w; }; - - CVar_SetRGBA(cvarName, colorsRGBA); - CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. - needs_save = true; - } - Tooltip("Revert colors to the game's original colors (GameCube version)\nOverwrites previously chosen color"); - } - - void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) { - LoadPickersColors(ColorRGBA, cvarName, default_colors, has_alpha); - - ImGuiColorEditFlags flags = ImGuiColorEditFlags_None; - - if (!TitleSameLine) { - ImGui::Text("%s", text); - flags = ImGuiColorEditFlags_NoLabel; - } - - ImGui::PushID(cvarName); - - if (!has_alpha) { - if (ImGui::ColorEdit3(text, (float*)&ColorRGBA, flags)) - { - Color_RGBA8 colors; - colors.r = ColorRGBA.x * 255.0; - colors.g = ColorRGBA.y * 255.0; - colors.b = ColorRGBA.z * 255.0; - colors.a = ColorRGBA.w * 255.0; - - CVar_SetRGBA(cvarName, colors); - needs_save = true; - } - } - else - { - if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags)) - { - Color_RGBA8 colors; - colors.r = ColorRGBA.x / 255; - colors.g = ColorRGBA.y / 255; - colors.b = ColorRGBA.z / 255; - colors.a = ColorRGBA.w / 255; - - CVar_SetRGBA(cvarName, colors); - needs_save = true; - } - } - - ImGui::PopID(); - - //ImGui::SameLine(); // Removing that one to gain some width spacing on the HUD editor - ImGui::PushItemWidth(-FLT_MIN); - ResetColor(cvarName, &ColorRGBA, default_colors, has_alpha); - ImGui::SameLine(); - RandomizeColor(cvarName, &ColorRGBA); - if (allow_rainbow) { - if (ImGui::GetContentRegionAvail().x > 185) { - ImGui::SameLine(); - } - RainbowColor(cvarName, &ColorRGBA); - } - ImGui::NewLine(); - ImGui::PopItemWidth(); - } - void DrawMainMenuAndCalculateGameSize(void) { console->Update(); ImGuiBackendNewFrame(); @@ -1028,13 +473,13 @@ namespace SohImGui { if ((ImGui::IsKeyDown(ImGuiKey_LeftSuper) || ImGui::IsKeyDown(ImGuiKey_RightSuper)) && ImGui::IsKeyPressed(ImGuiKey_R, false)) { - console->Dispatch("reset"); + DispatchConsoleCommand("reset"); } #else if ((ImGui::IsKeyDown(ImGuiKey_LeftCtrl) || ImGui::IsKeyDown(ImGuiKey_RightCtrl)) && ImGui::IsKeyPressed(ImGuiKey_R, false)) { - console->Dispatch("reset"); + DispatchConsoleCommand("reset"); } #endif @@ -1074,921 +519,7 @@ namespace SohImGui { ImGui::SetCursorPosY(0.0f); - if (ImGui::BeginMenu("Settings")) - { - if (ImGui::BeginMenu("Audio")) { - EnhancementSliderFloat("Master Volume: %d %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true); - InsertPadding(); - BindAudioSlider("Main Music Volume: %d %%", "gMainMusicVolume", 1.0f, SEQ_BGM_MAIN); - InsertPadding(); - BindAudioSlider("Sub Music Volume: %d %%", "gSubMusicVolume", 1.0f, SEQ_BGM_SUB); - InsertPadding(); - BindAudioSlider("Sound Effects Volume: %d %%", "gSFXMusicVolume", 1.0f, SEQ_SFX); - InsertPadding(); - BindAudioSlider("Fanfare Volume: %d %%", "gFanfareVolume", 1.0f, SEQ_FANFARE); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Controller")) { - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2 (12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - if (ImGui::Button(GetWindowButtonText("Controller Configuration", CVar_GetS32("gControllerConfigurationEnabled", 0)).c_str())) - { - bool currentValue = CVar_GetS32("gControllerConfigurationEnabled", 0); - CVar_SetS32("gControllerConfigurationEnabled", !currentValue); - needs_save = true; - if (CVar_GetS32("gControllerConfigurationEnabled", 0)) { - controller->Open(); - } else { - controller->Close(); - } - } - ImGui::PopStyleColor(1); - ImGui::PopStyleVar(3); - #ifndef __SWITCH__ - PaddedEnhancementCheckbox("Use Controller Navigation", "gControlNav", true, false); - Tooltip("Allows controller navigation of the menu bar\nD-pad to move between items, A to select, and X to grab focus on the menu bar"); - #endif - PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false); - Tooltip("Shows currently pressed inputs on the bottom right of the screen"); - InsertPadding(); - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 20.0f); - EnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false); - Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); - ImGui::PopItemWidth(); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Graphics")) { - #ifndef __APPLE__ - EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true, true); - Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing"); - gfx_current_dimensions.internal_mul = CVar_GetFloat("gInternalResolution", 1); - #endif - #ifndef __WIIU__ - PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, false, true, false); - Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel"); - gfx_msaa_level = CVar_GetS32("gMSAAValue", 1); - #endif - - if (impl.backend == Backend::DX11) - { - const char* cvar = "gExtraLatencyThreshold"; - int val = CVar_GetS32(cvar, 80); - val = MAX(MIN(val, 360), 0); - int fps = val; - - InsertPadding(); - - if (fps == 0) - { - ImGui::Text("Jitter fix: Off"); - } - else - { - ImGui::Text("Jitter fix: >= %d FPS", fps); - } - - std::string MinusBTNELT = " - ##ExtraLatencyThreshold"; - std::string PlusBTNELT = " + ##ExtraLatencyThreshold"; - if (ImGui::Button(MinusBTNELT.c_str())) { - val--; - CVar_SetS32(cvar, val); - needs_save = true; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); - if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 360, "", ImGuiSliderFlags_AlwaysClamp)) - { - CVar_SetS32(cvar, val); - needs_save = true; - } - ImGui::PopItemWidth(); - Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the CPU to work on one frame while GPU works on the previous frame.\nThis setting should be used when your computer is too slow to do CPU + GPU work in time."); - - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(PlusBTNELT.c_str())) { - val++; - CVar_SetS32(cvar, val); - needs_save = true; - } - - InsertPadding(); - } - - ImGui::Text("Renderer API (Needs reload)"); - if (ImGui::BeginCombo("##RApi", backends[lastBackendID].second)) { - for (uint8_t i = 0; i < sizeof(backends) / sizeof(backends[0]); i++) { - if (ImGui::Selectable(backends[i].second, i == lastBackendID)) { - pConf->setString("Window.GfxBackend", backends[i].first); - lastBackendID = i; - } - } - ImGui::EndCombo(); - } - - EXPERIMENTAL(); - - ImGui::Text("Texture Filter (Needs reload)"); - EnhancementCombobox("gTextureFilter", filters, 3, 0); - - InsertPadding(); - - overlay->DrawSettings(); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Languages")) { - EnhancementRadioButton("English", "gLanguages", 0); - EnhancementRadioButton("German", "gLanguages", 1); - EnhancementRadioButton("French", "gLanguages", 2); - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - - ImGui::SetCursorPosY(0.0f); - - if (ImGui::BeginMenu("Enhancements")) - { - - const char* enhancementPresets[4] = { "Default", "Vanilla Plus", "Enhanced", "Randomizer"}; - PaddedText("Enhancement Presets", false, true); - SohImGui::EnhancementCombobox("gSelectEnhancementPresets", enhancementPresets, 4, 0); - Tooltip( - "Default - Set all enhancements to their default values. The true vanilla SoH experience.\n" - "\n" - "Vanilla Plus - Adds Quality of Life features that enhance your experience, but don't alter gameplay. Recommended for a first playthrough of OoT.\n" - "\n" - "Enhanced - The \"Vanilla Plus\" preset, but with more quality of life enhancements that might alter gameplay slightly. Recommended for returning players.\n" - "\n" - "Randomizer - The \"Enhanced\" preset, plus any other enhancements that are recommended for playing Randomizer." - ); - - InsertPadding(); - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f)); - if (ImGui::Button("Apply Preset")) { - applyEnhancementPresets(); - needs_save = true; - } - ImGui::PopStyleVar(1); - - PaddedSeparator(); - - if (ImGui::BeginMenu("Controls")) { - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - float availableWidth = ImGui::GetContentRegionAvail().x; - if (ImGui::Button( - GetWindowButtonText("Customize Game Controls", CVar_GetS32("gGameControlEditorEnabled", 0)).c_str(), - ImVec2(availableWidth, 0) - )) { - bool currentValue = CVar_GetS32("gGameControlEditorEnabled", 0); - CVar_SetS32("gGameControlEditorEnabled", !currentValue); - needs_save = true; - customWindows["Game Control Editor"].enabled = CVar_GetS32("gGameControlEditorEnabled", 0); - } - ImGui::PopStyleVar(3); - ImGui::PopStyleColor(1); - - // TODO mutual exclusions -- There should be some system to prevent conclifting enhancements from being selected - PaddedEnhancementCheckbox("D-pad Support on Pause and File Select", "gDpadPauseName"); - Tooltip("Enables Pause and File Select screen navigation with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate"); - PaddedEnhancementCheckbox("D-pad Support in Text Choice", "gDpadText", true, false); - PaddedEnhancementCheckbox("D-pad Support for Browsing Shop Items", "gDpadShop", true, false); - PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips", true, false); - Tooltip("Allows the D-pad to be used as extra C buttons"); - PaddedEnhancementCheckbox("Allow the cursor to be on any slot", "gPauseAnyCursor", true, false); - Tooltip("Allows the cursor on the pause menu to be over any slot\nSimilar to Rando and Spaceworld 97"); - PaddedEnhancementCheckbox("Prevent Dropped Ocarina Inputs", "gDpadNoDropOcarinaInput", true, false); - Tooltip("Prevent dropping inputs when playing the ocarina quickly"); - PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL", true, false); - Tooltip("Speak to Navi with L but enter first-person camera with C-Up"); - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Gameplay")) - { - if (ImGui::BeginMenu("Time Savers")) - { - PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, false, false, true); - PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, false, false, true); - EnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3); - Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); - PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, false, false, true); - PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, false, false, true); - PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", true, false); - Tooltip("Speeds up lifting silver rocks and obelisks"); - PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); - Tooltip("Prevent forced Navi conversations"); - PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); - Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); - PaddedEnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood", true, false); - Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); - PaddedEnhancementCheckbox("Fast Chests", "gFastChests", true, false); - Tooltip("Kick open every chest"); - PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); - Tooltip("Skip pickup messages for new consumable items and bottle swipes"); - PaddedEnhancementCheckbox("Better Owl", "gBetterOwl", true, false); - Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); - PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); - Tooltip("Skip the part where the Ocarina playback is called when you play a song"); - PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false); - Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); - PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false); - Tooltip("Allow Link to put items away without having to wait around"); - PaddedEnhancementCheckbox("Instant Boomerang Recall", "gFastBoomerang", true, false); - Tooltip("Instantly return the boomerang to Link by pressing its item button while it's in the air"); - PaddedEnhancementCheckbox("Mask Select in Inventory", "gMaskSelect", true, false); - Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); - PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false); - Tooltip("When loading a save, places Link at the last entrance he went through.\n" - "This doesn't work if the save was made in a grotto."); - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Difficulty Options")) - { - ImGui::Text("Damage Multiplier"); - EnhancementCombobox("gDamageMul", powers, 9, 0); - Tooltip( - "Modifies all sources of damage not affected by other sliders\n\ - 2x: Can survive all common attacks from the start of the game\n\ - 4x: Dies in 1 hit to any substantial attack from the start of the game\n\ - 8x: Can only survive trivial damage from the start of the game\n\ - 16x: Can survive all common attacks with max health without double defense\n\ - 32x: Can survive all common attacks with max health and double defense\n\ - 64x: Can survive trivial damage with max health without double defense\n\ - 128x: Can survive trivial damage with max health and double defense\n\ - 256x: Cannot survive damage" - ); - PaddedText("Fall Damage Multiplier", true, false); - EnhancementCombobox("gFallDamageMul", powers, 8, 0); - Tooltip( - "Modifies all fall damage\n\ - 2x: Can survive all fall damage from the start of the game\n\ - 4x: Can only survive short fall damage from the start of the game\n\ - 8x: Cannot survive any fall damage from the start of the game\n\ - 16x: Can survive all fall damage with max health without double defense\n\ - 32x: Can survive all fall damage with max health and double defense\n\ - 64x: Can survive short fall damage with double defense\n\ - 128x: Cannot survive fall damage" - ); - PaddedText("Void Damage Multiplier", true, false); - EnhancementCombobox("gVoidDamageMul", powers, 7, 0); - Tooltip( - "Modifies damage taken after falling into a void\n\ - 2x: Can survive void damage from the start of the game\n\ - 4x: Cannot survive void damage from the start of the game\n\ - 8x: Can survive void damage twice with max health without double defense\n\ - 16x: Can survive void damage with max health without double defense\n\ - 32x: Can survive void damage with max health and double defense\n\ - 64x: Cannot survive void damage" - ); - PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); - Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); - PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false); - Tooltip("Bombchus will sometimes drop in place of bombs"); - PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); - Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); - PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); - Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot"); - InsertPadding(); - - if (ImGui::BeginMenu("Potion Values")) - { - EnhancementCheckbox("Change Red Potion Effect", "gRedPotionEffect"); - Tooltip("Enable the following changes to the amount of health restored by Red Potions"); - EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Red Potions"); - EnhancementCheckbox("Red Potion Percent Restore", "gRedPercentRestore"); - Tooltip("Toggles from Red Potions restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Green Potion Effect", "gGreenPotionEffect"); - Tooltip("Enable the following changes to the amount of mana restored by Green Potions"); - EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, "", 0, true); - Tooltip("Changes the amount of mana restored by Green Potions, base max mana is 48, max upgraded mana is 96"); - EnhancementCheckbox("Green Potion Percent Restore", "gGreenPercentRestore"); - Tooltip("Toggles from Green Potions restoring a fixed amount of mana to a percent of the player's current max mana"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Blue Potion Effects", "gBluePotionEffects"); - Tooltip("Enable the following changes to the amount of health and mana restored by Blue Potions"); - EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Blue Potions"); - EnhancementCheckbox("Blue Potion Health Percent Restore", "gBlueHealthPercentRestore"); - Tooltip("Toggles from Blue Potions restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, "", 0, true); - Tooltip("Changes the amount of mana restored by Blue Potions, base max mana is 48, max upgraded mana is 96"); - EnhancementCheckbox("Blue Potion Mana Percent Restore", "gBlueManaPercentRestore"); - Tooltip("Toggles from Blue Potions restoring a fixed amount of mana to a percent of the player's current max mana"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Milk Effect", "gMilkEffect"); - Tooltip("Enable the following changes to the amount of health restored by Milk"); - EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Milk"); - EnhancementCheckbox("Milk Percent Restore", "gMilkPercentRestore"); - Tooltip("Toggles from Milk restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementCheckbox("Separate Half Milk Effect", "gSeparateHalfMilkEffect"); - Tooltip("Enable the following changes to the amount of health restored by Half Milk\nIf this is disabled, Half Milk will behave the same as Full Milk."); - EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Half Milk"); - EnhancementCheckbox("Half Milk Percent Restore", "gHalfMilkPercentRestore"); - Tooltip("Toggles from Half Milk restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Fairy Effect", "gFairyEffect"); - Tooltip("Enable the following changes to the amount of health restored by Fairies"); - EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Fairies"); - EnhancementCheckbox("Fairy Percent Restore", "gFairyPercentRestore"); - Tooltip("Toggles from Fairies restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::Separator(); - - EnhancementCheckbox("Change Fairy Revive Effect", "gFairyReviveEffect"); - Tooltip("Enable the following changes to the amount of health restored by Fairy Revivals"); - EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, "", 0, true); - Tooltip("Changes the amount of health restored by Fairy Revivals"); - EnhancementCheckbox("Fairy Revive Percent Restore", "gFairyRevivePercentRestore"); - Tooltip("Toggles from Fairy Revivals restoring a fixed amount of health to a percent of the player's current max health"); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Fishing")) { - EnhancementCheckbox("Instant Fishing", "gInstantFishing"); - Tooltip("All fish will be caught instantly"); - PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false); - Tooltip("When a line is stable, guarantee bite. Otherwise use default logic"); - PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 6, 10, "", 10, false, true, false); - Tooltip("The minimum weight for the unique fishing reward as a child"); - PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 8, 13, "", 13, false, true, false); - Tooltip("The minimum weight for the unique fishing reward as an adult"); - ImGui::EndMenu(); - } - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Reduced Clutter")) - { - EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm"); - Tooltip("Disable the low HP beeping sound"); - PaddedEnhancementCheckbox("Minimal UI", "gMinimalUI", true, false); - Tooltip("Hides most of the UI when not needed\nNote: Doesn't activate until after loading a new scene"); - PaddedEnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio", true, false); - Tooltip("Disables the voice audio when Navi calls you"); - - ImGui::EndMenu(); - } - - InsertPadding(); - - EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); - Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); - PaddedEnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots", true, false); - Tooltip("Allows equipping the tunic and boots to c-buttons"); - PaddedEnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved", true, false); - Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); - PaddedEnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime", true, false); - Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods"); - PaddedEnhancementCheckbox("Enable visible guard vision", "gGuardVision", true, false); - PaddedEnhancementCheckbox("Enable passage of time on file select", "gTimeFlowFileSelect", true, false); - PaddedEnhancementCheckbox("Count Golden Skulltulas", "gInjectSkulltulaCount", true, false); - Tooltip("Injects Golden Skulltula total count in pickup messages"); - PaddedEnhancementCheckbox("Pull grave during the day", "gDayGravePull", true, false); - Tooltip("Allows graves to be pulled when child during the day"); - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Graphics")) - { - if (ImGui::BeginMenu("Animated Link in Pause Menu")) { - ImGui::Text("Rotation"); - EnhancementRadioButton("Disabled", "gPauseLiveLinkRotation", 0); - EnhancementRadioButton("Rotate Link with D-pad", "gPauseLiveLinkRotation", 1); - Tooltip("Allow you to rotate Link on the Equipment menu with the D-pad\nUse D-pad Up or D-pad Down to reset Link's rotation"); - EnhancementRadioButton("Rotate Link with C-buttons", "gPauseLiveLinkRotation", 2); - Tooltip("Allow you to rotate Link on the Equipment menu with the C-buttons\nUse C-Up or C-Down to reset Link's rotation"); - EnhancementRadioButton("Rotate Link with Right Stick", "gPauseLiveLinkRotation", 3); - Tooltip("Allow you to rotate Link on the Equipment menu with the Right Stick\nYou can zoom in by pointing up and reset Link's rotation by pointing down"); - if (CVar_GetS32("gPauseLiveLinkRotation", 0) != 0) { - EnhancementSliderInt("Rotation Speed: %d", "##MinRotationSpeed", "gPauseLiveLinkRotationSpeed", 1, 20, ""); - } - PaddedSeparator(); - ImGui::Text("Static loop"); - EnhancementRadioButton("Disabled", "gPauseLiveLink", 0); - EnhancementRadioButton("Idle (standing)", "gPauseLiveLink", 1); - EnhancementRadioButton("Idle (look around)", "gPauseLiveLink", 2); - EnhancementRadioButton("Idle (belt)", "gPauseLiveLink", 3); - EnhancementRadioButton("Idle (shield)", "gPauseLiveLink", 4); - EnhancementRadioButton("Idle (test sword)", "gPauseLiveLink", 5); - EnhancementRadioButton("Idle (yawn)", "gPauseLiveLink", 6); - EnhancementRadioButton("Battle Stance", "gPauseLiveLink", 7); - EnhancementRadioButton("Walking (no shield)", "gPauseLiveLink", 8); - EnhancementRadioButton("Walking (holding shield)", "gPauseLiveLink", 9); - EnhancementRadioButton("Running (no shield)", "gPauseLiveLink", 10); - EnhancementRadioButton("Running (holding shield)", "gPauseLiveLink", 11); - EnhancementRadioButton("Hand on hip", "gPauseLiveLink", 12); - EnhancementRadioButton("Spin attack charge", "gPauseLiveLink", 13); - EnhancementRadioButton("Look at hand", "gPauseLiveLink", 14); - PaddedSeparator(); - ImGui::Text("Randomize"); - EnhancementRadioButton("Random", "gPauseLiveLink", 15); - Tooltip("Randomize the animation played each time you open the menu"); - EnhancementRadioButton("Random cycle", "gPauseLiveLink", 16); - Tooltip("Randomize the animation played on the menu after a certain time"); - EnhancementRadioButton("Random cycle (Idle)", "gPauseLiveLink", 17); - Tooltip("Randomize the animation played on the menu after a certain time (Idle animations only)"); - if (CVar_GetS32("gPauseLiveLink", 0) >= 16) { - EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, "", 0, true); - } - - ImGui::EndMenu(); - } - PaddedEnhancementCheckbox("N64 Mode", "gN64Mode", true, false); - Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); - PaddedEnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops", true, false); - Tooltip("Change most 2D items and projectiles on the overworld to their 3D versions"); - PaddedEnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars", true, false); - Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); - PaddedEnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon", true, false); - Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); - PaddedEnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon", true, false); - Tooltip("Always shows dungeon entrance icons on the minimap"); - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Fixes")) - { - EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); - Tooltip("Makes the L and R buttons in the pause menu the same color"); - PaddedEnhancementCheckbox("Fix L&Z Page switch in Pause menu", "gNGCKaleidoSwitcher", true, false); - Tooltip("Makes L and R switch pages like on the GameCube\nZ opens the Debug Menu instead"); - PaddedEnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon", true, false); - Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); - PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false); - Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); - PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false); - Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); - PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false); - Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); - PaddedEnhancementCheckbox("Fix Navi text HUD position", "gNaviTextFix", true, false); - Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); - PaddedEnhancementCheckbox("Fix Anubis fireballs", "gAnubisFix", true, false); - Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); - PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", "gCrouchStabHammerFix", true, false); - Tooltip("Make the Megaton Hammer's crouch stab able to destroy rocks without first swinging it normally"); - if (CVar_GetS32("gCrouchStabHammerFix", 0) == 0) { - CVar_SetS32("gCrouchStabFix", 0); - } else { - PaddedEnhancementCheckbox("Remove power crouch stab", "gCrouchStabFix", true, false); - Tooltip("Make crouch stabbing always do the same damage as a regular slash"); - } - - ImGui::EndMenu(); - } - - InsertPadding(); - - if (ImGui::BeginMenu("Restoration")) - { - EnhancementCheckbox("Red Ganon blood", "gRedGanonBlood"); - Tooltip("Restore the original red blood from NTSC 1.0/1.1. Disable for green blood"); - PaddedEnhancementCheckbox("Fish while hovering", "gHoverFishing", true, false); - Tooltip("Restore a bug from NTSC 1.0 that allows casting the Fishing Rod while using the Hover Boots"); - PaddedEnhancementCheckbox("N64 Weird Frames", "gN64WeirdFrames", true, false); - Tooltip("Restores N64 Weird Frames allowing weirdshots to behave the same as N64"); - PaddedEnhancementCheckbox("Bombchus out of bounds", "gBombchusOOB", true, false); - Tooltip("Allows bombchus to explode out of bounds\nSimilar to GameCube and Wii VC"); - PaddedEnhancementCheckbox("Restore old Gold Skulltula cutscene", "gGsCutscene", true, false); - - ImGui::EndMenu(); - } - - PaddedEnhancementCheckbox("Autosave", "gAutosave", true, false); - Tooltip("Automatically save the game every time a new area is entered or item is obtained\n" - "To disable saving when obtaining an item, manually set gAutosaveAllItems and gAutosaveMajorItems to 0\n" - "gAutosaveAllItems takes priority over gAutosaveMajorItems if both are set to 1\n" - "gAutosaveMajorItems excludes rupees and health/magic/ammo refills (but includes bombchus)"); - - InsertPadding(); - - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - static ImVec2 buttonSize(200.0f, 0.0f); - if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVar_GetS32("gCosmeticsEditorEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gCosmeticsEditorEnabled", 0); - CVar_SetS32("gCosmeticsEditorEnabled", !currentValue); - needs_save = true; - customWindows["Cosmetics Editor"].enabled = CVar_GetS32("gCosmeticsEditorEnabled", 0); - } - ImGui::PopStyleVar(3); - ImGui::PopStyleColor(1); - - EXPERIMENTAL(); - - const char* fps_cvar = "gInterpolationFPS"; - { - #if defined(__SWITCH__) || defined(__WIIU__) - int minFps = 20; - int maxFps = 60; - #else - int minFps = 20; - int maxFps = 360; - #endif - - int val = CVar_GetS32(fps_cvar, minFps); - val = MAX(MIN(val, maxFps), 20); - - #ifdef __WIIU__ - // only support divisors of 60 on the Wii U - val = 60 / (60 / val); - #endif - - int fps = val; - - if (fps == 20) - { - ImGui::Text("Frame interpolation: Off"); - } - else - { - ImGui::Text("Frame interpolation: %d FPS", fps); - } - - std::string MinusBTNFPSI = " - ##FPSInterpolation"; - std::string PlusBTNFPSI = " + ##FPSInterpolation"; - if (ImGui::Button(MinusBTNFPSI.c_str())) { - #ifdef __WIIU__ - if (val >= 60) val = 30; - else val = 20; - #else - val--; - #endif - CVar_SetS32(fps_cvar, val); - needs_save = true; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - #ifdef __WIIU__ - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2); - #else - ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); - #endif - if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp)) - { - #ifdef __WIIU__ - // only support divisors of 60 on the Wii U - val = 60 / (60 / val); - #endif - if (val > 360) - { - val = 360; - } - else if (val < 20) - { - val = 20; - } - - CVar_SetS32(fps_cvar, val); - needs_save = true; - } - ImGui::PopItemWidth(); - Tooltip("Interpolate extra frames to get smoother graphics\n" - "Set to match your monitor's refresh rate, or a divisor of it\n" - "A higher target FPS than your monitor's refresh rate will just waste resources, " - "and might give a worse result.\n" - "For consistent input lag, set this value and your monitor's refresh rate to a multiple of 20\n" - "Ctrl+Click for keyboard input"); - - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(PlusBTNFPSI.c_str())) { - #ifdef __WIIU__ - if (val <= 20) val = 30; - else val = 60; - #else - val++; - #endif - CVar_SetS32(fps_cvar, val); - needs_save = true; - } - } - - if (impl.backend == Backend::DX11) - { - InsertPadding(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f)); - if (ImGui::Button("Match Refresh Rate")) - { - int hz = roundf(gfx_get_detected_hz()); - if (hz >= 20 && hz <= 360) - { - CVar_SetS32(fps_cvar, hz); - needs_save = true; - } - } - ImGui::PopStyleVar(1); - InsertPadding(); - } - EnhancementCheckbox("Disable LOD", "gDisableLOD"); - Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); - PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false); - Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); - if (CVar_GetS32("gDisableDrawDistance", 0) == 0) { - CVar_SetS32("gDisableKokiriDrawDistance", 0); - } else if (CVar_GetS32("gDisableDrawDistance", 0) == 1) { - PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); - Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); - } - PaddedEnhancementCheckbox("Skip Text", "gSkipText", true, false); - Tooltip("Holding down B skips text\nKnown to cause a cutscene softlock in Water Temple\nSoftlock can be fixed by pressing D-Right in Debug mode"); - PaddedEnhancementCheckbox("Free Camera", "gFreeCamera", true, false); - Tooltip("Enables 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."); - - #ifdef __SWITCH__ - InsertPadding(); - int slot = CVar_GetS32("gSwitchPerfMode", (int)SwitchProfiles::STOCK); - ImGui::Text("Switch performance mode"); - if (ImGui::BeginCombo("##perf", SWITCH_CPU_PROFILES[slot])) { - for (int sId = 0; sId <= SwitchProfiles::POWERSAVINGM3; sId++) { - if (ImGui::Selectable(SWITCH_CPU_PROFILES[sId], sId == slot)) { - SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]); - CVar_SetS32("gSwitchPerfMode", sId); - Switch::ApplyOverclock(); - needs_save = true; - } - - } - ImGui::EndCombo(); - } - #endif - - ImGui::EndMenu(); - } - - ImGui::SetCursorPosY(0.0f); - - if (ImGui::BeginMenu("Cheats")) - { - if (ImGui::BeginMenu("Infinite...")) { - EnhancementCheckbox("Money", "gInfiniteMoney"); - PaddedEnhancementCheckbox("Health", "gInfiniteHealth", true, false); - PaddedEnhancementCheckbox("Ammo", "gInfiniteAmmo", true, false); - PaddedEnhancementCheckbox("Magic", "gInfiniteMagic", true, false); - PaddedEnhancementCheckbox("Nayru's Love", "gInfiniteNayru", true, false); - PaddedEnhancementCheckbox("Epona Boost", "gInfiniteEpona", true, false); - - ImGui::EndMenu(); - } - - PaddedEnhancementCheckbox("No Clip", "gNoClip", true, false); - Tooltip("Allows you to walk through walls"); - PaddedEnhancementCheckbox("Climb Everything", "gClimbEverything", true, false); - Tooltip("Makes every surface in the game climbable"); - PaddedEnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL", true, false); - Tooltip("Holding L makes you float into the air"); - PaddedEnhancementCheckbox("Super Tunic", "gSuperTunic", true, false); - Tooltip("Makes every tunic have the effects of every other tunic"); - PaddedEnhancementCheckbox("Easy ISG", "gEzISG", true, false); - Tooltip("Passive Infinite Sword Glitch\nIt makes your sword's swing effect and hitbox stay active indefinitely"); - PaddedEnhancementCheckbox("Unrestricted Items", "gNoRestrictItems", true, false); - Tooltip("Allows you to use any item at any location"); - PaddedEnhancementCheckbox("Freeze Time", "gFreezeTime", true, false); - Tooltip("Freezes the time of day"); - PaddedEnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie", true, false); - Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); - PaddedEnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield", true, false); - Tooltip("Prevents the Deku Shield from burning on contact with fire"); - PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded", true, false); - Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); - PaddedEnhancementCheckbox("Time Sync", "gTimeSync", true, false); - Tooltip("This syncs the ingame time with the real world time"); - - { - static int32_t betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); - static int32_t lastBetaQuestEnabled = betaQuestEnabled; - static int32_t betaQuestWorld = CVar_GetS32("gBetaQuestWorld", 0xFFEF); - static int32_t lastBetaQuestWorld = betaQuestWorld; - - if (!isBetaQuestEnabled) { - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); - } - - PaddedEnhancementCheckbox("Enable Beta Quest", "gEnableBetaQuest", true, false); - Tooltip("Turns on OoT Beta Quest. *WARNING* This will reset your game."); - betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); - if (betaQuestEnabled) { - if (betaQuestEnabled != lastBetaQuestEnabled) { - betaQuestWorld = 0; - } - - ImGui::Text("Beta Quest World: %d", betaQuestWorld); - - if (ImGui::Button(" - ##BetaQuest")) { - betaQuestWorld--; - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - - ImGui::SliderInt("##BetaQuest", &betaQuestWorld, 0, 8, "", ImGuiSliderFlags_AlwaysClamp); - Tooltip("Set the Beta Quest world to explore. *WARNING* Changing this will reset your game.\nCtrl+Click to type in a value."); - - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); - if (ImGui::Button(" + ##BetaQuest")) { - betaQuestWorld++; - } - - if (betaQuestWorld > 8) { - betaQuestWorld = 8; - } - else if (betaQuestWorld < 0) { - betaQuestWorld = 0; - } - } - else { - lastBetaQuestWorld = betaQuestWorld = 0xFFEF; - CVar_SetS32("gBetaQuestWorld", betaQuestWorld); - } - if (betaQuestEnabled != lastBetaQuestEnabled || betaQuestWorld != lastBetaQuestWorld) - { - // Reset the game if the beta quest state or world changed because beta quest happens on redirecting the title screen cutscene. - lastBetaQuestEnabled = betaQuestEnabled; - lastBetaQuestWorld = betaQuestWorld; - CVar_SetS32("gEnableBetaQuest", betaQuestEnabled); - CVar_SetS32("gBetaQuestWorld", betaQuestWorld); - - console->Dispatch("reset"); - - needs_save = true; - } - - if (!isBetaQuestEnabled) { - ImGui::PopItemFlag(); - ImGui::PopStyleVar(1); - } - } - - ImGui::EndMenu(); - } - - ImGui::SetCursorPosY(0.0f); - - if (ImGui::BeginMenu("Developer Tools")) - { - EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); - Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen"); - PaddedEnhancementCheckbox("OoT Skulltula Debug", "gSkulltulaDebugEnabled", true, false); - Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); - PaddedEnhancementCheckbox("Fast File Select", "gSkipLogoTitle", true, false); - Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only if you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu"); - if (CVar_GetS32("gSkipLogoTitle", 0)) { - const char* FastFileSelect[5] = { - "File N.1", - "File N.2", - "File N.3", - "File select", - "Zelda Map Select (require OoT Debug Mode)" - }; - ImGui::Text("Loading :"); - EnhancementCombobox("gSaveFileID", FastFileSelect, 5, 0); - PaddedEnhancementCheckbox("Create a new save if none", "gCreateNewSave", true, false); - Tooltip("Enable the creation of a new save file if none exist in the File number selected\nNo file name will be assigned please do in Save editor once you see the first text else your save file name will be named \"00000000\"\nIf disabled you will fall back in File select menu"); - }; - PaddedSeparator(); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0,0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - static ImVec2 buttonSize(160.0f, 0.0f); - if (ImGui::Button(GetWindowButtonText("Stats", CVar_GetS32("gStatsEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gStatsEnabled", 0); - CVar_SetS32("gStatsEnabled", !currentValue); - statsWindowOpen = true; - needs_save = true; - } - Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on"); - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Console", CVar_GetS32("gConsoleEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gConsoleEnabled", 0); - CVar_SetS32("gConsoleEnabled", !currentValue); - needs_save = true; - if(CVar_GetS32("gConsoleEnabled", 0)){ - console->Open(); - } else { - console->Close(); - } - } - Tooltip("Enables the console window, allowing you to input commands, type help for some examples"); - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Save Editor", CVar_GetS32("gSaveEditorEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gSaveEditorEnabled", 0); - CVar_SetS32("gSaveEditorEnabled", !currentValue); - needs_save = true; - customWindows["Save Editor"].enabled = CVar_GetS32("gSaveEditorEnabled", 0); - } - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVar_GetS32("gCollisionViewerEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gCollisionViewerEnabled", 0); - CVar_SetS32("gCollisionViewerEnabled", !currentValue); - needs_save = true; - customWindows["Collision Viewer"].enabled = CVar_GetS32("gCollisionViewerEnabled", 0); - } - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVar_GetS32("gActorViewerEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gActorViewerEnabled", 0); - CVar_SetS32("gActorViewerEnabled", !currentValue); - needs_save = true; - customWindows["Actor Viewer"].enabled = CVar_GetS32("gActorViewerEnabled", 0); - } - ImGui::PopStyleVar(3); - ImGui::PopStyleColor(1); - - ImGui::EndMenu(); - } - - ImGui::SetCursorPosY(0.0f); - - if (ImGui::BeginMenu("Randomizer")) - { - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); - ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); - static ImVec2 buttonSize(200.0f, 0.0f); - if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVar_GetS32("gRandomizerSettingsEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gRandomizerSettingsEnabled", 0); - CVar_SetS32("gRandomizerSettingsEnabled", !currentValue); - needs_save = true; - customWindows["Randomizer Settings"].enabled = CVar_GetS32("gRandomizerSettingsEnabled", 0); - } - InsertPadding(); - if (ImGui::Button(GetWindowButtonText("Item Tracker", CVar_GetS32("gItemTrackerEnabled", 0)).c_str(), buttonSize)) - { - bool currentValue = CVar_GetS32("gItemTrackerEnabled", 0); - CVar_SetS32("gItemTrackerEnabled", !currentValue); - needs_save = true; - customWindows["Item Tracker"].enabled = CVar_GetS32("gItemTrackerEnabled", 0); - } - ImGui::PopStyleVar(3); - ImGui::PopStyleColor(1); - - ImGui::EndMenu(); - } + clientDrawMenu(); ImGui::PopStyleVar(1); ImGui::EndMenuBar(); @@ -2015,19 +546,19 @@ namespace SohImGui { ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); ImGui::Begin("Debug Stats", &statsWindowOpen, ImGuiWindowFlags_NoFocusOnAppearing); -#if defined(_WIN32) + #if defined(_WIN32) ImGui::Text("Platform: Windows"); -#elif defined(__APPLE__) + #elif defined(__APPLE__) ImGui::Text("Platform: macOS"); -#elif defined(__SWITCH__) + #elif defined(__SWITCH__) ImGui::Text("Platform: Nintendo Switch"); -#elif defined(__WIIU__) + #elif defined(__WIIU__) ImGui::Text("Platform: Nintendo Wii U"); -#elif defined(__linux__) + #elif defined(__linux__) ImGui::Text("Platform: Linux"); -#else + #else ImGui::Text("Platform: Unknown"); -#endif + #endif ImGui::Text("Status: %.3f ms/frame (%.1f FPS)", 1000.0f / framerate, framerate); ImGui::End(); ImGui::PopStyleColor(); @@ -2078,6 +609,14 @@ namespace SohImGui { overlay->Draw(); } + void RegisterMenuDrawMethod(std::function drawMethod) { + clientDrawMenu = drawMethod; + } + + void AddSetupHooksDelegate(std::function setupHooksMethod) { + clientSetupHooks = setupHooksMethod; + } + void DrawFramebufferAndGameInput(void) { const ImVec2 main_pos = ImGui::GetWindowPos(); ImVec2 size = ImGui::GetContentRegionAvail(); @@ -2146,360 +685,6 @@ namespace SohImGui { } } - void applyEnhancementPresets(void) { - - switch (CVar_GetS32("gSelectEnhancementPresets", 0)) { - // Default - case 0: - applyEnhancementPresetDefault(); - break; - - // Vanilla Plus - case 1: - applyEnhancementPresetDefault(); - applyEnhancementPresetVanillaPlus(); - break; - - // Enhanced - case 2: - applyEnhancementPresetDefault(); - applyEnhancementPresetVanillaPlus(); - applyEnhancementPresetEnhanced(); - break; - - // Randomizer - case 3: - applyEnhancementPresetDefault(); - applyEnhancementPresetVanillaPlus(); - applyEnhancementPresetEnhanced(); - applyEnhancementPresetRandomizer(); - break; - } - } - - void applyEnhancementPresetDefault(void) { - // D-pad Support on Pause and File Select - CVar_SetS32("gDpadPauseName", 0); - // D-pad Support in Ocarina and Text Choice - CVar_SetS32("gDpadOcarinaText", 0); - // D-pad Support for Browsing Shop Items - CVar_SetS32("gDpadShop", 0); - // D-pad as Equip Items - CVar_SetS32("gDpadEquips", 0); - // Allow the cursor to be on any slot - CVar_SetS32("gPauseAnyCursor", 0); - // Prevent Dropped Ocarina Inputs - CVar_SetS32("gDpadNoDropOcarinaInput", 0); - // Answer Navi Prompt with L Button - CVar_SetS32("gNaviOnL", 0); - - // Text Speed (1 to 5) - CVar_SetS32("gTextSpeed", 1); - // King Zora Speed (1 to 5) - CVar_SetS32("gMweepSpeed", 1); - // Biggoron Forge Time (0 to 3) - CVar_SetS32("gForgeTime", 3); - // Vine/Ladder Climb speed (+0 to +12) - CVar_SetS32("gClimbSpeed", 0); - // Faster Block Push (+0 to +5) - CVar_SetS32("gFasterBlockPush", 0); - // Faster Heavy Block Lift - CVar_SetS32("gFasterHeavyBlockLift", 0); - // No Forced Navi - CVar_SetS32("gNoForcedNavi", 0); - // No Skulltula Freeze - CVar_SetS32("gSkulltulaFreeze", 0); - // MM Bunny Hood - CVar_SetS32("gMMBunnyHood", 0); - // Fast Chests - CVar_SetS32("gFastChests", 0); - // Fast Drops - CVar_SetS32("gFastDrops", 0); - // Better Owl - CVar_SetS32("gBetterOwl", 0); - // Fast Ocarina Playback - CVar_SetS32("gFastOcarinaPlayback", 0); - // Instant Putaway - CVar_SetS32("gInstantPutaway", 0); - // Instant Boomerang Recall - CVar_SetS32("gFastBoomerang", 0); - // Mask Select in Inventory - CVar_SetS32("gMaskSelect", 0); - // Remember Save Location - CVar_SetS32("gRememberSaveLocation", 0); - - // Damage Multiplier (0 to 8) - CVar_SetS32("gDamageMul", 0); - // Fall Damage Multiplier (0 to 7) - CVar_SetS32("gFallDamageMul", 0); - // Void Damage Multiplier (0 to 6) - CVar_SetS32("gVoidDamageMul", 0); - // No Random Drops - CVar_SetS32("gNoRandomDrops", 0); - // No Heart Drops - CVar_SetS32("gNoHeartDrops", 0); - // Enable Bombchu Drops - CVar_SetS32("gBombchuDrops", 0); - // Always Win Goron Pot - CVar_SetS32("gGoronPot", 0); - - // Change Red Potion Effect - CVar_SetS32("gRedPotionEffect", 0); - // Red Potion Health (1 to 100) - CVar_SetS32("gRedPotionHealth", 1); - // Red Potion Percent Restore - CVar_SetS32("gRedPercentRestore", 0); - // Change Green Potion Effect - CVar_SetS32("gGreenPotionEffect", 0); - // Green Potion Mana (1 to 100) - CVar_SetS32("gGreenPotionMana", 1); - // Green Potion Percent Restore - CVar_SetS32("gGreenPercentRestore", 0); - // Change Blue Potion Effects - CVar_SetS32("gBluePotionEffects", 0); - // Blue Potion Health (1 to 100) - CVar_SetS32("gBluePotionHealth", 1); - // Blue Potion Health Percent Restore - CVar_SetS32("gBlueHealthPercentRestore", 0); - // Blue Potion Mana (1 to 100) - CVar_SetS32("gBluePotionMana", 1); - // Blue Potion Mana Percent Restore - CVar_SetS32("gBlueManaPercentRestore", 0); - // Change Milk Effect - CVar_SetS32("gMilkEffect", 0); - // Milk Health (1 to 100) - CVar_SetS32("gMilkHealth", 1); - // Milk Percent Restore - CVar_SetS32("gMilkPercentRestore", 0); - // Separate Half Milk Effect - CVar_SetS32("gSeparateHalfMilkEffect", 0); - // Half Milk Health (1 to 100) - CVar_SetS32("gHalfMilkHealth", 0); - // Half Milk Percent Restore - CVar_SetS32("gHalfMilkPercentRestore", 0); - // Change Fairy Effect - CVar_SetS32("gFairyEffect", 0); - // Fairy (1 to 100) - CVar_SetS32("gFairyHealth", 1); - // Fairy Percent Restore - CVar_SetS32("gFairyPercentRestore", 0); - // Change Fairy Revive Effect - CVar_SetS32("gFairyReviveEffect", 0); - // Fairy Revival (1 to 100) - CVar_SetS32("gFairyReviveHealth", 1); - // Fairy Revive Percent Restore - CVar_SetS32("gFairyRevivePercentRestore", 0); - - // Instant Fishing - CVar_SetS32("gInstantFishing", 0); - // Guarantee Bite - CVar_SetS32("gGuaranteeFishingBite", 0); - // Child Minimum Weight (6 to 10) - CVar_SetS32("gChildMinimumWeightFish", 10); - // Adult Minimum Weight (8 to 13) - CVar_SetS32("gAdultMinimumWeightFish", 13); - - // Mute Low HP Alarm - CVar_SetS32("gLowHpAlarm", 0); - // Minimal UI - CVar_SetS32("gMinimalUI", 0); - // Disable Navi Call Audio - CVar_SetS32("gDisableNaviCallAudio", 0); - - // Visual Stone of Agony - CVar_SetS32("gVisualAgony", 0); - // Assignable Tunics and Boots - CVar_SetS32("gAssignableTunicsAndBoots", 0); - // Equipment Toggle - CVar_SetS32("gEquipmentCanBeRemoved", 0); - // Link's Cow in Both Time Periods - CVar_SetS32("gCowOfTime", 0); - // Enable visible guard vision - CVar_SetS32("gGuardVision", 0); - // Enable passage of time on file select - CVar_SetS32("gTimeFlowFileSelect", 0); - // Count Golden Skulltulas - CVar_SetS32("gInjectSkulltulaCount", 0); - // Pull grave during the day - CVar_SetS32("gDayGravePull", 0); - - // Rotate link (0 to 2) - CVar_SetS32("gPauseLiveLinkRotation", 0); - // Pause link animation (0 to 16) - CVar_SetS32("gPauseLiveLink", 0); - // Frames to wait - CVar_SetS32("gMinFrameCount", 1); - - // N64 Mode - CVar_SetS32("gN64Mode", 0); - // Enable 3D Dropped items/projectiles - CVar_SetS32("gNewDrops", 0); - // Disable Black Bar Letterboxes - CVar_SetS32("gDisableBlackBars", 0); - // Dynamic Wallet Icon - CVar_SetS32("gDynamicWalletIcon", 0); - // Always show dungeon entrances - CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 0); - - // Fix L&R Pause menu - CVar_SetS32("gUniformLR", 0); - // Fix L&Z Page switch in Pause menu - CVar_SetS32("gNGCKaleidoSwitcher", 0); - // Fix Dungeon entrances - CVar_SetS32("gFixDungeonMinimapIcon", 0); - // Fix Two Handed idle animations - CVar_SetS32("gTwoHandedIdle", 0); - // Fix the Gravedigging Tour Glitch - CVar_SetS32("gGravediggingTourFix", 0); - // Fix Deku Nut upgrade - CVar_SetS32("gDekuNutUpgradeFix", 0); - // Fix Navi text HUD position - CVar_SetS32("gNaviTextFix", 0); - // Fix Anubis fireballs - CVar_SetS32("gAnubisFix", 0); - // Fix Megaton Hammer crouch stab - CVar_SetS32("gCrouchStabHammerFix", 0); - // Fix all crouch stab - CVar_SetS32("gCrouchStabFix", 0); - - // Red Ganon blood - CVar_SetS32("gRedGanonBlood", 0); - // Fish while hovering - CVar_SetS32("gHoverFishing", 0); - // N64 Weird Frames - CVar_SetS32("gN64WeirdFrames", 0); - // Bombchus out of bounds - CVar_SetS32("gBombchusOOB", 0); - - CVar_SetS32("gGsCutscene", 0); - // Autosave - CVar_SetS32("gAutosave", 0); - } - - void applyEnhancementPresetVanillaPlus(void) { - // D-pad Support in Ocarina and Text Choice - CVar_SetS32("gDpadOcarinaText", 1); - // D-pad Support for Browsing Shop Items - CVar_SetS32("gDpadShop", 1); - // D-pad as Equip Items - CVar_SetS32("gDpadEquips", 1); - // Prevent Dropped Ocarina Inputs - CVar_SetS32("gDpadNoDropOcarinaInput", 1); - - // Text Speed (1 to 5) - CVar_SetS32("gTextSpeed", 5); - // King Zora Speed (1 to 5) - CVar_SetS32("gMweepSpeed", 2); - // Faster Block Push (+0 to +5) - CVar_SetS32("gFasterBlockPush", 5); - // Better Owl - CVar_SetS32("gBetterOwl", 1); - - // Assignable Tunics and Boots - CVar_SetS32("gAssignableTunicsAndBoots", 1); - // Enable passage of time on file select - CVar_SetS32("gTimeFlowFileSelect", 1); - // Count Golden Skulltulas - CVar_SetS32("gInjectSkulltulaCount", 1); - - // Pause link animation (0 to 16) - CVar_SetS32("gPauseLiveLink", 1); - - // Dynamic Wallet Icon - CVar_SetS32("gDynamicWalletIcon", 1); - // Always show dungeon entrances - CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 1); - - // Fix L&R Pause menu - CVar_SetS32("gUniformLR", 1); - // Fix Dungeon entrances - CVar_SetS32("gFixDungeonMinimapIcon", 1); - // Fix Two Handed idle animations - CVar_SetS32("gTwoHandedIdle", 1); - // Fix the Gravedigging Tour Glitch - CVar_SetS32("gGravediggingTourFix", 1); - // Fix Deku Nut upgrade - CVar_SetS32("gDekuNutUpgradeFix", 1); - - // Red Ganon blood - CVar_SetS32("gRedGanonBlood", 1); - // Fish while hovering - CVar_SetS32("gHoverFishing", 1); - // N64 Weird Frames - CVar_SetS32("gN64WeirdFrames", 1); - // Bombchus out of bounds - CVar_SetS32("gBombchusOOB", 1); - } - - void applyEnhancementPresetEnhanced(void) { - // King Zora Speed (1 to 5) - CVar_SetS32("gMweepSpeed", 5); - // Biggoron Forge Time (0 to 3) - CVar_SetS32("gForgeTime", 0); - // Vine/Ladder Climb speed (+0 to +12) - CVar_SetS32("gClimbSpeed", 1); - // Faster Heavy Block Lift - CVar_SetS32("gFasterHeavyBlockLift", 1); - // No Forced Navi - CVar_SetS32("gNoForcedNavi", 1); - // No Skulltula Freeze - CVar_SetS32("gSkulltulaFreeze", 1); - // MM Bunny Hood - CVar_SetS32("gMMBunnyHood", 1); - // Fast Chests - CVar_SetS32("gFastChests", 1); - // Fast Drops - CVar_SetS32("gFastDrops", 1); - // Fast Ocarina Playback - CVar_SetS32("gFastOcarinaPlayback", 1); - // Instant Putaway - CVar_SetS32("gInstantPutaway", 1); - // Instant Boomerang Recall - CVar_SetS32("gFastBoomerang", 1); - // Mask Select in Inventory - CVar_SetS32("gMaskSelect", 1); - - // Disable Navi Call Audio - CVar_SetS32("gDisableNaviCallAudio", 1); - - // Equipment Toggle - CVar_SetS32("gEquipmentCanBeRemoved", 1); - // Count Golden Skulltulas - CVar_SetS32("gInjectSkulltulaCount", 1); - - // Enable 3D Dropped items/projectiles - CVar_SetS32("gNewDrops", 1); - - // Fix Anubis fireballs - CVar_SetS32("gAnubisFix", 1); - } - - void applyEnhancementPresetRandomizer(void) { - // Allow the cursor to be on any slot - CVar_SetS32("gPauseAnyCursor", 1); - - // Instant Fishing - CVar_SetS32("gInstantFishing", 1); - // Guarantee Bite - CVar_SetS32("gGuaranteeFishingBite", 1); - // Child Minimum Weight (6 to 10) - CVar_SetS32("gChildMinimumWeightFish", 6); - // Adult Minimum Weight (8 to 13) - CVar_SetS32("gAdultMinimumWeightFish", 8); - - // Visual Stone of Agony - CVar_SetS32("gVisualAgony", 1); - // Pull grave during the day - CVar_SetS32("gDayGravePull", 1); - // Pull out Ocarina to Summon Scarecrow - CVar_SetS32("gSkipScarecrow", 0); - - // Pause link animation (0 to 16) - CVar_SetS32("gPauseLiveLink", 16); - // Frames to wait - CVar_SetS32("gMinFrameCount", 200); - } - void Render() { ImGui::Render(); ImGuiRenderDrawData(ImGui::GetDrawData()); @@ -2526,8 +711,41 @@ namespace SohImGui { } } - void BindCmd(const std::string& cmd, CommandEntry entry) { - console->AddCommand(cmd, entry); + void DrawSettings() { + overlay->DrawSettings(); + } + + Backend WindowBackend() { + return impl.backend; + } + + float WindowRefreshRate() { + return gfx_get_detected_hz(); + } + + std::pair* GetAvailableRenderingBackends() { + return backends; + } + + std::pair GetCurrentRenderingBackend() { + return backends[lastBackendID]; + } + + void SetCurrentRenderingBackend(uint8_t index, std::pair backend) { + Window::GetInstance()->GetConfig()->setString("Window.GfxBackend", backend.first); + lastBackendID = index; + } + + const char** GetSupportedTextureFilters() { + return filters; + } + + void SetResolutionMultiplier(float multiplier) { + gfx_current_dimensions.internal_mul = multiplier; + } + + void SetMSAALevel(uint32_t value) { + gfx_msaa_level = value; } void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled, bool isHidden) { @@ -2548,30 +766,135 @@ namespace SohImGui { } } + void EnableWindow(const std::string& name, bool isEnabled) { + customWindows[name].enabled = isEnabled; + } + + Ship::GameOverlay* GetGameOverlay() { + return overlay; + } + + Ship::InputEditor* GetInputEditor() { + return controller; + } + + void ToggleInputEditorWindow(bool isOpen) { + if (isOpen) + controller->Open(); + else + controller->Close(); + } + + void ToggleStatisticsWindow(bool isOpen) { + statsWindowOpen = isOpen; + } + + std::shared_ptr GetConsole() { + return console; + } + + void ToggleConsoleWindow(bool isOpen) { + if (isOpen) + console->Open(); + else + console->Close(); + } + + void DispatchConsoleCommand(const std::string& line) { + console->Dispatch(line); + } + + void RequestCvarSaveOnNextTick() { + needs_save = true; + } + ImTextureID GetTextureByName(const std::string& name) { return GetTextureByID(DefaultAssets[name]->textureId); } ImTextureID GetTextureByID(int id) { -#ifdef ENABLE_DX11 + #ifdef ENABLE_DX11 if (impl.backend == Backend::DX11) { ImTextureID gfx_d3d11_get_texture_by_id(int id); return gfx_d3d11_get_texture_by_id(id); } -#endif -#ifdef __WIIU__ + #endif + #ifdef __WIIU__ if (impl.backend == Backend::GX2) { return gfx_gx2_texture_for_imgui(id); } -#endif + #endif return reinterpret_cast(id); } - void BeginGroupPanel(const char* name, const ImVec2& size) - { + void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) { + GfxRenderingAPI* api = gfx_get_current_rendering_api(); + const auto res = static_cast(Window::GetInstance()->GetResourceManager()->LoadResource(path).get()); + + std::vector texBuffer; + texBuffer.reserve(res->width * res->height * 4); + + switch (res->texType) { + case Ship::TextureType::RGBA32bpp: + texBuffer.assign(res->imageData, res->imageData + (res->width * res->height * 4)); + break; + case Ship::TextureType::GrayscaleAlpha8bpp: + for (int32_t i = 0; i < res->width * res->height; i++) { + uint8_t ia = res->imageData[i]; + uint8_t color = ((ia >> 4) & 0xF) * 255 / 15; + uint8_t alpha = (ia & 0xF) * 255 / 15; + texBuffer.push_back(color); + texBuffer.push_back(color); + texBuffer.push_back(color); + texBuffer.push_back(alpha); + } + break; + default: + // TODO convert other image types + SPDLOG_WARN("SohImGui::LoadResource: Attempting to load unsupporting image type %s", path.c_str()); + return; + } + + for (size_t pixel = 0; pixel < texBuffer.size() / 4; pixel++) { + texBuffer[pixel * 4 + 0] *= tint.x; + texBuffer[pixel * 4 + 1] *= tint.y; + texBuffer[pixel * 4 + 2] *= tint.z; + texBuffer[pixel * 4 + 3] *= tint.w; + } + + const auto asset = new GameAsset{ api->new_texture() }; + + api->select_texture(0, asset->textureId); + api->set_sampler_parameters(0, false, 0, 0); + api->upload_texture(texBuffer.data(), res->width, res->height); + + DefaultAssets[name] = asset; + } + + void ShowCursor(bool hide, Dialogues d) { + if (d == Dialogues::dLoadSettings) { + Window::GetInstance()->ShowCursor(hide); + return; + } + + if (d == Dialogues::dConsole && CVar_GetS32("gOpenMenuBar", 0)) { + return; + } + if (!Window::GetInstance()->IsFullscreen()) { + oldCursorState = false; + return; + } + + if (oldCursorState != hide) { + oldCursorState = hide; + Window::GetInstance()->ShowCursor(hide); + } + } + + void BeginGroupPanel(const char* name, const ImVec2& size) { ImGui::BeginGroup(); // auto cursorPos = ImGui::GetCursorScreenPos(); @@ -2605,13 +928,13 @@ namespace SohImGui { ImGui::PopStyleVar(2); -#if IMGUI_VERSION_NUM >= 17301 + #if IMGUI_VERSION_NUM >= 17301 ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f; ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f; ImGui::GetCurrentWindow()->InnerRect.Max.x -= frameHeight * 0.5f; -#else + #else ImGui::GetCurrentWindow()->ContentsRegionRect.Max.x -= frameHeight * 0.5f; -#endif + #endif ImGui::GetCurrentWindow()->Size.x -= frameHeight; auto itemWidth = ImGui::CalcItemWidth(); @@ -2676,101 +999,17 @@ namespace SohImGui { ImGui::PopStyleVar(2); -#if IMGUI_VERSION_NUM >= 17301 + #if IMGUI_VERSION_NUM >= 17301 ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f; ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f; ImGui::GetCurrentWindow()->InnerRect.Max.x += frameHeight * 0.5f; -#else + #else ImGui::GetCurrentWindow()->ContentsRegionRect.Max.x += frameHeight * 0.5f; -#endif + #endif ImGui::GetCurrentWindow()->Size.x += frameHeight; - InsertPadding(); + ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::EndGroup(); } - - // Automatically add newlines to break up tooltips longer than a specified number of characters - // Manually included newlines will still be respected and reset the line length - // Default line length is 60 characters - std::string BreakTooltip(const char* text, int lineLength) { - std::string newText(text); - const int tipLength = newText.length(); - int lastSpace = -1; - int currentLineLength = 0; - for (int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) { - if (newText[currentCharacter] == '\n') { - currentLineLength = 0; - lastSpace = -1; - continue; - } - else if (newText[currentCharacter] == ' ') { - lastSpace = currentCharacter; - } - - if ((currentLineLength >= lineLength) && (lastSpace >= 0)) { - newText[lastSpace] = '\n'; - currentLineLength = currentCharacter - lastSpace - 1; - lastSpace = -1; - } - currentLineLength++; - } - return newText; - } - - std::string BreakTooltip(const std::string& text, int lineLength) { - return BreakTooltip(text.c_str(), lineLength); - } - - void InsertPadding(float extraVerticalPadding) { - ImGui::Dummy(ImVec2(0.0f, extraVerticalPadding)); - } - - void PaddedSeparator(bool padTop, bool padBottom, float extraVerticalTopPadding, float extraVerticalBottomPadding) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, extraVerticalTopPadding)); - } - ImGui::Separator(); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, extraVerticalBottomPadding)); - } - } - - void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - EnhancementSliderInt(text, id, cvarName, min, max, format, defaultValue, PlusMinusButton); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - } - - void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, ImGuiCheckboxGraphics disabledGraphic) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - } - - void PaddedText(const char* text, bool padTop, bool padBottom) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - ImGui::Text("%s", text); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, 0.0f)); - } - } - - std::string GetWindowButtonText(const char* text, bool menuOpen) { - char buttonText[100] = ""; - if(menuOpen) { strcat(buttonText,"> "); } - strcat(buttonText, text); - if (!menuOpen) { strcat(buttonText, " "); } - return buttonText; - } } diff --git a/libultraship/libultraship/ImGuiImpl.h b/libultraship/libultraship/ImGuiImpl.h index 733e9d1cf..cd035ae8a 100644 --- a/libultraship/libultraship/ImGuiImpl.h +++ b/libultraship/libultraship/ImGuiImpl.h @@ -1,14 +1,5 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - void enableBetaQuest(); - void disableBetaQuest(); -#ifdef __cplusplus -} -#endif - #ifdef __cplusplus #include "GameOverlay.h" #include "Lib/ImGui/imgui.h" @@ -34,14 +25,6 @@ namespace SohImGui { dLoadSettings, }; - // Enumeration for disabled checkbox graphics - enum class ImGuiCheckboxGraphics - { - Cross, - Checkmark, - None - }; - typedef struct { Backend backend; union { @@ -76,8 +59,6 @@ namespace SohImGui { } gx2; } EventImpl; - extern WindowImpl impl; - using WindowDrawFunc = void(*)(bool& enabled); typedef struct { @@ -85,55 +66,49 @@ namespace SohImGui { WindowDrawFunc drawFunc; } CustomWindow; - extern std::shared_ptr console; - extern Ship::InputEditor* controller; - extern Ship::GameOverlay* overlay; - extern bool needs_save; void Init(WindowImpl window_impl); void Update(EventImpl event); - void Tooltip(const char* text); - - void EnhancementRadioButton(const char* text, const char* cvarName, int id); - void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", ImGuiCheckboxGraphics disabledGraphic = ImGuiCheckboxGraphics::Cross); - void EnhancementButton(const char* text, const char* cvarName); - void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false); - void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false); - void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); - void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); - void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue = 0); - - void applyEnhancementPresets(void); - void applyEnhancementPresetDefault(void); - void applyEnhancementPresetVanillaPlus(void); - void applyEnhancementPresetEnhanced(void); - void applyEnhancementPresetRandomizer(void); void DrawMainMenuAndCalculateGameSize(void); + void RegisterMenuDrawMethod(std::function drawMethod); + void AddSetupHooksDelegate(std::function setupHooksMethod); void DrawFramebufferAndGameInput(void); void Render(void); void CancelFrame(void); - void ShowCursor(bool hide, Dialogues w); - void BindCmd(const std::string& cmd, Ship::CommandEntry entry); - void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled=false, bool isHidden=false); - void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1)); - void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha=false); - int ClampFloatToInt(float value, int min, int max); - void RandomizeColor(const char* cvarName, ImVec4* colors); - void RainbowColor(const char* cvarName, ImVec4* colors); - void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha); + void DrawSettings(); + + Backend WindowBackend(); + float WindowRefreshRate(); + std::pair* GetAvailableRenderingBackends(); + std::pair GetCurrentRenderingBackend(); + void SetCurrentRenderingBackend(uint8_t index, std::pair); + const char** GetSupportedTextureFilters(); + void SetResolutionMultiplier(float multiplier); + void SetMSAALevel(uint32_t value); + + void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled = false, bool isHidden = false); + void EnableWindow(const std::string& name, bool isEnabled = true); + + Ship::GameOverlay* GetGameOverlay(); + + Ship::InputEditor* GetInputEditor(); + void ToggleInputEditorWindow(bool isOpen = true); + void ToggleStatisticsWindow(bool isOpen = true); + + std::shared_ptr GetConsole(); + void ToggleConsoleWindow(bool isOpen = true); + void DispatchConsoleCommand(const std::string& line); + + void RequestCvarSaveOnNextTick(); + ImTextureID GetTextureByID(int id); ImTextureID GetTextureByName(const std::string& name); + void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1)); + + void ShowCursor(bool hide, Dialogues w); void BeginGroupPanel(const char* name, const ImVec2 & size = ImVec2(0.0f, 0.0f)); void EndGroupPanel(float minHeight = 0.0f); - std::string BreakTooltip(const char* text, int lineLength = 60); - std::string BreakTooltip(const std::string& text, int lineLength = 60); - void InsertPadding(float extraVerticalPadding = 0.0f); - void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f); - void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true); - void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", ImGuiCheckboxGraphics disabledGraphic = ImGuiCheckboxGraphics::Cross); - void PaddedText(const char* text, bool padTop = true, bool padBottom = true); - std::string GetWindowButtonText(const char* text, bool menuOpen); } #endif diff --git a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h index 8a629aa1a..4bb8cf2c6 100644 --- a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h +++ b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h @@ -41,8 +41,8 @@ protected: } formatted.push_back('\0'); const char* msg_output = formatted.data(); - if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->IsOpened()) { - SohImGui::console->Append("Logs", msg.level, "%s", msg_output); + if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::GetConsole()->IsOpened()) { + SohImGui::GetConsole()->Append("Logs", msg.level, "%s", msg_output); } } @@ -57,4 +57,4 @@ private: using soh_sink_mt = sohconsole_sink; using soh_sink_st = sohconsole_sink; } // namespace sinks -} // namespace spdlog \ No newline at end of file +} // namespace spdlog diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index b9e84fd60..36a10b505 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -86,7 +86,7 @@ extern "C" { pad->gyro_x = 0; pad->gyro_y = 0; - if (SohImGui::controller->IsOpened()) return; + if (SohImGui::GetInputEditor()->IsOpened()) return; Ship::Window::GetInstance()->GetControlDeck()->WriteToPad(pad); Ship::ExecuteHooks(pad); diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 50bf5fa69..e903ee541 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -162,6 +162,7 @@ set(Header_Files__soh__Enhancements__controls ) source_group("Header Files\\soh\\Enhancements\\controls" FILES ${Header_Files__soh__Enhancements__controls}) + set(Header_Files__soh__Enhancements__cosmetics "soh/Enhancements/cosmetics/CosmeticsEditor.h" ) @@ -172,7 +173,6 @@ set(Header_Files__soh__Enhancements__debugger "soh/Enhancements/debugger/colViewer.h" "soh/Enhancements/debugger/debugger.h" "soh/Enhancements/debugger/debugSaveEditor.h" - "soh/Enhancements/debugger/ImGuiHelpers.h" ) source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__soh__Enhancements__debugger}) @@ -251,6 +251,10 @@ set(Source_Files__soh "soh/z_message_OTR.cpp" "soh/z_play_otr.cpp" "soh/z_scene_otr.cpp" + "soh/GameMenuBar.hpp" + "soh/GameMenuBar.cpp" + "soh/UIWidgets.hpp" + "soh/UIWidgets.cpp" ) source_group("Source Files\\soh" FILES ${Source_Files__soh}) @@ -277,7 +281,6 @@ set(Source_Files__soh__Enhancements__debugger "soh/Enhancements/debugger/colViewer.cpp" "soh/Enhancements/debugger/debugger.cpp" "soh/Enhancements/debugger/debugSaveEditor.cpp" - "soh/Enhancements/debugger/ImGuiHelpers.cpp" ) source_group("Source Files\\soh\\Enhancements\\debugger" FILES ${Source_Files__soh__Enhancements__debugger}) @@ -1669,14 +1672,13 @@ set(SDL2-INCLUDE ${SDL2_INCLUDE_DIRS}) target_include_directories(${PROJECT_NAME} PRIVATE assets ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${CMAKE_CURRENT_SOURCE_DIR}/src/ + ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship + ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/libjpeg/include/ - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/ ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/spdlog/include/ + ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64/PR ${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPDUtils - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64 - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/Lib/Fast3D/U64/PR ${SDL2-INCLUDE} - ${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/libultraship/ ${CMAKE_CURRENT_SOURCE_DIR}/assets/ . ) diff --git a/soh/include/global.h b/soh/include/global.h index 65203c1aa..aa904984f 100644 --- a/soh/include/global.h +++ b/soh/include/global.h @@ -6,7 +6,7 @@ #include "macros.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/gameconsole.h" -#include "Cvar.h" +#include diff --git a/soh/include/macros.h b/soh/include/macros.h index 1822cb1d6..e726d9f00 100644 --- a/soh/include/macros.h +++ b/soh/include/macros.h @@ -1,7 +1,7 @@ #ifndef MACROS_H #define MACROS_H -#include "endianness.h" +#include #define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0])) #define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0])) diff --git a/soh/include/z64.h b/soh/include/z64.h index 1f0bbc25c..7264b663b 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -26,7 +26,7 @@ #include "z64interface.h" #include "sequence.h" #include "sfx.h" -#include "color.h" +#include #include "ichain.h" #include "regs.h" diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h index e821d7f17..8f7b8f2b4 100644 --- a/soh/include/z64audio.h +++ b/soh/include/z64audio.h @@ -1,7 +1,7 @@ #ifndef Z64_AUDIO_H #define Z64_AUDIO_H -#include "endianness.h" +#include #define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0)) @@ -815,7 +815,7 @@ typedef struct { /* 0x0E */ u8 ttl; // duration after which the DMA can be discarded } SampleDma; // size = 0x10 -#include +#include typedef struct { /* 0x0000 */ char unk_0000; @@ -1122,4 +1122,4 @@ float Audio_GetGameVolume(int player_id); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/soh/include/z64effect.h b/soh/include/z64effect.h index 861eb9070..7b364f0ea 100644 --- a/soh/include/z64effect.h +++ b/soh/include/z64effect.h @@ -1,7 +1,7 @@ #ifndef Z64EFFECT_H #define Z64EFFECT_H -#include "color.h" +#include struct GraphicsContext; struct GlobalContext; diff --git a/soh/include/z64light.h b/soh/include/z64light.h index 639490022..d642a7364 100644 --- a/soh/include/z64light.h +++ b/soh/include/z64light.h @@ -4,7 +4,7 @@ #include "ultra64.h" #include "ultra64/gbi.h" #include "z64math.h" -#include "color.h" +#include typedef struct { /* 0x0 */ s16 x; diff --git a/soh/include/z64transition.h b/soh/include/z64transition.h index 2adb6f604..9c93e44b7 100644 --- a/soh/include/z64transition.h +++ b/soh/include/z64transition.h @@ -2,7 +2,7 @@ #define Z64TRANSITION_H #include "ultra64.h" -#include "color.h" +#include typedef struct { f32 unk_0; diff --git a/soh/soh/Enhancements/controls/GameControlEditor.cpp b/soh/soh/Enhancements/controls/GameControlEditor.cpp index ee8e33dea..f494711e6 100644 --- a/soh/soh/Enhancements/controls/GameControlEditor.cpp +++ b/soh/soh/Enhancements/controls/GameControlEditor.cpp @@ -6,12 +6,14 @@ #include #include -#include "Lib/ImGui/imgui.h" -#include "Lib/ImGui/imgui_internal.h" -#include "Cvar.h" -#include "UltraController.h" -#include "Utils/StringHelper.h" -#include "../libultraship/ImGuiImpl.h" +#include +#include +#include +#include +#include +#include + +#include "../../UIWidgets.hpp" namespace GameControlEditor { const ImGuiTableFlags PANEL_TABLE_FLAGS = @@ -50,7 +52,11 @@ namespace GameControlEditor { // place the ? button to the most of the right side of the cell it is using. ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15); ImGui::SmallButton("?"); - SohImGui::Tooltip(helptext.c_str()); + + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", helptext.c_str()); + } + if (sameline) { //I do not use ImGui::SameLine(); because it make some element vanish. ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22); @@ -119,7 +125,7 @@ namespace GameControlEditor { preview = "Unknown"; } - SohImGui::InsertPadding(); + UIWidgets::Spacer(0); ImVec2 cursorPos = ImGui::GetCursorPos(); ImVec2 textSize = ImGui::CalcTextSize(mapping.label); ImGui::SetCursorPosY(cursorPos.y + textSize.y / 4); @@ -140,7 +146,7 @@ namespace GameControlEditor { } ImGui::EndCombo(); } - SohImGui::InsertPadding(); + UIWidgets::Spacer(0); } void DrawOcarinaControlPanel() { @@ -157,7 +163,7 @@ namespace GameControlEditor { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - SohImGui::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls"); + UIWidgets::EnhancementCheckbox("Customize Ocarina Controls", "gCustomOcarinaControls"); if (CVar_GetS32("gCustomOcarinaControls", 0) == 1) { if (ImGui::BeginTable("tableCustomMainOcarinaControls", 2, ImGuiTableFlags_SizingStretchProp)) { @@ -194,10 +200,10 @@ namespace GameControlEditor { ImGui::EndTable(); } } else { - SohImGui::InsertPadding(); + UIWidgets::Spacer(0); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::TextWrapped("To modify the main ocarina controls, select the \"Customize Ocarina Controls\" checkbox."); - SohImGui::InsertPadding(); + UIWidgets::Spacer(0); } SohImGui::BeginGroupPanel("Alternate controls", ImGui::GetContentRegionAvail()); @@ -206,9 +212,9 @@ namespace GameControlEditor { ImGui::TableSetupColumn("Right stick", PANEL_TABLE_COLUMN_FLAGS); TableHelper::InitHeader(false); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - SohImGui::EnhancementCheckbox("Play with D-pad", "gDpadOcarina"); + UIWidgets::EnhancementCheckbox("Play with D-pad", "gDpadOcarina"); TableHelper::NextCol(); - SohImGui::EnhancementCheckbox("Play with camera stick", "gRStickOcarina"); + UIWidgets::EnhancementCheckbox("Play with camera stick", "gRStickOcarina"); ImGui::EndTable(); } SohImGui::EndGroupPanel(); @@ -223,17 +229,17 @@ namespace GameControlEditor { ImVec2 cursor = ImGui::GetCursorPos(); ImGui::SetCursorPos(ImVec2(cursor.x + 5, cursor.y + 5)); - SohImGui::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); - SohImGui::Tooltip("Inverts the Camera X Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Invert Camera X Axis", "gInvertXAxis"); + UIWidgets::Tooltip("Inverts the Camera X Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - SohImGui::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis"); - SohImGui::Tooltip("Inverts the Camera Y Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Invert Camera Y Axis", "gInvertYAxis"); + UIWidgets::Tooltip("Inverts the Camera Y Axis in:\n-Free camera\n-C-Up view\n-Weapon Aiming"); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - SohImGui::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); - SohImGui::Tooltip("Allows for aiming with the rights stick when:\n-Aiming in the C-Up view\n-Aiming with weapons"); + UIWidgets::PaddedEnhancementCheckbox("Right Stick Aiming", "gRightStickAiming"); + UIWidgets::Tooltip("Allows for aiming with the rights stick when:\n-Aiming in the C-Up view\n-Aiming with weapons"); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); - SohImGui::PaddedEnhancementCheckbox("Auto-Center First Person View", "gAutoCenterView"); - SohImGui::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); + UIWidgets::PaddedEnhancementCheckbox("Auto-Center First Person View", "gAutoCenterView"); + UIWidgets::Tooltip("Prevents the C-Up view from auto-centering, allowing for Gyro Aiming"); } void DrawUI(bool& open) { diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp index b04f30e35..5782119f1 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp @@ -1,11 +1,13 @@ #include "CosmeticsEditor.h" -#include "../libultraship/ImGuiImpl.h" +#include #include -#include +#include #include #include -#include +#include + +#include "../../UIWidgets.hpp" const char* RainbowColorCvarList[] = { //This is the list of possible CVars that has rainbow effect. @@ -51,9 +53,9 @@ void GetRandomColorRGB(CosmeticsColorSection* ColorSection, int SectionSize){ std::string cvarName = Element->CvarName; std::string Cvar_RBM = cvarName + "RBM"; colors = RANDOMIZE_32(255); - NewColors.r = SohImGui::ClampFloatToInt(colors.x * 255, 0, 255); - NewColors.g = SohImGui::ClampFloatToInt(colors.y * 255, 0, 255); - NewColors.b = SohImGui::ClampFloatToInt(colors.z * 255, 0, 255); + NewColors.r = fmin(fmax(colors.x * 255, 0), 255); + NewColors.g = fmin(fmax(colors.y * 255, 0), 255); + NewColors.b = fmin(fmax(colors.z * 255, 0), 255); Element->ModifiedColor = colors; CVar_SetRGBA(cvarName.c_str(), NewColors); CVar_SetS32(Cvar_RBM.c_str(), 0); @@ -149,9 +151,9 @@ void LoadRainbowColor(bool& open) { case 6: NewColor.x = 255; NewColor.y = 0; NewColor.z = a; break; } Color_RGBA8 NewColorRGB = { - SohImGui::ClampFloatToInt(NewColor.x, 0, 255), - SohImGui::ClampFloatToInt(NewColor.y, 0, 255), - SohImGui::ClampFloatToInt(NewColor.z, 0, 255), + fmin(fmax(NewColor.x, 0), 255), + fmin(fmax(NewColor.y, 0), 255), + fmin(fmax(NewColor.z, 0), 255), 255 }; if (CVar_GetS32(Cvar_RBM.c_str(), 0) != 0) { @@ -187,7 +189,7 @@ void Draw_HelpIcon(const std::string& helptext, bool sameline = true, int Pos = ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x-60); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 15); ImGui::SmallButton("?"); - SohImGui::Tooltip(helptext.c_str()); + UIWidgets::Tooltip(helptext.c_str()); if (sameline) { //I do not use ImGui::SameLine(); because it make some element vanish. ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 22); @@ -197,96 +199,96 @@ void Draw_HelpIcon(const std::string& helptext, bool sameline = true, int Pos = void DrawUseMarginsSlider(const std::string ElementName, const std::string CvarName){ std::string CvarLabel = CvarName + "UseMargins"; std::string Label = ElementName + " use margins"; - SohImGui::EnhancementCheckbox(Label.c_str(), CvarLabel.c_str()); - SohImGui::Tooltip("Using this allow you move the element with General margins sliders"); + UIWidgets::EnhancementCheckbox(Label.c_str(), CvarLabel.c_str()); + UIWidgets::Tooltip("Using this allow you move the element with General margins sliders"); } void DrawPositionsRadioBoxes(const std::string CvarName, bool NoAnchorEnabled = true){ std::string CvarLabel = CvarName + "PosType"; - SohImGui::EnhancementRadioButton("Original position", CvarLabel.c_str(), 0); - SohImGui::Tooltip("This will use original intended elements position"); - SohImGui::EnhancementRadioButton("Anchor to the left", CvarLabel.c_str(), 1); - SohImGui::Tooltip("This will make your elements follow the left side of your game window"); - SohImGui::EnhancementRadioButton("Anchor to the right", CvarLabel.c_str(), 2); - SohImGui::Tooltip("This will make your elements follow the right side of your game window"); + UIWidgets::EnhancementRadioButton("Original position", CvarLabel.c_str(), 0); + UIWidgets::Tooltip("This will use original intended elements position"); + UIWidgets::EnhancementRadioButton("Anchor to the left", CvarLabel.c_str(), 1); + UIWidgets::Tooltip("This will make your elements follow the left side of your game window"); + UIWidgets::EnhancementRadioButton("Anchor to the right", CvarLabel.c_str(), 2); + UIWidgets::Tooltip("This will make your elements follow the right side of your game window"); if (NoAnchorEnabled) { - SohImGui::EnhancementRadioButton("No anchors", CvarLabel.c_str(), 3); - SohImGui::Tooltip("This will make your elements to not follow any side\nBetter used for center elements"); + UIWidgets::EnhancementRadioButton("No anchors", CvarLabel.c_str(), 3); + UIWidgets::Tooltip("This will make your elements to not follow any side\nBetter used for center elements"); } - SohImGui::EnhancementRadioButton("Hidden", CvarLabel.c_str(), 4); - SohImGui::Tooltip("This will make your elements hidden"); + UIWidgets::EnhancementRadioButton("Hidden", CvarLabel.c_str(), 4); + UIWidgets::Tooltip("This will make your elements hidden"); } void DrawTransitions(const std::string CvarName){ - SohImGui::EnhancementRadioButton("Really slow fade (white)", CvarName.c_str(), 8); + UIWidgets::EnhancementRadioButton("Really slow fade (white)", CvarName.c_str(), 8); Table_NextCol(); - SohImGui::EnhancementRadioButton("Really slow fade (black)", CvarName.c_str(), 7); + UIWidgets::EnhancementRadioButton("Really slow fade (black)", CvarName.c_str(), 7); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow fade (white)", CvarName.c_str(), 10); + UIWidgets::EnhancementRadioButton("Slow fade (white)", CvarName.c_str(), 10); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow fade (black)", CvarName.c_str(), 9); + UIWidgets::EnhancementRadioButton("Slow fade (black)", CvarName.c_str(), 9); Table_NextLine(); - SohImGui::EnhancementRadioButton("Normal fade (white)", CvarName.c_str(), 3); + UIWidgets::EnhancementRadioButton("Normal fade (white)", CvarName.c_str(), 3); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal fade (black)", CvarName.c_str(), 2); + UIWidgets::EnhancementRadioButton("Normal fade (black)", CvarName.c_str(), 2); Table_NextLine(); - SohImGui::EnhancementRadioButton("Fast fade (white)", CvarName.c_str(), 5); + UIWidgets::EnhancementRadioButton("Fast fade (white)", CvarName.c_str(), 5); Table_NextCol(); - SohImGui::EnhancementRadioButton("Fast fade (black)", CvarName.c_str(), 4); + UIWidgets::EnhancementRadioButton("Fast fade (black)", CvarName.c_str(), 4); Table_NextLine(); - SohImGui::EnhancementRadioButton("Fast circle (white)", CvarName.c_str(), 40); + UIWidgets::EnhancementRadioButton("Fast circle (white)", CvarName.c_str(), 40); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal circle (black)", CvarName.c_str(), 32); + UIWidgets::EnhancementRadioButton("Normal circle (black)", CvarName.c_str(), 32); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow circle (white)", CvarName.c_str(), 41); + UIWidgets::EnhancementRadioButton("Slow circle (white)", CvarName.c_str(), 41); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow circle (black)", CvarName.c_str(), 33); + UIWidgets::EnhancementRadioButton("Slow circle (black)", CvarName.c_str(), 33); Table_NextLine(); - SohImGui::EnhancementRadioButton("Fast noise circle (white)", CvarName.c_str(), 42); + UIWidgets::EnhancementRadioButton("Fast noise circle (white)", CvarName.c_str(), 42); Table_NextCol(); - SohImGui::EnhancementRadioButton("Fast noise circle (black)", CvarName.c_str(), 34); + UIWidgets::EnhancementRadioButton("Fast noise circle (black)", CvarName.c_str(), 34); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow noise circle (white)", CvarName.c_str(), 43); + UIWidgets::EnhancementRadioButton("Slow noise circle (white)", CvarName.c_str(), 43); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow noise circle (black)", CvarName.c_str(), 35); + UIWidgets::EnhancementRadioButton("Slow noise circle (black)", CvarName.c_str(), 35); Table_NextLine(); - SohImGui::EnhancementRadioButton("Normal waves circle (white)", CvarName.c_str(), 44); + UIWidgets::EnhancementRadioButton("Normal waves circle (white)", CvarName.c_str(), 44); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal waves circle (black)", CvarName.c_str(), 36); + UIWidgets::EnhancementRadioButton("Normal waves circle (black)", CvarName.c_str(), 36); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow waves circle (white)", CvarName.c_str(), 45); + UIWidgets::EnhancementRadioButton("Slow waves circle (white)", CvarName.c_str(), 45); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow waves circle (black)", CvarName.c_str(), 37); + UIWidgets::EnhancementRadioButton("Slow waves circle (black)", CvarName.c_str(), 37); Table_NextLine(); - SohImGui::EnhancementRadioButton("Normal close circle (white)", CvarName.c_str(), 46); + UIWidgets::EnhancementRadioButton("Normal close circle (white)", CvarName.c_str(), 46); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal close circle (black)", CvarName.c_str(), 38); + UIWidgets::EnhancementRadioButton("Normal close circle (black)", CvarName.c_str(), 38); Table_NextLine(); - SohImGui::EnhancementRadioButton("Slow close circle (white)", CvarName.c_str(), 47); + UIWidgets::EnhancementRadioButton("Slow close circle (white)", CvarName.c_str(), 47); Table_NextCol(); - SohImGui::EnhancementRadioButton("Slow close circle (black)", CvarName.c_str(), 39); + UIWidgets::EnhancementRadioButton("Slow close circle (black)", CvarName.c_str(), 39); Table_NextLine(); - SohImGui::EnhancementRadioButton("Super fast circle (white)", CvarName.c_str(), 56); + UIWidgets::EnhancementRadioButton("Super fast circle (white)", CvarName.c_str(), 56); Table_NextCol(); - SohImGui::EnhancementRadioButton("Super fast circle (black)", CvarName.c_str(), 58); + UIWidgets::EnhancementRadioButton("Super fast circle (black)", CvarName.c_str(), 58); Table_NextLine(); - SohImGui::EnhancementRadioButton("Super fast noise circle (white)", CvarName.c_str(), 57); + UIWidgets::EnhancementRadioButton("Super fast noise circle (white)", CvarName.c_str(), 57); Table_NextCol(); - SohImGui::EnhancementRadioButton("Super fast noise circle (black)", CvarName.c_str(), 59); + UIWidgets::EnhancementRadioButton("Super fast noise circle (black)", CvarName.c_str(), 59); } void DrawPositionSlider(const std::string CvarName, int MinY, int MaxY, int MinX, int MaxX){ std::string PosXCvar = CvarName+"PosX"; std::string PosYCvar = CvarName+"PosY"; std::string InvisibleLabelX = "##"+PosXCvar; std::string InvisibleLabelY = "##"+PosYCvar; - SohImGui::EnhancementSliderInt("Up <-> Down : %d", InvisibleLabelY.c_str(), PosYCvar.c_str(), MinY, MaxY, "", 0, true); - SohImGui::Tooltip("This slider is used to move Up and Down your elements."); - SohImGui::EnhancementSliderInt("Left <-> Right : %d", InvisibleLabelX.c_str(), PosXCvar.c_str(), MinX, MaxX, "", 0, true); - SohImGui::Tooltip("This slider is used to move Left and Right your elements."); + UIWidgets::EnhancementSliderInt("Up <-> Down : %d", InvisibleLabelY.c_str(), PosYCvar.c_str(), MinY, MaxY, "", 0, true); + UIWidgets::Tooltip("This slider is used to move Up and Down your elements."); + UIWidgets::EnhancementSliderInt("Left <-> Right : %d", InvisibleLabelX.c_str(), PosXCvar.c_str(), MinX, MaxX, "", 0, true); + UIWidgets::Tooltip("This slider is used to move Left and Right your elements."); } void DrawScaleSlider(const std::string CvarName,float DefaultValue){ std::string InvisibleLabel = "##"+CvarName; std::string CvarLabel = CvarName+"Scale"; //Disabled for now. feature not done and several fixes needed to be merged. - //SohImGui::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true,true); + //UIWidgets::EnhancementSliderFloat("Scale : %dx", InvisibleLabel.c_str(), CvarLabel.c_str(), 0.1f, 3.0f,"",DefaultValue,true,true); } void DrawColorSection(CosmeticsColorSection* ColorSection, int SectionSize) { for (s16 i = 0; i < SectionSize; i++) { @@ -308,7 +310,7 @@ void DrawColorSection(CosmeticsColorSection* ColorSection, int SectionSize) { Table_NextLine(); } Draw_HelpIcon(Tooltip.c_str()); - SohImGui::EnhancementColor(Name.c_str(), Cvar.c_str(), ModifiedColor, DefaultColor, canRainbow, hasAlpha, sameLine); + UIWidgets::EnhancementColor(Name.c_str(), Cvar.c_str(), ModifiedColor, DefaultColor, canRainbow, hasAlpha, sameLine); } } void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSection* ColorSection, int SectionSize, bool isAllCosmetics = false){ @@ -335,21 +337,21 @@ void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSectio CVar_SetS32("gCCparated", 1); GetRandomColorRGB(ColorSection, SectionSize); } - SohImGui::Tooltip(Tooltip_RNG.c_str()); + UIWidgets::Tooltip(Tooltip_RNG.c_str()); Table_NextCol(); if(ImGui::Button(Reset_BtnText.c_str(), ImVec2( ImGui::GetContentRegionAvail().x, 20.0f))){ GetDefaultColorRGB(ColorSection, SectionSize); } - SohImGui::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); - SohImGui::Tooltip(Tooltip_RNG.c_str()); + UIWidgets::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); + UIWidgets::Tooltip(Tooltip_RNG.c_str()); ImGui::EndTable(); } } void Draw_Npcs(){ DrawRandomizeResetButton("all NPCs", NPCs_section, SECTION_SIZE(NPCs_section)); - SohImGui::EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol"); - SohImGui::Tooltip("Enable/Disable custom Navi colors\nIf disabled, default colors will be used\nColors go into effect when Navi goes back into your pockets"); + UIWidgets::EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol"); + UIWidgets::Tooltip("Enable/Disable custom Navi colors\nIf disabled, default colors will be used\nColors go into effect when Navi goes back into your pockets"); if (CVar_GetS32("gUseNaviCol",0)) { DrawRandomizeResetButton("Navi's", Navi_Section, SECTION_SIZE(Navi_Section)); }; @@ -360,8 +362,8 @@ void Draw_Npcs(){ DrawColorSection(Navi_Section, SECTION_SIZE(Navi_Section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom colors for Keese", "gUseKeeseCol"); - SohImGui::Tooltip("Enable/Disable custom Keese element colors\nIf disabled, default element colors will be used\nColors go into effect when Keese respawn (or when the room is reloaded)"); + UIWidgets::EnhancementCheckbox("Custom colors for Keese", "gUseKeeseCol"); + UIWidgets::Tooltip("Enable/Disable custom Keese element colors\nIf disabled, default element colors will be used\nColors go into effect when Keese respawn (or when the room is reloaded)"); if (CVar_GetS32("gUseKeeseCol",0) && ImGui::BeginTable("tableKeese", 2, FlagsTable)) { ImGui::TableSetupColumn("Fire colors##Keese", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("Ice colors##Keese", FlagsCell, TablesCellsWidth/2); @@ -369,8 +371,8 @@ void Draw_Npcs(){ DrawColorSection(Keese_Section, SECTION_SIZE(Keese_Section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom colors for Dogs", "gUseDogsCol"); - SohImGui::Tooltip("Enable/Disable custom colors for the two Dog variants\nIf disabled, default colors will be used"); + UIWidgets::EnhancementCheckbox("Custom colors for Dogs", "gUseDogsCol"); + UIWidgets::Tooltip("Enable/Disable custom colors for the two Dog variants\nIf disabled, default colors will be used"); if (CVar_GetS32("gUseDogsCol",0) && ImGui::BeginTable("tableDogs", 2, FlagsTable)) { ImGui::TableSetupColumn("White Dog color", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("Brown Dog color", FlagsCell, TablesCellsWidth/2); @@ -381,8 +383,8 @@ void Draw_Npcs(){ } void Draw_ItemsSkills(){ DrawRandomizeResetButton("all skills and items", AllItemsSkills_section, SECTION_SIZE(AllItemsSkills_section)); - SohImGui::EnhancementCheckbox("Custom tunics color", "gUseTunicsCol"); - SohImGui::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); + UIWidgets::EnhancementCheckbox("Custom tunics color", "gUseTunicsCol"); + UIWidgets::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics."); if (CVar_GetS32("gUseTunicsCol",0)) { DrawRandomizeResetButton("Link's tunics", Tunics_Section, SECTION_SIZE(Tunics_Section)); }; @@ -394,7 +396,7 @@ void Draw_ItemsSkills(){ DrawColorSection(Tunics_Section, SECTION_SIZE(Tunics_Section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom arrows colors", "gUseArrowsCol"); + UIWidgets::EnhancementCheckbox("Custom arrows colors", "gUseArrowsCol"); if (CVar_GetS32("gUseArrowsCol",0)) { DrawRandomizeResetButton("elemental arrows", Arrows_section, SECTION_SIZE(Arrows_section)); } @@ -405,7 +407,7 @@ void Draw_ItemsSkills(){ DrawColorSection(Arrows_section, SECTION_SIZE(Arrows_section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom spells colors", "gUseSpellsCol"); + UIWidgets::EnhancementCheckbox("Custom spells colors", "gUseSpellsCol"); if (CVar_GetS32("gUseSpellsCol",0)) { DrawRandomizeResetButton("spells", Spells_section, SECTION_SIZE(Spells_section)); } @@ -416,7 +418,7 @@ void Draw_ItemsSkills(){ DrawColorSection(Spells_section, SECTION_SIZE(Spells_section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom spin attack colors", "gUseChargedCol"); + UIWidgets::EnhancementCheckbox("Custom spin attack colors", "gUseChargedCol"); if (CVar_GetS32("gUseChargedCol",0)) { DrawRandomizeResetButton("spins attack", SpinAtk_section, SECTION_SIZE(SpinAtk_section)); } @@ -427,13 +429,13 @@ void Draw_ItemsSkills(){ DrawColorSection(SpinAtk_section, SECTION_SIZE(SpinAtk_section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("Custom trails color", "gUseTrailsCol"); + UIWidgets::EnhancementCheckbox("Custom trails color", "gUseTrailsCol"); if (CVar_GetS32("gUseTrailsCol",0) && ImGui::BeginTable("tabletrails", 1, FlagsTable)) { ImGui::TableSetupColumn("Custom Trails", FlagsCell, TablesCellsWidth); Table_InitHeader(); DrawColorSection(Trails_section, SECTION_SIZE(Trails_section)); - SohImGui::EnhancementSliderInt("Trails duration: %dx", "##TrailsMul", "gTrailDurantion", 1, 5, ""); - SohImGui::Tooltip("The longer the trails the weirder it become"); + UIWidgets::EnhancementSliderInt("Trails duration: %dx", "##TrailsMul", "gTrailDurantion", 1, 5, ""); + UIWidgets::Tooltip("The longer the trails the weirder it become"); ImGui::NewLine(); ImGui::EndTable(); } @@ -455,18 +457,18 @@ void Draw_Placements(){ if (ImGui::BeginTable("tableMargins", 1, FlagsTable)) { ImGui::TableSetupColumn("General margins settings", FlagsCell, TablesCellsWidth); Table_InitHeader(); - SohImGui::EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); - SohImGui::EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, ImGui::GetWindowViewport()->Size.x, "", 0, true); - SohImGui::EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0, true); - SohImGui::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); + UIWidgets::EnhancementSliderInt("Top : %dx", "##UIMARGINT", "gHUDMargin_T", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); + UIWidgets::EnhancementSliderInt("Left: %dx", "##UIMARGINL", "gHUDMargin_L", -25, ImGui::GetWindowViewport()->Size.x, "", 0, true); + UIWidgets::EnhancementSliderInt("Right: %dx", "##UIMARGINR", "gHUDMargin_R", (ImGui::GetWindowViewport()->Size.x)*-1, 25, "", 0, true); + UIWidgets::EnhancementSliderInt("Bottom: %dx", "##UIMARGINB", "gHUDMargin_B", (ImGui::GetWindowViewport()->Size.y/2)*-1, 25, "", 0, true); SetMarginAll("All margins on",true); - SohImGui::Tooltip("Set most of the element to use margin\nSome elements with default position will not be affected\nElements without Archor or Hidden will not be turned on"); + UIWidgets::Tooltip("Set most of the element to use margin\nSome elements with default position will not be affected\nElements without Archor or Hidden will not be turned on"); ImGui::SameLine(); SetMarginAll("All margins off",false); - SohImGui::Tooltip("Set all of the element to not use margin"); + UIWidgets::Tooltip("Set all of the element to not use margin"); ImGui::SameLine(); ResetPositionAll(); - SohImGui::Tooltip("Revert every element to use their original position and no margins"); + UIWidgets::Tooltip("Revert every element to use their original position and no margins"); ImGui::NewLine(); ImGui::EndTable(); } @@ -775,7 +777,7 @@ void Draw_HUDButtons(){ DrawColorSection(C_Btn_Unified_section, SECTION_SIZE(C_Btn_Unified_section)); ImGui::EndTable(); } - SohImGui::EnhancementCheckbox("C-Buttons use separate colors", "gCCparated"); + UIWidgets::EnhancementCheckbox("C-Buttons use separate colors", "gCCparated"); if (CVar_GetS32("gCCparated",0) && ImGui::CollapsingHeader("C Button individual colors")) { if (ImGui::BeginTable("tableBTN_CSep", 1, FlagsTable)) { ImGui::TableSetupColumn("C-Buttons individual colors", FlagsCell, TablesCellsWidth); @@ -813,19 +815,19 @@ void Draw_General(){ ImGui::TableSetupColumn("Custom Schemes", FlagsCell, TablesCellsWidth); Table_InitHeader(); Draw_HelpIcon("Change interface color to N64 style"); - SohImGui::EnhancementRadioButton("N64 Colors", "gHudColors", 0); + UIWidgets::EnhancementRadioButton("N64 Colors", "gHudColors", 0); Table_NextCol(); Draw_HelpIcon("Change interface color to GameCube style"); - SohImGui::EnhancementRadioButton("GCN Colors", "gHudColors", 1); + UIWidgets::EnhancementRadioButton("GCN Colors", "gHudColors", 1); Table_NextCol(); Draw_HelpIcon("Lets you change every interface color to your liking"); - SohImGui::EnhancementRadioButton("Custom Colors", "gHudColors", 2); + UIWidgets::EnhancementRadioButton("Custom Colors", "gHudColors", 2); ImGui::EndTable(); } if (CVar_GetS32("gHudColors",0) ==2 ){ DrawRandomizeResetButton("interface (excluding buttons)", Misc_Interface_section, SECTION_SIZE(Misc_Interface_section)); if (ImGui::CollapsingHeader("Hearts colors")) { - SohImGui::Tooltip("Hearts colors in general\nDD stand for Double Defense"); + UIWidgets::Tooltip("Hearts colors in general\nDD stand for Double Defense"); if (ImGui::BeginTable("tableHearts", 3, FlagsTable | ImGuiTableFlags_Hideable)) { ImGui::TableSetupColumn("Hearts (normal)", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable, TablesCellsWidth/3); ImGui::TableSetupColumn("Hearts (DD)", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_IndentEnable, TablesCellsWidth/3); @@ -874,25 +876,25 @@ void Draw_General(){ ImGui::TableSetupColumn("transitionother1", FlagsCell, TablesCellsWidth/2); ImGui::TableSetupColumn("transitionother2", FlagsCell, TablesCellsWidth/2); Table_InitHeader(false); - SohImGui::EnhancementRadioButton("Originals", "gSceneTransitions", 255); - SohImGui::Tooltip("This will make the game use original scenes transitions"); + UIWidgets::EnhancementRadioButton("Originals", "gSceneTransitions", 255); + UIWidgets::Tooltip("This will make the game use original scenes transitions"); Table_NextCol(); - SohImGui::EnhancementRadioButton("None", "gSceneTransitions", 11); - SohImGui::Tooltip("This will make the game use no any scenes transitions"); + UIWidgets::EnhancementRadioButton("None", "gSceneTransitions", 11); + UIWidgets::Tooltip("This will make the game use no any scenes transitions"); Table_NextLine(); - SohImGui::EnhancementRadioButton("Desert mode (persistant)", "gSceneTransitions", 14); - SohImGui::Tooltip("This will make the game use the sand storm scenes transitions that will persist in map"); + UIWidgets::EnhancementRadioButton("Desert mode (persistant)", "gSceneTransitions", 14); + UIWidgets::Tooltip("This will make the game use the sand storm scenes transitions that will persist in map"); Table_NextCol(); - SohImGui::EnhancementRadioButton("Desert mode (non persistant)", "gSceneTransitions", 15); - SohImGui::Tooltip("This will make the game use the sand storm scenes transitions"); + UIWidgets::EnhancementRadioButton("Desert mode (non persistant)", "gSceneTransitions", 15); + UIWidgets::Tooltip("This will make the game use the sand storm scenes transitions"); Table_NextLine(); - SohImGui::EnhancementRadioButton("Normal fade (green)", "gSceneTransitions", 18); - SohImGui::Tooltip("This will make the game use a greenish fade in/out scenes transitions"); + UIWidgets::EnhancementRadioButton("Normal fade (green)", "gSceneTransitions", 18); + UIWidgets::Tooltip("This will make the game use a greenish fade in/out scenes transitions"); Table_NextCol(); - SohImGui::EnhancementRadioButton("Normal fade (blue)", "gSceneTransitions", 19); - SohImGui::Tooltip("This will make the game use a blue fade in/out scenes transitions"); + UIWidgets::EnhancementRadioButton("Normal fade (blue)", "gSceneTransitions", 19); + UIWidgets::Tooltip("This will make the game use a blue fade in/out scenes transitions"); Table_NextLine(); - SohImGui::EnhancementRadioButton("Triforce", "gSceneTransitions", 1); + UIWidgets::EnhancementRadioButton("Triforce", "gSceneTransitions", 1); ImGui::EndTable(); } if (ImGui::BeginTable("tabletransitionCol", 2, FlagsTable | ImGuiTableFlags_Hideable)) { @@ -948,6 +950,7 @@ void DrawCosmeticsEditor(bool& open) { } ImGui::End(); } + void InitCosmeticsEditor() { //This allow to hide a window without disturbing the player nor adding things in menu //LoadRainbowColor() will this way run in background once it's window is activated @@ -955,4 +958,4 @@ void InitCosmeticsEditor() { SohImGui::AddWindow("Enhancements", "Rainbowfunction", LoadRainbowColor, true, true); //Draw the bar in the menu. SohImGui::AddWindow("Enhancements", "Cosmetics Editor", DrawCosmeticsEditor); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h index 4b6ea249b..cd104633d 100644 --- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h +++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.h @@ -1,5 +1,5 @@ #pragma once -#include "../libultraship/ImGuiImpl.h" +#include #define SECTION_SIZE(arr) (s32)(sizeof(arr) / sizeof(arr[0])) #define RANDOMIZE_32(Max) GetRandomValue(Max); #define CATEGORY_NPC 0 @@ -405,4 +405,4 @@ static CosmeticsColorSection AllItemsSkills_section[]{ void InitCosmeticsEditor();//Init the menu itself void LoadRainbowColor(); -void NewSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0); \ No newline at end of file +void NewSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0); diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index 409f2e4b5..36c9f9ea0 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -1,7 +1,7 @@ #include "debugconsole.h" -#include "../libultraship/ImGuiImpl.h" +#include #include "savestates.h" -#include "Console.h" +#include #include #include @@ -12,8 +12,8 @@ #define PATH_HACK #include -#include "Window.h" -#include "Lib/ImGui/imgui_internal.h" +#include +#include #undef PATH_HACK #undef Path @@ -25,18 +25,18 @@ extern "C" { extern GlobalContext* gGlobalCtx; } -#include "Cvar.h" +#include -#define CMD_REGISTER SohImGui::BindCmd +#define CMD_REGISTER SohImGui::GetConsole()->AddCommand static bool ActorSpawnHandler(std::shared_ptr Console, const std::vector& args) { if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) { - SohImGui::console->SendErrorMessage("Not enough arguments passed to actorspawn"); + SohImGui::GetConsole()->SendErrorMessage("Not enough arguments passed to actorspawn"); return CMD_FAILED; } if (gGlobalCtx == nullptr) { - SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } @@ -72,7 +72,7 @@ static bool ActorSpawnHandler(std::shared_ptr Console, const std: if (Actor_Spawn(&gGlobalCtx->actorCtx, gGlobalCtx, actorId, spawnPoint.pos.x, spawnPoint.pos.y, spawnPoint.pos.z, spawnPoint.rot.x, spawnPoint.rot.y, spawnPoint.rot.z, params) == NULL) { - SohImGui::console->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL"); + SohImGui::GetConsole()->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL"); return CMD_FAILED; } return CMD_SUCCESS; @@ -81,13 +81,13 @@ static bool ActorSpawnHandler(std::shared_ptr Console, const std: static bool KillPlayerHandler(std::shared_ptr Console, const std::vector&) { gSaveContext.health = 0; - SohImGui::console->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?"); + SohImGui::GetConsole()->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?"); return CMD_SUCCESS; } static bool SetPlayerHealthHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -96,18 +96,18 @@ static bool SetPlayerHealthHandler(std::shared_ptr Console, const try { health = std::stoi(args[1]); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] Health value must be an integer."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Health value must be an integer."); return CMD_FAILED; } if (health < 0) { - SohImGui::console->SendErrorMessage("[SOH] Health value must be a positive integer"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Health value must be a positive integer"); return CMD_SUCCESS; } gSaveContext.health = health * 0x10; - SohImGui::console->SendInfoMessage("[SOH] Player health updated to %d", health); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Player health updated to %d", health); return CMD_SUCCESS; } @@ -129,31 +129,31 @@ static bool RuppeHandler(std::shared_ptr Console, const std::vect rupeeAmount = std::stoi(args[1]); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] Rupee count must be an integer."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Rupee count must be an integer."); return CMD_FAILED; } if (rupeeAmount < 0) { - SohImGui::console->SendErrorMessage("[SOH] Rupee count must be positive"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Rupee count must be positive"); return CMD_FAILED; } gSaveContext.rupees = rupeeAmount; - SohImGui::console->SendInfoMessage("Set rupee count to %u", rupeeAmount); + SohImGui::GetConsole()->SendInfoMessage("Set rupee count to %u", rupeeAmount); return CMD_SUCCESS; } static bool SetPosHandler(std::shared_ptr Console, const std::vector args) { if (gGlobalCtx == nullptr) { - SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } Player* player = GET_PLAYER(gGlobalCtx); if (args.size() == 1) { - SohImGui::console->SendInfoMessage("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, + SohImGui::GetConsole()->SendInfoMessage("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y, player->actor.world.pos.z); return CMD_SUCCESS; @@ -165,7 +165,7 @@ static bool SetPosHandler(std::shared_ptr Console, const std::vec player->actor.world.pos.y = std::stof(args[2]); player->actor.world.pos.z = std::stof(args[3]); - SohImGui::console->SendInfoMessage("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, + SohImGui::GetConsole()->SendInfoMessage("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y, player->actor.world.pos.z); return CMD_SUCCESS; @@ -173,7 +173,7 @@ static bool SetPosHandler(std::shared_ptr Console, const std::vec static bool ResetHandler(std::shared_ptr Console, std::vector args) { if (gGlobalCtx == nullptr) { - SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } @@ -194,7 +194,7 @@ const static std::map ammoItems{ static bool AmmoHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 3) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -203,19 +203,19 @@ static bool AmmoHandler(std::shared_ptr Console, const std::vecto try { count = std::stoi(args[2]); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("Ammo count must be an integer"); + SohImGui::GetConsole()->SendErrorMessage("Ammo count must be an integer"); return CMD_FAILED; } if (count < 0) { - SohImGui::console->SendErrorMessage("Ammo count must be positive"); + SohImGui::GetConsole()->SendErrorMessage("Ammo count must be positive"); return CMD_FAILED; } const auto& it = ammoItems.find(args[1]); if (it == ammoItems.end()) { - SohImGui::console->SendErrorMessage("Invalid item passed"); + SohImGui::GetConsole()->SendErrorMessage("Invalid item passed"); return CMD_FAILED; } @@ -237,7 +237,7 @@ const static std::map bottleItems{ static bool BottleHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 3) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -245,19 +245,19 @@ static bool BottleHandler(std::shared_ptr Console, const std::vec try { slot = std::stoi(args[2]); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] Bottle slot must be an integer."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Bottle slot must be an integer."); return CMD_FAILED; } if ((slot < 1) || (slot > 4)) { - SohImGui::console->SendErrorMessage("Invalid slot passed"); + SohImGui::GetConsole()->SendErrorMessage("Invalid slot passed"); return CMD_FAILED; } const auto& it = bottleItems.find(args[1]); if (it == bottleItems.end()) { - SohImGui::console->SendErrorMessage("Invalid item passed"); + SohImGui::GetConsole()->SendErrorMessage("Invalid item passed"); return CMD_FAILED; } @@ -269,7 +269,7 @@ static bool BottleHandler(std::shared_ptr Console, const std::vec static bool BHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -279,7 +279,7 @@ static bool BHandler(std::shared_ptr Console, const std::vector Console, const std::vector& args) { if (args.size() != 3) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -290,7 +290,7 @@ static bool ItemHandler(std::shared_ptr Console, const std::vecto static bool EntranceHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -299,7 +299,7 @@ static bool EntranceHandler(std::shared_ptr Console, const std::v try { entrance = std::stoi(args[1], nullptr, 16); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] Entrance value must be a Hex number."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Entrance value must be a Hex number."); return CMD_FAILED; } @@ -319,7 +319,7 @@ static bool VoidHandler(std::shared_ptr Console, const std::vecto gGlobalCtx->fadeTransition = 2; gSaveContext.nextTransition = 2; } else { - SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr"); return CMD_FAILED; } return CMD_SUCCESS; @@ -332,7 +332,7 @@ static bool ReloadHandler(std::shared_ptr Console, const std::vec gGlobalCtx->fadeTransition = 11; gSaveContext.nextTransition = 11; } else { - SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr"); return CMD_FAILED; } return CMD_SUCCESS; @@ -345,11 +345,11 @@ static bool FWHandler(std::shared_ptr Console, const std::vector< gGlobalCtx->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_TOP].entranceIndex; gGlobalCtx->fadeTransition = 5; } else { - SohImGui::console->SendErrorMessage("Farore's wind not set!"); + SohImGui::GetConsole()->SendErrorMessage("Farore's wind not set!"); } } else { - SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr"); return CMD_FAILED; } @@ -361,7 +361,7 @@ static bool FileSelectHandler(std::shared_ptr Console, const std: SET_NEXT_GAMESTATE(&gGlobalCtx->state, FileChoose_Init, FileChooseContext); gGlobalCtx->state.running = 0; } else { - SohImGui::console->SendErrorMessage("gGlobalCtx == nullptr"); + SohImGui::GetConsole()->SendErrorMessage("gGlobalCtx == nullptr"); return CMD_FAILED; } return CMD_SUCCESS; @@ -378,10 +378,10 @@ static bool SaveStateHandler(std::shared_ptr Console, const std:: switch (rtn) { case SaveStateReturn::SUCCESS: - SohImGui::console->SendInfoMessage("[SOH] Saved state to slot %u", slot); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Saved state to slot %u", slot); return CMD_SUCCESS; case SaveStateReturn::FAIL_WRONG_GAMESTATE: - SohImGui::console->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\""); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\""); return CMD_FAILED; } } @@ -392,16 +392,16 @@ static bool LoadStateHandler(std::shared_ptr Console, const std:: switch (rtn) { case SaveStateReturn::SUCCESS: - SohImGui::console->SendInfoMessage("[SOH] Loaded state from slot (%u)", slot); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Loaded state from slot (%u)", slot); return CMD_SUCCESS; case SaveStateReturn::FAIL_INVALID_SLOT: - SohImGui::console->SendErrorMessage("[SOH] Invalid State Slot Number (%u)", slot); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Invalid State Slot Number (%u)", slot); return CMD_FAILED; case SaveStateReturn::FAIL_STATE_EMPTY: - SohImGui::console->SendErrorMessage("[SOH] State Slot (%u) is empty", slot); + SohImGui::GetConsole()->SendErrorMessage("[SOH] State Slot (%u) is empty", slot); return CMD_FAILED; case SaveStateReturn::FAIL_WRONG_GAMESTATE: - SohImGui::console->SendErrorMessage("[SOH] Can not load a state outside of \"GamePlay\""); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Can not load a state outside of \"GamePlay\""); return CMD_FAILED; } @@ -409,7 +409,7 @@ static bool LoadStateHandler(std::shared_ptr Console, const std:: static bool StateSlotSelectHandler(std::shared_ptr Console, const std::vector& args) { if (args.size() != 2) { - SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } int slot; @@ -417,17 +417,17 @@ static bool StateSlotSelectHandler(std::shared_ptr Console, const try { slot = std::stoi(args[1], nullptr, 10); } catch (std::invalid_argument const& ex) { - SohImGui::console->SendErrorMessage("[SOH] SaveState slot value must be a number."); + SohImGui::GetConsole()->SendErrorMessage("[SOH] SaveState slot value must be a number."); return CMD_FAILED; } if (slot < 0) { - SohImGui::console->SendErrorMessage("[SOH] Invalid slot passed. Slot must be between 0 and 2"); + SohImGui::GetConsole()->SendErrorMessage("[SOH] Invalid slot passed. Slot must be between 0 and 2"); return CMD_FAILED; } OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot); - SohImGui::console->SendInfoMessage("[SOH] Slot %u selected", + SohImGui::GetConsole()->SendInfoMessage("[SOH] Slot %u selected", OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot()); return CMD_SUCCESS; } @@ -488,7 +488,7 @@ static bool SetCVarHandler(std::shared_ptr Console, const std::ve CVar_Save(); - //SohImGui::console->SendInfoMessage("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z); + //SohImGui::GetConsole()->SendInfoMessage("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z); return CMD_SUCCESS; } @@ -502,17 +502,17 @@ static bool GetCVarHandler(std::shared_ptr Console, const std::ve if (cvar != nullptr) { if (cvar->type == CVarType::S32) - SohImGui::console->SendInfoMessage("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32); else if (cvar->type == CVarType::Float) - SohImGui::console->SendInfoMessage("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); else if (cvar->type == CVarType::String) - SohImGui::console->SendInfoMessage("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); else if (cvar->type == CVarType::RGBA) - SohImGui::console->SendInfoMessage("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA); } else { - SohImGui::console->SendInfoMessage("[SOH] Could not find variable %s", args[1].c_str()); + SohImGui::GetConsole()->SendInfoMessage("[SOH] Could not find variable %s", args[1].c_str()); } diff --git a/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp b/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp deleted file mode 100644 index 7fec0de14..000000000 --- a/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "ImGuiHelpers.h" -#include "../../../../libultraship/libultraship/ImGuiImpl.h" - -// Adds a text tooltip for the previous ImGui item -void SetLastItemHoverText(const std::string& text) { - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str()); - ImGui::EndTooltip(); - } -} - -// Adds a "?" next to the previous ImGui item with a custom tooltip -void InsertHelpHoverText(const std::string& text) { - ImGui::SameLine(); - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str()); - ImGui::EndTooltip(); - } -} diff --git a/soh/soh/Enhancements/debugger/ImGuiHelpers.h b/soh/soh/Enhancements/debugger/ImGuiHelpers.h deleted file mode 100644 index 7f01e4580..000000000 --- a/soh/soh/Enhancements/debugger/ImGuiHelpers.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "../libultraship/Lib/ImGui/imgui.h" - -#include - -void SetLastItemHoverText(const std::string& text); - -void InsertHelpHoverText(const std::string& text); diff --git a/soh/soh/Enhancements/debugger/actorViewer.cpp b/soh/soh/Enhancements/debugger/actorViewer.cpp index 33bc532a0..8c6a4d543 100644 --- a/soh/soh/Enhancements/debugger/actorViewer.cpp +++ b/soh/soh/Enhancements/debugger/actorViewer.cpp @@ -1,13 +1,13 @@ #include "actorViewer.h" #include "../../util.h" -#include "../libultraship/ImGuiImpl.h" -#include "ImGuiHelpers.h" +#include "../../UIWidgets.hpp" +#include #include #include #include #include -#include +#include extern "C" { #include @@ -632,7 +632,7 @@ void DrawActorViewer(bool& open) { if (display.category == ACTORCAT_BOSS || display.category == ACTORCAT_ENEMY) { ImGui::InputScalar("Enemy Health", ImGuiDataType_U8, &display.colChkInfo.health); - InsertHelpHoverText("Some actors might not use this!"); + UIWidgets::InsertHelpHoverText("Some actors might not use this!"); } if (ImGui::Button("Refresh")) { @@ -667,7 +667,7 @@ void DrawActorViewer(bool& open) { rm = TARGET; } } - InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies"); + UIWidgets::InsertHelpHoverText("Grabs actor with target arrow above it. You might need C-Up for enemies"); if (ImGui::Button("Fetch from Held")) { Player* player = GET_PLAYER(gGlobalCtx); fetch = player->heldActor; @@ -678,7 +678,7 @@ void DrawActorViewer(bool& open) { rm = HELD; } } - InsertHelpHoverText("Grabs actor that Link is holding"); + UIWidgets::InsertHelpHoverText("Grabs actor that Link is holding"); if (ImGui::Button("Fetch from Interaction")) { Player* player = GET_PLAYER(gGlobalCtx); fetch = player->interactRangeActor; @@ -689,7 +689,7 @@ void DrawActorViewer(bool& open) { rm = INTERACT; } } - InsertHelpHoverText("Grabs actor from \"interaction range\""); + UIWidgets::InsertHelpHoverText("Grabs actor from \"interaction range\""); ImGui::TreePop(); } @@ -776,4 +776,4 @@ void DrawActorViewer(bool& open) { void InitActorViewer() { SohImGui::AddWindow("Developer Tools", "Actor Viewer", DrawActorViewer); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/debugger/colViewer.cpp b/soh/soh/Enhancements/debugger/colViewer.cpp index e98ff0399..0146e626f 100644 --- a/soh/soh/Enhancements/debugger/colViewer.cpp +++ b/soh/soh/Enhancements/debugger/colViewer.cpp @@ -1,12 +1,12 @@ #include "colViewer.h" -#include "../libultraship/ImGuiImpl.h" -#include "ImGuiHelpers.h" +#include #include "../../frame_interpolation.h" +#include "../../UIWidgets.hpp" #include #include #include -#include +#include extern "C" { #include @@ -62,42 +62,42 @@ void DrawColViewerWindow(bool& open) { ImGui::End(); return; } - SohImGui::EnhancementCheckbox("Enabled", "gColViewerEnabled"); + UIWidgets::EnhancementCheckbox("Enabled", "gColViewerEnabled"); - SohImGui::EnhancementCombo("Scene", "gColViewerScene", ColRenderSettingNames); - SohImGui::EnhancementCombo("Bg Actors", "gColViewerBgActors", ColRenderSettingNames); - SohImGui::EnhancementCombo("Col Check", "gColViewerColCheck", ColRenderSettingNames); - SohImGui::EnhancementCombo("Waterbox", "gColViewerWaterbox", ColRenderSettingNames); + UIWidgets::EnhancementCombo("Scene", "gColViewerScene", ColRenderSettingNames); + UIWidgets::EnhancementCombo("Bg Actors", "gColViewerBgActors", ColRenderSettingNames); + UIWidgets::EnhancementCombo("Col Check", "gColViewerColCheck", ColRenderSettingNames); + UIWidgets::EnhancementCombo("Waterbox", "gColViewerWaterbox", ColRenderSettingNames); - SohImGui::EnhancementCheckbox("Apply as decal", "gColViewerDecal"); - InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " + UIWidgets::EnhancementCheckbox("Apply as decal", "gColViewerDecal"); + UIWidgets::InsertHelpHoverText("Applies the collision as a decal display. This can be useful if there is z-fighting occuring " "with the scene geometry, but can cause other artifacts."); - SohImGui::EnhancementCheckbox("Shaded", "gColViewerShaded"); - InsertHelpHoverText("Applies the scene's shading to the collision display."); + UIWidgets::EnhancementCheckbox("Shaded", "gColViewerShaded"); + UIWidgets::InsertHelpHoverText("Applies the scene's shading to the collision display."); // This has to be duplicated in both code paths due to the nature of ImGui::IsItemHovered() const std::string colorHelpText = "View and change the colors used for collision display."; if (ImGui::TreeNode("Colors")) { - InsertHelpHoverText(colorHelpText); + UIWidgets::InsertHelpHoverText(colorHelpText); - SohImGui::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false); - SohImGui::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255), + UIWidgets::EnhancementColor("Normal", "gColViewerColorNormal", scene_col, ImVec4(255, 255, 255, 255), false); + UIWidgets::EnhancementColor("Hookshot", "gColViewerColorHookshot", hookshot_col, ImVec4(128, 128, 255, 255), false); - SohImGui::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false); - SohImGui::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface", + UIWidgets::EnhancementColor("Entrance", "gColViewerColorEntrance", entrance_col, ImVec4(0, 255, 0, 255), false); + UIWidgets::EnhancementColor("Special Surface (Grass/Sand/Etc)", "gColViewerColorSpecialSurface", specialSurface_col, ImVec4(192, 255, 192, 255), false); - SohImGui::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable", + UIWidgets::EnhancementColor("Interactable (Vines/Crawlspace/Etc)", "gColViewerColorInteractable", interactable_col, ImVec4(192, 0, 192, 255), false); - SohImGui::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false); - SohImGui::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false); - SohImGui::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false); - SohImGui::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false); - SohImGui::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false); - SohImGui::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false); + UIWidgets::EnhancementColor("Slope", "gColViewerColorSlope", slope_col, ImVec4(255, 255, 128, 255), false); + UIWidgets::EnhancementColor("Void", "gColViewerColorVoid", void_col, ImVec4(255, 0, 0, 255), false); + UIWidgets::EnhancementColor("OC", "gColViewerColorOC", oc_col, ImVec4(255, 255, 255, 255), false); + UIWidgets::EnhancementColor("AC", "gColViewerColorAC", ac_col, ImVec4(0, 0, 255, 255), false); + UIWidgets::EnhancementColor("AT", "gColViewerColorAT", at_col, ImVec4(255, 0, 0, 255), false); + UIWidgets::EnhancementColor("Waterbox", "gColViewerColorWaterbox", waterbox_col, ImVec4(0, 0, 255, 255), false); ImGui::TreePop(); } else { - InsertHelpHoverText(colorHelpText); + UIWidgets::InsertHelpHoverText(colorHelpText); } ImGui::End(); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 5e21cec08..dfe947be8 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1,13 +1,13 @@ #include "debugSaveEditor.h" #include "../../util.h" -#include "../libultraship/ImGuiImpl.h" -#include "ImGuiHelpers.h" +#include +#include "../../UIWidgets.hpp" #include #include #include #include -#include +#include extern "C" { #include @@ -309,7 +309,7 @@ void DrawInfoTab() { ImGui::PushItemWidth(ImGui::GetFontSize() * 6); ImGui::Text("Name: %s", name.c_str()); - InsertHelpHoverText("Player Name"); + UIWidgets::InsertHelpHoverText("Player Name"); std::string nameID; for (int i = 0; i < 8; i++) { nameID = z2ASCII(i); @@ -326,7 +326,7 @@ void DrawInfoTab() { if (ImGui::IsItemDeactivated()) { gSaveContext.healthCapacity = healthIntermediary; } - InsertHelpHoverText("Maximum health. 16 units per full heart"); + UIWidgets::InsertHelpHoverText("Maximum health. 16 units per full heart"); if (gSaveContext.health > gSaveContext.healthCapacity) { gSaveContext.health = gSaveContext.healthCapacity; // Clamp health to new max } @@ -335,7 +335,7 @@ void DrawInfoTab() { const uint16_t healthMax = gSaveContext.healthCapacity; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SliderScalar("Health", ImGuiDataType_S16, &gSaveContext.health, &healthMin, &healthMax); - InsertHelpHoverText("Current health. 16 units per full heart"); + UIWidgets::InsertHelpHoverText("Current health. 16 units per full heart"); bool doubleDefense = gSaveContext.doubleDefense != 0; if (ImGui::Checkbox("Double Defense", &doubleDefense)) { @@ -343,7 +343,7 @@ void DrawInfoTab() { gSaveContext.inventory.defenseHearts = gSaveContext.doubleDefense ? 20 : 0; // Set to get the border drawn in the UI } - InsertHelpHoverText("Is double defense unlocked?"); + UIWidgets::InsertHelpHoverText("Is double defense unlocked?"); std::string magicName; if (gSaveContext.magicLevel == 2) { @@ -373,7 +373,7 @@ void DrawInfoTab() { ImGui::EndCombo(); } - InsertHelpHoverText("Current magic level"); + UIWidgets::InsertHelpHoverText("Current magic level"); gSaveContext.unk_13F4 = gSaveContext.magicLevel * 0x30; // Set to get the bar drawn in the UI if (gSaveContext.magic > gSaveContext.unk_13F4) { gSaveContext.magic = gSaveContext.unk_13F4; // Clamp magic to new max @@ -383,16 +383,16 @@ void DrawInfoTab() { const uint8_t magicMax = gSaveContext.unk_13F4; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SliderScalar("Magic", ImGuiDataType_S8, &gSaveContext.magic, &magicMin, &magicMax); - InsertHelpHoverText("Current magic. 48 units per magic level"); + UIWidgets::InsertHelpHoverText("Current magic. 48 units per magic level"); ImGui::InputScalar("Rupees", ImGuiDataType_S16, &gSaveContext.rupees); - InsertHelpHoverText("Current rupees"); + UIWidgets::InsertHelpHoverText("Current rupees"); const uint16_t dayTimeMin = 0; const uint16_t dayTimeMax = 0xFFFF; ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15); ImGui::SliderScalar("Time", ImGuiDataType_U16, &gSaveContext.dayTime, &dayTimeMin, &dayTimeMax); - InsertHelpHoverText("Time of day"); + UIWidgets::InsertHelpHoverText("Time of day"); if (ImGui::Button("Dawn")) { gSaveContext.dayTime = 0x4000; } @@ -410,43 +410,43 @@ void DrawInfoTab() { } ImGui::InputScalar("Total Days", ImGuiDataType_S32, &gSaveContext.totalDays); - InsertHelpHoverText("Total number of days elapsed since the start of the game"); + UIWidgets::InsertHelpHoverText("Total number of days elapsed since the start of the game"); ImGui::InputScalar("Deaths", ImGuiDataType_U16, &gSaveContext.deaths); - InsertHelpHoverText("Total number of deaths"); + UIWidgets::InsertHelpHoverText("Total number of deaths"); bool bgsFlag = gSaveContext.bgsFlag != 0; if (ImGui::Checkbox("Has BGS", &bgsFlag)) { gSaveContext.bgsFlag = bgsFlag; } - InsertHelpHoverText("Is Biggoron sword unlocked? Replaces Giant's knife"); + UIWidgets::InsertHelpHoverText("Is Biggoron sword unlocked? Replaces Giant's knife"); ImGui::InputScalar("Sword Health", ImGuiDataType_U16, &gSaveContext.swordHealth); - InsertHelpHoverText("Giant's knife health. Default is 8. Must be >0 for Biggoron sword to work"); + UIWidgets::InsertHelpHoverText("Giant's knife health. Default is 8. Must be >0 for Biggoron sword to work"); ImGui::InputScalar("Bgs Day Count", ImGuiDataType_S32, &gSaveContext.bgsDayCount); - InsertHelpHoverText("Total number of days elapsed since giving Biggoron the claim check"); + UIWidgets::InsertHelpHoverText("Total number of days elapsed since giving Biggoron the claim check"); ImGui::InputScalar("Entrance Index", ImGuiDataType_S32, &gSaveContext.entranceIndex); - InsertHelpHoverText("From which entrance did Link arrive?"); + UIWidgets::InsertHelpHoverText("From which entrance did Link arrive?"); ImGui::InputScalar("Cutscene Index", ImGuiDataType_S32, &gSaveContext.cutsceneIndex); - InsertHelpHoverText("Which cutscene is this?"); + UIWidgets::InsertHelpHoverText("Which cutscene is this?"); ImGui::InputScalar("Navi Timer", ImGuiDataType_U16, &gSaveContext.naviTimer); - InsertHelpHoverText("Navi wants to talk at 600 units, decides not to at 3000."); + UIWidgets::InsertHelpHoverText("Navi wants to talk at 600 units, decides not to at 3000."); ImGui::InputScalar("Timer 1 State", ImGuiDataType_S16, &gSaveContext.timer1State); - InsertHelpHoverText("Heat timer, race timer, etc. Has white font"); + UIWidgets::InsertHelpHoverText("Heat timer, race timer, etc. Has white font"); ImGui::InputScalar("Timer 1 Value", ImGuiDataType_S16, &gSaveContext.timer1Value, &one, NULL); - InsertHelpHoverText("Time, in seconds"); + UIWidgets::InsertHelpHoverText("Time, in seconds"); ImGui::InputScalar("Timer 2 State", ImGuiDataType_S16, &gSaveContext.timer2State); - InsertHelpHoverText("Trade timer, Ganon collapse timer, etc. Has yellow font"); + UIWidgets::InsertHelpHoverText("Trade timer, Ganon collapse timer, etc. Has yellow font"); ImGui::InputScalar("Timer 2 Value", ImGuiDataType_S16, &gSaveContext.timer2Value, &one, NULL); - InsertHelpHoverText("Time, in seconds"); + UIWidgets::InsertHelpHoverText("Time, in seconds"); const char* audioName; switch (gSaveContext.audioSetting) { @@ -481,13 +481,13 @@ void DrawInfoTab() { ImGui::EndCombo(); } - InsertHelpHoverText("Sound setting"); + UIWidgets::InsertHelpHoverText("Sound setting"); bool n64DDFlag = gSaveContext.n64ddFlag != 0; if (ImGui::Checkbox("64 DD file?", &n64DDFlag)) { gSaveContext.n64ddFlag = n64DDFlag; } - InsertHelpHoverText("WARNING! If you save, your file may be locked! Use caution!"); + UIWidgets::InsertHelpHoverText("WARNING! If you save, your file may be locked! Use caution!"); if (ImGui::BeginCombo("Z Target Mode", gSaveContext.zTargetSetting ? "Hold" : "Switch")) { if (ImGui::Selectable("Switch")) { @@ -498,7 +498,7 @@ void DrawInfoTab() { } ImGui::EndCombo(); } - InsertHelpHoverText("Z-Targeting behavior"); + UIWidgets::InsertHelpHoverText("Z-Targeting behavior"); ImGui::PushItemWidth(ImGui::GetFontSize() * 10); @@ -529,7 +529,7 @@ void DrawInventoryTab() { static bool restrictToValid = true; ImGui::Checkbox("Restrict to valid items", &restrictToValid); - InsertHelpHoverText("Restricts items and ammo to only what is possible to legally acquire in-game"); + UIWidgets::InsertHelpHoverText("Restricts items and ammo to only what is possible to legally acquire in-game"); for (int32_t y = 0; y < 4; y++) { for (int32_t x = 0; x < 6; x++) { @@ -568,7 +568,7 @@ void DrawInventoryTab() { gSaveContext.inventory.items[selectedIndex] = ITEM_NONE; ImGui::CloseCurrentPopup(); } - SetLastItemHoverText("None"); + UIWidgets::SetLastItemHoverText("None"); std::vector possibleItems; if (restrictToValid) { @@ -598,7 +598,7 @@ void DrawInventoryTab() { gSaveContext.inventory.items[selectedIndex] = slotEntry.id; ImGui::CloseCurrentPopup(); } - SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); } ImGui::EndPopup(); @@ -682,7 +682,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Switch"); - InsertHelpHoverText("Permanently-saved switch flags"); + UIWidgets::InsertHelpHoverText("Permanently-saved switch flags"); DrawFlagArray32("Switch", act->flags.swch); }); @@ -690,13 +690,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Switch"); - InsertHelpHoverText("Temporary switch flags. Unset on scene transitions"); + UIWidgets::InsertHelpHoverText("Temporary switch flags. Unset on scene transitions"); DrawFlagArray32("Temp Switch", act->flags.tempSwch); }); DrawGroupWithBorder([&]() { ImGui::Text("Clear"); - InsertHelpHoverText("Permanently-saved room-clear flags"); + UIWidgets::InsertHelpHoverText("Permanently-saved room-clear flags"); DrawFlagArray32("Clear", act->flags.clear); }); @@ -704,13 +704,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Clear"); - InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions"); + UIWidgets::InsertHelpHoverText("Temporary room-clear flags. Unset on scene transitions"); DrawFlagArray32("Temp Clear", act->flags.tempClear); }); DrawGroupWithBorder([&]() { ImGui::Text("Collect"); - InsertHelpHoverText("Permanently-saved collect flags"); + UIWidgets::InsertHelpHoverText("Permanently-saved collect flags"); DrawFlagArray32("Collect", act->flags.collect); }); @@ -718,13 +718,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Temp Collect"); - InsertHelpHoverText("Temporary collect flags. Unset on scene transitions"); + UIWidgets::InsertHelpHoverText("Temporary collect flags. Unset on scene transitions"); DrawFlagArray32("Temp Collect", act->flags.tempCollect); }); DrawGroupWithBorder([&]() { ImGui::Text("Chest"); - InsertHelpHoverText("Permanently-saved chest flags"); + UIWidgets::InsertHelpHoverText("Permanently-saved chest flags"); DrawFlagArray32("Chest", act->flags.chest); }); @@ -738,7 +738,7 @@ void DrawFlagsTab() { act->flags.collect = gSaveContext.sceneFlags[gGlobalCtx->sceneNum].collect; act->flags.chest = gSaveContext.sceneFlags[gGlobalCtx->sceneNum].chest; } - SetLastItemHoverText("Load flags from saved scene flags. Normally happens on scene load"); + UIWidgets::SetLastItemHoverText("Load flags from saved scene flags. Normally happens on scene load"); if (ImGui::Button("Save Flags")) { gSaveContext.sceneFlags[gGlobalCtx->sceneNum].swch = act->flags.swch; @@ -746,7 +746,7 @@ void DrawFlagsTab() { gSaveContext.sceneFlags[gGlobalCtx->sceneNum].collect = act->flags.collect; gSaveContext.sceneFlags[gGlobalCtx->sceneNum].chest = act->flags.chest; } - SetLastItemHoverText("Save current scene flags. Normally happens on scene exit"); + UIWidgets::SetLastItemHoverText("Save current scene flags. Normally happens on scene exit"); ImGui::EndGroup(); } else { @@ -776,12 +776,12 @@ void DrawFlagsTab() { if (ImGui::Button("Current")) { selectedSceneFlagMap = gGlobalCtx->sceneNum; } - SetLastItemHoverText("Open flags for current scene"); + UIWidgets::SetLastItemHoverText("Open flags for current scene"); } DrawGroupWithBorder([&]() { ImGui::Text("Switch"); - InsertHelpHoverText("Switch flags"); + UIWidgets::InsertHelpHoverText("Switch flags"); DrawFlagArray32("Switch", gSaveContext.sceneFlags[selectedSceneFlagMap].swch); }); @@ -789,13 +789,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Clear"); - InsertHelpHoverText("Room-clear flags"); + UIWidgets::InsertHelpHoverText("Room-clear flags"); DrawFlagArray32("Clear", gSaveContext.sceneFlags[selectedSceneFlagMap].clear); }); DrawGroupWithBorder([&]() { ImGui::Text("Collect"); - InsertHelpHoverText("Collect flags"); + UIWidgets::InsertHelpHoverText("Collect flags"); DrawFlagArray32("Collect", gSaveContext.sceneFlags[selectedSceneFlagMap].collect); }); @@ -803,13 +803,13 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Chest"); - InsertHelpHoverText("Chest flags"); + UIWidgets::InsertHelpHoverText("Chest flags"); DrawFlagArray32("Chest", gSaveContext.sceneFlags[selectedSceneFlagMap].chest); }); DrawGroupWithBorder([&]() { ImGui::Text("Rooms"); - InsertHelpHoverText("Flags for visted rooms"); + UIWidgets::InsertHelpHoverText("Flags for visted rooms"); DrawFlagArray32("Rooms", gSaveContext.sceneFlags[selectedSceneFlagMap].rooms); }); @@ -817,7 +817,7 @@ void DrawFlagsTab() { DrawGroupWithBorder([&]() { ImGui::Text("Floors"); - InsertHelpHoverText("Flags for visted floors"); + UIWidgets::InsertHelpHoverText("Flags for visted floors"); DrawFlagArray32("Floors", gSaveContext.sceneFlags[selectedSceneFlagMap].floors); }); @@ -870,7 +870,7 @@ void DrawFlagsTab() { static bool keepGsCountUpdated = true; ImGui::Checkbox("Keep GS Count Updated", &keepGsCountUpdated); - InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags"); + UIWidgets::InsertHelpHoverText("Automatically adjust the number of gold skulltula tokens acquired based on set flags"); int32_t gsCount = 0; if (keepGsCountUpdated) { for (int32_t gsFlagIndex = 0; gsFlagIndex < 6; gsFlagIndex++) { @@ -883,85 +883,85 @@ void DrawFlagsTab() { if (ImGui::TreeNode("Event Check Inf Flags")) { DrawGroupWithBorder([&]() { ImGui::Text("0"); - InsertHelpHoverText("Mostly Kokiri Forest related"); + UIWidgets::InsertHelpHoverText("Mostly Kokiri Forest related"); DrawFlagArray16("eci0", gSaveContext.eventChkInf[0]); }); DrawGroupWithBorder([&]() { ImGui::Text("1"); - InsertHelpHoverText("Mostly Lon Lon Ranch related"); + UIWidgets::InsertHelpHoverText("Mostly Lon Lon Ranch related"); DrawFlagArray16("eci1", gSaveContext.eventChkInf[1]); }); DrawGroupWithBorder([&]() { ImGui::Text("2"); - InsertHelpHoverText("Dodongo Related?"); + UIWidgets::InsertHelpHoverText("Dodongo Related?"); DrawFlagArray16("eci2", gSaveContext.eventChkInf[2]); }); DrawGroupWithBorder([&]() { ImGui::Text("3"); - InsertHelpHoverText("Mostly Zora related"); + UIWidgets::InsertHelpHoverText("Mostly Zora related"); DrawFlagArray16("eci3", gSaveContext.eventChkInf[3]); }); DrawGroupWithBorder([&]() { ImGui::Text("4"); - InsertHelpHoverText("Random"); + UIWidgets::InsertHelpHoverText("Random"); DrawFlagArray16("eci4", gSaveContext.eventChkInf[4]); }); DrawGroupWithBorder([&]() { ImGui::Text("5"); - InsertHelpHoverText("Mostly song learning related"); + UIWidgets::InsertHelpHoverText("Mostly song learning related"); DrawFlagArray16("eci5", gSaveContext.eventChkInf[5]); }); DrawGroupWithBorder([&]() { ImGui::Text("6"); - InsertHelpHoverText("Random"); + UIWidgets::InsertHelpHoverText("Random"); DrawFlagArray16("eci6", gSaveContext.eventChkInf[6]); }); DrawGroupWithBorder([&]() { ImGui::Text("7"); - InsertHelpHoverText("Boss Battle related"); + UIWidgets::InsertHelpHoverText("Boss Battle related"); DrawFlagArray16("eci7", gSaveContext.eventChkInf[7]); }); DrawGroupWithBorder([&]() { ImGui::Text("8"); - InsertHelpHoverText("Mask related?"); + UIWidgets::InsertHelpHoverText("Mask related?"); DrawFlagArray16("eci8", gSaveContext.eventChkInf[8]); }); DrawGroupWithBorder([&]() { ImGui::Text("9"); - InsertHelpHoverText("Mostly carpenter related"); + UIWidgets::InsertHelpHoverText("Mostly carpenter related"); DrawFlagArray16("eci9", gSaveContext.eventChkInf[9]); }); DrawGroupWithBorder([&]() { ImGui::Text("A"); - InsertHelpHoverText("First-time overworld entrance cs related"); + UIWidgets::InsertHelpHoverText("First-time overworld entrance cs related"); DrawFlagArray16("eci10", gSaveContext.eventChkInf[10]); }); DrawGroupWithBorder([&]() { ImGui::Text("B"); - InsertHelpHoverText("First-time dungeon entrance cs/trial cs related"); + UIWidgets::InsertHelpHoverText("First-time dungeon entrance cs/trial cs related"); DrawFlagArray16("eci11", gSaveContext.eventChkInf[11]); }); DrawGroupWithBorder([&]() { ImGui::Text("C"); - InsertHelpHoverText("Random"); + UIWidgets::InsertHelpHoverText("Random"); DrawFlagArray16("eci12", gSaveContext.eventChkInf[12]); }); DrawGroupWithBorder([&]() { ImGui::Text("D"); - InsertHelpHoverText("Frog songs/GS rewards"); + UIWidgets::InsertHelpHoverText("Frog songs/GS rewards"); DrawFlagArray16("eci13", gSaveContext.eventChkInf[13]); }); @@ -1014,7 +1014,7 @@ void DrawUpgrade(const std::string& categoryName, int32_t categoryId, const std: ImGui::EndCombo(); } ImGui::PopID(); - SetLastItemHoverText(categoryName.c_str()); + UIWidgets::SetLastItemHoverText(categoryName.c_str()); } // Draws a combo that lets you choose and upgrade value from a popup grid of icons @@ -1039,7 +1039,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const } ImGui::PopStyleVar(); ImGui::PopStyleColor(); - SetLastItemHoverText(categoryName.c_str()); + UIWidgets::SetLastItemHoverText(categoryName.c_str()); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); if (ImGui::BeginPopup(upgradePopupPicker)) { @@ -1053,7 +1053,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const Inventory_ChangeUpgrade(categoryId, pickerIndex); ImGui::CloseCurrentPopup(); } - SetLastItemHoverText("None"); + UIWidgets::SetLastItemHoverText("None"); } else { const ItemMapEntry& slotEntry = itemMapping[items[pickerIndex]]; if (ImGui::ImageButton(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), @@ -1061,7 +1061,7 @@ void DrawUpgradeIcon(const std::string& categoryName, int32_t categoryId, const Inventory_ChangeUpgrade(categoryId, pickerIndex); ImGui::CloseCurrentPopup(); } - SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); } } @@ -1103,7 +1103,7 @@ void DrawEquipmentTab() { } ImGui::PopStyleColor(); ImGui::PopID(); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } const std::vector bulletBagValues = { @@ -1193,7 +1193,7 @@ void DrawQuestItemButton(uint32_t item) { } } ImGui::PopStyleColor(); - SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); } // Draws a toggleable icon for a dungeon item that is faded when disabled @@ -1211,7 +1211,7 @@ void DrawDungeonItemButton(uint32_t item, uint32_t scene) { } } ImGui::PopStyleColor(); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } void DrawQuestStatusTab() { @@ -1258,11 +1258,11 @@ void DrawQuestStatusTab() { } } ImGui::PopStyleColor(); - SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); } ImGui::InputScalar("GS Count", ImGuiDataType_S16, &gSaveContext.inventory.gsTokens); - InsertHelpHoverText("Number of gold skulltula tokens aquired"); + UIWidgets::InsertHelpHoverText("Number of gold skulltula tokens aquired"); uint32_t bitMask = 1 << QUEST_SKULL_TOKEN; bool gsUnlocked = (bitMask & gSaveContext.inventory.questItems) != 0; @@ -1273,7 +1273,7 @@ void DrawQuestStatusTab() { gSaveContext.inventory.questItems &= ~bitMask; } } - InsertHelpHoverText("If unlocked, enables showing the gold skulltula count in the quest status menu"); + UIWidgets::InsertHelpHoverText("If unlocked, enables showing the gold skulltula count in the quest status menu"); int32_t pohCount = (gSaveContext.inventory.questItems & 0xF0000000) >> 28; if (ImGui::BeginCombo("PoH count", std::to_string(pohCount).c_str())) { @@ -1285,7 +1285,7 @@ void DrawQuestStatusTab() { } ImGui::EndCombo(); } - InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container"); + UIWidgets::InsertHelpHoverText("The number of pieces of heart acquired towards the next heart container"); DrawGroupWithBorder([&]() { ImGui::Text("Dungeon Items"); @@ -1410,7 +1410,7 @@ void DrawPlayerTab() { DrawGroupWithBorder([&]() { ImGui::Text("Link's Rotation"); - InsertHelpHoverText("For Link's rotation in relation to the world"); + UIWidgets::InsertHelpHoverText("For Link's rotation in relation to the world"); ImGui::InputScalar("X Rot", ImGuiDataType_S16, &player->actor.world.rot.x); ImGui::SameLine(); ImGui::InputScalar("Y Rot", ImGuiDataType_S16, &player->actor.world.rot.y); @@ -1420,7 +1420,7 @@ void DrawPlayerTab() { DrawGroupWithBorder([&]() { ImGui::Text("Link's Model Rotation"); - InsertHelpHoverText("For Link's actual model"); + UIWidgets::InsertHelpHoverText("For Link's actual model"); ImGui::InputScalar("X ModRot", ImGuiDataType_S16, &player->actor.shape.rot.x); ImGui::SameLine(); ImGui::InputScalar("Y ModRot", ImGuiDataType_S16, &player->actor.shape.rot.y); @@ -1429,19 +1429,19 @@ void DrawPlayerTab() { }); ImGui::InputScalar("Linear Velocity", ImGuiDataType_Float, &player->linearVelocity); - InsertHelpHoverText("Link's speed along the XZ plane"); + UIWidgets::InsertHelpHoverText("Link's speed along the XZ plane"); ImGui::InputScalar("Y Velocity", ImGuiDataType_Float, &player->actor.velocity.y); - InsertHelpHoverText("Link's speed along the Y plane. Caps at -20"); + UIWidgets::InsertHelpHoverText("Link's speed along the Y plane. Caps at -20"); ImGui::InputScalar("Wall Height", ImGuiDataType_Float, &player->wallHeight); - InsertHelpHoverText("Height used to determine whether Link can climb or grab a ledge at the top"); + UIWidgets::InsertHelpHoverText("Height used to determine whether Link can climb or grab a ledge at the top"); ImGui::InputScalar("Invincibility Timer", ImGuiDataType_S8, &player->invincibilityTimer); - InsertHelpHoverText("Can't take damage while this is nonzero"); + UIWidgets::InsertHelpHoverText("Can't take damage while this is nonzero"); ImGui::InputScalar("Gravity", ImGuiDataType_Float, &player->actor.gravity); - InsertHelpHoverText("Rate at which Link falls. Default -4.0f"); + UIWidgets::InsertHelpHoverText("Rate at which Link falls. Default -4.0f"); if (ImGui::BeginCombo("Link Age on Load", gGlobalCtx->linkAgeOnLoad == 0 ? "Adult" : "Child")) { if (ImGui::Selectable("Adult")) { @@ -1453,7 +1453,7 @@ void DrawPlayerTab() { ImGui::EndCombo(); } - InsertHelpHoverText("This will change Link's age when you load a map"); + UIWidgets::InsertHelpHoverText("This will change Link's age when you load a map"); ImGui::Separator(); diff --git a/soh/soh/Enhancements/gameconsole.h b/soh/soh/Enhancements/gameconsole.h index 33301afe6..27838ff63 100644 --- a/soh/soh/Enhancements/gameconsole.h +++ b/soh/soh/Enhancements/gameconsole.h @@ -3,7 +3,7 @@ #include #include -#include "Cvar.h" +#include #define MAX_CVARS 2048 @@ -39,4 +39,4 @@ s32 GameConsole_Split(char* str, char** argv); } #endif -#endif \ No newline at end of file +#endif diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp index 144759e29..549624760 100644 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include std::list entranceOverrides = {}; bool noRandomEntrances = false; diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 14bf594c2..34037f3a1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include using namespace CustomMessages; using namespace Logic; diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 4c18524fc..b5f0743fb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -12,7 +12,7 @@ #include "trial.hpp" #include "entrance.hpp" #include "z64item.h" -#include +#include using namespace CustomMessages; using namespace Logic; diff --git a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp index 27101864b..83cf12b30 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp @@ -6,7 +6,7 @@ #include "shops.hpp" #include "debug.hpp" #include "keys.hpp" -#include +#include //Location definitions static std::array locationTable; @@ -1577,4 +1577,4 @@ void CreateItemOverrides() { } SPDLOG_DEBUG("Overrides Created: "); SPDLOG_DEBUG(std::to_string(overrides.size())); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index b7ed68ea6..ad85bd401 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -9,7 +9,7 @@ #include "settings.hpp" #include "spoiler_log.hpp" #include "z64item.h" -#include +#include using namespace Settings; diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp index f7699b754..468758fe3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp @@ -13,8 +13,8 @@ #include "spoiler_log.hpp" #include "location_access.hpp" #include "debug.hpp" -#include -#include "soh/Enhancements/randomizer/randomizerTypes.h" +#include +#include "../../randomizer/randomizerTypes.h" namespace { bool seedChanged; @@ -547,4 +547,4 @@ std::string GenerateRandomizer(std::unordered_map std::string GetInput(const char* hintText) { return std::string(); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index 7d0fc8b14..ac68e579b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -5,9 +5,9 @@ #include "location_access.hpp" #include "rando_main.hpp" // #include -#include -#include -#include +#include +#include +#include #define TICKS_PER_SEC 268123480.0 @@ -25,4 +25,4 @@ void RandoMain::GenerateRando(std::unordered_map cvarS CVar_Save(); CVar_Load(); CVar_SetS32("gNewSeedGenerated", 1); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index c9af08082..9ea43f2b2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -11,7 +11,7 @@ #include "utils.hpp" #include "shops.hpp" #include "hints.hpp" -#include "Lib/nlohmann/json.hpp" +#include #include #include @@ -26,7 +26,7 @@ #include #include -#include "Window.h" +#include using json = nlohmann::json; @@ -771,4 +771,4 @@ bool PlacementLog_Write() { contentNode->SetCData(true); return true; -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 495850361..0d0f4300b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1,21 +1,21 @@ #include "randomizer.h" -#include "Lib/nlohmann/json.hpp" +#include #include #include #include #include #include -#include +#include #include #include -#include "../libultraship/ImGuiImpl.h" +#include #include #include "3drando/rando_main.hpp" -#include -#include "Lib/ImGui/imgui_internal.h" -#include -#include -#include +#include "../../UIWidgets.hpp" +#include +#include "../custom-message/CustomMessageManager.h" +#include "../custom-message/CustomMessageTypes.h" +#include "../item-tables/ItemTableManager.h" #include using json = nlohmann::json; @@ -3364,7 +3364,7 @@ void DrawRandoEditor(bool& open) { ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * disableEditingRandoSettings ? 0.5f : 1.0f); - SohImGui::EnhancementCheckbox("Enable Randomizer", "gRandomizer"); + UIWidgets::EnhancementCheckbox("Enable Randomizer", "gRandomizer"); if (CVar_GetS32("gRandomizer", 0) == 1) { if (ImGui::Button("Generate Seed")) { @@ -3404,17 +3404,17 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Forest"); switch (CVar_GetS32("gRandomizeForest", 1)) { case 1: - InsertHelpHoverText("Mido no longer blocks the path to the Deku Tree\n" + UIWidgets::InsertHelpHoverText("Mido no longer blocks the path to the Deku Tree\n" "The Kokiri boy no longer blocks the path out of the forest."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The Kokiri boy no longer blocks the path out of the forest\nMido " "still blocks the path to the Deku Tree, requiring the Kokiri Sword " "and a Deku Shield to access the Deku Tree."); break; case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Beating Deku Tree is logically required to leave the forest area " "(Kokiri Forest / Lost Woods / Sacred Forest Meadow / Deku Tree) " "while the Kokiri Sword and a Deku Shield are required to access the " @@ -3422,125 +3422,125 @@ void DrawRandoEditor(bool& open) { "forest area.\nThis setting is incompatible with starting as adult."); break; } - SohImGui::EnhancementCombobox("gRandomizeForest", randoForest, 3, 1); + UIWidgets::EnhancementCombobox("gRandomizeForest", randoForest, 3, 1); ImGui::Separator(); // Kakariko Gate ImGui::Text("Kakariko Gate"); switch (CVar_GetS32("gRandomizeKakarikoGate", 0)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The gate and the Happy Mask Shop both remain closed until showing " "Zelda's Letter to the guard in Kakariko."); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The gate is always open instead of needing Zelda's Letter.\nThe Happy Mask Shop " "opens upon obtaining Zelda's Letter without needing to show it to the guard."); break; } - SohImGui::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 1); + UIWidgets::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 1); ImGui::Separator(); // Door of Time ImGui::Text("Door of Time"); switch (CVar_GetS32("gRandomizeDoorOfTime", 0)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The Door of Time starts opened instead of needing to play the Song of Time."); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Only an Ocarina and the Song of Time need to be found to open the Door of Time."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The Ocarina of Time, the Song of Time and all Spiritual Stones need to " "be found to open the Door of Time."); break; } - SohImGui::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); ImGui::Separator(); // Zora's Fountain ImGui::Text("Zora's Fountain"); switch (CVar_GetS32("gRandomizeZorasFountain", 0)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "King Zora obstructs the way to Zora's Fountain.\nRuto's Letter must be " "shown as child in order to move him from both eras."); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "King Zora is always moved in the adult era.\nThis means Ruto's Letter is " "only required to access Zora's fountain as child."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "King Zora starts as moved in both the child and adult eras.\nThis also " "removes Ruto's Letter from the pool since it can't be used."); break; } - SohImGui::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); ImGui::Separator(); // Gerudo Fortress ImGui::Text("Gerudo Fortress"); switch (CVar_GetS32("gRandomizeGerudoFortress", 0)) { case 0: - InsertHelpHoverText("All 4 carpenters can be rescued."); + UIWidgets::InsertHelpHoverText("All 4 carpenters can be rescued."); break; case 1: - InsertHelpHoverText("Only the bottom left carpenter must be rescued."); + UIWidgets::InsertHelpHoverText("Only the bottom left carpenter must be rescued."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The carpenters are rescued from the start of the game and if \"Shuffle " "Gerudo Card\" is disabled, the player starts with the Gerudo Card in " "the inventory allowing access to Gerudo Training Grounds."); break; } - SohImGui::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 1); + UIWidgets::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 1); ImGui::Separator(); // Rainbow Bridge ImGui::Text("Rainbow Bridge"); - SohImGui::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 3); + UIWidgets::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 3); switch (CVar_GetS32("gRandomizeRainbowBridge", 3)) { case 1: - InsertHelpHoverText("The Rainbow Bridge requires Shadow and Spirit Medallions as well " + UIWidgets::InsertHelpHoverText("The Rainbow Bridge requires Shadow and Spirit Medallions as well " "as Light Arrows."); break; case 2: - InsertHelpHoverText("The Rainbow Bridge requires collecting a configurable number of " + UIWidgets::InsertHelpHoverText("The Rainbow Bridge requires collecting a configurable number of " "Spiritual Stones."); - SohImGui::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", + UIWidgets::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", "gRandomizeStoneCount", 0, 3, ""); - SetLastItemHoverText( + UIWidgets::SetLastItemHoverText( "Sets the number of Spiritual Stones required to spawn the Rainbow Bridge."); break; case 3: - SohImGui::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", + UIWidgets::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", "gRandomizeMedallionCount", 0, 6, "", 6); - SetLastItemHoverText( + UIWidgets::SetLastItemHoverText( "The Rainbow Bridge requires collecting a configurable number of Medallions."); break; case 4: - SohImGui::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", + UIWidgets::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", "gRandomizeRewardCount", 0, 9, ""); - SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " + UIWidgets::SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " "Dungeon Rewards."); break; case 5: - SohImGui::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", + UIWidgets::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", "gRandomizeDungeonCount", 0, 8, ""); - SetLastItemHoverText( + UIWidgets::SetLastItemHoverText( "The Rainbow Bridge requires completing a configurable number of Dungeons.\nDungeons " "are considered complete when Link steps into the blue warp at the end of them."); break; case 6: - SohImGui::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", + UIWidgets::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", "gRandomizeTokenCount", 0, 100, ""); - SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " + UIWidgets::SetLastItemHoverText("The Rainbow Bridge requires collecting a configurable number of " "Gold Skulltula Tokens."); break; } @@ -3557,8 +3557,8 @@ void DrawRandoEditor(bool& open) { // "gRandomizeGanonTrialCount", 0, 6, ""); //InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); // RANDTODO: Switch back to slider when pre-completing some of Ganon's Trials is properly implemnted. - SohImGui::EnhancementCheckbox("Skip Ganon's Trials", "gRandomizeGanonTrialCount"); - InsertHelpHoverText( + UIWidgets::EnhancementCheckbox("Skip Ganon's Trials", "gRandomizeGanonTrialCount"); + UIWidgets::InsertHelpHoverText( "Sets whether or not Ganon's Castle Trials are required to enter Ganon's Tower."); // } @@ -3698,23 +3698,23 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Shuffle Dungeon Rewards"); switch (CVar_GetS32("gRandomizeShuffleDungeonReward", 0)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Medallions and Spiritual Stones will be given as rewards for beating dungeons.\n" "This setting will force Link's Pocket to be a Medallion or a Spiritual Stone."); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Medallions and Spiritual Stones can only appear inside of dungeons."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Medallions and Spiritual Stones can only appear outside dungeons."); break; case 3: - InsertHelpHoverText("Medallions and Spiritual Stones can appear anywhere."); + UIWidgets::InsertHelpHoverText("Medallions and Spiritual Stones can appear anywhere."); break; } - SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, + UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); // todo: support non dungeon rewards for link's pocket @@ -3748,10 +3748,10 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Shuffle Songs"); switch (CVar_GetS32("gRandomizeShuffleSongs", 0)) { case 0: - InsertHelpHoverText("Songs will only appear at locations that normally teach songs."); + UIWidgets::InsertHelpHoverText("Songs will only appear at locations that normally teach songs."); break; case 1: - InsertHelpHoverText("Songs appear at the end of dungeons.\nFor major dungeons, they " + UIWidgets::InsertHelpHoverText("Songs appear at the end of dungeons.\nFor major dungeons, they " "will be at the boss heart container location.\nThe remaining 4 " "songs are placed at:\n- Zelda's Lullaby location\n" "- Ice Cavern's Serenade of Water Location\n" @@ -3759,10 +3759,10 @@ void DrawRandoEditor(bool& open) { "- Gerudo Training Ground's Ice Arrow Location."); break; case 2: - InsertHelpHoverText("Songs can appear in any location"); + UIWidgets::InsertHelpHoverText("Songs can appear in any location"); break; } - SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); ImGui::Separator(); // todo implement shops @@ -3863,19 +3863,19 @@ void DrawRandoEditor(bool& open) { if(CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { // Shuffle Kokiri Sword ImGui::Text("Shuffle Kokiri Sword"); - InsertHelpHoverText("Enabling this shuffles the Kokiri Sword into the item pool.\nThis will " + UIWidgets::InsertHelpHoverText("Enabling this shuffles the Kokiri Sword into the item pool.\nThis will " "require extensive use of sticks until the sword is found."); - SohImGui::EnhancementCombobox("gRandomizeShuffleKokiriSword", randoShuffleKokiriSword, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleKokiriSword", randoShuffleKokiriSword, 2, 0); ImGui::Separator(); } if(CVar_GetS32("gRandomizeStartingOcarina", 0) == 0) { // Shuffle Ocarinas ImGui::Text("Shuffle Ocarinas"); - InsertHelpHoverText("Enabling this shuffles the Fairy Ocarina and the Ocarina of time into " + UIWidgets::InsertHelpHoverText("Enabling this shuffles the Fairy Ocarina and the Ocarina of time into " "the item pool.\n" "This will require finding an Ocarina before being able to play songs."); - SohImGui::EnhancementCombobox("gRandomizeShuffleOcarinas", randoShuffleOcarinas, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleOcarinas", randoShuffleOcarinas, 2, 0); ImGui::Separator(); } @@ -3883,22 +3883,22 @@ void DrawRandoEditor(bool& open) { if(CVar_GetS32("gRandomizeSkipChildZelda", 0) == 0) { // Shuffle Weird Egg ImGui::Text("Shuffle Weird Egg"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Enabling this shuffles the Weird Egg from Malon into the item pool.\nThis " "will require finding the Weird Egg to talk to Zelda in Hyrule Castle which " "in turn unlocks rewards from Impa, Saria, Malon and Talon as well as the " "Happy Mask Sidequest.\nThe Weird egg is also required for Zelda's Letter to " "unlock the Kakariko Gate as child which can lock some progression."); - SohImGui::EnhancementCombobox("gRandomizeShuffleWeirdEgg", randoShuffleWeirdEgg, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleWeirdEgg", randoShuffleWeirdEgg, 2, 0); ImGui::Separator(); } // Shuffle Gerudo Membership Card ImGui::Text("Shuffle Gerudo Membership Card"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Enabling this shuffles the Gerudo Membership Card into the item pool.\nThe Gerudo " "Token is required to enter the Gerudo Training Ground."); - SohImGui::EnhancementCombobox("gRandomizeShuffleGerudoToken", randoShuffleGerudoToken, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleGerudoToken", randoShuffleGerudoToken, 2, 0); ImGui::Separator(); // todo implement magic bean 10 pack @@ -3939,14 +3939,14 @@ void DrawRandoEditor(bool& open) { ImGui::PopItemWidth(); ImGui::TableNextColumn(); - SohImGui::EnhancementCheckbox("Start with Fairy Ocarina", "gRandomizeStartingOcarina"); - SohImGui::EnhancementCheckbox("Start with Kokiri Sword", "gRandomizeStartingKokiriSword"); - SohImGui::EnhancementCheckbox("Start with Deku Shield", "gRandomizeStartingDekuShield"); - SohImGui::EnhancementCheckbox("Start with Maps/Compasses", "gRandomizeStartingMapsCompasses"); - SohImGui::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); - SohImGui::EnhancementCheckbox("Start with Consumables", "gRandomizeStartingConsumables"); - SohImGui::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); - InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); + UIWidgets::EnhancementCheckbox("Start with Fairy Ocarina", "gRandomizeStartingOcarina"); + UIWidgets::EnhancementCheckbox("Start with Kokiri Sword", "gRandomizeStartingKokiriSword"); + UIWidgets::EnhancementCheckbox("Start with Deku Shield", "gRandomizeStartingDekuShield"); + UIWidgets::EnhancementCheckbox("Start with Maps/Compasses", "gRandomizeStartingMapsCompasses"); + UIWidgets::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); + UIWidgets::EnhancementCheckbox("Start with Consumables", "gRandomizeStartingConsumables"); + UIWidgets::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); + UIWidgets::InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); // todo dungeon items stuff (more details in commented out block) // ImGui::TableNextColumn(); @@ -4088,19 +4088,19 @@ void DrawRandoEditor(bool& open) { // Ganon's Boss Key ImGui::PushItemWidth(-FLT_MIN); ImGui::Text("Ganon's Boss Key"); - SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 3, + UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 3, 0); switch (CVar_GetS32("gRandomizeShuffleGanonBossKey", 0)) { case 0: - SetLastItemHoverText( + UIWidgets::SetLastItemHoverText( "Ganon's Boss Key is given to you from the start and you don't " "have to worry about finding it."); break; case 1: - SetLastItemHoverText("Ganon's Boss Key will appear in the vanilla location."); + UIWidgets::SetLastItemHoverText("Ganon's Boss Key will appear in the vanilla location."); break; case 2: - SetLastItemHoverText("Ganon's Boss Key will appear somewhere inside Ganon's Castle."); + UIWidgets::SetLastItemHoverText("Ganon's Boss Key will appear somewhere inside Ganon's Castle."); break; // case 0: // SetLastItemHoverText( @@ -4219,30 +4219,30 @@ void DrawRandoEditor(bool& open) { // ImGui::Separator(); // Cuccos to return - SohImGui::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", + UIWidgets::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", "gRandomizeCuccosToReturn", 0, 7, "", 7); - InsertHelpHoverText("The cucco Lady will give a reward for returning this many of her cuccos to the pen."); + UIWidgets::InsertHelpHoverText("The cucco Lady will give a reward for returning this many of her cuccos to the pen."); ImGui::Separator(); // // Big Poe Target Count - SohImGui::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", + UIWidgets::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", "gRandomizeBigPoeTargetCount", 1, 10, "", 10); - InsertHelpHoverText("The Poe buyer will give a reward for turning in the chosen number of Big Poes."); + UIWidgets::InsertHelpHoverText("The Poe buyer will give a reward for turning in the chosen number of Big Poes."); ImGui::Separator(); // // Skip child stealth - SohImGui::EnhancementCheckbox("Skip Child Stealth", "gRandomizeSkipChildStealth"); - InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); + UIWidgets::EnhancementCheckbox("Skip Child Stealth", "gRandomizeSkipChildStealth"); + UIWidgets::InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); ImGui::Separator(); // Skip Epona race - SohImGui::EnhancementCheckbox("Skip Epona Race", "gRandomizeSkipEponaRace"); - InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); + UIWidgets::EnhancementCheckbox("Skip Epona Race", "gRandomizeSkipEponaRace"); + UIWidgets::InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); ImGui::Separator(); // Skip tower escape - SohImGui::EnhancementCheckbox("Skip Tower Escape", "gRandomizeSkipTowerEscape"); - InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); + UIWidgets::EnhancementCheckbox("Skip Tower Escape", "gRandomizeSkipTowerEscape"); + UIWidgets::InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); ImGui::Separator(); // todo implement complete mask quest @@ -4275,53 +4275,53 @@ void DrawRandoEditor(bool& open) { ImGui::PushItemWidth(-FLT_MIN); // Gossip Stone Hints ImGui::Text("Gossip Stone Hints"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Gossip Stones can be made to give hints about where items can be found.\nDifferent settings can " "be chosen to decide which item is needed to speak to Gossip Stones. \nChoosing to stick with the " "Mask of Truth will make the hints very difficult to obtain.\nHints for \"on the way of the " "hero\" are locations that contain items that are required to beat the game."); - SohImGui::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); + UIWidgets::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); if (CVar_GetS32("gRandomizeGossipStoneHints", 1) != 0) { // Hint Clarity ImGui::Indent(); ImGui::Text("Hint Clarity"); switch (CVar_GetS32("gRandomizeHintClarity", 2)) { case 0: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the difficulty of hints.\nObscure: Hints are unique for each thing, but the " "writing may be confusing.\nEx: Kokiri Sword > a butter knife"); break; case 1: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the difficulty of hints.\nAmbiguous: Hints are clearly written, " "but may refer to more than one thing.\nEx: Kokiri Sword > a sword"); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the difficulty of hints.\nClear: Hints are clearly written and " "are unique for each thing.\nEx: Kokiri Sword > the Kokiri Sword"); break; } - SohImGui::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); + UIWidgets::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); // Hint Distribution ImGui::Text("Hint Distribution"); switch (CVar_GetS32("gRandomizeHintDistribution", 1)) { case 0: - InsertHelpHoverText("Only junk hints."); + UIWidgets::InsertHelpHoverText("Only junk hints."); break; case 1: - InsertHelpHoverText("Recommended hint spread."); + UIWidgets::InsertHelpHoverText("Recommended hint spread."); break; case 2: - InsertHelpHoverText("More useful hints."); + UIWidgets::InsertHelpHoverText("More useful hints."); break; case 3: - InsertHelpHoverText("Many powerful hints."); + UIWidgets::InsertHelpHoverText("Many powerful hints."); break; } - SohImGui::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); + UIWidgets::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); ImGui::Unindent(); } ImGui::Separator(); @@ -4375,43 +4375,43 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Item Pool"); switch (CVar_GetS32("gRandomizeItemPool", 1)) { case 0: - InsertHelpHoverText("Extra major items are added to the pool."); + UIWidgets::InsertHelpHoverText("Extra major items are added to the pool."); break; case 1: - InsertHelpHoverText("Original item pool."); + UIWidgets::InsertHelpHoverText("Original item pool."); break; case 2: - InsertHelpHoverText("Some excess items are removed, including health upgrades."); + UIWidgets::InsertHelpHoverText("Some excess items are removed, including health upgrades."); break; case 3: - InsertHelpHoverText("Most excess items are removed."); + UIWidgets::InsertHelpHoverText("Most excess items are removed."); break; } - SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); + UIWidgets::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); ImGui::Separator(); // // Ice Traps ImGui::Text("Ice Traps"); switch (CVar_GetS32("gRandomizeIceTraps", 1)) { case 0: - InsertHelpHoverText("All Ice Traps are removed."); + UIWidgets::InsertHelpHoverText("All Ice Traps are removed."); break; case 1: - InsertHelpHoverText("Only Ice Traps from the base item pool are placed."); + UIWidgets::InsertHelpHoverText("Only Ice Traps from the base item pool are placed."); break; case 2: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Chance to add extra Ice Traps when junk items are added to the item pool."); break; case 3: - InsertHelpHoverText("All added junk items will be Ice Traps."); + UIWidgets::InsertHelpHoverText("All added junk items will be Ice Traps."); break; case 4: - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "All junk items will be replaced by Ice Traps, even those in the base pool."); break; } - SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); + UIWidgets::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); ImGui::Separator(); // todo implement double defense getitem @@ -4450,17 +4450,17 @@ void DrawRandoEditor(bool& open) { ImGui::TableNextColumn(); // COLUMN 2 - OPEN EXCLUDE LOCATIONS ImGui::NewLine(); - SohImGui::EnhancementCheckbox("Deku Theater Mask of Truth", "gRandomizeExcludeDekuTheaterMaskOfTruth"); + UIWidgets::EnhancementCheckbox("Deku Theater Mask of Truth", "gRandomizeExcludeDekuTheaterMaskOfTruth"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("10 Skulltula Reward", "gRandomizeExcludeKak10SkullReward"); + UIWidgets::EnhancementCheckbox("10 Skulltula Reward", "gRandomizeExcludeKak10SkullReward"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("20 Skulltula Reward", "gRandomizeExcludeKak20SkullReward"); + UIWidgets::EnhancementCheckbox("20 Skulltula Reward", "gRandomizeExcludeKak20SkullReward"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("30 Skulltula Reward", "gRandomizeExcludeKak30SkullReward"); + UIWidgets::EnhancementCheckbox("30 Skulltula Reward", "gRandomizeExcludeKak30SkullReward"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("40 Skulltula Reward", "gRandomizeExcludeKak40SkullReward"); + UIWidgets::EnhancementCheckbox("40 Skulltula Reward", "gRandomizeExcludeKak40SkullReward"); ImGui::NewLine(); - SohImGui::EnhancementCheckbox("50 Skulltula Reward", "gRandomizeExcludeKak50SkullReward"); + UIWidgets::EnhancementCheckbox("50 Skulltula Reward", "gRandomizeExcludeKak50SkullReward"); // ImGui::TableNextColumn(); // // COLUMN 3 - LOGICAL TRICKS // ImGui::NewLine(); @@ -4742,4 +4742,4 @@ void Rando_Init(void) { InitRando(); } -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 2dcef684c..e9b321434 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -1,13 +1,13 @@ #include "randomizer_item_tracker.h" #include "../../util.h" -#include "../libultraship/ImGuiImpl.h" -#include +#include +#include "../../UIWidgets.hpp" #include #include #include #include -#include +#include extern "C" { #include @@ -20,6 +20,7 @@ extern GlobalContext* gGlobalCtx; #include "textures/icon_item_24_static/icon_item_24_static.h" } + typedef struct { uint32_t id; std::string name; @@ -252,7 +253,7 @@ void DrawEquip(uint32_t itemId) { ImGui::Image(SohImGui::GetTextureByName(hasEquip ? entry.name : entry.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } std::unordered_map questTrackerMap = { @@ -300,7 +301,7 @@ void DrawQuest(uint32_t itemId) { ImGui::EndGroup(); - SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); }; std::unordered_map itemTrackerMap = { @@ -677,7 +678,7 @@ void DrawItem(uint32_t itemId) { } ImGui::EndGroup(); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } void DrawBottle(uint32_t itemId, uint32_t bottleSlot) { @@ -688,7 +689,7 @@ void DrawBottle(uint32_t itemId, uint32_t bottleSlot) { ImGui::Image(SohImGui::GetTextureByName(hasItem ? entry.name : entry.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); }; typedef struct { @@ -733,12 +734,12 @@ void DrawUpgrade(int32_t categoryId) { const ItemTrackerUpgradeEntry& entry = upgradeTrackerMap[categoryId][0]; ImGui::Image(SohImGui::GetTextureByName(entry.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } else { const ItemTrackerUpgradeEntry& entry = upgradeTrackerMap[categoryId][CUR_UPG_VALUE(categoryId) - 1]; ImGui::Image(SohImGui::GetTextureByName(entry.name), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } } @@ -804,7 +805,7 @@ void DrawSong(int32_t songId) { bool hasSong = (bitMask & gSaveContext.inventory.questItems) != 0; ImGui::Image(SohImGui::GetTextureByName(hasSong ? entry.name : entry.nameFaded), ImVec2(iconSize/1.5, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(entry.id)); } void DrawItemTracker(bool& open) { @@ -983,12 +984,12 @@ void DrawItemTracker(bool& open) { } else { minimalSpacingX = 32; } - SohImGui::EnhancementCheckbox("Display \"Ammo/MaxAmo\"", "gItemTrackerAmmoDisplay"); - SohImGui::EnhancementCheckbox("Randomizer colors for Songs", "gItemTrackeSongColor"); - SohImGui::Tooltip("Will display non-warp songs with randomizer colors instead of pure white"); - SohImGui::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gRandoTrackIconSize", 32, 128, ""); + UIWidgets::EnhancementCheckbox("Display \"Ammo/MaxAmo\"", "gItemTrackerAmmoDisplay"); + UIWidgets::EnhancementCheckbox("Randomizer colors for Songs", "gItemTrackeSongColor"); + UIWidgets::Tooltip("Will display non-warp songs with randomizer colors instead of pure white"); + UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gRandoTrackIconSize", 32, 128, ""); - SohImGui::EnhancementSliderInt("X spacing : %dpx", "##ITEMTRACKERSPACINGX", "gRandoTrackIconSpacingX", minimalSpacingX, 256, + UIWidgets::EnhancementSliderInt("X spacing : %dpx", "##ITEMTRACKERSPACINGX", "gRandoTrackIconSpacingX", minimalSpacingX, 256, ""); // SohImGui::EnhancementSliderInt("Y Spacing : %dpx", "##ITEMTRACKERSPACINGY", "gRandoTrackIconSpacingY", 0, // 16, ""); @@ -1016,4 +1017,4 @@ void DrawItemTracker(bool& open) { void InitItemTracker() { SohImGui::AddWindow("Randomizer", "Item Tracker", DrawItemTracker); -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/savestates.cpp b/soh/soh/Enhancements/savestates.cpp index 37856aa81..4296ce869 100644 --- a/soh/soh/Enhancements/savestates.cpp +++ b/soh/soh/Enhancements/savestates.cpp @@ -1,6 +1,6 @@ #include "savestates.h" -#include "GameVersions.h" +#include #include // std::sprintf @@ -9,7 +9,7 @@ #include #include -#include +#include #include "z64.h" #include "z64save.h" @@ -823,7 +823,7 @@ extern "C" void ProcessSaveStateRequests(void) { } void SaveStateMgr::SetCurrentSlot(unsigned int slot) { - SohImGui::overlay->TextDrawNotification(1.0f, true, "slot %u set", slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "slot %u set", slot); this->currentSlot = slot; } @@ -841,12 +841,12 @@ void SaveStateMgr::ProcessSaveStateRequests(void) { this->states[request.slot] = std::make_shared(OTRGlobals::Instance->gSaveStateMgr, request.slot); } this->states[request.slot]->Save(); - SohImGui::overlay->TextDrawNotification(1.0f, true, "saved state %u", request.slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "saved state %u", request.slot); break; case RequestType::LOAD: if (this->states.contains(request.slot)) { this->states[request.slot]->Load(); - SohImGui::overlay->TextDrawNotification(1.0f, true, "loaded state %u", request.slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "loaded state %u", request.slot); } else { SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); } @@ -862,7 +862,7 @@ void SaveStateMgr::ProcessSaveStateRequests(void) { SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) { if (gGlobalCtx == nullptr) { SPDLOG_ERROR("[SOH] Can not save or load a state outside of \"GamePlay\""); - SohImGui::overlay->TextDrawNotification(1.0f, true, "states not available here", request.slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "states not available here", request.slot); return SaveStateReturn::FAIL_WRONG_GAMESTATE; } @@ -876,7 +876,7 @@ SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) { return SaveStateReturn::SUCCESS; } else { SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); - SohImGui::overlay->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot); + SohImGui::GetGameOverlay()->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot); return SaveStateReturn::FAIL_INVALID_SLOT; } [[unlikely]] default: diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp new file mode 100644 index 000000000..cf843cc8b --- /dev/null +++ b/soh/soh/GameMenuBar.cpp @@ -0,0 +1,1367 @@ +// +// GameMenuBar.cpp +// soh +// +// Created by David Chavez on 24.08.22. +// + +#include "GameMenuBar.hpp" + +#include +#include +#define IMGUI_DEFINE_MATH_OPERATORS +#include +#include +#include +#include +#include +#include +#include + +#ifdef __SWITCH__ +#include +#endif + +#include "UIWidgets.hpp" +#include "include/z64audio.h" + +#define EXPERIMENTAL() \ + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ + UIWidgets::Spacer(3.0f); \ + ImGui::Text("Experimental"); \ + ImGui::PopStyleColor(); \ + UIWidgets::PaddedSeparator(false, true); + +bool isBetaQuestEnabled = false; + +extern "C" { + void enableBetaQuest() { isBetaQuestEnabled = true; } + void disableBetaQuest() { isBetaQuestEnabled = false; } +} + +enum SeqPlayers { + /* 0 */ SEQ_BGM_MAIN, + /* 1 */ SEQ_FANFARE, + /* 2 */ SEQ_SFX, + /* 3 */ SEQ_BGM_SUB, + /* 4 */ SEQ_MAX +}; + +namespace GameMenuBar { + + // MARK: - Properties + + const char* powers[9] = { + "Vanilla (1x)", + "Double (2x)", + "Quadruple (4x)", + "Octuple (8x)", + "Hexadecuple (16x)", + "Duotrigintuple (32x)", + "Quattuorsexagintuple (64x)", + "Octoviginticentuple (128x)", + "Hexaquinquagintiducentuple (256x)" + }; + + // MARK: - Helpers + + std::string GetWindowButtonText(const char* text, bool menuOpen) { + char buttonText[100] = ""; + if(menuOpen) { strcat(buttonText,"> "); } + strcat(buttonText, text); + if (!menuOpen) { strcat(buttonText, " "); } + return buttonText; + } + + void BindAudioSlider(const char* name, const char* key, float defaultValue, SeqPlayers playerId) { + float value = CVar_GetFloat(key, defaultValue); + + ImGui::Text(name, static_cast(100 * value)); + if (ImGui::SliderFloat((std::string("##") + key).c_str(), &value, 0.0f, 1.0f, "")) { + const float volume = floorf(value * 100) / 100; + CVar_SetFloat(key, volume); + SohImGui::RequestCvarSaveOnNextTick(); + Audio_SetGameVolume(playerId, volume); + } + } + + void UpdateAudio() { + Audio_SetGameVolume(SEQ_BGM_MAIN, CVar_GetFloat("gMainMusicVolume", 1)); + Audio_SetGameVolume(SEQ_BGM_SUB, CVar_GetFloat("gSubMusicVolume", 1)); + Audio_SetGameVolume(SEQ_FANFARE, CVar_GetFloat("gSFXMusicVolume", 1)); + Audio_SetGameVolume(SEQ_SFX, CVar_GetFloat("gFanfareVolume", 1)); + } + + void applyEnhancementPresetDefault(void) { + // D-pad Support on Pause and File Select + CVar_SetS32("gDpadPauseName", 0); + // D-pad Support in Ocarina and Text Choice + CVar_SetS32("gDpadOcarinaText", 0); + // D-pad Support for Browsing Shop Items + CVar_SetS32("gDpadShop", 0); + // D-pad as Equip Items + CVar_SetS32("gDpadEquips", 0); + // Allow the cursor to be on any slot + CVar_SetS32("gPauseAnyCursor", 0); + // Prevent Dropped Ocarina Inputs + CVar_SetS32("gDpadNoDropOcarinaInput", 0); + // Answer Navi Prompt with L Button + CVar_SetS32("gNaviOnL", 0); + + // Text Speed (1 to 5) + CVar_SetS32("gTextSpeed", 1); + // King Zora Speed (1 to 5) + CVar_SetS32("gMweepSpeed", 1); + // Biggoron Forge Time (0 to 3) + CVar_SetS32("gForgeTime", 3); + // Vine/Ladder Climb speed (+0 to +12) + CVar_SetS32("gClimbSpeed", 0); + // Faster Block Push (+0 to +5) + CVar_SetS32("gFasterBlockPush", 0); + // Faster Heavy Block Lift + CVar_SetS32("gFasterHeavyBlockLift", 0); + // No Forced Navi + CVar_SetS32("gNoForcedNavi", 0); + // No Skulltula Freeze + CVar_SetS32("gSkulltulaFreeze", 0); + // MM Bunny Hood + CVar_SetS32("gMMBunnyHood", 0); + // Fast Chests + CVar_SetS32("gFastChests", 0); + // Fast Drops + CVar_SetS32("gFastDrops", 0); + // Better Owl + CVar_SetS32("gBetterOwl", 0); + // Fast Ocarina Playback + CVar_SetS32("gFastOcarinaPlayback", 0); + // Instant Putaway + CVar_SetS32("gInstantPutaway", 0); + // Instant Boomerang Recall + CVar_SetS32("gFastBoomerang", 0); + // Mask Select in Inventory + CVar_SetS32("gMaskSelect", 0); + // Remember Save Location + CVar_SetS32("gRememberSaveLocation", 0); + + // Damage Multiplier (0 to 8) + CVar_SetS32("gDamageMul", 0); + // Fall Damage Multiplier (0 to 7) + CVar_SetS32("gFallDamageMul", 0); + // Void Damage Multiplier (0 to 6) + CVar_SetS32("gVoidDamageMul", 0); + // No Random Drops + CVar_SetS32("gNoRandomDrops", 0); + // No Heart Drops + CVar_SetS32("gNoHeartDrops", 0); + // Enable Bombchu Drops + CVar_SetS32("gBombchuDrops", 0); + // Always Win Goron Pot + CVar_SetS32("gGoronPot", 0); + + // Change Red Potion Effect + CVar_SetS32("gRedPotionEffect", 0); + // Red Potion Health (1 to 100) + CVar_SetS32("gRedPotionHealth", 1); + // Red Potion Percent Restore + CVar_SetS32("gRedPercentRestore", 0); + // Change Green Potion Effect + CVar_SetS32("gGreenPotionEffect", 0); + // Green Potion Mana (1 to 100) + CVar_SetS32("gGreenPotionMana", 1); + // Green Potion Percent Restore + CVar_SetS32("gGreenPercentRestore", 0); + // Change Blue Potion Effects + CVar_SetS32("gBluePotionEffects", 0); + // Blue Potion Health (1 to 100) + CVar_SetS32("gBluePotionHealth", 1); + // Blue Potion Health Percent Restore + CVar_SetS32("gBlueHealthPercentRestore", 0); + // Blue Potion Mana (1 to 100) + CVar_SetS32("gBluePotionMana", 1); + // Blue Potion Mana Percent Restore + CVar_SetS32("gBlueManaPercentRestore", 0); + // Change Milk Effect + CVar_SetS32("gMilkEffect", 0); + // Milk Health (1 to 100) + CVar_SetS32("gMilkHealth", 1); + // Milk Percent Restore + CVar_SetS32("gMilkPercentRestore", 0); + // Separate Half Milk Effect + CVar_SetS32("gSeparateHalfMilkEffect", 0); + // Half Milk Health (1 to 100) + CVar_SetS32("gHalfMilkHealth", 0); + // Half Milk Percent Restore + CVar_SetS32("gHalfMilkPercentRestore", 0); + // Change Fairy Effect + CVar_SetS32("gFairyEffect", 0); + // Fairy (1 to 100) + CVar_SetS32("gFairyHealth", 1); + // Fairy Percent Restore + CVar_SetS32("gFairyPercentRestore", 0); + // Change Fairy Revive Effect + CVar_SetS32("gFairyReviveEffect", 0); + // Fairy Revival (1 to 100) + CVar_SetS32("gFairyReviveHealth", 1); + // Fairy Revive Percent Restore + CVar_SetS32("gFairyRevivePercentRestore", 0); + + // Instant Fishing + CVar_SetS32("gInstantFishing", 0); + // Guarantee Bite + CVar_SetS32("gGuaranteeFishingBite", 0); + // Child Minimum Weight (6 to 10) + CVar_SetS32("gChildMinimumWeightFish", 10); + // Adult Minimum Weight (8 to 13) + CVar_SetS32("gAdultMinimumWeightFish", 13); + + // Mute Low HP Alarm + CVar_SetS32("gLowHpAlarm", 0); + // Minimal UI + CVar_SetS32("gMinimalUI", 0); + // Disable Navi Call Audio + CVar_SetS32("gDisableNaviCallAudio", 0); + + // Visual Stone of Agony + CVar_SetS32("gVisualAgony", 0); + // Assignable Tunics and Boots + CVar_SetS32("gAssignableTunicsAndBoots", 0); + // Equipment Toggle + CVar_SetS32("gEquipmentCanBeRemoved", 0); + // Link's Cow in Both Time Periods + CVar_SetS32("gCowOfTime", 0); + // Enable visible guard vision + CVar_SetS32("gGuardVision", 0); + // Enable passage of time on file select + CVar_SetS32("gTimeFlowFileSelect", 0); + // Count Golden Skulltulas + CVar_SetS32("gInjectSkulltulaCount", 0); + // Pull grave during the day + CVar_SetS32("gDayGravePull", 0); + + // Rotate link (0 to 2) + CVar_SetS32("gPauseLiveLinkRotation", 0); + // Pause link animation (0 to 16) + CVar_SetS32("gPauseLiveLink", 0); + // Frames to wait + CVar_SetS32("gMinFrameCount", 1); + + // N64 Mode + CVar_SetS32("gN64Mode", 0); + // Enable 3D Dropped items/projectiles + CVar_SetS32("gNewDrops", 0); + // Disable Black Bar Letterboxes + CVar_SetS32("gDisableBlackBars", 0); + // Dynamic Wallet Icon + CVar_SetS32("gDynamicWalletIcon", 0); + // Always show dungeon entrances + CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 0); + + // Fix L&R Pause menu + CVar_SetS32("gUniformLR", 0); + // Fix L&Z Page switch in Pause menu + CVar_SetS32("gNGCKaleidoSwitcher", 0); + // Fix Dungeon entrances + CVar_SetS32("gFixDungeonMinimapIcon", 0); + // Fix Two Handed idle animations + CVar_SetS32("gTwoHandedIdle", 0); + // Fix the Gravedigging Tour Glitch + CVar_SetS32("gGravediggingTourFix", 0); + // Fix Deku Nut upgrade + CVar_SetS32("gDekuNutUpgradeFix", 0); + // Fix Navi text HUD position + CVar_SetS32("gNaviTextFix", 0); + // Fix Anubis fireballs + CVar_SetS32("gAnubisFix", 0); + // Fix Megaton Hammer crouch stab + CVar_SetS32("gCrouchStabHammerFix", 0); + // Fix all crouch stab + CVar_SetS32("gCrouchStabFix", 0); + + // Red Ganon blood + CVar_SetS32("gRedGanonBlood", 0); + // Fish while hovering + CVar_SetS32("gHoverFishing", 0); + // N64 Weird Frames + CVar_SetS32("gN64WeirdFrames", 0); + // Bombchus out of bounds + CVar_SetS32("gBombchusOOB", 0); + + CVar_SetS32("gGsCutscene", 0); + // Autosave + CVar_SetS32("gAutosave", 0); + } + + void applyEnhancementPresetVanillaPlus(void) { + // D-pad Support in Ocarina and Text Choice + CVar_SetS32("gDpadOcarinaText", 1); + // D-pad Support for Browsing Shop Items + CVar_SetS32("gDpadShop", 1); + // D-pad as Equip Items + CVar_SetS32("gDpadEquips", 1); + // Prevent Dropped Ocarina Inputs + CVar_SetS32("gDpadNoDropOcarinaInput", 1); + + // Text Speed (1 to 5) + CVar_SetS32("gTextSpeed", 5); + // King Zora Speed (1 to 5) + CVar_SetS32("gMweepSpeed", 2); + // Faster Block Push (+0 to +5) + CVar_SetS32("gFasterBlockPush", 5); + // Better Owl + CVar_SetS32("gBetterOwl", 1); + + // Assignable Tunics and Boots + CVar_SetS32("gAssignableTunicsAndBoots", 1); + // Enable passage of time on file select + CVar_SetS32("gTimeFlowFileSelect", 1); + // Count Golden Skulltulas + CVar_SetS32("gInjectSkulltulaCount", 1); + + // Pause link animation (0 to 16) + CVar_SetS32("gPauseLiveLink", 1); + + // Dynamic Wallet Icon + CVar_SetS32("gDynamicWalletIcon", 1); + // Always show dungeon entrances + CVar_SetS32("gAlwaysShowDungeonMinimapIcon", 1); + + // Fix L&R Pause menu + CVar_SetS32("gUniformLR", 1); + // Fix Dungeon entrances + CVar_SetS32("gFixDungeonMinimapIcon", 1); + // Fix Two Handed idle animations + CVar_SetS32("gTwoHandedIdle", 1); + // Fix the Gravedigging Tour Glitch + CVar_SetS32("gGravediggingTourFix", 1); + // Fix Deku Nut upgrade + CVar_SetS32("gDekuNutUpgradeFix", 1); + + // Red Ganon blood + CVar_SetS32("gRedGanonBlood", 1); + // Fish while hovering + CVar_SetS32("gHoverFishing", 1); + // N64 Weird Frames + CVar_SetS32("gN64WeirdFrames", 1); + // Bombchus out of bounds + CVar_SetS32("gBombchusOOB", 1); + } + + void applyEnhancementPresetEnhanced(void) { + // King Zora Speed (1 to 5) + CVar_SetS32("gMweepSpeed", 5); + // Biggoron Forge Time (0 to 3) + CVar_SetS32("gForgeTime", 0); + // Vine/Ladder Climb speed (+0 to +12) + CVar_SetS32("gClimbSpeed", 1); + // Faster Heavy Block Lift + CVar_SetS32("gFasterHeavyBlockLift", 1); + // No Forced Navi + CVar_SetS32("gNoForcedNavi", 1); + // No Skulltula Freeze + CVar_SetS32("gSkulltulaFreeze", 1); + // MM Bunny Hood + CVar_SetS32("gMMBunnyHood", 1); + // Fast Chests + CVar_SetS32("gFastChests", 1); + // Fast Drops + CVar_SetS32("gFastDrops", 1); + // Fast Ocarina Playback + CVar_SetS32("gFastOcarinaPlayback", 1); + // Instant Putaway + CVar_SetS32("gInstantPutaway", 1); + // Instant Boomerang Recall + CVar_SetS32("gFastBoomerang", 1); + // Mask Select in Inventory + CVar_SetS32("gMaskSelect", 1); + + // Disable Navi Call Audio + CVar_SetS32("gDisableNaviCallAudio", 1); + + // Equipment Toggle + CVar_SetS32("gEquipmentCanBeRemoved", 1); + // Count Golden Skulltulas + CVar_SetS32("gInjectSkulltulaCount", 1); + + // Enable 3D Dropped items/projectiles + CVar_SetS32("gNewDrops", 1); + + // Fix Anubis fireballs + CVar_SetS32("gAnubisFix", 1); + } + + void applyEnhancementPresetRandomizer(void) { + // Allow the cursor to be on any slot + CVar_SetS32("gPauseAnyCursor", 1); + + // Instant Fishing + CVar_SetS32("gInstantFishing", 1); + // Guarantee Bite + CVar_SetS32("gGuaranteeFishingBite", 1); + // Child Minimum Weight (6 to 10) + CVar_SetS32("gChildMinimumWeightFish", 6); + // Adult Minimum Weight (8 to 13) + CVar_SetS32("gAdultMinimumWeightFish", 8); + + // Visual Stone of Agony + CVar_SetS32("gVisualAgony", 1); + // Pull grave during the day + CVar_SetS32("gDayGravePull", 1); + // Pull out Ocarina to Summon Scarecrow + CVar_SetS32("gSkipScarecrow", 0); + + // Pause link animation (0 to 16) + CVar_SetS32("gPauseLiveLink", 16); + // Frames to wait + CVar_SetS32("gMinFrameCount", 200); + } + + void applyEnhancementPresets(void) { + switch (CVar_GetS32("gSelectEnhancementPresets", 0)) { + // Default + case 0: + applyEnhancementPresetDefault(); + break; + + // Vanilla Plus + case 1: + applyEnhancementPresetDefault(); + applyEnhancementPresetVanillaPlus(); + break; + + // Enhanced + case 2: + applyEnhancementPresetDefault(); + applyEnhancementPresetVanillaPlus(); + applyEnhancementPresetEnhanced(); + break; + + // Randomizer + case 3: + applyEnhancementPresetDefault(); + applyEnhancementPresetVanillaPlus(); + applyEnhancementPresetEnhanced(); + applyEnhancementPresetRandomizer(); + break; + } + } + + // MARK: - Delegates + + void SetupHooks() { + Ship::RegisterHook(UpdateAudio); + Ship::RegisterHook(UpdateAudio); + } + + void Draw() { + if (ImGui::BeginMenu("Settings")) + { + if (ImGui::BeginMenu("Audio")) { + UIWidgets::EnhancementSliderFloat("Master Volume: %d %%", "##Master_Vol", "gGameMasterVolume", 0.0f, 1.0f, "", 1.0f, true); + UIWidgets::Spacer(0); + BindAudioSlider("Main Music Volume: %d %%", "gMainMusicVolume", 1.0f, SEQ_BGM_MAIN); + UIWidgets::Spacer(0); + BindAudioSlider("Sub Music Volume: %d %%", "gSubMusicVolume", 1.0f, SEQ_BGM_SUB); + UIWidgets::Spacer(0); + BindAudioSlider("Sound Effects Volume: %d %%", "gSFXMusicVolume", 1.0f, SEQ_SFX); + UIWidgets::Spacer(0); + BindAudioSlider("Fanfare Volume: %d %%", "gFanfareVolume", 1.0f, SEQ_FANFARE); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Controller")) { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2 (12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + if (ImGui::Button(GetWindowButtonText("Controller Configuration", CVar_GetS32("gControllerConfigurationEnabled", 0)).c_str())) + { + bool currentValue = CVar_GetS32("gControllerConfigurationEnabled", 0); + CVar_SetS32("gControllerConfigurationEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::ToggleInputEditorWindow(CVar_GetS32("gControllerConfigurationEnabled", 0)); + } + ImGui::PopStyleColor(1); + ImGui::PopStyleVar(3); + #ifndef __SWITCH__ + UIWidgets::PaddedEnhancementCheckbox("Use Controller Navigation", "gControlNav", true, false); + UIWidgets::Tooltip("Allows controller navigation of the menu bar\nD-pad to move between items, A to select, and X to grab focus on the menu bar"); + #endif + UIWidgets::PaddedEnhancementCheckbox("Show Inputs", "gInputEnabled", true, false); + UIWidgets::Tooltip("Shows currently pressed inputs on the bottom right of the screen"); + UIWidgets::Spacer(0); + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 20.0f); + UIWidgets::EnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false); + UIWidgets::Tooltip("Sets the on screen size of the displayed inputs from the Show Inputs setting"); + ImGui::PopItemWidth(); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Graphics")) { + #ifndef __APPLE__ + UIWidgets::EnhancementSliderFloat("Internal Resolution: %d %%", "##IMul", "gInternalResolution", 0.5f, 2.0f, "", 1.0f, true, true); + UIWidgets::Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing"); + SohImGui::SetResolutionMultiplier(CVar_GetFloat("gInternalResolution", 1)); + #endif + #ifndef __WIIU__ + UIWidgets::PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, false, true, false); + UIWidgets::Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel"); + SohImGui::SetMSAALevel(CVar_GetS32("gMSAAValue", 1)); + #endif + + if (SohImGui::WindowBackend() == SohImGui::Backend::DX11) + { + const char* cvar = "gExtraLatencyThreshold"; + int val = CVar_GetS32(cvar, 80); + val = fmax(fmin(val, 360), 0); + int fps = val; + + UIWidgets::Spacer(0); + + if (fps == 0) + { + ImGui::Text("Jitter fix: Off"); + } + else + { + ImGui::Text("Jitter fix: >= %d FPS", fps); + } + + std::string MinusBTNELT = " - ##ExtraLatencyThreshold"; + std::string PlusBTNELT = " + ##ExtraLatencyThreshold"; + if (ImGui::Button(MinusBTNELT.c_str())) { + val--; + CVar_SetS32(cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); + if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 360, "", ImGuiSliderFlags_AlwaysClamp)) + { + CVar_SetS32(cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::PopItemWidth(); + UIWidgets::Tooltip("When Interpolation FPS setting is at least this threshold, add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter. This setting allows the CPU to work on one frame while GPU works on the previous frame.\nThis setting should be used when your computer is too slow to do CPU + GPU work in time."); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNELT.c_str())) { + val++; + CVar_SetS32(cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + UIWidgets::Spacer(0); + } + + ImGui::Text("Renderer API (Needs reload)"); + auto backends = SohImGui::GetAvailableRenderingBackends(); + auto currentBackend = SohImGui::GetCurrentRenderingBackend(); + + if (ImGui::BeginCombo("##RApi", currentBackend.second)) { + for (uint8_t i = 0; i < sizeof(backends) / sizeof(backends[0]); i++) { + if (ImGui::Selectable(backends[i].second, backends[i] == currentBackend)) { + SohImGui::SetCurrentRenderingBackend(i, backends[i]); + } + } + + ImGui::EndCombo(); + } + + EXPERIMENTAL(); + + ImGui::Text("Texture Filter (Needs reload)"); + UIWidgets::EnhancementCombobox("gTextureFilter", SohImGui::GetSupportedTextureFilters(), 3, 0); + + UIWidgets::Spacer(0); + + SohImGui::DrawSettings(); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Languages")) { + UIWidgets::EnhancementRadioButton("English", "gLanguages", 0); + UIWidgets::EnhancementRadioButton("German", "gLanguages", 1); + UIWidgets::EnhancementRadioButton("French", "gLanguages", 2); + ImGui::EndMenu(); + } + ImGui::EndMenu(); + } + + ImGui::SetCursorPosY(0.0f); + + if (ImGui::BeginMenu("Enhancements")) + { + + const char* enhancementPresets[4] = { "Default", "Vanilla Plus", "Enhanced", "Randomizer"}; + UIWidgets::PaddedText("Enhancement Presets", false, true); + UIWidgets::EnhancementCombobox("gSelectEnhancementPresets", enhancementPresets, 4, 0); + UIWidgets::Tooltip( + "Default - Set all enhancements to their default values. The true vanilla SoH experience.\n" + "\n" + "Vanilla Plus - Adds Quality of Life features that enhance your experience, but don't alter gameplay. Recommended for a first playthrough of OoT.\n" + "\n" + "Enhanced - The \"Vanilla Plus\" preset, but with more quality of life enhancements that might alter gameplay slightly. Recommended for returning players.\n" + "\n" + "Randomizer - The \"Enhanced\" preset, plus any other enhancements that are recommended for playing Randomizer." + ); + + UIWidgets::Spacer(0); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f)); + if (ImGui::Button("Apply Preset")) { + applyEnhancementPresets(); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::PopStyleVar(1); + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Controls")) { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + float availableWidth = ImGui::GetContentRegionAvail().x; + if (ImGui::Button( + GetWindowButtonText("Customize Game Controls", CVar_GetS32("gGameControlEditorEnabled", 0)).c_str(), + ImVec2(availableWidth, 0) + )) { + bool currentValue = CVar_GetS32("gGameControlEditorEnabled", 0); + CVar_SetS32("gGameControlEditorEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Game Control Editor", CVar_GetS32("gGameControlEditorEnabled", 0)); + } + ImGui::PopStyleVar(3); + ImGui::PopStyleColor(1); + + // TODO mutual exclusions -- There should be some system to prevent conclifting enhancements from being selected + UIWidgets::PaddedEnhancementCheckbox("D-pad Support on Pause and File Select", "gDpadPauseName"); + UIWidgets::Tooltip("Enables Pause and File Select screen navigation with the D-pad\nIf used with D-pad as Equip Items, you must hold C-Up to equip instead of navigate"); + UIWidgets::PaddedEnhancementCheckbox("D-pad Support in Text Choice", "gDpadText", true, false); + UIWidgets::PaddedEnhancementCheckbox("D-pad Support for Browsing Shop Items", "gDpadShop", true, false); + UIWidgets::PaddedEnhancementCheckbox("D-pad as Equip Items", "gDpadEquips", true, false); + UIWidgets::Tooltip("Allows the D-pad to be used as extra C buttons"); + UIWidgets::PaddedEnhancementCheckbox("Allow the cursor to be on any slot", "gPauseAnyCursor", true, false); + UIWidgets::Tooltip("Allows the cursor on the pause menu to be over any slot\nSimilar to Rando and Spaceworld 97"); + UIWidgets::PaddedEnhancementCheckbox("Prevent Dropped Ocarina Inputs", "gDpadNoDropOcarinaInput", true, false); + UIWidgets::Tooltip("Prevent dropping inputs when playing the ocarina quickly"); + UIWidgets::PaddedEnhancementCheckbox("Answer Navi Prompt with L Button", "gNaviOnL", true, false); + UIWidgets::Tooltip("Speak to Navi with L but enter first-person camera with C-Up"); + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Gameplay")) + { + if (ImGui::BeginMenu("Time Savers")) + { + UIWidgets::PaddedEnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "", 1, false, false, true); + UIWidgets::PaddedEnhancementSliderInt("King Zora Speed: %dx", "##MWEEPSPEED", "gMweepSpeed", 1, 5, "", 1, false, false, true); + UIWidgets::EnhancementSliderInt("Biggoron Forge Time: %d days", "##FORGETIME", "gForgeTime", 0, 3, "", 3); + UIWidgets::Tooltip("Allows you to change the number of days it takes for Biggoron to forge the Biggoron Sword"); + UIWidgets::PaddedEnhancementSliderInt("Vine/Ladder Climb speed +%d", "##CLIMBSPEED", "gClimbSpeed", 0, 12, "", 0, false, false, true); + UIWidgets::PaddedEnhancementSliderInt("Block pushing speed +%d", "##BLOCKSPEED", "gFasterBlockPush", 0, 5, "", 0, false, false, true); + UIWidgets::PaddedEnhancementCheckbox("Faster Heavy Block Lift", "gFasterHeavyBlockLift", true, false); + UIWidgets::Tooltip("Speeds up lifting silver rocks and obelisks"); + UIWidgets::PaddedEnhancementCheckbox("No Forced Navi", "gNoForcedNavi", true, false); + UIWidgets::Tooltip("Prevent forced Navi conversations"); + UIWidgets::PaddedEnhancementCheckbox("No Skulltula Freeze", "gSkulltulaFreeze", true, false); + UIWidgets::Tooltip("Stops the game from freezing the player when picking up Gold Skulltulas"); + UIWidgets::PaddedEnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood", true, false); + UIWidgets::Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask"); + UIWidgets::PaddedEnhancementCheckbox("Fast Chests", "gFastChests", true, false); + UIWidgets::Tooltip("Kick open every chest"); + UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); + UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); + UIWidgets::PaddedEnhancementCheckbox("Better Owl", "gBetterOwl", true, false); + UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); + UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); + UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); + UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false); + UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); + UIWidgets::PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false); + UIWidgets::Tooltip("Allow Link to put items away without having to wait around"); + UIWidgets::PaddedEnhancementCheckbox("Instant Boomerang Recall", "gFastBoomerang", true, false); + UIWidgets::Tooltip("Instantly return the boomerang to Link by pressing its item button while it's in the air"); + UIWidgets::PaddedEnhancementCheckbox("Mask Select in Inventory", "gMaskSelect", true, false); + UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); + UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false); + UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" + "This doesn't work if the save was made in a grotto."); + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Difficulty Options")) + { + ImGui::Text("Damage Multiplier"); + UIWidgets::EnhancementCombobox("gDamageMul", powers, 9, 0); + UIWidgets::Tooltip( + "Modifies all sources of damage not affected by other sliders\n\ + 2x: Can survive all common attacks from the start of the game\n\ + 4x: Dies in 1 hit to any substantial attack from the start of the game\n\ + 8x: Can only survive trivial damage from the start of the game\n\ + 16x: Can survive all common attacks with max health without double defense\n\ + 32x: Can survive all common attacks with max health and double defense\n\ + 64x: Can survive trivial damage with max health without double defense\n\ + 128x: Can survive trivial damage with max health and double defense\n\ + 256x: Cannot survive damage" + ); + UIWidgets::PaddedText("Fall Damage Multiplier", true, false); + UIWidgets::EnhancementCombobox("gFallDamageMul", powers, 8, 0); + UIWidgets::Tooltip( + "Modifies all fall damage\n\ + 2x: Can survive all fall damage from the start of the game\n\ + 4x: Can only survive short fall damage from the start of the game\n\ + 8x: Cannot survive any fall damage from the start of the game\n\ + 16x: Can survive all fall damage with max health without double defense\n\ + 32x: Can survive all fall damage with max health and double defense\n\ + 64x: Can survive short fall damage with double defense\n\ + 128x: Cannot survive fall damage" + ); + UIWidgets::PaddedText("Void Damage Multiplier", true, false); + UIWidgets::EnhancementCombobox("gVoidDamageMul", powers, 7, 0); + UIWidgets::Tooltip( + "Modifies damage taken after falling into a void\n\ + 2x: Can survive void damage from the start of the game\n\ + 4x: Cannot survive void damage from the start of the game\n\ + 8x: Can survive void damage twice with max health without double defense\n\ + 16x: Can survive void damage with max health without double defense\n\ + 32x: Can survive void damage with max health and double defense\n\ + 64x: Cannot survive void damage" + ); + UIWidgets::PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); + UIWidgets::Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); + UIWidgets::PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false); + UIWidgets::Tooltip("Bombchus will sometimes drop in place of bombs"); + UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); + UIWidgets::Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); + UIWidgets::PaddedEnhancementCheckbox("Always Win Goron Pot", "gGoronPot", true, false); + UIWidgets::Tooltip("Always get the heart piece/purple rupee from the spinning Goron pot"); + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Potion Values")) + { + UIWidgets::EnhancementCheckbox("Change Red Potion Effect", "gRedPotionEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Red Potions"); + UIWidgets::EnhancementSliderInt("Red Potion Health: %d", "##REDPOTIONHEALTH", "gRedPotionHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Red Potions"); + UIWidgets::EnhancementCheckbox("Red Potion Percent Restore", "gRedPercentRestore"); + UIWidgets::Tooltip("Toggles from Red Potions restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Green Potion Effect", "gGreenPotionEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of mana restored by Green Potions"); + UIWidgets::EnhancementSliderInt("Green Potion Mana: %d", "##GREENPOTIONMANA", "gGreenPotionMana", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of mana restored by Green Potions, base max mana is 48, max upgraded mana is 96"); + UIWidgets::EnhancementCheckbox("Green Potion Percent Restore", "gGreenPercentRestore"); + UIWidgets::Tooltip("Toggles from Green Potions restoring a fixed amount of mana to a percent of the player's current max mana"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Blue Potion Effects", "gBluePotionEffects"); + UIWidgets::Tooltip("Enable the following changes to the amount of health and mana restored by Blue Potions"); + UIWidgets::EnhancementSliderInt("Blue Potion Health: %d", "##BLUEPOTIONHEALTH", "gBluePotionHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Blue Potions"); + UIWidgets::EnhancementCheckbox("Blue Potion Health Percent Restore", "gBlueHealthPercentRestore"); + UIWidgets::Tooltip("Toggles from Blue Potions restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementSliderInt("Blue Potion Mana: %d", "##BLUEPOTIONMANA", "gBluePotionMana", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of mana restored by Blue Potions, base max mana is 48, max upgraded mana is 96"); + UIWidgets::EnhancementCheckbox("Blue Potion Mana Percent Restore", "gBlueManaPercentRestore"); + UIWidgets::Tooltip("Toggles from Blue Potions restoring a fixed amount of mana to a percent of the player's current max mana"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Milk Effect", "gMilkEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Milk"); + UIWidgets::EnhancementSliderInt("Milk Health: %d", "##MILKHEALTH", "gMilkHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Milk"); + UIWidgets::EnhancementCheckbox("Milk Percent Restore", "gMilkPercentRestore"); + UIWidgets::Tooltip("Toggles from Milk restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Separate Half Milk Effect", "gSeparateHalfMilkEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Half Milk\nIf this is disabled, Half Milk will behave the same as Full Milk."); + UIWidgets::EnhancementSliderInt("Half Milk Health: %d", "##HALFMILKHEALTH", "gHalfMilkHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Half Milk"); + UIWidgets::EnhancementCheckbox("Half Milk Percent Restore", "gHalfMilkPercentRestore"); + UIWidgets::Tooltip("Toggles from Half Milk restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Fairy Effect", "gFairyEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Fairies"); + UIWidgets::EnhancementSliderInt("Fairy: %d", "##FAIRYHEALTH", "gFairyHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Fairies"); + UIWidgets::EnhancementCheckbox("Fairy Percent Restore", "gFairyPercentRestore"); + UIWidgets::Tooltip("Toggles from Fairies restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::Separator(); + + UIWidgets::EnhancementCheckbox("Change Fairy Revive Effect", "gFairyReviveEffect"); + UIWidgets::Tooltip("Enable the following changes to the amount of health restored by Fairy Revivals"); + UIWidgets::EnhancementSliderInt("Fairy Revival: %d", "##FAIRYREVIVEHEALTH", "gFairyReviveHealth", 1, 100, "", 0, true); + UIWidgets::Tooltip("Changes the amount of health restored by Fairy Revivals"); + UIWidgets::EnhancementCheckbox("Fairy Revive Percent Restore", "gFairyRevivePercentRestore"); + UIWidgets::Tooltip("Toggles from Fairy Revivals restoring a fixed amount of health to a percent of the player's current max health"); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Fishing")) { + UIWidgets::EnhancementCheckbox("Instant Fishing", "gInstantFishing"); + UIWidgets::Tooltip("All fish will be caught instantly"); + UIWidgets::PaddedEnhancementCheckbox("Guarantee Bite", "gGuaranteeFishingBite", true, false); + UIWidgets::Tooltip("When a line is stable, guarantee bite. Otherwise use default logic"); + UIWidgets::PaddedEnhancementSliderInt("Child Minimum Weight: %d", "##cMinimumWeight", "gChildMinimumWeightFish", 6, 10, "", 10, false, true, false); + UIWidgets::Tooltip("The minimum weight for the unique fishing reward as a child"); + UIWidgets::PaddedEnhancementSliderInt("Adult Minimum Weight: %d", "##aMinimumWeight", "gAdultMinimumWeightFish", 8, 13, "", 13, false, true, false); + UIWidgets::Tooltip("The minimum weight for the unique fishing reward as an adult"); + ImGui::EndMenu(); + } + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Reduced Clutter")) + { + UIWidgets::EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm"); + UIWidgets::Tooltip("Disable the low HP beeping sound"); + UIWidgets::PaddedEnhancementCheckbox("Minimal UI", "gMinimalUI", true, false); + UIWidgets::Tooltip("Hides most of the UI when not needed\nNote: Doesn't activate until after loading a new scene"); + UIWidgets::PaddedEnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio", true, false); + UIWidgets::Tooltip("Disables the voice audio when Navi calls you"); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + UIWidgets::EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony"); + UIWidgets::Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble"); + UIWidgets::PaddedEnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots", true, false); + UIWidgets::Tooltip("Allows equipping the tunic and boots to c-buttons"); + UIWidgets::PaddedEnhancementCheckbox("Equipment Toggle", "gEquipmentCanBeRemoved", true, false); + UIWidgets::Tooltip("Allows equipment to be removed by toggling it off on\nthe equipment subscreen."); + UIWidgets::PaddedEnhancementCheckbox("Link's Cow in Both Time Periods", "gCowOfTime", true, false); + UIWidgets::Tooltip("Allows the Lon Lon Ranch obstacle course reward to be shared across time periods"); + UIWidgets::PaddedEnhancementCheckbox("Enable visible guard vision", "gGuardVision", true, false); + UIWidgets::PaddedEnhancementCheckbox("Enable passage of time on file select", "gTimeFlowFileSelect", true, false); + UIWidgets::PaddedEnhancementCheckbox("Count Golden Skulltulas", "gInjectSkulltulaCount", true, false); + UIWidgets::Tooltip("Injects Golden Skulltula total count in pickup messages"); + UIWidgets::PaddedEnhancementCheckbox("Pull grave during the day", "gDayGravePull", true, false); + UIWidgets::Tooltip("Allows graves to be pulled when child during the day"); + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Graphics")) + { + if (ImGui::BeginMenu("Animated Link in Pause Menu")) { + ImGui::Text("Rotation"); + UIWidgets::EnhancementRadioButton("Disabled", "gPauseLiveLinkRotation", 0); + UIWidgets::EnhancementRadioButton("Rotate Link with D-pad", "gPauseLiveLinkRotation", 1); + UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the D-pad\nUse D-pad Up or D-pad Down to reset Link's rotation"); + UIWidgets::EnhancementRadioButton("Rotate Link with C-buttons", "gPauseLiveLinkRotation", 2); + UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the C-buttons\nUse C-Up or C-Down to reset Link's rotation"); + UIWidgets::EnhancementRadioButton("Rotate Link with Right Stick", "gPauseLiveLinkRotation", 3); + UIWidgets::Tooltip("Allow you to rotate Link on the Equipment menu with the Right Stick\nYou can zoom in by pointing up and reset Link's rotation by pointing down"); + if (CVar_GetS32("gPauseLiveLinkRotation", 0) != 0) { + UIWidgets::EnhancementSliderInt("Rotation Speed: %d", "##MinRotationSpeed", "gPauseLiveLinkRotationSpeed", 1, 20, ""); + } + UIWidgets::PaddedSeparator(); + ImGui::Text("Static loop"); + UIWidgets::EnhancementRadioButton("Disabled", "gPauseLiveLink", 0); + UIWidgets::EnhancementRadioButton("Idle (standing)", "gPauseLiveLink", 1); + UIWidgets::EnhancementRadioButton("Idle (look around)", "gPauseLiveLink", 2); + UIWidgets::EnhancementRadioButton("Idle (belt)", "gPauseLiveLink", 3); + UIWidgets::EnhancementRadioButton("Idle (shield)", "gPauseLiveLink", 4); + UIWidgets::EnhancementRadioButton("Idle (test sword)", "gPauseLiveLink", 5); + UIWidgets::EnhancementRadioButton("Idle (yawn)", "gPauseLiveLink", 6); + UIWidgets::EnhancementRadioButton("Battle Stance", "gPauseLiveLink", 7); + UIWidgets::EnhancementRadioButton("Walking (no shield)", "gPauseLiveLink", 8); + UIWidgets::EnhancementRadioButton("Walking (holding shield)", "gPauseLiveLink", 9); + UIWidgets::EnhancementRadioButton("Running (no shield)", "gPauseLiveLink", 10); + UIWidgets::EnhancementRadioButton("Running (holding shield)", "gPauseLiveLink", 11); + UIWidgets::EnhancementRadioButton("Hand on hip", "gPauseLiveLink", 12); + UIWidgets::EnhancementRadioButton("Spin attack charge", "gPauseLiveLink", 13); + UIWidgets::EnhancementRadioButton("Look at hand", "gPauseLiveLink", 14); + UIWidgets::PaddedSeparator(); + ImGui::Text("Randomize"); + UIWidgets::EnhancementRadioButton("Random", "gPauseLiveLink", 15); + UIWidgets::Tooltip("Randomize the animation played each time you open the menu"); + UIWidgets::EnhancementRadioButton("Random cycle", "gPauseLiveLink", 16); + UIWidgets::Tooltip("Randomize the animation played on the menu after a certain time"); + UIWidgets::EnhancementRadioButton("Random cycle (Idle)", "gPauseLiveLink", 17); + UIWidgets::Tooltip("Randomize the animation played on the menu after a certain time (Idle animations only)"); + if (CVar_GetS32("gPauseLiveLink", 0) >= 16) { + UIWidgets::EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, "", 0, true); + } + + ImGui::EndMenu(); + } + UIWidgets::PaddedEnhancementCheckbox("N64 Mode", "gN64Mode", true, false); + UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); + UIWidgets::PaddedEnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops", true, false); + UIWidgets::Tooltip("Change most 2D items and projectiles on the overworld to their 3D versions"); + UIWidgets::PaddedEnhancementCheckbox("Disable Black Bar Letterboxes", "gDisableBlackBars", true, false); + UIWidgets::Tooltip("Disables Black Bar Letterboxes during cutscenes and Z-targeting\nNote: there may be minor visual glitches that were covered up by the black bars\nPlease disable this setting before reporting a bug"); + UIWidgets::PaddedEnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon", true, false); + UIWidgets::Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have"); + UIWidgets::PaddedEnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon", true, false); + UIWidgets::Tooltip("Always shows dungeon entrance icons on the minimap"); + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Fixes")) + { + UIWidgets::EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR"); + UIWidgets::Tooltip("Makes the L and R buttons in the pause menu the same color"); + UIWidgets::PaddedEnhancementCheckbox("Fix L&Z Page switch in Pause menu", "gNGCKaleidoSwitcher", true, false); + UIWidgets::Tooltip("Makes L and R switch pages like on the GameCube\nZ opens the Debug Menu instead"); + UIWidgets::PaddedEnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon", true, false); + UIWidgets::Tooltip("Removes the dungeon entrance icon on the top-left corner of the screen when no dungeon is present on the current map"); + UIWidgets::PaddedEnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle", true, false); + UIWidgets::Tooltip("Re-enables the two-handed idle animation, a seemingly finished animation that was disabled on accident in the original game"); + UIWidgets::PaddedEnhancementCheckbox("Fix the Gravedigging Tour Glitch", "gGravediggingTourFix", true, false); + UIWidgets::Tooltip("Fixes a bug where the Gravedigging Tour Heart Piece disappears if the area reloads"); + UIWidgets::PaddedEnhancementCheckbox("Fix Deku Nut upgrade", "gDekuNutUpgradeFix", true, false); + UIWidgets::Tooltip("Prevents the Forest Stage Deku Nut upgrade from becoming unobtainable after receiving the Poacher's Saw"); + UIWidgets::PaddedEnhancementCheckbox("Fix Navi text HUD position", "gNaviTextFix", true, false); + UIWidgets::Tooltip("Correctly centers the Navi text prompt on the HUD's C-Up button"); + UIWidgets::PaddedEnhancementCheckbox("Fix Anubis fireballs", "gAnubisFix", true, false); + UIWidgets::Tooltip("Make Anubis fireballs do fire damage when reflected back at them with the Mirror Shield"); + UIWidgets::PaddedEnhancementCheckbox("Fix Megaton Hammer crouch stab", "gCrouchStabHammerFix", true, false); + UIWidgets::Tooltip("Make the Megaton Hammer's crouch stab able to destroy rocks without first swinging it normally"); + if (CVar_GetS32("gCrouchStabHammerFix", 0) == 0) { + CVar_SetS32("gCrouchStabFix", 0); + } else { + UIWidgets::PaddedEnhancementCheckbox("Remove power crouch stab", "gCrouchStabFix", true, false); + UIWidgets::Tooltip("Make crouch stabbing always do the same damage as a regular slash"); + } + + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + + if (ImGui::BeginMenu("Restoration")) + { + UIWidgets::EnhancementCheckbox("Red Ganon blood", "gRedGanonBlood"); + UIWidgets::Tooltip("Restore the original red blood from NTSC 1.0/1.1. Disable for green blood"); + UIWidgets::PaddedEnhancementCheckbox("Fish while hovering", "gHoverFishing", true, false); + UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows casting the Fishing Rod while using the Hover Boots"); + UIWidgets::PaddedEnhancementCheckbox("N64 Weird Frames", "gN64WeirdFrames", true, false); + UIWidgets::Tooltip("Restores N64 Weird Frames allowing weirdshots to behave the same as N64"); + UIWidgets::PaddedEnhancementCheckbox("Bombchus out of bounds", "gBombchusOOB", true, false); + UIWidgets::Tooltip("Allows bombchus to explode out of bounds\nSimilar to GameCube and Wii VC"); + UIWidgets::PaddedEnhancementCheckbox("Restore old Gold Skulltula cutscene", "gGsCutscene", true, false); + + ImGui::EndMenu(); + } + + UIWidgets::PaddedEnhancementCheckbox("Autosave", "gAutosave", true, false); + UIWidgets::Tooltip("Automatically save the game every time a new area is entered or item is obtained\n" + "To disable saving when obtaining an item, manually set gAutosaveAllItems and gAutosaveMajorItems to 0\n" + "gAutosaveAllItems takes priority over gAutosaveMajorItems if both are set to 1\n" + "gAutosaveMajorItems excludes rupees and health/magic/ammo refills (but includes bombchus)"); + + UIWidgets::Spacer(0); + + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + static ImVec2 buttonSize(200.0f, 0.0f); + if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVar_GetS32("gCosmeticsEditorEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gCosmeticsEditorEnabled", 0); + CVar_SetS32("gCosmeticsEditorEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Cosmetics Editor", CVar_GetS32("gCosmeticsEditorEnabled", 0)); + } + ImGui::PopStyleVar(3); + ImGui::PopStyleColor(1); + + EXPERIMENTAL(); + + const char* fps_cvar = "gInterpolationFPS"; + { + #if defined(__SWITCH__) || defined(__WIIU__) + int minFps = 20; + int maxFps = 60; + #else + int minFps = 20; + int maxFps = 360; + #endif + + int val = CVar_GetS32(fps_cvar, minFps); + val = fmax(fmin(val, maxFps), 20); + + #ifdef __WIIU__ + // only support divisors of 60 on the Wii U + val = 60 / (60 / val); + #endif + + int fps = val; + + if (fps == 20) + { + ImGui::Text("Frame interpolation: Off"); + } + else + { + ImGui::Text("Frame interpolation: %d FPS", fps); + } + + std::string MinusBTNFPSI = " - ##FPSInterpolation"; + std::string PlusBTNFPSI = " + ##FPSInterpolation"; + if (ImGui::Button(MinusBTNFPSI.c_str())) { + #ifdef __WIIU__ + if (val >= 60) val = 30; + else val = 20; + #else + val--; + #endif + CVar_SetS32(fps_cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + #ifdef __WIIU__ + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2); + #else + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); + #endif + if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp)) + { + #ifdef __WIIU__ + // only support divisors of 60 on the Wii U + val = 60 / (60 / val); + #endif + if (val > 360) + { + val = 360; + } + else if (val < 20) + { + val = 20; + } + + CVar_SetS32(fps_cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::PopItemWidth(); + UIWidgets::Tooltip("Interpolate extra frames to get smoother graphics\n" + "Set to match your monitor's refresh rate, or a divisor of it\n" + "A higher target FPS than your monitor's refresh rate will just waste resources, " + "and might give a worse result.\n" + "For consistent input lag, set this value and your monitor's refresh rate to a multiple of 20\n" + "Ctrl+Click for keyboard input"); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNFPSI.c_str())) { + #ifdef __WIIU__ + if (val <= 20) val = 30; + else val = 60; + #else + val++; + #endif + CVar_SetS32(fps_cvar, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + if (SohImGui::WindowBackend() == SohImGui::Backend::DX11) + { + UIWidgets::Spacer(0); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f)); + if (ImGui::Button("Match Refresh Rate")) + { + int hz = roundf(SohImGui::WindowRefreshRate()); + if (hz >= 20 && hz <= 360) + { + CVar_SetS32(fps_cvar, hz); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + ImGui::PopStyleVar(1); + UIWidgets::Spacer(0); + } + UIWidgets::EnhancementCheckbox("Disable LOD", "gDisableLOD"); + UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); + UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false); + UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); + if (CVar_GetS32("gDisableDrawDistance", 0) == 0) { + CVar_SetS32("gDisableKokiriDrawDistance", 0); + } else if (CVar_GetS32("gDisableDrawDistance", 0) == 1) { + UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); + UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); + } + UIWidgets::PaddedEnhancementCheckbox("Skip Text", "gSkipText", true, false); + UIWidgets::Tooltip("Holding down B skips text\nKnown to cause a cutscene softlock in Water Temple\nSoftlock can be fixed by pressing D-Right in Debug mode"); + UIWidgets::PaddedEnhancementCheckbox("Free Camera", "gFreeCamera", true, false); + UIWidgets::Tooltip("Enables 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."); + + #ifdef __SWITCH__ + UIWidgets::Spacer(0); + int slot = CVar_GetS32("gSwitchPerfMode", (int)Ship::SwitchProfiles::STOCK); + ImGui::Text("Switch performance mode"); + if (ImGui::BeginCombo("##perf", SWITCH_CPU_PROFILES[slot])) { + for (int sId = 0; sId <= Ship::SwitchProfiles::POWERSAVINGM3; sId++) { + if (ImGui::Selectable(SWITCH_CPU_PROFILES[sId], sId == slot)) { + SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]); + CVar_SetS32("gSwitchPerfMode", sId); + Ship::Switch::ApplyOverclock(); + SohImGui::RequestCvarSaveOnNextTick(); + } + + } + ImGui::EndCombo(); + } + #endif + + ImGui::EndMenu(); + } + + ImGui::SetCursorPosY(0.0f); + + if (ImGui::BeginMenu("Cheats")) + { + if (ImGui::BeginMenu("Infinite...")) { + UIWidgets::EnhancementCheckbox("Money", "gInfiniteMoney"); + UIWidgets::PaddedEnhancementCheckbox("Health", "gInfiniteHealth", true, false); + UIWidgets::PaddedEnhancementCheckbox("Ammo", "gInfiniteAmmo", true, false); + UIWidgets::PaddedEnhancementCheckbox("Magic", "gInfiniteMagic", true, false); + UIWidgets::PaddedEnhancementCheckbox("Nayru's Love", "gInfiniteNayru", true, false); + UIWidgets::PaddedEnhancementCheckbox("Epona Boost", "gInfiniteEpona", true, false); + + ImGui::EndMenu(); + } + + UIWidgets::PaddedEnhancementCheckbox("No Clip", "gNoClip", true, false); + UIWidgets::Tooltip("Allows you to walk through walls"); + UIWidgets::PaddedEnhancementCheckbox("Climb Everything", "gClimbEverything", true, false); + UIWidgets::Tooltip("Makes every surface in the game climbable"); + UIWidgets::PaddedEnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL", true, false); + UIWidgets::Tooltip("Holding L makes you float into the air"); + UIWidgets::PaddedEnhancementCheckbox("Super Tunic", "gSuperTunic", true, false); + UIWidgets::Tooltip("Makes every tunic have the effects of every other tunic"); + UIWidgets::PaddedEnhancementCheckbox("Easy ISG", "gEzISG", true, false); + UIWidgets::Tooltip("Passive Infinite Sword Glitch\nIt makes your sword's swing effect and hitbox stay active indefinitely"); + UIWidgets::PaddedEnhancementCheckbox("Unrestricted Items", "gNoRestrictItems", true, false); + UIWidgets::Tooltip("Allows you to use any item at any location"); + UIWidgets::PaddedEnhancementCheckbox("Freeze Time", "gFreezeTime", true, false); + UIWidgets::Tooltip("Freezes the time of day"); + UIWidgets::PaddedEnhancementCheckbox("Drops Don't Despawn", "gDropsDontDie", true, false); + UIWidgets::Tooltip("Drops from enemies, grass, etc. don't disappear after a set amount of time"); + UIWidgets::PaddedEnhancementCheckbox("Fireproof Deku Shield", "gFireproofDekuShield", true, false); + UIWidgets::Tooltip("Prevents the Deku Shield from burning on contact with fire"); + UIWidgets::PaddedEnhancementCheckbox("Shield with Two-Handed Weapons", "gShieldTwoHanded", true, false); + UIWidgets::Tooltip("This allows you to put up your shield with any two-handed weapon in hand except for Deku Sticks"); + UIWidgets::PaddedEnhancementCheckbox("Time Sync", "gTimeSync", true, false); + UIWidgets::Tooltip("This syncs the ingame time with the real world time"); + + { + static int32_t betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); + static int32_t lastBetaQuestEnabled = betaQuestEnabled; + static int32_t betaQuestWorld = CVar_GetS32("gBetaQuestWorld", 0xFFEF); + static int32_t lastBetaQuestWorld = betaQuestWorld; + + if (!isBetaQuestEnabled) { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); + } + + UIWidgets::PaddedEnhancementCheckbox("Enable Beta Quest", "gEnableBetaQuest", true, false); + UIWidgets::Tooltip("Turns on OoT Beta Quest. *WARNING* This will reset your game."); + betaQuestEnabled = CVar_GetS32("gEnableBetaQuest", 0); + if (betaQuestEnabled) { + if (betaQuestEnabled != lastBetaQuestEnabled) { + betaQuestWorld = 0; + } + + ImGui::Text("Beta Quest World: %d", betaQuestWorld); + + if (ImGui::Button(" - ##BetaQuest")) { + betaQuestWorld--; + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + + ImGui::SliderInt("##BetaQuest", &betaQuestWorld, 0, 8, "", ImGuiSliderFlags_AlwaysClamp); + UIWidgets::Tooltip("Set the Beta Quest world to explore. *WARNING* Changing this will reset your game.\nCtrl+Click to type in a value."); + + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(" + ##BetaQuest")) { + betaQuestWorld++; + } + + if (betaQuestWorld > 8) { + betaQuestWorld = 8; + } + else if (betaQuestWorld < 0) { + betaQuestWorld = 0; + } + } + else { + lastBetaQuestWorld = betaQuestWorld = 0xFFEF; + CVar_SetS32("gBetaQuestWorld", betaQuestWorld); + } + if (betaQuestEnabled != lastBetaQuestEnabled || betaQuestWorld != lastBetaQuestWorld) + { + // Reset the game if the beta quest state or world changed because beta quest happens on redirecting the title screen cutscene. + lastBetaQuestEnabled = betaQuestEnabled; + lastBetaQuestWorld = betaQuestWorld; + CVar_SetS32("gEnableBetaQuest", betaQuestEnabled); + CVar_SetS32("gBetaQuestWorld", betaQuestWorld); + + SohImGui::DispatchConsoleCommand("reset"); + + SohImGui::RequestCvarSaveOnNextTick(); + } + + if (!isBetaQuestEnabled) { + ImGui::PopItemFlag(); + ImGui::PopStyleVar(1); + } + } + + ImGui::EndMenu(); + } + + ImGui::SetCursorPosY(0.0f); + + if (ImGui::BeginMenu("Developer Tools")) + { + UIWidgets::EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled"); + UIWidgets::Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right, and open the debug menu with L on the pause screen"); + UIWidgets::PaddedEnhancementCheckbox("OoT Skulltula Debug", "gSkulltulaDebugEnabled", true, false); + UIWidgets::Tooltip("Enables Skulltula Debug, when moving the cursor in the menu above various map icons (boss key, compass, map screen locations, etc) will set the GS bits in that area.\nUSE WITH CAUTION AS IT DOES NOT UPDATE THE GS COUNT."); + UIWidgets::PaddedEnhancementCheckbox("Fast File Select", "gSkipLogoTitle", true, false); + UIWidgets::Tooltip("Load the game to the selected menu or file\n\"Zelda Map Select\" require debug mode else you will fallback to File choose menu\nUsing a file number that don't have save will create a save file only if you toggle on \"Create a new save if none ?\" else it will bring you to the File choose menu"); + if (CVar_GetS32("gSkipLogoTitle", 0)) { + const char* FastFileSelect[5] = { + "File N.1", + "File N.2", + "File N.3", + "File select", + "Zelda Map Select (require OoT Debug Mode)" + }; + ImGui::Text("Loading :"); + UIWidgets::EnhancementCombobox("gSaveFileID", FastFileSelect, 5, 0); + UIWidgets::PaddedEnhancementCheckbox("Create a new save if none", "gCreateNewSave", true, false); + UIWidgets::Tooltip("Enable the creation of a new save file if none exist in the File number selected\nNo file name will be assigned please do in Save editor once you see the first text else your save file name will be named \"00000000\"\nIf disabled you will fall back in File select menu"); + }; + UIWidgets::PaddedSeparator(); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0,0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + static ImVec2 buttonSize(160.0f, 0.0f); + if (ImGui::Button(GetWindowButtonText("Stats", CVar_GetS32("gStatsEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gStatsEnabled", 0); + CVar_SetS32("gStatsEnabled", !currentValue); + SohImGui::ToggleStatisticsWindow(true); + SohImGui::RequestCvarSaveOnNextTick(); + } + UIWidgets::Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on"); + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Console", CVar_GetS32("gConsoleEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gConsoleEnabled", 0); + CVar_SetS32("gConsoleEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::ToggleConsoleWindow(!currentValue); + } + UIWidgets::Tooltip("Enables the console window, allowing you to input commands, type help for some examples"); + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Save Editor", CVar_GetS32("gSaveEditorEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gSaveEditorEnabled", 0); + CVar_SetS32("gSaveEditorEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Save Editor", CVar_GetS32("gSaveEditorEnabled", 0)); + } + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Collision Viewer", CVar_GetS32("gCollisionViewerEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gCollisionViewerEnabled", 0); + CVar_SetS32("gCollisionViewerEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Collision Viewer", CVar_GetS32("gCollisionViewerEnabled", 0)); + } + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Actor Viewer", CVar_GetS32("gActorViewerEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gActorViewerEnabled", 0); + CVar_SetS32("gActorViewerEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Actor Viewer", CVar_GetS32("gActorViewerEnabled", 0)); + } + ImGui::PopStyleVar(3); + ImGui::PopStyleColor(1); + + ImGui::EndMenu(); + } + + ImGui::SetCursorPosY(0.0f); + + if (ImGui::BeginMenu("Randomizer")) + { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12.0f, 6.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f)); + static ImVec2 buttonSize(200.0f, 0.0f); + if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVar_GetS32("gRandomizerSettingsEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gRandomizerSettingsEnabled", 0); + CVar_SetS32("gRandomizerSettingsEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Randomizer Settings", CVar_GetS32("gRandomizerSettingsEnabled", 0)); + } + UIWidgets::Spacer(0); + if (ImGui::Button(GetWindowButtonText("Item Tracker", CVar_GetS32("gItemTrackerEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gItemTrackerEnabled", 0); + CVar_SetS32("gItemTrackerEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Item Tracker", CVar_GetS32("gItemTrackerEnabled", 0)); + } + ImGui::PopStyleVar(3); + ImGui::PopStyleColor(1); + + ImGui::EndMenu(); + } + } +} diff --git a/soh/soh/GameMenuBar.hpp b/soh/soh/GameMenuBar.hpp new file mode 100644 index 000000000..07280707b --- /dev/null +++ b/soh/soh/GameMenuBar.hpp @@ -0,0 +1,27 @@ +// +// GameMenuBar.hpp +// soh +// +// Created by David Chavez on 24.08.22. +// + +#ifndef GameMenuBar_hpp +#define GameMenuBar_hpp + +#include + +#ifdef __cplusplus +extern "C" { +#endif + void enableBetaQuest(); + void disableBetaQuest(); +#ifdef __cplusplus +} +#endif + +namespace GameMenuBar { + void SetupHooks(); + void Draw(); +} + +#endif /* GameMenuBar_hpp */ diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 66aa22868..d7ae15bcc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -5,45 +5,45 @@ #include #include -#include "ResourceMgr.h" -#include "DisplayList.h" -#include "PlayerAnimation.h" -#include "Skeleton.h" -#include "Window.h" +#include +#include +#include +#include +#include #include "z64animation.h" #include "z64bgcheck.h" #include "Enhancements/gameconsole.h" #include -#include +#include #ifdef _WIN32 #include #else #include #endif -#include -#include -#include -#include "Lib/stb/stb_image.h" +#include +#include +#include +#include #define DRMP3_IMPLEMENTATION -#include "Lib/dr_libs/mp3.h" +#include #define DRWAV_IMPLEMENTATION -#include "Lib/dr_libs/wav.h" -#include "AudioPlayer.h" +#include +#include #include "Enhancements/controls/GameControlEditor.h" #include "Enhancements/cosmetics/CosmeticsEditor.h" #include "Enhancements/debugconsole.h" #include "Enhancements/debugger/debugger.h" -#include +#include "Enhancements/randomizer/randomizer_item_tracker.h" #include "Enhancements/n64_weird_frame_data.inc" -#include "soh/frame_interpolation.h" +#include "frame_interpolation.h" #include "variables.h" #include "macros.h" #include -#include "Hooks.h" -#include +#include +#include "Enhancements/custom-message/CustomMessageManager.h" -#include "Lib/Fast3D/gfx_pc.h" -#include "Lib/Fast3D/gfx_rendering_api.h" +#include +#include #ifdef __APPLE__ #include @@ -52,15 +52,16 @@ #endif #ifdef __SWITCH__ -#include "SwitchImpl.h" +#include #elif defined(__WIIU__) -#include "WiiUImpl.h" +#include #endif -#include -#include +#include +#include "Enhancements/custom-message/CustomMessageTypes.h" #include -#include +#include "Enhancements/item-tables/ItemTableManager.h" +#include "GameMenuBar.hpp" OTRGlobals* OTRGlobals::Instance; SaveManager* SaveManager::Instance; @@ -321,6 +322,9 @@ extern "C" void InitOTR() { #elif defined(__WIIU__) Ship::WiiU::Init(); #endif + SohImGui::AddSetupHooksDelegate(GameMenuBar::SetupHooks); + SohImGui::RegisterMenuDrawMethod(GameMenuBar::Draw); + OTRGlobals::Instance = new OTRGlobals(); SaveManager::Instance = new SaveManager(); CustomMessageManager::Instance = new CustomMessageManager(); diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 4858c41b2..658044ed8 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -7,7 +7,7 @@ #include #ifdef __cplusplus -#include "Window.h" +#include #include "Enhancements/savestates.h" #include "Enhancements/randomizer/randomizer.h" diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 9bf99ac12..d02584413 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -4,7 +4,7 @@ #include "z64.h" #include "functions.h" #include "macros.h" -#include "Cvar.h" +#include #define NOGDI // avoid various windows defines that conflict with things in z64.h #include "spdlog/spdlog.h" @@ -1599,4 +1599,4 @@ extern "C" void Save_DeleteFile(int fileNum) { extern "C" bool Save_Exist(int fileNum) { return SaveManager::Instance->SaveFile_Exist(fileNum); -} \ No newline at end of file +} diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 06a382baa..1acbcbfc9 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -23,7 +23,7 @@ typedef struct { #include #include -#include "Lib/nlohmann/json.hpp" +#include class SaveManager { public: diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp new file mode 100644 index 000000000..d61ddc0f9 --- /dev/null +++ b/soh/soh/UIWidgets.cpp @@ -0,0 +1,523 @@ +// +// UIWidgets.cpp +// soh +// +// Created by David Chavez on 25.08.22. +// + +#include "UIWidgets.hpp" + +#define IMGUI_DEFINE_MATH_OPERATORS +#include +#include +#include + +#include + +namespace UIWidgets { + + // MARK: - Layout Helper + + // Automatically adds newlines to break up text longer than a specified number of characters + // Manually included newlines will still be respected and reset the line length + // If line is midword when it hits the limit, text should break at the last encountered space + char* WrappedText(const char* text, unsigned int charactersPerLine) { + std::string newText(text); + const size_t tipLength = newText.length(); + int lastSpace = -1; + size_t currentLineLength = 0; + for (unsigned int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) { + if (newText[currentCharacter] == '\n') { + currentLineLength = 0; + lastSpace = -1; + continue; + } else if (newText[currentCharacter] == ' ') { + lastSpace = currentCharacter; + } + + if ((currentLineLength >= charactersPerLine) && (lastSpace >= 0)) { + newText[lastSpace] = '\n'; + currentLineLength = currentCharacter - lastSpace - 1; + lastSpace = -1; + } + currentLineLength++; + } + + return strdup(newText.c_str()); + } + + char* WrappedText(const std::string& text, unsigned int charactersPerLine) { + return WrappedText(text.c_str(), charactersPerLine); + } + + void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha) + { + Color_RGBA8 defaultColors; + defaultColors.r = default_colors.x; + defaultColors.g = default_colors.y; + defaultColors.b = default_colors.z; + defaultColors.a = default_colors.w; + + Color_RGBA8 cvarColor = CVar_GetRGBA(cvarname, defaultColors); + + ColorArray.x = cvarColor.r / 255.0; + ColorArray.y = cvarColor.g / 255.0; + ColorArray.z = cvarColor.b / 255.0; + ColorArray.w = cvarColor.a / 255.0; + } + + void SetLastItemHoverText(const std::string& text) { + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("%s", WrappedText(text, 60)); + ImGui::EndTooltip(); + } + } + + // Adds a "?" next to the previous ImGui item with a custom tooltip + void InsertHelpHoverText(const std::string& text) { + ImGui::SameLine(); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::Text("%s", WrappedText(text, 60)); + ImGui::EndTooltip(); + } + } + + + // MARK: - UI Elements + + void Tooltip(const char* text) { + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", WrappedText(text)); + } + } + + void Spacer(float height) { + ImGui::Dummy(ImVec2(0.0f, height)); + } + + void PaddedSeparator(bool padTop, bool padBottom, float extraVerticalTopPadding, float extraVerticalBottomPadding) { + if (padTop) + Spacer(0); + + ImGui::Separator(); + + if (padBottom) + Spacer(0); + } + + void RenderCross(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) { + float thickness = ImMax(sz / 5.0f, 1.0f); + sz -= thickness * 0.5f; + pos += ImVec2(thickness * 0.25f, thickness * 0.25f); + + draw_list->PathLineTo(ImVec2(pos.x, pos.y)); + draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y + sz)); + draw_list->PathStroke(col, 0, thickness); + + draw_list->PathLineTo(ImVec2(pos.x + sz, pos.y)); + draw_list->PathLineTo(ImVec2(pos.x, pos.y + sz)); + draw_list->PathStroke(col, 0, thickness); + } + + bool CustomCheckbox(const char* label, bool* v, bool disabled, CheckboxGraphics disabledGraphic) { + ImGuiWindow* window = ImGui::GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + const ImGuiID id = window->GetID(label); + const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); + + const float square_sz = ImGui::GetFrameHeight(); + const ImVec2 pos = window->DC.CursorPos; + const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); + ImGui::ItemSize(total_bb, style.FramePadding.y); + if (!ImGui::ItemAdd(total_bb, id)) { + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); + return false; + } + + bool hovered, held; + bool pressed = ImGui::ButtonBehavior(total_bb, id, &hovered, &held); + if (pressed) { + *v = !(*v); + ImGui::MarkItemEdited(id); + } + + const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); + ImGui::RenderNavHighlight(total_bb, id); + ImGui::RenderFrame(check_bb.Min, check_bb.Max, ImGui::GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); + ImU32 check_col = ImGui::GetColorU32(ImGuiCol_CheckMark); + ImU32 cross_col = ImGui::GetColorU32(ImVec4(0.50f, 0.50f, 0.50f, 1.00f)); + bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0; + if (mixed_value) { + // Undocumented tristate/mixed/indeterminate checkbox (#2644) + // This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox) + ImVec2 pad(ImMax(1.0f, IM_FLOOR(square_sz / 3.6f)), ImMax(1.0f, IM_FLOOR(square_sz / 3.6f))); + window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); + } else if ((!disabled && *v) || (disabled && disabledGraphic == CheckboxGraphics::Checkmark)) { + const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); + ImGui::RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); + } else if (disabled && disabledGraphic == CheckboxGraphics::Cross) { + const float pad = ImMax(1.0f, IM_FLOOR(square_sz / 6.0f)); + RenderCross(window->DrawList, check_bb.Min + ImVec2(pad, pad), cross_col, square_sz - pad * 2.0f); + } + + ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); + if (g.LogEnabled) + ImGui::LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); + if (label_size.x > 0.0f) + ImGui::RenderText(label_pos, label); + + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); + return pressed; + } + + void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic) { + if (disabled) { + ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f); + } + bool val = (bool)CVar_GetS32(cvarName, 0); + if (CustomCheckbox(text, &val, disabled, disabledGraphic)) { + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + if (disabled) { + ImGui::PopStyleVar(1); + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(disabledTooltipText, "") != 0) { + ImGui::SetTooltip("%s", disabledTooltipText); + } + ImGui::PopItemFlag(); + } + } + + void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop, bool padBottom, bool disabled, const char* disabledTooltipText, CheckboxGraphics disabledGraphic) { + if (padTop) Spacer(0); + + EnhancementCheckbox(text, cvarName, disabled, disabledTooltipText, disabledGraphic); + + if (padBottom) Spacer(0); + } + + void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue) { + if (ImGui::BeginCombo(name.c_str(), items[static_cast(CVar_GetS32(cvarName, defaultValue))].c_str())) { + for (int settingIndex = 0; settingIndex < (int) items.size(); settingIndex++) { + if (ImGui::Selectable(items[settingIndex].c_str())) { + CVar_SetS32(cvarName, settingIndex); + SohImGui::RequestCvarSaveOnNextTick(); + + } + } + ImGui::EndCombo(); + } + } + + void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue) { + if (FirstTimeValue <= 0) { + FirstTimeValue = 0; + } + uint8_t selected = CVar_GetS32(name, FirstTimeValue); + uint8_t DefaultValue = selected; + std::string comboName = std::string("##") + std::string(name); + if (ImGui::BeginCombo(comboName.c_str(), ComboArray[DefaultValue])) { + for (uint8_t i = 0; i < arraySize; i++) { + if (strlen(ComboArray[i]) > 1) { + if (ImGui::Selectable(ComboArray[i], i == selected)) { + CVar_SetS32(name, i); + selected = i; + SohImGui::RequestCvarSaveOnNextTick(); + } + } + } + ImGui::EndCombo(); + } + } + + void PaddedText(const char* text, bool padTop, bool padBottom) { + if (padTop) + Spacer(0); + + ImGui::Text("%s", text); + + if (padBottom) + Spacer(0); + } + + void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton) { + int val = CVar_GetS32(cvarName, defaultValue); + ImGui::Text(text, val); + if(PlusMinusButton) { + std::string MinusBTNName = " - ##"; + MinusBTNName += cvarName; + if (ImGui::Button(MinusBTNName.c_str())) { + val--; + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + } + + if (ImGui::SliderInt(id, &val, min, max, format)) + { + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + if(PlusMinusButton) { + std::string PlusBTNName = " + ##"; + PlusBTNName += cvarName; + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNName.c_str())) { + val++; + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + if (val < min) + { + val = min; + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + if (val > max) + { + val = max; + CVar_SetS32(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton) { + float val = CVar_GetFloat(cvarName, defaultValue); + + if (!isPercentage) + ImGui::Text(text, val); + else + ImGui::Text(text, static_cast(100 * val)); + + Spacer(0); + + if(PlusMinusButton) { + std::string MinusBTNName = " - ##"; + MinusBTNName += cvarName; + if (ImGui::Button(MinusBTNName.c_str())) { + if (!isPercentage) + val -= 0.1f; + else + val -= 0.01f; + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + } + if (PlusMinusButton) { + #ifdef __WIIU__ + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2); + #else + ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f); + #endif + } + if (ImGui::SliderFloat(id, &val, min, max, format)) + { + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + if (PlusMinusButton) { + ImGui::PopItemWidth(); + } + if(PlusMinusButton) { + std::string PlusBTNName = " + ##"; + PlusBTNName += cvarName; + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f); + if (ImGui::Button(PlusBTNName.c_str())) { + if (!isPercentage) + val += 0.1f; + else + val += 0.01f; + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + if (val < min) + { + val = min; + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + + if (val > max) + { + val = max; + CVar_SetFloat(cvarName, val); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue, bool PlusMinusButton, bool padTop, bool padBottom) { + if (padTop) + Spacer(0); + + EnhancementSliderInt(text, id, cvarName, min, max, format, defaultValue, PlusMinusButton); + + if (padBottom) + Spacer(0); + } + + void EnhancementRadioButton(const char* text, const char* cvarName, int id) { + /*Usage : + EnhancementRadioButton("My Visible Name","gMyCVarName", MyID); + First arg is the visible name of the Radio button + Second is the cvar name where MyID will be saved. + Note: the CVar name should be the same to each Buddies. + Example : + EnhancementRadioButton("English", "gLanguages", 0); + EnhancementRadioButton("German", "gLanguages", 1); + EnhancementRadioButton("French", "gLanguages", 2); + */ + std::string make_invisible = "##"; + make_invisible += text; + make_invisible += cvarName; + + int val = CVar_GetS32(cvarName, 0); + if (ImGui::RadioButton(make_invisible.c_str(), id == val)) { + CVar_SetS32(cvarName, id); + SohImGui::RequestCvarSaveOnNextTick(); + } + ImGui::SameLine(); + ImGui::Text("%s", text); + } + + void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha) { + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "Reset"; + MakeInvisible += "##"; + MakeInvisible += cvarName; + MakeInvisible += "Reset"; + if (ImGui::Button(MakeInvisible.c_str())) { + colors->x = defaultcolors.x; + colors->y = defaultcolors.y; + colors->z = defaultcolors.z; + if (has_alpha) { colors->w = defaultcolors.w; }; + + Color_RGBA8 colorsRGBA; + colorsRGBA.r = defaultcolors.x; + colorsRGBA.g = defaultcolors.y; + colorsRGBA.b = defaultcolors.z; + if (has_alpha) { colorsRGBA.a = defaultcolors.w; }; + + CVar_SetRGBA(cvarName, colorsRGBA); + CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode. + SohImGui::RequestCvarSaveOnNextTick(); + } + Tooltip("Revert colors to the game's original colors (GameCube version)\nOverwrites previously chosen color"); + } + + void RandomizeColor(const char* cvarName, ImVec4* colors) { + Color_RGBA8 NewColors = {0,0,0,255}; + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "##"; + MakeInvisible += cvarName; + MakeInvisible += "Random"; + std::string FullName = "Random"; + FullName += MakeInvisible; + if (ImGui::Button(FullName.c_str())) { + s16 RND_R = rand() % (255 - 0); + s16 RND_G = rand() % (255 - 0); + s16 RND_B = rand() % (255 - 0); + colors->x = (float)RND_R / 255; + colors->y = (float)RND_G / 255; + colors->z = (float)RND_B / 255; + NewColors.r = fmin(fmax(colors->x, 0), 255); + NewColors.g = fmin(fmax(colors->y, 0), 255); + NewColors.b = fmin(fmax(colors->z, 0), 255); + CVar_SetRGBA(cvarName, NewColors); + CVar_SetS32(Cvar_RBM.c_str(), 0); // On click disable rainbow mode. + SohImGui::RequestCvarSaveOnNextTick(); + } + Tooltip("Chooses a random color\nOverwrites previously chosen color"); + } + + void RainbowColor(const char* cvarName, ImVec4* colors) { + std::string Cvar_RBM = cvarName; + Cvar_RBM += "RBM"; + std::string MakeInvisible = "Rainbow"; + MakeInvisible += "##"; + MakeInvisible += cvarName; + MakeInvisible += "Rainbow"; + + EnhancementCheckbox(MakeInvisible.c_str(), Cvar_RBM.c_str()); + Tooltip("Cycles through colors on a timer\nOverwrites previously chosen color"); + } + + void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) { + LoadPickersColors(ColorRGBA, cvarName, default_colors, has_alpha); + + ImGuiColorEditFlags flags = ImGuiColorEditFlags_None; + + if (!TitleSameLine) { + ImGui::Text("%s", text); + flags = ImGuiColorEditFlags_NoLabel; + } + + ImGui::PushID(cvarName); + + if (!has_alpha) { + if (ImGui::ColorEdit3(text, (float*)&ColorRGBA, flags)) + { + Color_RGBA8 colors; + colors.r = ColorRGBA.x * 255.0; + colors.g = ColorRGBA.y * 255.0; + colors.b = ColorRGBA.z * 255.0; + colors.a = ColorRGBA.w * 255.0; + + CVar_SetRGBA(cvarName, colors); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + else + { + if (ImGui::ColorEdit4(text, (float*)&ColorRGBA, flags)) + { + Color_RGBA8 colors; + colors.r = ColorRGBA.x / 255; + colors.g = ColorRGBA.y / 255; + colors.b = ColorRGBA.z / 255; + colors.a = ColorRGBA.w / 255; + + CVar_SetRGBA(cvarName, colors); + SohImGui::RequestCvarSaveOnNextTick(); + } + } + + ImGui::PopID(); + + //ImGui::SameLine(); // Removing that one to gain some width spacing on the HUD editor + ImGui::PushItemWidth(-FLT_MIN); + ResetColor(cvarName, &ColorRGBA, default_colors, has_alpha); + ImGui::SameLine(); + RandomizeColor(cvarName, &ColorRGBA); + if (allow_rainbow) { + if (ImGui::GetContentRegionAvail().x > 185) { + ImGui::SameLine(); + } + RainbowColor(cvarName, &ColorRGBA); + } + ImGui::NewLine(); + ImGui::PopItemWidth(); + } +} diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp new file mode 100644 index 000000000..6ea62a9fa --- /dev/null +++ b/soh/soh/UIWidgets.hpp @@ -0,0 +1,49 @@ +// +// UIWidgets.hpp +// soh +// +// Created by David Chavez on 25.08.22. +// + +#ifndef UIWidgets_hpp +#define UIWidgets_hpp + +#include +#include +#include +#include + +namespace UIWidgets { + + // MARK: - Enums + + enum class CheckboxGraphics { + Cross, + Checkmark, + None + }; + + char* WrappedText(const char* text, unsigned int charactersPerLine = 60); + char* WrappedText(const std::string& text, unsigned int charactersPerLine); + + void SetLastItemHoverText(const std::string& text); + void InsertHelpHoverText(const std::string& text); + + void Tooltip(const char* text); + void Spacer(float height); + + void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalTopPadding = 0.0f, float extraVerticalBottomPadding = 0.0f); + void EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross); + void PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross); + void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue = 0); + void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); + void PaddedText(const char* text, bool padTop = true, bool padBottom = true); + void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false); + void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true); + void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage, bool PlusMinusButton = false); + void EnhancementRadioButton(const char* text, const char* cvarName, int id); + + void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false); +} + +#endif /* UIWidgets_hpp */ diff --git a/soh/soh/frame_interpolation.cpp b/soh/soh/frame_interpolation.cpp index 44c255db1..79ac23d43 100644 --- a/soh/soh/frame_interpolation.cpp +++ b/soh/soh/frame_interpolation.cpp @@ -1,4 +1,4 @@ -#include "Cvar.h" +#include #include #include diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index c6be43964..1c5e82b43 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -1,13 +1,13 @@ #include "OTRGlobals.h" -#include "ResourceMgr.h" -#include "Scene.h" -#include "Utils/StringHelper.h" +#include +#include +#include #include "global.h" #include "vt.h" -#include +#include #include -#include -#include +#include "Enhancements/custom-message/CustomMessageManager.h" +#include "Enhancements/custom-message/CustomMessageTypes.h" extern "C" MessageTableEntry* sNesMessageEntryTablePtr; extern "C" MessageTableEntry* sGerMessageEntryTablePtr; diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index 1a07ceb7e..52b71c905 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -1,10 +1,10 @@ -#include "OTRGlobals.h" -#include "ResourceMgr.h" -#include "Scene.h" -#include "Utils/StringHelper.h" +#include "OTRGlobals.h" +#include +#include +#include #include "global.h" #include "vt.h" -#include "Vertex.h" +#include extern "C" void Gameplay_InitScene(GlobalContext * globalCtx, s32 spawn); extern "C" void Gameplay_InitEnvironment(GlobalContext * globalCtx, s16 skyboxId); @@ -76,4 +76,4 @@ void OTRGameplay_InitScene(GlobalContext* globalCtx, s32 spawn) { auto data2 = ResourceMgr_LoadVtxByCRC(0x68d4ea06044e228f);*/ volatile int a = 0; -} \ No newline at end of file +} diff --git a/soh/soh/z_scene_otr.cpp b/soh/soh/z_scene_otr.cpp index 73953c681..97c0b8040 100644 --- a/soh/soh/z_scene_otr.cpp +++ b/soh/soh/z_scene_otr.cpp @@ -1,15 +1,15 @@ -#include "OTRGlobals.h" -#include "ResourceMgr.h" -#include "Scene.h" -#include "Utils/StringHelper.h" +#include "OTRGlobals.h" +#include +#include +#include #include "global.h" #include "vt.h" -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include extern Ship::Resource* OTRGameplay_LoadFile(GlobalContext* globalCtx, const char* fileName); extern "C" s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId); diff --git a/soh/src/code/audio_playback.c b/soh/src/code/audio_playback.c index b2017b514..2c7ff425d 100644 --- a/soh/src/code/audio_playback.c +++ b/soh/src/code/audio_playback.c @@ -1,5 +1,5 @@ #include "global.h" -#include "Cvar.h" +#include extern bool gUseLegacySD; diff --git a/soh/src/code/audio_synthesis.c b/soh/src/code/audio_synthesis.c index 67f7033ea..72dbb25ec 100644 --- a/soh/src/code/audio_synthesis.c +++ b/soh/src/code/audio_synthesis.c @@ -1,6 +1,6 @@ #include "ultra64.h" #include "global.h" -#include "mixer.h" +#include #define DEFAULT_LEN_1CH 0x1A0 #define DEFAULT_LEN_2CH 0x340 diff --git a/soh/src/code/code_800F9280.c b/soh/src/code/code_800F9280.c index 6ca2ad75d..5fa3d50fa 100644 --- a/soh/src/code/code_800F9280.c +++ b/soh/src/code/code_800F9280.c @@ -1,7 +1,7 @@ #include "ultra64.h" #include "global.h" -#include "ultra64/abi.h" -#include "mixer.h" +#include +#include typedef struct { u8 unk_0; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index 6b311fd4c..f831bc830 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -4,7 +4,7 @@ #include #include "soh/Enhancements/gameconsole.h" -#include "../libultraship/ImGuiImpl.h" +#include #include "soh/frame_interpolation.h" #include diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index 73da17185..de83f8c2a 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -10,7 +10,7 @@ #include "alloca.h" #include "textures/nintendo_rogo_static/nintendo_rogo_static.h" #include -#include "GameVersions.h" +#include #include const char* GetGameVersionString(); From fba8fc2b74607e85567b383361f19f7c79a89396 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 3 Sep 2022 00:20:07 -0400 Subject: [PATCH 26/52] Fix Ganons Trials coming from old save files. Fixes #1365 --- soh/soh/Enhancements/randomizer/randomizer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b8442e241..cb0ef6e5b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1136,6 +1136,8 @@ void Randomizer::ParseRequiredTrialsFile(const char* spoilerFileName) { return; } + this->trialsRequired.clear(); + try { json spoilerFileJson; spoilerFileStream >> spoilerFileJson; From a07ea091f00adbb817f6f373d1e7204a32924c93 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 3 Sep 2022 00:20:50 -0400 Subject: [PATCH 27/52] Fixes crash when entering Ganon's Castle lobby on linux. --- soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c b/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c index 6d0b51db2..b2dc185d7 100644 --- a/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c +++ b/soh/src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.c @@ -88,7 +88,7 @@ s32 DemoKekkai_CheckEventFlag(s32 params) { if ((params < KEKKAI_TOWER) || (params > KEKKAI_FOREST)) { return true; } - if (gSaveContext.n64ddFlag) { + if (gSaveContext.n64ddFlag && params > KEKKAI_TOWER) { return Flags_GetRandomizerInf(trialParamToRandInf(params)); } return Flags_GetEventChkInf(eventFlags[params]); From 8118947ab059b4ffec91ed87620f777e1b0ef09e Mon Sep 17 00:00:00 2001 From: louist103 <35883445+louist103@users.noreply.github.com> Date: Sat, 3 Sep 2022 01:15:43 -0400 Subject: [PATCH 28/52] Windows crash handler. (#1383) * Windows crash handler. * Fix naming convention. --- libultraship/libultraship/CrashHandler.cpp | 437 +++++++++++++++------ libultraship/libultraship/CrashHandler.h | 23 +- soh/src/code/main.c | 2 + 3 files changed, 333 insertions(+), 129 deletions(-) diff --git a/libultraship/libultraship/CrashHandler.cpp b/libultraship/libultraship/CrashHandler.cpp index f8d66beab..f454ddfdc 100644 --- a/libultraship/libultraship/CrashHandler.cpp +++ b/libultraship/libultraship/CrashHandler.cpp @@ -1,6 +1,9 @@ #include "spdlog/spdlog.h" #include "Utils/StringHelper.h" #include "CrashHandler.h" +#include "Window.h" + +extern "C" void DeinitOTR(void); #if defined(__linux__) #include @@ -10,163 +13,343 @@ #include #include -extern "C" void DeinitOTR(void); static void PrintRegisters(ucontext_t* ctx) { - char regbuffer[1024]; - SPDLOG_CRITICAL("Registers:"); + char regbuffer[1024]; + SPDLOG_CRITICAL("Registers:"); #if defined(__x86_64__) - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]); - SPDLOG_CRITICAL("RAX: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]); - SPDLOG_CRITICAL("RDI: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]); - SPDLOG_CRITICAL("RSI: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]); - SPDLOG_CRITICAL("RDX: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]); - SPDLOG_CRITICAL("RCX: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]); - SPDLOG_CRITICAL("R8 : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]); - SPDLOG_CRITICAL("R9 : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]); - SPDLOG_CRITICAL("R10: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]); - SPDLOG_CRITICAL("R11: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]); - SPDLOG_CRITICAL("RSP: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]); - SPDLOG_CRITICAL("RBX: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]); - SPDLOG_CRITICAL("RBP: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]); - SPDLOG_CRITICAL("R12: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]); - SPDLOG_CRITICAL("R13: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]); - SPDLOG_CRITICAL("R14: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]); - SPDLOG_CRITICAL("R15: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]); - SPDLOG_CRITICAL("RIP: {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]); - SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]); + SPDLOG_CRITICAL("RAX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]); + SPDLOG_CRITICAL("RDI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]); + SPDLOG_CRITICAL("RSI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]); + SPDLOG_CRITICAL("RDX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]); + SPDLOG_CRITICAL("RCX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]); + SPDLOG_CRITICAL("R8 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]); + SPDLOG_CRITICAL("R9 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]); + SPDLOG_CRITICAL("R10: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]); + SPDLOG_CRITICAL("R11: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]); + SPDLOG_CRITICAL("RSP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]); + SPDLOG_CRITICAL("RBX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]); + SPDLOG_CRITICAL("RBP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]); + SPDLOG_CRITICAL("R12: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]); + SPDLOG_CRITICAL("R13: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]); + SPDLOG_CRITICAL("R14: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]); + SPDLOG_CRITICAL("R15: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]); + SPDLOG_CRITICAL("RIP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer); #else - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]); - SPDLOG_CRITICAL("EDI : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]); - SPDLOG_CRITICAL("ESI : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]); - SPDLOG_CRITICAL("EBP : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]); - SPDLOG_CRITICAL("ESP : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]); - SPDLOG_CRITICAL("EBX : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]); - SPDLOG_CRITICAL("EDX : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]); - SPDLOG_CRITICAL("ECX : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]); - SPDLOG_CRITICAL("EAX : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]); - SPDLOG_CRITICAL("EIP : {} ", regbuffer); - snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]); - SPDLOG_CRITICAL("EFL : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]); + SPDLOG_CRITICAL("EDI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]); + SPDLOG_CRITICAL("ESI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]); + SPDLOG_CRITICAL("EBP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]); + SPDLOG_CRITICAL("ESP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]); + SPDLOG_CRITICAL("EBX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]); + SPDLOG_CRITICAL("EDX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]); + SPDLOG_CRITICAL("ECX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]); + SPDLOG_CRITICAL("EAX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]); + SPDLOG_CRITICAL("EIP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFL : {} ", regbuffer); #endif } -static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) -{ - std::array arr; - ucontext_t* ctx = static_cast(data); - constexpr size_t nMaxFrames = arr.size(); - size_t size = backtrace(arr.data(), nMaxFrames); - char** symbols = backtrace_symbols(arr.data(), nMaxFrames); +static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) { + std::array arr; + ucontext_t* ctx = static_cast(data); + constexpr size_t nMaxFrames = arr.size(); + size_t size = backtrace(arr.data(), nMaxFrames); + char** symbols = backtrace_symbols(arr.data(), nMaxFrames); - SPDLOG_CRITICAL("(Signal: {})\n", sig); + SPDLOG_CRITICAL("(Signal: {})", sig); - switch (sig) { - case SIGILL: - SPDLOG_CRITICAL("ILLEGAL INSTRUCTION"); - break; - case SIGABRT: - SPDLOG_CRITICAL("ABORT"); - break; - case SIGFPE: - SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION"); - break; - case SIGSEGV: - SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE"); - break; - } + switch (sig) { + case SIGILL: + SPDLOG_CRITICAL("ILLEGAL INSTRUCTION"); + break; + case SIGABRT: + SPDLOG_CRITICAL("ABORT"); + break; + case SIGFPE: + SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION"); + break; + case SIGSEGV: + SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE"); + break; + } - PrintRegisters(ctx); + PrintRegisters(ctx); - SPDLOG_CRITICAL("Traceback:\n"); - for (size_t i = 1; i < size; i++) - { - Dl_info info; - int gotAddress = dladdr(arr[i], &info); - std::string functionName(symbols[i]); + SPDLOG_CRITICAL("Traceback:"); + for (size_t i = 1; i < size; i++) { + Dl_info info; + int gotAddress = dladdr(arr[i], &info); + std::string functionName(symbols[i]); - if (gotAddress != 0 && info.dli_sname != nullptr) - { + if (gotAddress != 0 && info.dli_sname != nullptr) { FILE* pipe; - int32_t status; - char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); - const char* nameFound = info.dli_sname; + int32_t status; + char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); + const char* nameFound = info.dli_sname; - if (status == 0) - { - nameFound = demangled; - } + if (status == 0) { + nameFound = demangled; + } #if 0 - char command[256]; + char command[256]; char addrLine[128]; snprintf(command, sizeof(command), "addr2line -e soh.elf %s + 0x%lX", nameFound, (uintptr_t)arr[i] - (uintptr_t)info.dli_saddr); - pipe = popen(command, "r"); + pipe = popen(command, "r"); fgets(addrLine, 128, pipe); - #endif - + #endif + functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound, - (char*)arr[i] - (char*)info.dli_saddr); - free(demangled); - } + (char*)arr[i] - (char*)info.dli_saddr); + free(demangled); + } - SPDLOG_CRITICAL("{} {}", i, functionName.c_str()); - } + SPDLOG_CRITICAL("{} {}", i, functionName.c_str()); + } - free(symbols); - DeinitOTR(); - exit(1); + free(symbols); + DeinitOTR(); + exit(1); } static void ShutdownHandler(int sig, siginfo_t* sigInfo, void* data) { - DeinitOTR(); - exit(1); + DeinitOTR(); + exit(1); } extern "C" void SetupHandlerLinux() { - struct sigaction action; - struct sigaction shutdownAction; + struct sigaction action; + struct sigaction shutdownAction; - action.sa_flags = SA_SIGINFO; - action.sa_sigaction = ErrorHandler; - - sigaction(SIGILL, &action, nullptr); - sigaction(SIGABRT, &action, nullptr); - sigaction(SIGFPE, &action, nullptr); - sigaction(SIGSEGV, &action, nullptr); - - shutdownAction.sa_flags = SA_SIGINFO; - shutdownAction.sa_sigaction = ShutdownHandler; - sigaction(SIGINT, &shutdownAction, nullptr); - sigaction(SIGTERM, &shutdownAction, nullptr); - sigaction(SIGQUIT, &shutdownAction, nullptr); - sigaction(SIGKILL, &shutdownAction, nullptr); + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = ErrorHandler; + sigaction(SIGILL, &action, nullptr); + sigaction(SIGABRT, &action, nullptr); + sigaction(SIGFPE, &action, nullptr); + sigaction(SIGSEGV, &action, nullptr); + shutdownAction.sa_flags = SA_SIGINFO; + shutdownAction.sa_sigaction = ShutdownHandler; + sigaction(SIGINT, &shutdownAction, nullptr); + sigaction(SIGTERM, &shutdownAction, nullptr); + sigaction(SIGQUIT, &shutdownAction, nullptr); + sigaction(SIGKILL, &shutdownAction, nullptr); } +#elif _WIN32 + +#if defined(_WIN32) && !defined(_WIN64) +#define WINDOWS_32_BIT +#endif + +static void PrintRegisters(CONTEXT* ctx) { + SPDLOG_CRITICAL("Register dump"); + char regBuff[50]; +#if defined(_M_AMD64) + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rax); + SPDLOG_CRITICAL("RAX: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rcx); + SPDLOG_CRITICAL("RCX: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rdx); + SPDLOG_CRITICAL("RDX: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rbx); + SPDLOG_CRITICAL("RBX: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rsp); + SPDLOG_CRITICAL("RSP: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rbp); + SPDLOG_CRITICAL("RBP: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rsi); + SPDLOG_CRITICAL("RSI: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rdi); + SPDLOG_CRITICAL("RDI: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R9); + SPDLOG_CRITICAL("R9: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R10); + SPDLOG_CRITICAL("R10: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R11); + SPDLOG_CRITICAL("R11: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R12); + SPDLOG_CRITICAL("R12: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R13); + SPDLOG_CRITICAL("R13: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R14); + SPDLOG_CRITICAL("R14: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->R15); + SPDLOG_CRITICAL("R15: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%016llX", ctx->Rip); + SPDLOG_CRITICAL("RIP: {}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->EFlags); + SPDLOG_CRITICAL("EFLAGS: {}", regBuff); +#elif WINDOWS_32_BIT + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Edi); + SPDLOG_CRITICAL("EDI: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Esi); + SPDLOG_CRITICAL("ESI: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ebx); + SPDLOG_CRITICAL("EBX: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ecx); + SPDLOG_CRITICAL("ECX: 0x{}", ctx->Ecx); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Eax); + SPDLOG_CRITICAL("EAX: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Ebp); + SPDLOG_CRITICAL("EBP: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Esp); + SPDLOG_CRITICAL("ESP: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->EFlags); + SPDLOG_CRITICAL("EFLAGS: 0x{}", regBuff); + + snprintf(regBuff, std::size(regBuff), "0x%08lX", ctx->Eip); + SPDLOG_CRITICAL("EIP: 0x{}", regBuff); +#endif +} + +static void printStack(CONTEXT* ctx) { + BOOL result; + HANDLE process; + HANDLE thread; + HMODULE hModule; + ULONG frame; + DWORD64 displacement; + DWORD disp; + +#if defined(_M_AMD64) + STACKFRAME64 stack; + memset(&stack, 0, sizeof(STACKFRAME64)); +#elif WINDOWS_32_BIT + STACKFRAME stack; + memset(&stack, 0, sizeof(STACKFRAME)); + stack.AddrPC.Offset = (*ctx).Eip; + stack.AddrPC.Mode = AddrModeFlat; + stack.AddrStack.Offset = (*ctx).Esp; + stack.AddrStack.Mode = AddrModeFlat; + stack.AddrFrame.Offset = (*ctx).Ebp; + stack.AddrFrame.Mode = AddrModeFlat; +#endif + + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME + sizeof(TCHAR)]; + char module[512]; + + PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer; + + CONTEXT ctx2; + memcpy(&ctx2, ctx, sizeof(CONTEXT)); + + PrintRegisters(&ctx2); + + process = GetCurrentProcess(); + thread = GetCurrentThread(); + SymInitialize(process, nullptr, true); + + + constexpr DWORD machineType = +#if defined(_M_AMD64) + IMAGE_FILE_MACHINE_AMD64; +#elif WINDOWS_32_BIT + IMAGE_FILE_MACHINE_I386; +#endif + + displacement = 0; + for (frame = 0;; frame++) { + result = StackWalk(machineType, process, thread, &stack, &ctx2, nullptr, SymFunctionTableAccess, + SymGetModuleBase, nullptr); + if (!result) { + break; + } + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol->MaxNameLen = MAX_SYM_NAME; + SymFromAddr(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol); +#if defined(_M_AMD64) + IMAGEHLP_LINE64 line; + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); +#elif WINDOWS_32_BIT + IMAGEHLP_LINE line; + line.SizeOfStruct = sizeof(IMAGEHLP_LINE); +#endif + if (SymGetLineFromAddr(process, stack.AddrPC.Offset, &disp, &line)) { + SPDLOG_CRITICAL("{} in {}: line: {}: ", symbol->Name, line.FileName, line.LineNumber); + } + else { + char addrString[25]; + snprintf(addrString, std::size(addrString), "0x%016llX", symbol->Address); + SPDLOG_CRITICAL("at {}, addr 0x{}", symbol->Name, addrString); + hModule = nullptr; + GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCTSTR)(stack.AddrPC.Offset), &hModule); + + if (hModule != nullptr) { + GetModuleFileNameA(hModule, module, sizeof(module)); + } + SPDLOG_CRITICAL("In {}", module); + } + } + Ship::Window::GetInstance()->GetLogger()->flush(); + spdlog::shutdown(); + DeinitOTR(); +} + +extern "C" LONG seh_filter(struct _EXCEPTION_POINTERS* ex) { + char exceptionString[20]; + + snprintf(exceptionString, std::size(exceptionString), "0x%x", ex->ExceptionRecord->ExceptionCode); + + SPDLOG_CRITICAL("EXCEPTION {} occurred", exceptionString); + printStack(ex->ContextRecord); + MessageBox(nullptr, L"SoH Has crashed. Please upload the logs to the support channel in discord.", L"Crash", MB_OK | MB_ICONERROR); + + return EXCEPTION_EXECUTE_HANDLER; +} + + #endif diff --git a/libultraship/libultraship/CrashHandler.h b/libultraship/libultraship/CrashHandler.h index e068a4e38..103034ea4 100644 --- a/libultraship/libultraship/CrashHandler.h +++ b/libultraship/libultraship/CrashHandler.h @@ -13,6 +13,25 @@ void SetupHandlerLinux(void); } #endif -#endif // __linux__ +#elif _WIN32 // __linux__ ^^^^ _WIN32 vvvvv +#include +#include -#endif // CRASH_HANDLER_H \ No newline at end of file +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +LONG seh_filter(struct _EXCEPTION_POINTERS* ex); + +#ifdef __cplusplus +} +#endif + +#pragma comment(lib, "Dbghelp.lib") +#endif + +#endif // CRASH_HANDLER_H diff --git a/soh/src/code/main.c b/soh/src/code/main.c index 8e9fe1776..07e54b5be 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -42,6 +42,8 @@ int main(int argc, char** argv) { #ifdef __linux__ SetupHandlerLinux(); +#elif _WIN32 + SetUnhandledExceptionFilter(seh_filter); #endif GameConsole_Init(); From a5804ca2b23508ecaf270d4b8b1548fe776a7685 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 3 Sep 2022 01:21:56 -0400 Subject: [PATCH 29/52] Makes `Item_Give` safe to use with a NULL globalCtx. This should allow it's use for giving items to Link's Pocket during rando save initialization. --- soh/src/code/z_parameter.c | 78 +++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index ac751cca3..4d4807442 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1575,6 +1575,17 @@ void func_80084BF4(GlobalContext* globalCtx, u16 flag) { } } +/** + * @brief Adds the given item to Link's inventory. + * + * NOTE: This function has been edited to be safe to use with a NULL globalCtx. + * If you need to add to this function, be sure you check if the globalCtx is not + * NULL before doing any operations requiring it. + * + * @param globalCtx + * @param item + * @return u8 + */ u8 Item_Give(GlobalContext* globalCtx, u8 item) { static s16 sAmmoRefillCounts[] = { 5, 10, 20, 30, 5, 10, 30, 0, 5, 20, 1, 5, 20, 50, 200, 10 }; s16 i; @@ -1654,7 +1665,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { if (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) { gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; - Interface_LoadItemIcon1(globalCtx, 0); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, 0); + } } } @@ -1662,7 +1675,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; gSaveContext.equips.equipment &= 0xFFF0; gSaveContext.equips.equipment |= 0x0002; - Interface_LoadItemIcon1(globalCtx, 0); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, 0); + } } return ITEM_NONE; @@ -1677,7 +1692,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return ITEM_NONE; } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { // Boss Key, Compass, and Dungeon Map exceptions for rando. - if (gSaveContext.n64ddFlag) { + // Rando should never be able to get here for Link's Pocket unless something goes wrong, + // but we check for a globalCtx here so the game won't crash if we do somehow get here. + if (gSaveContext.n64ddFlag && globalCtx != NULL) { if (globalCtx->sceneNum == 13) { // ganon's castle -> ganon's tower gSaveContext.inventory.dungeonItems[10] |= 1; } else if (globalCtx->sceneNum == 92) { // Desert Colossus -> Spirit Temple. @@ -1691,7 +1708,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return ITEM_NONE; } else if (item == ITEM_KEY_SMALL) { // Small key exceptions for rando with keysanity off. - if (gSaveContext.n64ddFlag) { + // Rando should never be able to get here for Link's Pocket unless something goes wrong, + // but we check for a globalCtx here so the game won't crash if we do somehow get here. + if (gSaveContext.n64ddFlag && globalCtx != NULL) { if (globalCtx->sceneNum == 10) { // ganon's tower -> ganon's castle if (gSaveContext.inventory.dungeonKeys[13] < 0) { gSaveContext.inventory.dungeonKeys[13] = 1; @@ -1828,7 +1847,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (gSaveContext.equips.buttonItems[i] == ITEM_HOOKSHOT) { gSaveContext.equips.buttonItems[i] = ITEM_LONGSHOT; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } // update the adult/child equips when rando'd (accounting for equp swapped hookshot as child) @@ -1836,7 +1857,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) { if (gSaveContext.adultEquips.buttonItems[i] == ITEM_HOOKSHOT) { gSaveContext.adultEquips.buttonItems[i] = ITEM_LONGSHOT; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } } @@ -1844,7 +1867,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) { if (gSaveContext.childEquips.buttonItems[i] == ITEM_HOOKSHOT) { gSaveContext.childEquips.buttonItems[i] = ITEM_LONGSHOT; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } } @@ -1989,7 +2014,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) { if (gSaveContext.adultEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) { gSaveContext.adultEquips.buttonItems[i] = ITEM_OCARINA_TIME; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } } @@ -1997,7 +2024,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) { if (gSaveContext.childEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) { gSaveContext.childEquips.buttonItems[i] = ITEM_OCARINA_TIME; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } } @@ -2021,14 +2050,20 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return ITEM_NONE; } else if (item == ITEM_HEART) { osSyncPrintf("回復ハート回復ハート回復ハート\n"); // "Recovery Heart" - Health_ChangeBy(globalCtx, 0x10); + if (globalCtx != NULL) { + Health_ChangeBy(globalCtx, 0x10); + } return item; } else if (item == ITEM_MAGIC_SMALL) { if (gSaveContext.unk_13F0 != 10) { - Magic_Fill(globalCtx); + if (globalCtx != NULL) { + Magic_Fill(globalCtx); + } } - func_80087708(globalCtx, 12, 5); + if (globalCtx != NULL) { + func_80087708(globalCtx, 12, 5); + } if (!(gSaveContext.infTable[25] & 0x100)) { gSaveContext.infTable[25] |= 0x100; @@ -2038,10 +2073,13 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return item; } else if (item == ITEM_MAGIC_LARGE) { if (gSaveContext.unk_13F0 != 10) { - Magic_Fill(globalCtx); + if (globalCtx != NULL) { + Magic_Fill(globalCtx); + } + } + if (globalCtx != NULL) { + func_80087708(globalCtx, 24, 5); } - - func_80087708(globalCtx, 24, 5); if (!(gSaveContext.infTable[25] & 0x100)) { gSaveContext.infTable[25] |= 0x100; @@ -2080,7 +2118,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (int buttonIndex = 1; buttonIndex < ARRAY_COUNT(gSaveContext.equips.buttonItems); buttonIndex++) { if ((temp + i) == gSaveContext.equips.cButtonSlots[buttonIndex - 1]) { gSaveContext.equips.buttonItems[buttonIndex] = item; - Interface_LoadItemIcon2(globalCtx, buttonIndex); + if (globalCtx != NULL) { + Interface_LoadItemIcon2(globalCtx, buttonIndex); + } gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(buttonIndex)] = BTN_ENABLED; break; } @@ -2115,7 +2155,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { if (temp == gSaveContext.equips.buttonItems[i]) { if (item != ITEM_SOLD_OUT) { gSaveContext.equips.buttonItems[i] = item; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } else { gSaveContext.equips.buttonItems[i] = ITEM_NONE; } @@ -2132,7 +2174,7 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { INV_CONTENT(item) = item; // Autosave after getting items by default (cvars are not shown in the UI) - if (CVar_GetS32("gAutosave", 0)) { + if (CVar_GetS32("gAutosave", 0) && globalCtx != NULL) { if (CVar_GetS32("gAutosaveAllItems", 1)) { Gameplay_PerformSave(globalCtx); } From edb5261b07c3b22af2591ced7fbc1783f4312d3a Mon Sep 17 00:00:00 2001 From: Ada <60364512+GreatArgorath@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:20:15 +0100 Subject: [PATCH 30/52] Fixes ToT Fog --- libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index cca872f99..23b72a944 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -2134,6 +2134,10 @@ static void gfx_run_dl(Gfx* cmd) { switch (opcode) { // RSP commands: + case G_LOAD_UCODE: + rsp.fog_mul = 0; + rsp.fog_offset = 0; + break; case G_MARKER: { cmd++; From b14fb37b814f06fa8b75d8ce9312abf1f501ebfe Mon Sep 17 00:00:00 2001 From: Ada <60364512+GreatArgorath@users.noreply.github.com> Date: Wed, 17 Aug 2022 14:47:43 +0100 Subject: [PATCH 31/52] Update libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp Co-authored-by: David Chavez --- libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp index 23b72a944..9fde7e276 100644 --- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp +++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp @@ -2134,7 +2134,7 @@ static void gfx_run_dl(Gfx* cmd) { switch (opcode) { // RSP commands: - case G_LOAD_UCODE: + case G_LOAD_UCODE: rsp.fog_mul = 0; rsp.fog_offset = 0; break; From d2fa0d648544a2149cf7d6053cafd50c20437724 Mon Sep 17 00:00:00 2001 From: Baoulettes Date: Mon, 22 Aug 2022 04:19:02 +0200 Subject: [PATCH 32/52] Rando: Fix Fast File Select seed loading (#1252) * FixRandoLoading * better methode --- soh/src/overlays/gamestates/ovl_title/z_title.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/soh/src/overlays/gamestates/ovl_title/z_title.c b/soh/src/overlays/gamestates/ovl_title/z_title.c index de83f8c2a..7c63ef35c 100644 --- a/soh/src/overlays/gamestates/ovl_title/z_title.c +++ b/soh/src/overlays/gamestates/ovl_title/z_title.c @@ -301,6 +301,9 @@ void Title_Init(GameState* thisx) { saveloading = true; gSaveContext.fileNum = selectedfile; Sram_OpenSave(); + Randomizer_LoadSettings(""); + Randomizer_LoadHintLocations(""); + Randomizer_LoadItemLocations("", true); gSaveContext.gameMode = 0; gSaveContext.magic = gSaveContext.magic; SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext); From 2015e3a041e5f5ae066ea61be43b4bbbea0f83d1 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 3 Sep 2022 01:48:07 -0400 Subject: [PATCH 33/52] Converts Song from Impa to use `Item_Give` --- soh/src/code/z_sram.c | 68 +------------------------------------------ 1 file changed, 1 insertion(+), 67 deletions(-) diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index c131f172f..6d4b68bc0 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -858,73 +858,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { s32 giid = getItem.getItemId; if (getItem.modIndex == MOD_NONE) { - if (getItem.itemId >= ITEM_MEDALLION_FOREST && getItem.itemId <= ITEM_ZORA_SAPPHIRE) { - GiveLinkDungeonReward(getItem.getItemId); - } else if (getItem.itemId >= ITEM_SONG_MINUET && getItem.itemId <= ITEM_SONG_STORMS) { - GiveLinkSong(getItem.getItemId); - } else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED || - giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) { - GiveLinkRupeesByGetItemId(giid); - } else if (giid == GI_BOMBCHUS_10 || giid == GI_BOMBCHUS_5 || giid == GI_BOMBCHUS_20) { - GiveLinkBombchus(giid); - } else if (giid == GI_STICKS_1 || giid == GI_STICKS_5 || giid == GI_STICKS_10) { - GiveLinkDekuSticksByGetItemId(giid); - } else if (giid == GI_NUTS_5 || giid == GI_NUTS_10) { - GiveLinkDekuNutsByGetItemId(giid); - } else if (giid == GI_BEAN) { - GiveLinkBeans(); - } else if (giid == GI_SWORD_KOKIRI) { - GiveLinkKokiriSword(); - } else if (giid == GI_SWORD_BGS) { - GiveLinkBiggoronSword(); - } else if (giid == GI_SWORD_KNIFE) { - GiveLinkGiantsKnife(); - } else if (giid == GI_SHIELD_DEKU) { - GiveLinkDekuShield(); - } else if (giid == GI_SHIELD_HYLIAN) { - GiveLinkHylianShield(); - } else if (giid == GI_SHIELD_MIRROR) { - GiveLinkMirrorShield(); - } else if (giid == GI_TUNIC_GORON) { - GiveLinkGoronTunic(); - } else if (giid == GI_TUNIC_ZORA) { - GiveLinkZoraTunic(); - } else if (giid == GI_BOOTS_IRON) { - GiveLinkIronBoots(); - } else if (giid == GI_BOOTS_HOVER) { - GiveLinkHoverBoots(); - } else if (giid == GI_SLINGSHOT || giid == GI_BULLET_BAG_40 || giid == GI_BULLET_BAG_50) { - GiveLinkBulletBagUpgrade(giid); - } else if (giid == GI_BOW || giid == GI_QUIVER_40 || giid == GI_QUIVER_50) { - GiveLinkQuiverUpgrade(giid); - } else if (giid == GI_BOMB_BAG_20 || giid == GI_BOMB_BAG_30 || giid == GI_BOMB_BAG_40) { - GiveLinkBombBagUpgrade(giid); - } else if (giid == GI_BRACELET || giid == GI_GAUNTLETS_SILVER || giid == GI_GAUNTLETS_GOLD) { - GiveLinkStrengthUpgrade(giid); - } else if (giid == GI_SCALE_SILVER || giid == GI_SCALE_GOLD) { - GiveLinkScaleUpgrade(giid); - } else if (giid == GI_WALLET_ADULT || giid == GI_WALLET_GIANT) { - GiveLinkWalletUpgrade(giid); - } else if (giid == GI_STONE_OF_AGONY) { - GiveLinkStoneOfAgony(); - } else if (giid == GI_GERUDO_CARD) { - GiveLinkGerudoCard(); - } else if (giid == GI_HEART_PIECE) { - GiveLinkPieceOfHeart(); - } else if (giid == GI_HEART_CONTAINER) { - GiveLinkHeartContainer(); - } else if (giid == GI_STICK_UPGRADE_20 || giid == GI_STICK_UPGRADE_30) { - GiveLinkDekuStickUpgrade(giid); - } else if (giid == GI_NUT_UPGRADE_30 || giid == GI_NUT_UPGRADE_40) { - GiveLinkDekuNutUpgrade(giid); - } else if (giid == GI_SKULL_TOKEN) { - GiveLinkSkullToken(); - } else if (giid >= GI_POCKET_EGG && giid <= GI_CLAIM_CHECK || giid == GI_COJIRO) { - GiveLinkAdultTradeItem(giid); - } else { - s32 iid = getItem.itemId; - if (iid != -1) INV_CONTENT(iid) = iid; - } + Item_Give(NULL, getItem.itemId); } else if (getItem.modIndex == MOD_RANDOMIZER) { Randomizer_Item_Give(NULL, getItem); } From 6daf357fd95d4a500b0b47273306d1a29e9b3701 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Sat, 3 Sep 2022 02:13:20 -0400 Subject: [PATCH 34/52] fix include fix build (#1385) Co-authored-by: briaguya --- soh/src/code/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/code/main.c b/soh/src/code/main.c index 07e54b5be..7a6d6c6d9 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -3,7 +3,7 @@ #include #include "soh/OTRGlobals.h" -#include "../libultraship/CrashHandler.h" +#include s32 gScreenWidth = SCREEN_WIDTH; From 36cc9d562c4c15e92801c1a45746f85ec1f629cf Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 3 Sep 2022 02:34:21 -0400 Subject: [PATCH 35/52] Adds more options for Link's starting item. --- .../randomizer/3drando/settings.cpp | 2 ++ .../Enhancements/randomizer/randomizer.cpp | 24 ++++++++++++++++++- .../Enhancements/randomizer/randomizerTypes.h | 3 ++- soh/src/code/z_sram.c | 14 +++++++---- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index dd9f6d2de..dba8859e9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2592,6 +2592,8 @@ namespace Settings { NightGSExpectSuns.SetSelectedIndex(cvarSettings[RSK_SKULLS_SUNS_SONG]); + LinksPocketItem.SetSelectedIndex(cvarSettings[RSK_LINKS_POCKET]); + // RANDOTODO implement chest shuffle with keysanity // ShuffleChestMinigame.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3f5ae1bb4..fdb705095 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -567,12 +567,13 @@ std::unordered_map SpoilerfileSettingNameToEn { "Open Settings:Token Count", RSK_RAINBOW_BRIDGE_TOKEN_COUNT }, { "Open Settings:Random Ganon's Trials", RSK_RANDOM_TRIALS }, { "Open Settings:Trial Count", RSK_TRIAL_COUNT }, + { "Shuffle Settings:Link's Pocket", RSK_LINKS_POCKET}, { "Shuffle Settings:Shuffle Gerudo Card", RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD }, { "Shuffle Settings:Scrub Shuffle", RSK_SHUFFLE_SCRUBS }, { "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS }, { "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS }, { "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE }, - { "Shuffle Settings:Shuffle Magic Beans", RSK_SHUFFLE_MAGIC_BEANS}, + { "Shuffle Settings:Shuffle Magic Beans", RSK_SHUFFLE_MAGIC_BEANS }, { "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD }, { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, @@ -969,6 +970,17 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { gSaveContext.randoSettings[index].value = 3; } break; + case RSK_LINKS_POCKET: + if (it.value() == "Dungeon Reward") { + gSaveContext.randoSettings[index].value = 0; + } else if (it.value() == "Advancement") { + gSaveContext.randoSettings[index].value = 1; + } else if (it.value() == "Anything") { + gSaveContext.randoSettings[index].value = 2; + } else if (it.value() == "Nothing") { + gSaveContext.randoSettings[index].value = 3; + } + break; } index++; } @@ -3457,6 +3469,9 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVar_GetS32("gRandomizeEnableGlitchCutscenes", 0); cvarSettings[RSK_SKULLS_SUNS_SONG] = CVar_GetS32("gRandomizeGsExpectSunsSong", 0); + // Link's Pocket has to have a dungeon reward if the other rewards are shuffled to end of dungeon. + cvarSettings[RSK_LINKS_POCKET] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0) != 0 ? + CVar_GetS32("gRandomizeLinksPocket", 0) : 0; // todo: this efficently when we build out cvar array support std::set excludedLocations; @@ -4506,6 +4521,13 @@ void DrawRandoEditor(bool& open) { ImGui::TableNextColumn(); window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildStartingEquipment", ImVec2(0, -8)); + // Don't display this option if Dungeon Rewards are Shuffled to End of Dungeon. + // TODO: Show this but disabled when we have options for disabled Comboboxes. + if (CVar_GetS32("gRandomizeShuffleDungeonReward", 0) != 0) { + ImGui::Text(Settings::LinksPocketItem.GetName().c_str()); + SohImGui::EnhancementCombobox("gRandomizeLinksPocket", randoLinksPocket, 4, 0); + PaddedSeparator(); + } SohImGui::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), "gRandomizeStartingKokiriSword"); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index bd7e25a46..064cdc499 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1018,7 +1018,8 @@ typedef enum { RSK_SKULLS_SUNS_SONG, RSK_SHUFFLE_ADULT_TRADE, RSK_SHUFFLE_MAGIC_BEANS, - RSK_BOMBCHUS_IN_LOGIC + RSK_BOMBCHUS_IN_LOGIC, + RSK_LINKS_POCKET } RandomizerSettingKey; typedef enum { diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 6d4b68bc0..19e384be6 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -560,10 +560,16 @@ void GiveLinkAdultTradeItem(GetItemID giid) { INV_CONTENT(ITEM_TRADE_ADULT) = item; } -void GiveLinksPocketMedallion() { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE); +void GiveLinksPocketItem() { + if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) < 3) { + GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE); - GiveLinkDungeonReward(getItemEntry.getItemId); + if (getItemEntry.modIndex == MOD_NONE) { + Item_Give(NULL, getItemEntry.itemId); + } else if (getItemEntry.modIndex == MOD_RANDOMIZER) { + Randomizer_Item_Give(NULL, getItemEntry); + } + } } /** @@ -802,7 +808,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { } // Give Link's pocket item - GiveLinksPocketMedallion(); + GiveLinksPocketItem(); int openForest = Randomizer_GetSettingValue(RSK_FOREST); switch (openForest) { From 350d0b91ede4f5931d0d90a0f0ac2d65a8fc5a72 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 3 Sep 2022 02:47:42 -0400 Subject: [PATCH 36/52] Removes unneeded `GiveLinkItem` functions. --- soh/src/code/z_sram.c | 470 +----------------------------------------- 1 file changed, 3 insertions(+), 467 deletions(-) diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 19e384be6..20d255bca 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -54,31 +54,6 @@ void GiveLinkRupees(int numOfRupees) { } } -void GiveLinkRupeesByGetItemId(GetItemID giid) { - if (giid == GI_RUPEE_GREEN) { - GiveLinkRupees(1); - } else if (giid == GI_RUPEE_BLUE) { - GiveLinkRupees(5); - } else if (giid == GI_RUPEE_RED) { - GiveLinkRupees(20); - } else if (giid == GI_RUPEE_PURPLE) { - GiveLinkRupees(50); - } else if (giid == GI_RUPEE_GOLD) { - GiveLinkRupees(100); - } -} - -void GiveLinkBombchus(GetItemID giid) { - INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU; - if (giid == GI_BOMBCHUS_5) { - AMMO(ITEM_BOMBCHU) += 5; - } else if (giid == GI_BOMBCHUS_10) { - AMMO(ITEM_BOMBCHU) += 10; - } else if (giid == GI_BOMBCHUS_20) { - AMMO(ITEM_BOMBCHU) += 20; - } -} - void GiveLinkDekuSticks(int howManySticks) { int maxStickCount; if (CUR_UPG_VALUE(UPG_STICKS) == 0) { @@ -100,16 +75,6 @@ void GiveLinkDekuSticks(int howManySticks) { } } -void GiveLinkDekuSticksByGetItemId(GetItemID giid) { - if (giid == GI_STICKS_1) { - GiveLinkDekuSticks(1); - } else if (giid == GI_STICKS_5) { - GiveLinkDekuSticks(5); - } else if (giid == GI_STICKS_10) { - GiveLinkDekuSticks(10); - } -} - void GiveLinkDekuNuts(int howManyNuts) { int maxNutCount; if (CUR_UPG_VALUE(UPG_NUTS) == 0) { @@ -131,435 +96,6 @@ void GiveLinkDekuNuts(int howManyNuts) { } } -void GiveLinkDekuNutsByGetItemId(GetItemID giid) { - if (giid == GI_NUTS_5) { - GiveLinkDekuNuts(5); - } else if (giid == GI_NUTS_10) { - GiveLinkDekuNuts(10); - } -} - -void GiveLinkBeans() { - INV_CONTENT(ITEM_BEAN) = ITEM_BEAN; - AMMO(ITEM_BEAN)++; -} - -void GiveLinkKokiriSword() { - uint32_t bitMask = 1 << 0; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkGiantsKnife() { - gSaveContext.bgsFlag = 0; - gSaveContext.swordHealth = 8; - uint32_t bitMask = 1 << 2; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkBiggoronSword() { - gSaveContext.bgsFlag = 1; - gSaveContext.swordHealth = 8; - uint32_t bitMask = 1 << 2; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkDekuShield() { - uint32_t bitMask = 1 << 4; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkHylianShield() { - uint32_t bitMask = 1 << 5; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkMirrorShield() { - uint32_t bitMask = 1 << 6; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkGoronTunic() { - uint32_t bitMask = 1 << 9; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkZoraTunic() { - uint32_t bitMask = 1 << 10; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkIronBoots() { - uint32_t bitMask = 1 << 13; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkHoverBoots() { - uint32_t bitMask = 1 << 14; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkStoneOfAgony() { - uint32_t bitMask = 1 << QUEST_STONE_OF_AGONY; - gSaveContext.inventory.questItems |= bitMask; -} - -void GiveLinkGerudoCard() { - uint32_t bitMask = 1 << QUEST_GERUDO_CARD; - gSaveContext.inventory.questItems |= bitMask; -} - -void GiveLinkPieceOfHeart() { - int32_t pohCount = (gSaveContext.inventory.questItems & 0xF0000000) >> 28; - pohCount++; - gSaveContext.inventory.questItems |= (pohCount << 28); -} - -void GiveLinkHeartContainer() { - gSaveContext.healthCapacity += 16; - gSaveContext.health += 16; -} - -void GiveLinkBulletBagUpgrade(GetItemID giid) { - if (giid == GI_SLINGSHOT) { - INV_CONTENT(ITEM_SLINGSHOT) = ITEM_SLINGSHOT; - AMMO(ITEM_SLINGSHOT) = 30; - Inventory_ChangeUpgrade(UPG_BULLET_BAG, 1); - } else if (giid == GI_BULLET_BAG_40) { - Inventory_ChangeUpgrade(UPG_BULLET_BAG, 2); - AMMO(ITEM_SLINGSHOT) = 40; - } else if (giid == GI_BULLET_BAG_50) { - Inventory_ChangeUpgrade(UPG_BULLET_BAG, 3); - AMMO(ITEM_SLINGSHOT) = 50; - } -} - -void GiveLinkQuiverUpgrade(GetItemID giid) { - if (giid == GI_BOW) { - INV_CONTENT(ITEM_BOW) = ITEM_BOW; - Inventory_ChangeUpgrade(UPG_QUIVER, 1); - AMMO(ITEM_BOW) = 30; - } else if (giid == GI_QUIVER_40) { - Inventory_ChangeUpgrade(UPG_QUIVER, 2); - AMMO(ITEM_BOW) = 40; - } else if (giid == GI_QUIVER_50) { - Inventory_ChangeUpgrade(UPG_QUIVER, 3); - AMMO(ITEM_BOW) = 50; - } -} - -void GiveLinkBombBagUpgrade(GetItemID giid) { - if (giid == GI_BOMB_BAG_20) { - INV_CONTENT(ITEM_BOMB) = ITEM_BOMB; - Inventory_ChangeUpgrade(UPG_BOMB_BAG, 1); - AMMO(ITEM_BOMB) = 20; - } else if (giid == GI_BOMB_BAG_30) { - Inventory_ChangeUpgrade(UPG_BOMB_BAG, 2); - AMMO(ITEM_BOMB) = 30; - } else if (giid == GI_BOMB_BAG_40) { - Inventory_ChangeUpgrade(UPG_BOMB_BAG, 3); - AMMO(ITEM_BOMB) = 40; - } -} - -void GiveLinkStrengthUpgrade(GetItemID giid) { - if (giid == GI_BRACELET) { - Inventory_ChangeUpgrade(UPG_STRENGTH, 1); - } else if (giid == GI_GAUNTLETS_SILVER) { - Inventory_ChangeUpgrade(UPG_STRENGTH, 2); - } else if (giid == GI_GAUNTLETS_GOLD) { - Inventory_ChangeUpgrade(UPG_STRENGTH, 3); - } -} - -void GiveLinkScaleUpgrade(GetItemID giid) { - if (giid == GI_SCALE_SILVER) { - Inventory_ChangeUpgrade(UPG_SCALE, 1); - } else if (giid == GI_SCALE_GOLD) { - Inventory_ChangeUpgrade(UPG_SCALE, 2); - } -} - -void GiveLinkWalletUpgrade(GetItemID giid) { - if (giid == GI_WALLET_ADULT) { - Inventory_ChangeUpgrade(UPG_WALLET, 1); - } else if (giid == GI_WALLET_GIANT) { - Inventory_ChangeUpgrade(UPG_WALLET, 2); - } -} - -void GiveLinkDekuStickUpgrade(GetItemID giid) { - if (giid == GI_STICK_UPGRADE_20) { - INV_CONTENT(ITEM_STICK) = ITEM_STICK; - Inventory_ChangeUpgrade(UPG_STICKS, 2); - AMMO(ITEM_STICK) = 20; - } else if (giid == GI_STICK_UPGRADE_30) { - Inventory_ChangeUpgrade(UPG_STICKS, 3); - AMMO(ITEM_STICK) = 30; - } -} - -void GiveLinkDekuNutUpgrade(GetItemID giid) { - if (giid == GI_NUT_UPGRADE_30) { - INV_CONTENT(ITEM_NUT) = ITEM_NUT; - Inventory_ChangeUpgrade(UPG_NUTS, 2); - AMMO(ITEM_NUT) = 30; - } else if (giid == GI_NUT_UPGRADE_40) { - Inventory_ChangeUpgrade(UPG_NUTS, 3); - AMMO(ITEM_NUT) = 40; - } -} - -void GiveLinkSkullToken() { - gSaveContext.inventory.questItems |= gBitFlags[QUEST_SKULL_TOKEN]; - gSaveContext.inventory.gsTokens++; -} - -void GiveLinkMagic(GetItemID giid) { - if (giid == RG_MAGIC_SINGLE) { - gSaveContext.magicLevel = 1; - gSaveContext.magicAcquired = true; - gSaveContext.doubleMagic = false; - } else if (giid == RG_MAGIC_DOUBLE) { - gSaveContext.magicLevel = 2; - gSaveContext.magicAcquired = true; - gSaveContext.doubleMagic = true; - } -} - -void GiveLinkDoubleDefense() { - gSaveContext.doubleDefense = 1; - gSaveContext.inventory.defenseHearts = 20; -} - -void GiveLinkSong(GetItemID getItemId) { - uint32_t bitMask; - - switch (getItemId) { - case RG_ZELDAS_LULLABY: - bitMask = 1 << QUEST_SONG_LULLABY; - break; - case RG_SUNS_SONG: - bitMask = 1 << QUEST_SONG_SUN; - break; - case RG_EPONAS_SONG: - bitMask = 1 << QUEST_SONG_EPONA; - break; - case RG_SONG_OF_STORMS: - bitMask = 1 << QUEST_SONG_STORMS; - break; - case RG_SONG_OF_TIME: - bitMask = 1 << QUEST_SONG_TIME; - break; - case RG_SARIAS_SONG: - bitMask = 1 << QUEST_SONG_SARIA; - break; - case RG_MINUET_OF_FOREST: - bitMask = 1 << QUEST_SONG_MINUET; - break; - case RG_BOLERO_OF_FIRE: - bitMask = 1 << QUEST_SONG_BOLERO; - break; - case RG_SERENADE_OF_WATER: - bitMask = 1 << QUEST_SONG_SERENADE; - break; - case RG_NOCTURNE_OF_SHADOW: - bitMask = 1 << QUEST_SONG_NOCTURNE; - break; - case RG_REQUIEM_OF_SPIRIT: - bitMask = 1 << QUEST_SONG_REQUIEM; - break; - case RG_PRELUDE_OF_LIGHT: - bitMask = 1 << QUEST_SONG_PRELUDE; - break; - } - - gSaveContext.inventory.questItems |= bitMask; -} - -void GiveLinkDungeonReward(uint16_t getItemId) { - s16 item; - - u8 medallion = 0; - - switch (getItemId) { - case RG_FOREST_MEDALLION: - item = ITEM_MEDALLION_FOREST; - medallion = 1; - break; - case RG_FIRE_MEDALLION: - item = ITEM_MEDALLION_FIRE; - medallion = 1; - break; - case RG_WATER_MEDALLION: - item = ITEM_MEDALLION_WATER; - medallion = 1; - break; - case RG_SHADOW_MEDALLION: - item = ITEM_MEDALLION_SHADOW; - medallion = 1; - break; - case RG_SPIRIT_MEDALLION: - item = ITEM_MEDALLION_SPIRIT; - medallion = 1; - break; - case RG_LIGHT_MEDALLION: - item = ITEM_MEDALLION_LIGHT; - medallion = 1; - break; - case RG_KOKIRI_EMERALD: - item = ITEM_KOKIRI_EMERALD; - break; - case RG_GORON_RUBY: - item = ITEM_GORON_RUBY; - break; - case RG_ZORA_SAPPHIRE: - item = ITEM_ZORA_SAPPHIRE; - break; - } - - if (medallion == 1) { - gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST]; - } else { - gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_KOKIRI_EMERALD + QUEST_KOKIRI_EMERALD]; - } -} - -void GiveLinkDungeonItem(GetItemID getItemId) { - int mapIndex; - - switch (getItemId) { - case RG_DEKU_TREE_MAP: - case RG_DEKU_TREE_COMPASS: - mapIndex = SCENE_YDAN; - break; - case RG_DODONGOS_CAVERN_MAP: - case RG_DODONGOS_CAVERN_COMPASS: - mapIndex = SCENE_DDAN; - break; - case RG_JABU_JABUS_BELLY_MAP: - case RG_JABU_JABUS_BELLY_COMPASS: - mapIndex = SCENE_BDAN; - break; - case RG_FOREST_TEMPLE_MAP: - case RG_FOREST_TEMPLE_COMPASS: - case RG_FOREST_TEMPLE_SMALL_KEY: - case RG_FOREST_TEMPLE_BOSS_KEY: - mapIndex = SCENE_BMORI1; - break; - case RG_FIRE_TEMPLE_MAP: - case RG_FIRE_TEMPLE_COMPASS: - case RG_FIRE_TEMPLE_SMALL_KEY: - case RG_FIRE_TEMPLE_BOSS_KEY: - mapIndex = SCENE_HIDAN; - break; - case RG_WATER_TEMPLE_MAP: - case RG_WATER_TEMPLE_COMPASS: - case RG_WATER_TEMPLE_SMALL_KEY: - case RG_WATER_TEMPLE_BOSS_KEY: - mapIndex = SCENE_MIZUSIN; - break; - case RG_SPIRIT_TEMPLE_MAP: - case RG_SPIRIT_TEMPLE_COMPASS: - case RG_SPIRIT_TEMPLE_SMALL_KEY: - case RG_SPIRIT_TEMPLE_BOSS_KEY: - mapIndex = SCENE_JYASINZOU; - break; - case RG_SHADOW_TEMPLE_MAP: - case RG_SHADOW_TEMPLE_COMPASS: - case RG_SHADOW_TEMPLE_SMALL_KEY: - case RG_SHADOW_TEMPLE_BOSS_KEY: - mapIndex = SCENE_HAKADAN; - break; - case RG_BOTTOM_OF_THE_WELL_MAP: - case RG_BOTTOM_OF_THE_WELL_COMPASS: - case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: - mapIndex = SCENE_HAKADANCH; - break; - case RG_ICE_CAVERN_MAP: - case RG_ICE_CAVERN_COMPASS: - mapIndex = SCENE_ICE_DOUKUTO; - break; - case RG_GANONS_CASTLE_BOSS_KEY: - mapIndex = SCENE_GANON; - break; - case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: - mapIndex = SCENE_MEN; - break; - case RG_GERUDO_FORTRESS_SMALL_KEY: - mapIndex = SCENE_GERUDOWAY; - break; - case RG_GANONS_CASTLE_SMALL_KEY: - mapIndex = SCENE_GANONTIKA; - break; - } - - if ((getItemId >= RG_GERUDO_FORTRESS_SMALL_KEY) && (getItemId <= RG_GANONS_CASTLE_SMALL_KEY)) { - if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { - gSaveContext.inventory.dungeonKeys[mapIndex] = 1; - } else { - gSaveContext.inventory.dungeonKeys[mapIndex]++; - } - } else { - int bitmask; - if ((getItemId >= RG_DEKU_TREE_MAP) && (getItemId <= RG_ICE_CAVERN_MAP)) { - bitmask = gBitFlags[2]; - } else if ((getItemId >= RG_DEKU_TREE_COMPASS) && (getItemId <= RG_ICE_CAVERN_COMPASS)) { - bitmask = gBitFlags[1]; - } else { - bitmask = gBitFlags[0]; - } - - gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask; - } -} - -void GiveLinkAdultTradeItem(GetItemID giid) { - ItemID item; - switch (giid) { - case GI_POCKET_EGG: - item = ITEM_POCKET_EGG; - break; - case GI_POCKET_CUCCO: - item = ITEM_POCKET_CUCCO; - break; - case GI_COJIRO: - item = ITEM_COJIRO; - break; - case GI_ODD_MUSHROOM: - item = ITEM_ODD_MUSHROOM; - break; - case GI_ODD_POTION: - item = ITEM_ODD_POTION; - break; - case GI_SAW: - item = ITEM_SAW; - break; - case GI_SWORD_BROKEN: - item = ITEM_SWORD_BROKEN; - break; - case GI_PRESCRIPTION: - item = ITEM_PRESCRIPTION; - break; - case GI_FROG: - item = ITEM_FROG; - break; - case GI_EYEDROPS: - item = ITEM_EYEDROPS; - break; - case GI_CLAIM_CHECK: - item = ITEM_CLAIM_CHECK; - break; - } - if ((item == ITEM_SAW) && CVar_GetS32("gDekuNutUpgradeFix", 0) == 0) { - gSaveContext.itemGetInf[1] |= 0x8000; - } - - if (item >= ITEM_POCKET_EGG) { - gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item); - } - INV_CONTENT(ITEM_TRADE_ADULT) = item; -} - void GiveLinksPocketItem() { if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) < 3) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE); @@ -837,8 +373,8 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { break; } - if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) GiveLinkKokiriSword(); - if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) GiveLinkDekuShield(); + if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) Item_Give(NULL, ITEM_SWORD_KOKIRI); + if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) Item_Give(NULL, ITEM_SHIELD_DEKU); if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; @@ -973,7 +509,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { gSaveContext.sceneFlags[12].collect |= (1 << 0x0C); if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { - GiveLinkGerudoCard(); + Item_Give(NULL, ITEM_GERUDO_CARD); } } From 3a6d7fcfd042880c7d14018ec267230b33c2993f Mon Sep 17 00:00:00 2001 From: briaguya Date: Sat, 3 Sep 2022 04:23:25 -0400 Subject: [PATCH 37/52] and make it build --- .../Enhancements/debugger/ImGuiHelpers.cpp | 32 -- soh/soh/Enhancements/debugger/ImGuiHelpers.h | 10 - .../Enhancements/debugger/debugSaveEditor.cpp | 3 +- .../Enhancements/randomizer/randomizer.cpp | 296 +++++++++--------- .../randomizer/randomizer_check_objects.cpp | 2 +- .../randomizer/randomizer_item_tracker.cpp | 25 +- soh/src/code/z_en_item00.c | 2 +- 7 files changed, 165 insertions(+), 205 deletions(-) delete mode 100644 soh/soh/Enhancements/debugger/ImGuiHelpers.cpp delete mode 100644 soh/soh/Enhancements/debugger/ImGuiHelpers.h diff --git a/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp b/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp deleted file mode 100644 index d0ccab0eb..000000000 --- a/soh/soh/Enhancements/debugger/ImGuiHelpers.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "ImGuiHelpers.h" -#include "../../../../libultraship/libultraship/ImGuiImpl.h" - -// Adds a text tooltip for the previous ImGui item -void SetLastItemHoverText(const std::string& text) { - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str()); - ImGui::EndTooltip(); - } -} - -// Adds a "?" next to the previous ImGui item with a custom tooltip -void InsertHelpHoverText(const std::string& text) { - ImGui::SameLine(); - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::Text(SohImGui::BreakTooltip(text, 60).c_str()); - ImGui::EndTooltip(); - } -} - -void PaddedSeparator(bool padTop, bool padBottom, float extraVerticalPadding) { - if (padTop) { - ImGui::Dummy(ImVec2(0.0f, extraVerticalPadding)); - } - ImGui::Separator(); - if (padBottom) { - ImGui::Dummy(ImVec2(0.0f, extraVerticalPadding)); - } -} diff --git a/soh/soh/Enhancements/debugger/ImGuiHelpers.h b/soh/soh/Enhancements/debugger/ImGuiHelpers.h deleted file mode 100644 index 91df059aa..000000000 --- a/soh/soh/Enhancements/debugger/ImGuiHelpers.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include "../libultraship/Lib/ImGui/imgui.h" - -#include - -void SetLastItemHoverText(const std::string& text); - -void InsertHelpHoverText(const std::string& text); - -void PaddedSeparator(bool padTop = true, bool padBottom = true, float extraVerticalPadding = 0); diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index dc365c69e..3765f5d6b 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -1,5 +1,6 @@ #include "debugSaveEditor.h" #include "../../util.h" +#include "../../OTRGlobals.h" #include #include "../../UIWidgets.hpp" @@ -623,7 +624,7 @@ void DrawInventoryTab() { gSaveContext.inventory.items[selectedIndex] = slotEntry.id; // Set adult trade item flag if you're playing adult trade shuffle in rando if (gSaveContext.n64ddFlag && - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE); + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) && selectedIndex == SLOT_TRADE_ADULT && slotEntry.id >= ITEM_POCKET_EGG && slotEntry.id <= ITEM_CLAIM_CHECK) { gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(slotEntry.id); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 4744bfd8d..a81fdb839 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3567,7 +3567,7 @@ void DrawRandoEditor(bool& open) { bool disableEditingRandoSettings = CVar_GetS32("gRandoGenerating", 0) || CVar_GetS32("gOnFileSelectNameEntry", 0); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, disableEditingRandoSettings); ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * (disableEditingRandoSettings ? 0.5f : 1.0f)); - SohImGui::EnhancementCheckbox("Enable Randomizer", "gRandomizer"); + UIWidgets::EnhancementCheckbox("Enable Randomizer", "gRandomizer"); if (CVar_GetS32("gRandomizer", 0)) { ImGui::Dummy(ImVec2(0.0f, 0.0f)); @@ -3585,7 +3585,7 @@ void DrawRandoEditor(bool& open) { // ImGui::Text("Settings File: %s", presetfilepath.c_str()); } - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGuiWindow* window = ImGui::GetCurrentWindow(); static ImVec2 cellPadding(8.0f, 8.0f); @@ -3611,7 +3611,7 @@ void DrawRandoEditor(bool& open) { // Forest ImGui::Text(Settings::OpenForest.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Closed - Kokiri sword & shield are required to access " "the Deku Tree, and completing the Deku Tree is required to " "access the Hyrule Field exit.\n" @@ -3623,26 +3623,26 @@ void DrawRandoEditor(bool& open) { "Open - Mido no longer blocks the path to the Deku Tree. Kokiri " "boy no longer blocks the path out of the forest." ); - SohImGui::EnhancementCombobox("gRandomizeForest", randoForest, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeForest", randoForest, 3, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Kakariko Gate ImGui::Text(Settings::OpenKakariko.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Closed - The gate will remain closed until Zelda's letter " "is shown to the guard.\n" "\n" "Open - The gate is always open. The happy mask shop " "will open immediately after obtaining Zelda's letter." ); - SohImGui::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeKakarikoGate", randoKakarikoGate, 2, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Door of Time ImGui::Text(Settings::OpenDoorOfTime.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Closed - The Ocarina of Time, the Song of Time and all " "three spiritual stones are required to open the Door of Time.\n" "\n" @@ -3651,13 +3651,13 @@ void DrawRandoEditor(bool& open) { "\n" "Open - The Door of Time is permanently open with no requirements." ); - SohImGui::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeDoorOfTime", randoDoorOfTime, 3, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Zora's Fountain ImGui::Text(Settings::ZorasFountain.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Closed - King Zora obstructs the way to Zora's Fountain. " "Ruto's letter must be shown as child Link in order to move " "him in both time periods.\n" @@ -3668,9 +3668,9 @@ void DrawRandoEditor(bool& open) { "Open - King Zora has already mweeped out of the way in both " "time periods. Ruto's Letter is removed from the item pool." ); - SohImGui::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeZorasFountain", randoZorasFountain, 3, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::EndChild(); @@ -3682,7 +3682,7 @@ void DrawRandoEditor(bool& open) { // Gerudo Fortress ImGui::Text("Gerudo Fortress Carpenters"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the amount of carpenters required to repair the bridge " "in Gerudo Valley.\n" "\n" @@ -3692,13 +3692,13 @@ void DrawRandoEditor(bool& open) { "\n" "Open - The bridge is repaired from the start." ); - SohImGui::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeGerudoFortress", randoGerudoFortress, 3, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Rainbow Bridge ImGui::Text("Rainbow Bridge Requirements"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Alters the requirements to open the bridge to Ganon's Castle.\n" "\n" "Vanilla - Obtain the Shadow Medallion, Spirit Medallion and Light Arrows.\n" @@ -3719,7 +3719,7 @@ void DrawRandoEditor(bool& open) { "Tokens - Obtain the specified amount of Skulltula tokens." ); - SohImGui::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 0); + UIWidgets::EnhancementCombobox("gRandomizeRainbowBridge", randoRainbowBridge, 7, 0); ImGui::PopItemWidth(); switch (CVar_GetS32("gRandomizeRainbowBridge", 0)) { case 0: @@ -3728,37 +3728,37 @@ void DrawRandoEditor(bool& open) { break; case 2: ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", + UIWidgets::EnhancementSliderInt("Stone Count: %d", "##RandoStoneCount", "gRandomizeStoneCount", 1, 3, "", 3, true); break; case 3: ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", + UIWidgets::EnhancementSliderInt("Medallion Count: %d", "##RandoMedallionCount", "gRandomizeMedallionCount", 1, 6, "", 6, true); break; case 4: ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", + UIWidgets::EnhancementSliderInt("Reward Count: %d", "##RandoRewardCount", "gRandomizeRewardCount", 1, 9, "", 9, true); break; case 5: ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", + UIWidgets::EnhancementSliderInt("Dungeon Count: %d", "##RandoDungeonCount", "gRandomizeDungeonCount", 1, 8, "", 8, true); break; case 6: ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", + UIWidgets::EnhancementSliderInt("Token Count: %d", "##RandoTokenCount", "gRandomizeTokenCount", 1, 100, "", 100, true); break; } - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Ganon's Trials ImGui::PushItemWidth(-FLT_MIN); ImGui::Text("Ganon's Trials"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the number of Ganon's Trials required to dispel the barrier.\n" "\n" "Skip - No Trials are required and the barrier is already dispelled.\n" @@ -3768,16 +3768,16 @@ void DrawRandoEditor(bool& open) { "\n" "Random Number - A Random number and set of trials will be required." ); - SohImGui::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeGanonTrial", randoGanonsTrial, 3, 0); ImGui::PopItemWidth(); if (CVar_GetS32("gRandomizeGanonTrial", 0) == 1) { ImGui::Dummy(ImVec2(0.0f, 0.0f)); - SohImGui::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", + UIWidgets::EnhancementSliderInt("Ganon's Trial Count: %d", "##RandoTrialCount", "gRandomizeGanonTrialCount", 1, 6, "", 6, true); - InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); + UIWidgets::InsertHelpHoverText("Set the number of trials required to enter Ganon's Tower."); } - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::EndChild(); @@ -3789,7 +3789,7 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Coming soon"); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::PopItemWidth(); ImGui::EndChild(); @@ -3819,7 +3819,7 @@ void DrawRandoEditor(bool& open) { // Shuffle Songs ImGui::Text(Settings::ShuffleSongs.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Song locations - Songs will only appear at locations that normally teach songs.\n" "\n" "Dungeon rewards - Songs appear after beating a major dungeon boss.\n" @@ -3831,13 +3831,13 @@ void DrawRandoEditor(bool& open) { "\n" "Anywhere - Songs can appear at any location." ); - SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Shuffle Tokens ImGui::Text(Settings::Tokensanity.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Shuffles Golden Skulltula Tokens into the item pool. This means " "Golden Skulltulas can contain other items as well.\n" "\n" @@ -3849,53 +3849,53 @@ void DrawRandoEditor(bool& open) { "\n" "All Tokens - Shuffle all 100 GS tokens." ); - SohImGui::EnhancementCombobox("gRandomizeShuffleTokens", randoTokensanity, 4, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleTokens", randoTokensanity, 4, 0); ImGui::Dummy(ImVec2(0,0)); - SohImGui::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong"); - InsertHelpHoverText( + UIWidgets::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong"); + UIWidgets::InsertHelpHoverText( "All Golden Skulltulas that require nighttime to appear will only be " "expected to be collected after getting Sun's Song." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Shuffle Kokiri Sword // Disabled when Start with Kokiri Sword is active bool disableShuffleKokiriSword = CVar_GetS32("gRandomizeStartingKokiriSword", 0); const char* disableShuffleKokiriSwordText = "This option is disabled because \"Start with Kokiri Sword\" is enabled."; - SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword", + UIWidgets::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword", disableShuffleKokiriSword, disableShuffleKokiriSwordText); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Shuffles the Kokiri Sword into the item pool.\n" "\n" "This will require the use of sticks until the Kokiri Sword is found." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Shuffle Ocarinas // Disabled when Start with Ocarina is active bool disableShuffleOcarinas = CVar_GetS32("gRandomizeStartingOcarina", 0); const char* disableShuffleOcarinasText = "This option is disabled because \"Start with Fairy Ocarina\" is enabled."; - SohImGui::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), "gRandomizeShuffleOcarinas", + UIWidgets::EnhancementCheckbox(Settings::ShuffleOcarinas.GetName().c_str(), "gRandomizeShuffleOcarinas", disableShuffleOcarinas, disableShuffleOcarinasText); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Enabling this shuffles the Fairy Ocarina and the Ocarina of Time into the item pool.\n" "\n" "This will require finding an Ocarina before being able to play songs." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Shuffle Weird Egg // Disabled when Skip Child Zelda is active bool disableShuffleWeirdEgg = CVar_GetS32("gRandomizeSkipChildZelda", 0); const char* disableShuffleWeirdEggText = "This option is disabled because \"Skip Child Zelda\" is enabled."; - SohImGui::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), "gRandomizeShuffleWeirdEgg", + UIWidgets::EnhancementCheckbox(Settings::ShuffleWeirdEgg.GetName().c_str(), "gRandomizeShuffleWeirdEgg", disableShuffleWeirdEgg, disableShuffleWeirdEggText); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Shuffles the Weird Egg from Malon in to the item pool. Enabling " "\"Skip Child Zelda\" disables this feature.\n" "\n" @@ -3907,19 +3907,19 @@ void DrawRandoEditor(bool& open) { " - Happy Mask Shop sidequest\n" ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Shuffle Gerudo Membership Card - SohImGui::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), + UIWidgets::EnhancementCheckbox(Settings::ShuffleGerudoToken.GetName().c_str(), "gRandomizeShuffleGerudoToken"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Shuffles the Gerudo Membership Card into the item pool.\n" "\n" "The Gerudo Card is required to enter the Gerudo Training Grounds, opening " "the gate to Haunted Wasteland and the Horseback Archery minigame." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::PopItemWidth(); ImGui::EndChild(); @@ -3932,7 +3932,7 @@ void DrawRandoEditor(bool& open) { // Shuffle Scrubs ImGui::Text(Settings::Scrubsanity.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Off - Scrubs will not be shuffled. The 3 Scrubs that give one-time items in the vanilla game " "(PoH, Deku Nut capacity, and Deku Stick capacity) will have random items.\n" "\n" @@ -3941,27 +3941,27 @@ void DrawRandoEditor(bool& open) { "Expensive - Scrubs will be shuffled and their item will cost the vanilla price.\n" "\n" "Random - Scrubs will be shuffled and their item will cost will be between 0-95 rupees.\n"); - SohImGui::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleScrubs", randoShuffleScrubs, 4, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Shuffle Cows - SohImGui::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); - InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); + UIWidgets::EnhancementCheckbox(Settings::ShuffleCows.GetName().c_str(), "gRandomizeShuffleCows"); + UIWidgets::InsertHelpHoverText("Cows give a randomized item from the pool upon performing Epona's Song in front of them."); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); - SohImGui::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), "gRandomizeShuffleBeans"); - InsertHelpHoverText( + UIWidgets::EnhancementCheckbox(Settings::ShuffleMagicBeans.GetName().c_str(), "gRandomizeShuffleBeans"); + UIWidgets::InsertHelpHoverText( "Enabling this adds a pack of 10 beans to the item pool and changes the Magic Bean " "Salesman to sell a random item at a price of 60 rupees." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Shuffle Frog Song Rupees - SohImGui::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees"); - InsertHelpHoverText( + UIWidgets::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees"); + UIWidgets::InsertHelpHoverText( "Shuffles 5 Purple Rupees into to the item pool, and allows\n" "you to earn items by playing songs at the Frog Choir.\n" "\n" @@ -3969,12 +3969,12 @@ void DrawRandoEditor(bool& open) { "the Song of Storms and the frog song minigame." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Shuffle Adult Trade Quest - SohImGui::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), + UIWidgets::EnhancementCheckbox(Settings::ShuffleAdultTradeQuest.GetName().c_str(), "gRandomizeShuffleAdultTrade"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Adds all of the adult trade quest items into the pool, each of which " "can be traded for a unique reward.\n" "\n" @@ -3985,7 +3985,7 @@ void DrawRandoEditor(bool& open) { "If disabled, only the Claim Check will be found in the pool." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::PopItemWidth(); ImGui::EndChild(); @@ -3998,7 +3998,7 @@ void DrawRandoEditor(bool& open) { // Shuffle Dungeon Rewards ImGui::Text(Settings::ShuffleRewards.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Shuffles the location of spiritual stones and medallions.\n" "\n" "End of dungeons - Spiritual stones and medallions will be given as rewards " @@ -4010,13 +4010,13 @@ void DrawRandoEditor(bool& open) { "\n" "Anywhere - Spiritual stones and medallions can appear anywhere." ); - SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); + UIWidgets::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Maps & Compasses ImGui::Text(Settings::MapsAndCompasses.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Start with - You will start with Maps & Compasses from all dungeons.\n" "\n" "Vanilla - Maps & Compasses will appear in their vanilla locations.\n" @@ -4029,13 +4029,13 @@ void DrawRandoEditor(bool& open) { "\n" "Anywhere - Maps & Compasses can appear anywhere in the world." ); - SohImGui::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2); + UIWidgets::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Keysanity ImGui::Text(Settings::Keysanity.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Start with - You will start with all Small Keys from all dungeons.\n" "\n" "Vanilla - Small Keys will appear in their vanilla locations.\n" @@ -4048,13 +4048,13 @@ void DrawRandoEditor(bool& open) { "\n" "Anywhere - Small Keys can appear anywhere in the world." ); - SohImGui::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, 2); + UIWidgets::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, 2); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Gerudo Keys ImGui::Text(Settings::GerudoKeys.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n" "\n" "Any dungeon - Thieve's Hideout Keys can only appear inside of any dungon.\n" @@ -4063,13 +4063,13 @@ void DrawRandoEditor(bool& open) { "\n" "Anywhere - Thieve's Hideout Keys can appear anywhere in the world." ); - SohImGui::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, 0); + UIWidgets::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Boss Keysanity ImGui::Text(Settings::BossKeysanity.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Start with - You will start with Boss keys from all dungeons.\n" "\n" "Vanilla - Boss Keys will appear in their vanilla locations.\n" @@ -4082,13 +4082,13 @@ void DrawRandoEditor(bool& open) { "\n" "Anywhere - Boss Keys can appear anywhere in the world." ); - SohImGui::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2); + UIWidgets::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Ganon's Boss Key ImGui::Text(Settings::GanonsBossKey.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Vanilla - Ganon's Boss Key will appear in the vanilla location.\n" "\n" "Own dungeon - Ganon's Boss Key can appear anywhere inside Ganon's Castle.\n" @@ -4101,9 +4101,9 @@ void DrawRandoEditor(bool& open) { "\n" "Anywhere - Ganon's Boss Key Key can appear anywhere in the world." ); - SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1); + UIWidgets::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::PopItemWidth(); ImGui::EndChild(); @@ -4130,53 +4130,53 @@ void DrawRandoEditor(bool& open) { ImGui::BeginChild("ChildTimeSavers", ImVec2(0, -8)); // Cuccos to return - SohImGui::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", + UIWidgets::EnhancementSliderInt("Cuccos to return: %d", "##RandoCuccosToReturn", "gRandomizeCuccosToReturn", 0, 7, "", 7, true); - InsertHelpHoverText("The amount of cuccos needed to claim the reward from Anju the cucco lady"); + UIWidgets::InsertHelpHoverText("The amount of cuccos needed to claim the reward from Anju the cucco lady"); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Big Poe Target Count - SohImGui::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", + UIWidgets::EnhancementSliderInt("Big Poe Target Count: %d", "##RandoBigPoeTargetCount", "gRandomizeBigPoeTargetCount", 1, 10, "", 10, true); - InsertHelpHoverText("The Poe collector will give a reward for turning in this many Big Poes."); + UIWidgets::InsertHelpHoverText("The Poe collector will give a reward for turning in this many Big Poes."); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Skip child stealth // Disabled when Skip Child Zelda is active bool disableChildStealth = CVar_GetS32("gRandomizeSkipChildZelda", 0); const char* disableChildStealthText = "This option is disabled because \"Skip Child Zelda\" is enabled"; - SohImGui::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), "gRandomizeSkipChildStealth", disableChildStealth, disableChildStealthText); - InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); + UIWidgets::EnhancementCheckbox(Settings::SkipChildStealth.GetName().c_str(), "gRandomizeSkipChildStealth", disableChildStealth, disableChildStealthText); + UIWidgets::InsertHelpHoverText("The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Skip child zelda - SohImGui::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); - InsertHelpHoverText("Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " + UIWidgets::EnhancementCheckbox("Skip Child Zelda", "gRandomizeSkipChildZelda"); + UIWidgets::InsertHelpHoverText("Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg."); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Skip Epona race - SohImGui::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), "gRandomizeSkipEponaRace"); - InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); + UIWidgets::EnhancementCheckbox(Settings::SkipEponaRace.GetName().c_str(), "gRandomizeSkipEponaRace"); + UIWidgets::InsertHelpHoverText("Epona can be summoned with Epona's Song without needing to race Ingo."); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Skip tower escape - SohImGui::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), "gRandomizeSkipTowerEscape"); - InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); + UIWidgets::EnhancementCheckbox(Settings::SkipTowerEscape.GetName().c_str(), "gRandomizeSkipTowerEscape"); + UIWidgets::InsertHelpHoverText("The tower escape sequence between Ganondorf and Ganon will be skipped."); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Complete mask quest - SohImGui::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), + UIWidgets::EnhancementCheckbox(Settings::CompleteMaskQuest.GetName().c_str(), "gRandomizeCompleteMaskQuest"); - InsertHelpHoverText("Once the happy mask shop is opened, all masks will be available to be borrowed."); + UIWidgets::InsertHelpHoverText("Once the happy mask shop is opened, all masks will be available to be borrowed."); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::EndChild(); @@ -4188,7 +4188,7 @@ void DrawRandoEditor(bool& open) { // Item Pool Settings ImGui::Text(Settings::ItemPoolValue.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets how many major items appear in the item pool.\n" "\n" "Plentiful - Extra major items are added to the pool.\n" @@ -4199,12 +4199,12 @@ void DrawRandoEditor(bool& open) { "\n" "Minimal - Most excess items are removed." ); - SohImGui::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); - PaddedSeparator(); + UIWidgets::EnhancementCombobox("gRandomizeItemPool", randoItemPool, 4, 1); + UIWidgets::PaddedSeparator(); // Ice Traps ImGui::Text(Settings::IceTrapValue.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets how many items are replaced by ice traps.\n" "\n" "Off - No ice traps.\n" @@ -4218,13 +4218,13 @@ void DrawRandoEditor(bool& open) { "Onslaught - All junk items will be replaced by Ice Traps, even those " "in the base pool." ); - SohImGui::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); + UIWidgets::EnhancementCombobox("gRandomizeIceTraps", randoIceTraps, 5, 1); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Gossip Stone Hints ImGui::Text(Settings::GossipStoneHints.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Allows Gossip Stones to provide hints on item locations. Hints mentioning " "\"Way of the Hero\" indicate a location that holds an item required to beat " "the seed.\n" @@ -4236,13 +4236,13 @@ void DrawRandoEditor(bool& open) { "Need Stone of Agony - Hints are only available after obtaining the Stone of Agony.\n" "\n" "Need Mask of Truth - Hints are only available whilst wearing the Mask of Truth.\n"); - SohImGui::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); + UIWidgets::EnhancementCombobox("gRandomizeGossipStoneHints", randoGossipStoneHints, 4, 1); if (CVar_GetS32("gRandomizeGossipStoneHints", 1) != 0) { // Hint Clarity ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Indent(); ImGui::Text(Settings::ClearerHints.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets the difficulty of hints.\n" "\n" "Obscure - Hints are unique for each item, but the writing may be cryptic.\n" @@ -4254,12 +4254,12 @@ void DrawRandoEditor(bool& open) { "Clear - Hints are clearly written and are unique for each item.\n" "Ex: Kokiri Sword > the Kokiri Sword" ); - SohImGui::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); + UIWidgets::EnhancementCombobox("gRandomizeHintClarity", randoHintClarity, 3, 2); // Hint Distribution ImGui::Dummy(ImVec2(0.0f, 0.0f)); ImGui::Text(Settings::HintDistribution.GetName().c_str()); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Sets how many hints will be useful.\n" "\n" "Useless - Only junk hints.\n" @@ -4270,11 +4270,11 @@ void DrawRandoEditor(bool& open) { "\n" "Very Strong - Many powerful hints." ); - SohImGui::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); + UIWidgets::EnhancementCombobox("gRandomizeHintDistribution", randoHintDistribution, 4, 1); ImGui::Unindent(); } - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::PopItemWidth(); ImGui::EndChild(); @@ -4285,14 +4285,14 @@ void DrawRandoEditor(bool& open) { ImGui::BeginChild("ChildAdditionalFeatures", ImVec2(0, -8)); ImGui::PushItemWidth(-FLT_MIN); - SohImGui::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); - InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); + UIWidgets::EnhancementCheckbox("Full Wallets", "gRandomizeFullWallets"); + UIWidgets::InsertHelpHoverText("Start with a full wallet. All wallet upgrades come filled with rupees."); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Bombchus in Logic - SohImGui::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), "gRandomizeBombchusInLogic"); - InsertHelpHoverText( + UIWidgets::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), "gRandomizeBombchusInLogic"); + UIWidgets::InsertHelpHoverText( "Bombchus are properly considered in logic.\n" "\n" "The first Bombchu pack will always be 20, and subsequent packs will be " @@ -4302,23 +4302,23 @@ void DrawRandoEditor(bool& open) { "Bombchu Bowling is opened by obtaining Bombchus." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); - SohImGui::EnhancementCheckbox("WIP - Blue Fire Arrows", "gRandomizeBlueIceArrows", true, "In development"); - InsertHelpHoverText( + UIWidgets::EnhancementCheckbox("WIP - Blue Fire Arrows", "gRandomizeBlueIceArrows", true, "In development"); + UIWidgets::InsertHelpHoverText( "Ice Arrows act like Blue Fire, making them able to melt red ice. " "Item placement logic will respect this option, so it might be required to use this to progress." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); - SohImGui::EnhancementCheckbox("WIP - Sunlight Arrows", "gRandomizeSunlightArrows", true, "In development"); - InsertHelpHoverText( + UIWidgets::EnhancementCheckbox("WIP - Sunlight Arrows", "gRandomizeSunlightArrows", true, "In development"); + UIWidgets::InsertHelpHoverText( "Light Arrows can be used to light up the sun switches instead of using the Mirror Shield. " "Item placement logic will respect this option, so it might be required to use this to progress." ); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::PopItemWidth(); ImGui::EndChild(); @@ -4386,7 +4386,7 @@ void DrawRandoEditor(bool& open) { excludedLocationString += ","; } CVar_SetString("gRandomizeExcludedLocations", excludedLocationString.c_str()); - SohImGui::needs_save = true; + SohImGui::RequestCvarSaveOnNextTick(); } ImGui::SameLine(); ImGui::Text(locationIt.rcShortName.c_str()); @@ -4427,7 +4427,7 @@ void DrawRandoEditor(bool& open) { excludedLocationString += ","; } CVar_SetString("gRandomizeExcludedLocations", excludedLocationString.c_str()); - SohImGui::needs_save = true; + SohImGui::RequestCvarSaveOnNextTick(); } ImGui::SameLine(); ImGui::Text(locationIt.rcShortName.c_str()); @@ -4455,19 +4455,19 @@ void DrawRandoEditor(bool& open) { ImGui::TableNextColumn(); ImGui::PushItemWidth(170.0); ImGui::Text("Logic Rules"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "Glitchless - No glitches are required, but may require some minor tricks.\n" "\n" "No logic - Item placement is completely random. MAY BE IMPOSSIBLE TO BEAT." ); - SohImGui::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, 2, 0); + UIWidgets::EnhancementCombobox("gRandomizeLogicRules", randoLogicRules, 2, 0); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); // Enable Glitch-Useful Cutscenes - SohImGui::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), + UIWidgets::EnhancementCheckbox(Settings::EnableGlitchCutscenes.GetName().c_str(), "gRandomizeEnableGlitchCutscenes"); - InsertHelpHoverText( + UIWidgets::InsertHelpHoverText( "The cutscenes of the Poes in Forest Temple and Darunia in Fire Temple will not be skipped. " "These cutscenes are only useful for glitched gameplay and can be safely skipped otherwise."); @@ -4525,17 +4525,17 @@ void DrawRandoEditor(bool& open) { // TODO: Show this but disabled when we have options for disabled Comboboxes. if (CVar_GetS32("gRandomizeShuffleDungeonReward", 0) != 0) { ImGui::Text(Settings::LinksPocketItem.GetName().c_str()); - SohImGui::EnhancementCombobox("gRandomizeLinksPocket", randoLinksPocket, 4, 0); - PaddedSeparator(); + UIWidgets::EnhancementCombobox("gRandomizeLinksPocket", randoLinksPocket, 4, 0); + UIWidgets::PaddedSeparator(); } - SohImGui::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), + UIWidgets::EnhancementCheckbox(Settings::StartingKokiriSword.GetName().c_str(), "gRandomizeStartingKokiriSword"); - PaddedSeparator(); - SohImGui::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), + UIWidgets::PaddedSeparator(); + UIWidgets::EnhancementCheckbox(Settings::StartingDekuShield.GetName().c_str(), "gRandomizeStartingDekuShield"); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::EndChild(); @@ -4544,11 +4544,11 @@ void DrawRandoEditor(bool& open) { window->DC.CurrLineTextBaseOffset = 0.0f; ImGui::BeginChild("ChildStartingItems", ImVec2(0, -8)); - SohImGui::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), "gRandomizeStartingOcarina"); - PaddedSeparator(); - SohImGui::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), + UIWidgets::EnhancementCheckbox(Settings::StartingOcarina.GetName().c_str(), "gRandomizeStartingOcarina"); + UIWidgets::PaddedSeparator(); + UIWidgets::EnhancementCheckbox(Settings::StartingConsumables.GetName().c_str(), "gRandomizeStartingConsumables"); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::EndChild(); @@ -4559,7 +4559,7 @@ void DrawRandoEditor(bool& open) { ImGui::Text("Coming soon"); - PaddedSeparator(); + UIWidgets::PaddedSeparator(); ImGui::EndChild(); ImGui::EndTable(); diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index 67327985b..0f3031887 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include /* typedef struct { diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 38fdcc43c..3696fa67f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -7,6 +7,7 @@ #include #include #include +#include extern "C" { #include @@ -349,7 +350,7 @@ void DrawEquip(ItemTrackerItem item) { ImGui::Image(SohImGui::GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(item.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id)); } void DrawQuest(ItemTrackerItem item) { @@ -365,7 +366,7 @@ void DrawQuest(ItemTrackerItem item) { ImGui::EndGroup(); - SetLastItemHoverText(SohUtils::GetQuestItemName(item.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(item.id)); }; void DrawItem(ItemTrackerItem item) { @@ -416,7 +417,7 @@ void DrawItem(ItemTrackerItem item) { DrawItemCount(item); ImGui::EndGroup(); - SetLastItemHoverText(SohUtils::GetItemName(item.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id)); } void DrawBottle(ItemTrackerItem item) { @@ -431,7 +432,7 @@ void DrawBottle(ItemTrackerItem item) { ImGui::Image(SohImGui::GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetItemName(item.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id)); }; void DrawDungeonItem(ItemTrackerItem item) { @@ -469,7 +470,7 @@ void DrawDungeonItem(ItemTrackerItem item) { } ImGui::EndGroup(); - SetLastItemHoverText(SohUtils::GetItemName(item.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetItemName(item.id)); } void DrawSong(ItemTrackerItem item) { @@ -480,7 +481,7 @@ void DrawSong(ItemTrackerItem item) { ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y)); ImGui::Image(SohImGui::GetTextureByName(hasSong && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize / 1.5, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - SetLastItemHoverText(SohUtils::GetQuestItemName(item.id)); + UIWidgets::SetLastItemHoverText(SohUtils::GetQuestItemName(item.id)); } void DrawNotes(bool resizeable = false) { @@ -645,7 +646,7 @@ void LabeledComboBoxRightAligned(const char* label, const char* cvar, std::vecto for (int i = 0; i < options.size(); i++) { if (ImGui::Selectable(options[i].c_str())) { CVar_SetS32(cvar, i); - SohImGui::needs_save = true; + SohImGui::RequestCvarSaveOnNextTick(); shouldUpdateVectors = true; } } @@ -662,7 +663,7 @@ void PaddedEnhancementCheckbox(const char* text, const char* cvarName, s32 defau bool val = (bool)CVar_GetS32(cvarName, defaultValue); if (ImGui::Checkbox(text, &val)) { CVar_SetS32(cvarName, val); - SohImGui::needs_save = true; + SohImGui::RequestCvarSaveOnNextTick(); shouldUpdateVectors = true; } if (padBottom) { @@ -856,7 +857,7 @@ void DrawItemTrackerOptions(bool& open) { CVar_SetFloat("gItemTrackerBgColorG", ChromaKeyBackground.y); CVar_SetFloat("gItemTrackerBgColorB", ChromaKeyBackground.z); CVar_SetFloat("gItemTrackerBgColorA", ChromaKeyBackground.w); - SohImGui::needs_save = true; + SohImGui::RequestCvarSaveOnNextTick(); } ImGui::PopItemWidth(); @@ -871,9 +872,9 @@ void DrawItemTrackerOptions(bool& open) { LabeledComboBoxRightAligned("Combo Button 2", "gItemTrackerComboButton2", { "A", "B", "C-Up", "C-Down", "C-Left", "C-Right", "L", "Z", "R", "Start", "D-Up", "D-Down", "D-Left", "D-Right" }, 8); } } - PaddedSeparator(); - SohImGui::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gItemTrackerIconSize", 25, 128, "", 36, true); - SohImGui::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gItemTrackerIconSpacing", -5, 50, "", 12, true); + UIWidgets::PaddedSeparator(); + UIWidgets::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gItemTrackerIconSize", 25, 128, "", 36, true); + UIWidgets::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gItemTrackerIconSpacing", -5, 50, "", 12, true); PaddedEnhancementCheckbox("Display \"Current/Max\" values", "gItemTrackerDisplayCurrentMax", 0); if (CVar_GetS32("gItemTrackerDisplayCurrentMax", 0) == 0) { PaddedEnhancementCheckbox("Align count to left side", "gItemTrackerCurrentOnLeft", 0); diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 7d955e77d..986d5a135 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -519,7 +519,7 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) { if (!gSaveContext.n64ddFlag) { func_8002F554(&this->actor, globalCtx, getItemId); } else { - getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId); GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } } From ea4e0652e7c3a3ba114af032bc0d683bbc1972fa Mon Sep 17 00:00:00 2001 From: briaguya Date: Sat, 3 Sep 2022 04:41:43 -0400 Subject: [PATCH 38/52] bring back new rando dropdown --- soh/soh/GameMenuBar.cpp | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index cf843cc8b..26b4b1ffb 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -1350,7 +1350,7 @@ namespace GameMenuBar { SohImGui::RequestCvarSaveOnNextTick(); SohImGui::EnableWindow("Randomizer Settings", CVar_GetS32("gRandomizerSettingsEnabled", 0)); } - UIWidgets::Spacer(0); + ImGui::Dummy(ImVec2(0.0f, 0.0f)); if (ImGui::Button(GetWindowButtonText("Item Tracker", CVar_GetS32("gItemTrackerEnabled", 0)).c_str(), buttonSize)) { bool currentValue = CVar_GetS32("gItemTrackerEnabled", 0); @@ -1358,9 +1358,42 @@ namespace GameMenuBar { SohImGui::RequestCvarSaveOnNextTick(); SohImGui::EnableWindow("Item Tracker", CVar_GetS32("gItemTrackerEnabled", 0)); } + ImGui::Dummy(ImVec2(0.0f, 0.0f)); + if (ImGui::Button(GetWindowButtonText("Item Tracker Settings", CVar_GetS32("gItemTrackerSettingsEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gItemTrackerSettingsEnabled", 0); + CVar_SetS32("gItemTrackerSettingsEnabled", !currentValue); + SohImGui::RequestCvarSaveOnNextTick(); + SohImGui::EnableWindow("Item Tracker Settings", CVar_GetS32("gItemTrackerSettingsEnabled", 0)); + } ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); + UIWidgets::PaddedSeparator(); + + if (ImGui::BeginMenu("Rando Enhancements")) + { + UIWidgets::EnhancementCheckbox("Rando-Relevant Navi Hints", "gRandoRelevantNavi"); + UIWidgets::Tooltip( + "Replace Navi's overworld quest hints with rando-related gameplay hints." + ); + UIWidgets::PaddedEnhancementCheckbox("Random Rupee Names", "gRandomizeRupeeNames", true, false); + UIWidgets::Tooltip( + "When obtaining rupees, randomize what the rupee is called in the textbox." + ); + UIWidgets::PaddedEnhancementCheckbox("Key Colors Match Dungeon", "gRandoMatchKeyColors", true, false); + UIWidgets::Tooltip( + "Matches the color of small keys and boss keys to the dungeon they belong to. " + "This helps identify keys from afar and adds a little bit of flair.\n\nThis only " + "applies to seeds with keys and boss keys shuffled to Any Dungeon, Overworld, or Anywhere."); + UIWidgets::PaddedEnhancementCheckbox("Quest Item Fanfares", "gRandoQuestItemFanfares", true, false); + UIWidgets::Tooltip( + "Play unique fanfares when obtaining quest items " + "(medallions/stones/songs). Note that these fanfares are longer than usual." + ); + ImGui::EndMenu(); + } + ImGui::EndMenu(); } } From f1dc980de84766053a8fe28420ca1701d4367432 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 3 Sep 2022 11:16:43 +0200 Subject: [PATCH 39/52] Fixed autobreak after ImGui cleanup --- soh/soh/UIWidgets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index d61ddc0f9..148a820c2 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -25,7 +25,7 @@ namespace UIWidgets { std::string newText(text); const size_t tipLength = newText.length(); int lastSpace = -1; - size_t currentLineLength = 0; + int currentLineLength = 0; for (unsigned int currentCharacter = 0; currentCharacter < tipLength; currentCharacter++) { if (newText[currentCharacter] == '\n') { currentLineLength = 0; From 3aefd4c5192c044492ace6004639d94c81df76ee Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 3 Sep 2022 12:47:32 +0200 Subject: [PATCH 40/52] gSaveContext access in GameMenuBar.cpp --- soh/soh/GameMenuBar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index 26b4b1ffb..e9db4c949 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -24,6 +24,7 @@ #include "UIWidgets.hpp" #include "include/z64audio.h" +#include "include/variables.h" #define EXPERIMENTAL() \ ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ From 8d2f63419f94b26e4bcdd4f8618b0dbcf03c20b5 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 3 Sep 2022 14:40:41 +0200 Subject: [PATCH 41/52] Implement Skip Scarecrow's Song --- soh/soh/Enhancements/randomizer/3drando/logic.cpp | 2 +- soh/soh/Enhancements/randomizer/3drando/settings.cpp | 4 +++- .../Enhancements/randomizer/3drando/spoiler_log.cpp | 3 ++- soh/soh/Enhancements/randomizer/randomizer.cpp | 12 ++++++++++++ soh/soh/Enhancements/randomizer/randomizerTypes.h | 1 + soh/soh/GameMenuBar.cpp | 9 +++++++-- .../overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c | 10 ++++++---- 7 files changed, 32 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/logic.cpp b/soh/soh/Enhancements/randomizer/3drando/logic.cpp index f85e4ed2a..f23c78649 100644 --- a/soh/soh/Enhancements/randomizer/3drando/logic.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/logic.cpp @@ -685,7 +685,7 @@ namespace Logic { MasterSword = MasterSword || IsAdult; BiggoronSword = BiggoronSword || ProgressiveGiantKnife >= 2; - ScarecrowSong = ScarecrowSong || (ChildScarecrow && AdultScarecrow); + ScarecrowSong = ScarecrowSong || FreeScarecrow || (ChildScarecrow && AdultScarecrow); Scarecrow = Hookshot && CanPlay(ScarecrowSong); DistantScarecrow = Longshot && CanPlay(ScarecrowSong); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index dba8859e9..ed53f12f6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -258,7 +258,7 @@ namespace Settings { Option SkipTowerEscape = Option::Bool("Skip Tower Escape", {"Don't Skip", "Skip"}, {skipTowerEscapeDesc}, OptionCategory::Setting, SKIP); Option SkipEponaRace = Option::Bool("Skip Epona Race", {"Don't Skip", "Skip"}, {skipEponaRaceDesc}); Option SkipMinigamePhases = Option::Bool("Minigames repetitions", {"Don't Skip", "Skip"}, {skipMinigamePhasesDesc}); - Option FreeScarecrow = Option::Bool("Free Scarecrow", {"Off", "On"}, {freeScarecrowDesc}); + Option FreeScarecrow = Option::Bool("Skip Scarecrow's Song", {"Off", "On"}, {freeScarecrowDesc}); Option FourPoesCutscene = Option::Bool("Four Poes Cutscene", {"Don't Skip", "Skip"}, {fourPoesDesc}, OptionCategory::Setting, SKIP); Option LakeHyliaOwl = Option::Bool("Lake Hylia Owl", {"Don't Skip", "Skip"}, {lakeHyliaOwlDesc}, OptionCategory::Setting, SKIP); Option BigPoeTargetCount = Option::U8 ("Big Poe Target Count", {NumOpts(1, 10)}, {bigPoeTargetCountDesc}); @@ -2588,6 +2588,8 @@ namespace Settings { CompleteMaskQuest.SetSelectedIndex(cvarSettings[RSK_COMPLETE_MASK_QUEST]); + FreeScarecrow.SetSelectedIndex(cvarSettings[RSK_SKIP_SCARECROWS_SONG]); + EnableGlitchCutscenes.SetSelectedIndex(cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES]); NightGSExpectSuns.SetSelectedIndex(cvarSettings[RSK_SKULLS_SUNS_SONG]); diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 09f98f6ce..461b54cb9 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -346,7 +346,8 @@ static void WriteSettings(const bool printAll = false) { setting->GetName() == "Skip Epona Race" || setting->GetName() == "Skip Tower Escape" || setting->GetName() == "Skip Child Stealth" || - setting->GetName() == "Complete Mask Quest" || + setting->GetName() == "Complete Mask Quest" || + setting->GetName() == "Skip Scarecrow's Song" || setting->GetName() == "Enable Glitch-Useful Cutscenes") { std::string settingName = menu->name + ":" + setting->GetName(); jsonData["settings"][settingName] = setting->GetSelectedOptionText(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index a81fdb839..7dfa20c3b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -595,6 +595,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "Timesaver Settings:Skip Epona Race", RSK_SKIP_EPONA_RACE }, { "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE }, { "Timesaver Settings:Complete Mask Quest", RSK_COMPLETE_MASK_QUEST }, + { "Timesaver Settings:Skip Scarecrow's Song", RSK_SKIP_SCARECROWS_SONG }, { "Timesaver Settings:Enable Glitch-Useful Cutscenes", RSK_ENABLE_GLITCH_CUTSCENES }, }; @@ -823,6 +824,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { case RSK_STARTING_DEKU_SHIELD: case RSK_STARTING_KOKIRI_SWORD: case RSK_COMPLETE_MASK_QUEST: + case RSK_SKIP_SCARECROWS_SONG: case RSK_ENABLE_GLITCH_CUTSCENES: case RSK_BOMBCHUS_IN_LOGIC: if(it.value() == "Off") { @@ -3466,6 +3468,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SKIP_EPONA_RACE] = CVar_GetS32("gRandomizeSkipEponaRace", 0); cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVar_GetS32("gRandomizeSkipTowerEscape", 0); cvarSettings[RSK_COMPLETE_MASK_QUEST] = CVar_GetS32("gRandomizeCompleteMaskQuest", 0); + cvarSettings[RSK_SKIP_SCARECROWS_SONG] = CVar_GetS32("gRandomizeSkipScarecrowsSong", 0); cvarSettings[RSK_ENABLE_GLITCH_CUTSCENES] = CVar_GetS32("gRandomizeEnableGlitchCutscenes", 0); cvarSettings[RSK_SKULLS_SUNS_SONG] = CVar_GetS32("gRandomizeGsExpectSunsSong", 0); @@ -4178,6 +4181,15 @@ void DrawRandoEditor(bool& open) { UIWidgets::PaddedSeparator(); + // Skip Scarecrow Song + UIWidgets::EnhancementCheckbox(Settings::FreeScarecrow.GetName().c_str(), + "gRandomizeSkipScarecrowsSong"); + UIWidgets::InsertHelpHoverText( + "Start with the ability to summon Pierre the scarecrow. Pulling out an ocarina in the usual locations will automatically summon him." + ); + + UIWidgets::PaddedSeparator(); + ImGui::EndChild(); // COLUMN 2 - Item Pool & Hint Settings diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 064cdc499..9619f7db3 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1014,6 +1014,7 @@ typedef enum { RSK_SKIP_EPONA_RACE, RSK_SKIP_TOWER_ESCAPE, RSK_COMPLETE_MASK_QUEST, + RSK_SKIP_SCARECROWS_SONG, RSK_ENABLE_GLITCH_CUTSCENES, RSK_SKULLS_SUNS_SONG, RSK_SHUFFLE_ADULT_TRADE, diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index e9db4c949..4e27c5777 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -23,8 +23,8 @@ #endif #include "UIWidgets.hpp" +#include "include/global.h" #include "include/z64audio.h" -#include "include/variables.h" #define EXPERIMENTAL() \ ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \ @@ -689,8 +689,13 @@ namespace GameMenuBar { UIWidgets::PaddedEnhancementCheckbox("Better Owl", "gBetterOwl", true, false); UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said"); UIWidgets::PaddedEnhancementCheckbox("Fast Ocarina Playback", "gFastOcarinaPlayback", true, false); + bool forceSkipScarecrow = gSaveContext.n64ddFlag && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SKIP_SCARECROWS_SONG); + const char* forceSkipScarecrowText = + "This setting is forcefully enabled because a savefile\nwith \"Skip Scarecrow Song\" is loaded"; UIWidgets::Tooltip("Skip the part where the Ocarina playback is called when you play a song"); - UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false); + UIWidgets::PaddedEnhancementCheckbox("Skip Scarecrow Song", "gSkipScarecrow", true, false, + forceSkipScarecrow, forceSkipScarecrowText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Pierre appears when Ocarina is pulled out. Requires learning scarecrow song."); UIWidgets::PaddedEnhancementCheckbox("Instant Putaway", "gInstantPutaway", true, false); UIWidgets::Tooltip("Allow Link to put items away without having to wait around"); diff --git a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c index a7be7866d..f6f37e489 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c @@ -118,10 +118,12 @@ void func_80A90264(EnKakasi2* this, GlobalContext* globalCtx) { this->unk_194++; - if (((BREG(1) != 0) || ((CVar_GetS32("gSkipScarecrow", 0) != 0) && - (globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY) && gSaveContext.scarecrowSpawnSongSet)) && - (this->actor.xzDistToPlayer < this->maxSpawnDistance.x) && - (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < this->maxSpawnDistance.y)){ + bool skipScarecrow = + (CVar_GetS32("gSkipScarecrow", 0) && gSaveContext.scarecrowSpawnSongSet && globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY) || + (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_SCARECROWS_SONG) && globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY); + + if ((BREG(1) != 0) || skipScarecrow && (this->actor.xzDistToPlayer < this->maxSpawnDistance.x) && + (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < this->maxSpawnDistance.y)) { this->actor.draw = func_80A90948; Collider_InitCylinder(globalCtx, &this->collider); Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit); From f5fae6df32307e19b7451fd460979178626950eb Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Sat, 3 Sep 2022 07:51:28 -0500 Subject: [PATCH 42/52] Reimplement progressive Bombchus --- soh/soh/Enhancements/randomizer/randomizer.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index a81fdb839..cd8cd61f9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1323,15 +1323,15 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_BUY_BOMBCHU_10: case RG_BUY_BOMBCHU_20: case RG_BUY_BOMBCHU_5: + case RG_BOMBCHU_DROP: // If Bombchus aren't in logic, you need a bomb bag to purchase them // If they are in logic, you need to have already obtained them somewhere else + // Bombchu Drop is only used as a bowling reward, so it needs the same logic if (GetRandoSettingValue(RSK_BOMBCHUS_IN_LOGIC)) { return INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; } else { return CUR_UPG_VALUE(UPG_BOMB_BAG) ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; } - case RG_BOMBCHU_DROP: - return INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU ? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE; case RG_PROGRESSIVE_HOOKSHOT: switch (INV_CONTENT(ITEM_HOOKSHOT)) { case ITEM_NONE: @@ -1690,7 +1690,13 @@ GetItemID Randomizer::GetItemIdFromRandomizerGet(RandomizerGet randoGet, GetItem return GI_OCARINA_OOT; } case RG_PROGRESSIVE_BOMBCHUS: - return GI_BOMBCHUS_20; + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { + return GI_BOMBCHUS_20; + } + if (AMMO(ITEM_BOMBCHU) < 5) { + return GI_BOMBCHUS_10; + } + return GI_BOMBCHUS_5; case RG_BOMBCHU_5: case RG_BUY_BOMBCHU_5: case RG_BOMBCHU_DROP: From 5421ad27c99699597baca039cc1d0e570d18ebaa Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 3 Sep 2022 09:24:37 -0400 Subject: [PATCH 43/52] Rando-next: Deku Nut and Seed ammo gives a blue rupee Fixes #1390 --- soh/soh/OTRGlobals.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 2781d6a6e..b70533a77 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1637,6 +1637,10 @@ extern "C" GetItemEntry ItemTable_RetrieveEntry(s16 tableID, s16 getItemID) { extern "C" GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId) { s16 getItemModIndex; RandomizerCheck randomizerCheck = OTRGlobals::Instance->gRandomizer->GetCheckFromActor(actorId, sceneNum, actorParams); + // if we got unknown check here, we don't need to do anything else, just return the ogId. + if (randomizerCheck == RC_UNKNOWN_CHECK) { + return ItemTable_RetrieveEntry(MOD_NONE, ogId); + } if (OTRGlobals::Instance->gRandomizer->CheckContainsVanillaItem(randomizerCheck)) { getItemModIndex = MOD_NONE; } else { @@ -1653,6 +1657,11 @@ extern "C" GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s extern "C" GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogId) { s16 getItemModIndex; + + // if we got unknown check here, we don't need to do anything else, just return the ogId. + if (randomizerCheck == RC_UNKNOWN_CHECK) { + return ItemTable_RetrieveEntry(MOD_NONE, ogId); + } if (OTRGlobals::Instance->gRandomizer->CheckContainsVanillaItem(randomizerCheck)) { getItemModIndex = MOD_NONE; } else { From e079c254f1ad7cb705141b1f0f12fa22744a0e18 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 3 Sep 2022 09:39:03 -0400 Subject: [PATCH 44/52] Fixes Link starting with BGS --- soh/src/code/z_sram.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 20d255bca..9a9407277 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -101,6 +101,9 @@ void GiveLinksPocketItem() { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE); if (getItemEntry.modIndex == MOD_NONE) { + if (getItemEntry.getItemId == GI_SWORD_BGS) { + gSaveContext.bgsFlag = true; + } Item_Give(NULL, getItemEntry.itemId); } else if (getItemEntry.modIndex == MOD_RANDOMIZER) { Randomizer_Item_Give(NULL, getItemEntry); @@ -400,6 +403,9 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { s32 giid = getItem.getItemId; if (getItem.modIndex == MOD_NONE) { + if (getItem.getItemId == GI_SWORD_BGS) { + gSaveContext.bgsFlag = true; + } Item_Give(NULL, getItem.itemId); } else if (getItem.modIndex == MOD_RANDOMIZER) { Randomizer_Item_Give(NULL, getItem); From ed8966054c07ba5a9becfa14e67894fb715e7d7e Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sat, 3 Sep 2022 09:15:05 -0500 Subject: [PATCH 45/52] Persist item tracker notes --- libultraship/libultraship/Hooks.h | 1 + .../randomizer/randomizer_item_tracker.cpp | 11 ++++++++++- soh/soh/SaveManager.cpp | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/libultraship/libultraship/Hooks.h b/libultraship/libultraship/Hooks.h index 5f29a831c..f9cd8b4ba 100644 --- a/libultraship/libultraship/Hooks.h +++ b/libultraship/libultraship/Hooks.h @@ -31,4 +31,5 @@ namespace Ship { DEFINE_HOOK(LoadTexture, void(const char* path, uint8_t** texture)); DEFINE_HOOK(GfxInit, void()); DEFINE_HOOK(ExitGame, void()); + DEFINE_HOOK(LoadFile, void(uint32_t fileNum)); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 8cede9a66..f39e1d944 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -485,6 +485,8 @@ void DrawSong(ItemTrackerItem item) { SetLastItemHoverText(SohUtils::GetQuestItemName(item.id)); } +static ImVector itemTrackerNotes; + void DrawNotes(bool resizeable = false) { ImGui::BeginGroup(); int iconSize = CVar_GetS32("gItemTrackerIconSize", 36); @@ -510,12 +512,15 @@ void DrawNotes(bool resizeable = false) { (void*)itemTrackerNotes); } }; - static ImVector itemTrackerNotes; if (itemTrackerNotes.empty()) { itemTrackerNotes.push_back(0); } ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) : ImVec2(((iconSize + iconSpacing) * 6) - 8, 200); ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput); + if (ImGui::IsItemDeactivatedAfterEdit() && IsValidSaveFile()) { + CVar_SetString(("gItemTrackerNotes" + std::to_string(gSaveContext.fileNum)).c_str(), std::string(std::begin(itemTrackerNotes), std::end(itemTrackerNotes)).c_str()); + SohImGui::needs_save = true; + } ImGui::EndGroup(); } @@ -925,4 +930,8 @@ void InitItemTracker() { Ship::RegisterHook([](OSContPad* cont_pad) { buttonsPressed = cont_pad; }); + Ship::RegisterHook([](uint32_t fileNum) { + const char* initialTrackerNotes = CVar_GetString(("gItemTrackerNotes" + std::to_string(gSaveContext.fileNum)).c_str(), ""); + strcpy(itemTrackerNotes.Data, initialTrackerNotes); + }); } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 8d8e7cd77..7050813b6 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -5,6 +5,7 @@ #include "functions.h" #include "macros.h" #include "Cvar.h" +#include "Hooks.h" #define NOGDI // avoid various windows defines that conflict with things in z64.h #include "spdlog/spdlog.h" @@ -1570,6 +1571,7 @@ extern "C" void Save_SaveGlobal(void) { extern "C" void Save_LoadFile(void) { SaveManager::Instance->LoadFile(gSaveContext.fileNum); + Ship::ExecuteHooks(gSaveContext.fileNum); } extern "C" void Save_AddLoadFunction(char* name, int version, SaveManager::LoadFunc func) { From 90bf5988eec51e459d32fd55a2f72fe82a24ba8b Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sat, 3 Sep 2022 09:30:53 -0500 Subject: [PATCH 46/52] Adjust Hooks include --- soh/soh/SaveManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 16aa0fff0..8de0b0f18 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -4,7 +4,7 @@ #include "z64.h" #include "functions.h" #include "macros.h" -#include "Hooks.h" +#include #include #define NOGDI // avoid various windows defines that conflict with things in z64.h From b92b1eaee6f046f5f06d07020e344eb1f26ec703 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sat, 3 Sep 2022 09:33:54 -0500 Subject: [PATCH 47/52] Use SohImGui::RequestCvarSaveOnNextTick --- soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 2bcb73e87..36b5593ea 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -518,7 +518,7 @@ void DrawNotes(bool resizeable = false) { ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput); if (ImGui::IsItemDeactivatedAfterEdit() && IsValidSaveFile()) { CVar_SetString(("gItemTrackerNotes" + std::to_string(gSaveContext.fileNum)).c_str(), std::string(std::begin(itemTrackerNotes), std::end(itemTrackerNotes)).c_str()); - SohImGui::needs_save = true; + SohImGui::RequestCvarSaveOnNextTick(); } ImGui::EndGroup(); } From 274242e0d714cba83234b880f2f5e4974c910cb4 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 3 Sep 2022 20:17:12 +0200 Subject: [PATCH 48/52] Implement rando bombchu drops --- .../randomizer/3drando/settings.cpp | 4 +++- .../Enhancements/randomizer/randomizer.cpp | 19 +++++++++++++++++++ .../Enhancements/randomizer/randomizerTypes.h | 1 + soh/soh/GameMenuBar.cpp | 8 +++++++- soh/src/code/z_en_item00.c | 3 ++- 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index dba8859e9..94093f833 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2561,8 +2561,10 @@ namespace Settings { MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]); + // RANDOTODO: Implement ammo drops entirely. Currently only "On" (index 0) or "On + Bombchus" (index 1) is implemented. + AmmoDrops.SetSelectedIndex(cvarSettings[RSK_ENABLE_BOMBCHU_DROPS]); + BombchusInLogic.SetSelectedIndex(cvarSettings[RSK_BOMBCHUS_IN_LOGIC]); - AmmoDrops.SetSelectedIndex(AMMODROPS_VANILLA); // Ensure logic knows bombchu drops aren't implemented yet StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]); StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index a81fdb839..5856ab0c5 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -582,6 +582,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "Shuffle Dungeon Items:Gerudo Fortress Keys", RSK_GERUDO_KEYS }, { "Shuffle Dungeon Items:Boss Keys", RSK_BOSS_KEYSANITY }, { "Shuffle Dungeon Items:Ganon's Boss Key", RSK_GANONS_BOSS_KEY }, + { "World Settings:Ammo Drops", RSK_ENABLE_BOMBCHU_DROPS }, { "World Settings:Bombchus in Logic", RSK_BOMBCHUS_IN_LOGIC }, { "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS }, { "Misc Settings:Hint Clarity", RSK_HINT_CLARITY }, @@ -831,6 +832,15 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { gSaveContext.randoSettings[index].value = 1; } break; + // Uses Ammo Drops option for now. "Off" not yet implemented + case RSK_ENABLE_BOMBCHU_DROPS: + if (it.value() == "On") { + gSaveContext.randoSettings[index].value = 0; + } else if (it.value() == "On + Bombchu") { + gSaveContext.randoSettings[index].value = 1; + } else if (it.value() == "Off") { + gSaveContext.randoSettings[index].value = 2; + } case RSK_STARTING_MAPS_COMPASSES: if(it.value() == "Start With") { gSaveContext.randoSettings[index].value = 0; @@ -3429,6 +3439,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0); cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0); cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVar_GetS32("gRandomizeShuffleBeans", 0); + cvarSettings[RSK_ENABLE_BOMBCHU_DROPS] = CVar_GetS32("gRandomizeEnableBombchuDrops", 0); cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVar_GetS32("gRandomizeBombchusInLogic", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); @@ -4304,6 +4315,14 @@ void DrawRandoEditor(bool& open) { UIWidgets::PaddedSeparator(); + // Enable Bombchu Drops + UIWidgets::EnhancementCheckbox("Enable Bombchu Drops", "gRandomizeEnableBombchuDrops"); + UIWidgets::InsertHelpHoverText( + "Once you obtain bombchus for the first time, refills can be found in bushes and other places where bomb drops can normally spawn." + ); + + UIWidgets::PaddedSeparator(); + UIWidgets::EnhancementCheckbox("WIP - Blue Fire Arrows", "gRandomizeBlueIceArrows", true, "In development"); UIWidgets::InsertHelpHoverText( "Ice Arrows act like Blue Fire, making them able to melt red ice. " diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 064cdc499..ea7446f36 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1018,6 +1018,7 @@ typedef enum { RSK_SKULLS_SUNS_SONG, RSK_SHUFFLE_ADULT_TRADE, RSK_SHUFFLE_MAGIC_BEANS, + RSK_ENABLE_BOMBCHU_DROPS, RSK_BOMBCHUS_IN_LOGIC, RSK_LINKS_POCKET } RandomizerSettingKey; diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index 26b4b1ffb..93c816d8d 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -23,6 +23,7 @@ #endif #include "UIWidgets.hpp" +#include "include/global.h" #include "include/z64audio.h" #define EXPERIMENTAL() \ @@ -745,7 +746,12 @@ namespace GameMenuBar { ); UIWidgets::PaddedEnhancementCheckbox("No Random Drops", "gNoRandomDrops", true, false); UIWidgets::Tooltip("Disables random drops, except from the Goron Pot, Dampe, and bosses"); - UIWidgets::PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false); + bool forceEnableBombchuDrops = gSaveContext.n64ddFlag && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1; + const char* forceEnableBombchuDropsText = + "This setting is forcefully enabled because a savefile\nwith \"Enable Bombchu Drops\" is loaded."; + UIWidgets::PaddedEnhancementCheckbox("Enable Bombchu Drops", "gBombchuDrops", true, false, + forceEnableBombchuDrops, forceEnableBombchuDropsText, UIWidgets::CheckboxGraphics::Checkmark); UIWidgets::Tooltip("Bombchus will sometimes drop in place of bombs"); UIWidgets::PaddedEnhancementCheckbox("No Heart Drops", "gNoHeartDrops", true, false); UIWidgets::Tooltip("Disables heart drops, but not heart placements, like from a Deku Scrub running off\nThis simulates Hero Mode from other games in the series"); diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 986d5a135..2279abc71 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -1507,7 +1507,8 @@ s16 func_8001F404(s16 dropId) { } } - if (CVar_GetS32("gBombchuDrops", 0) && + if ((CVar_GetS32("gBombchuDrops", 0) || + (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1)) && (dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL)) { dropId = EnItem00_ConvertBombDropToBombchu(dropId); } From ae0ccb9ccae350983afc34c603baae2057d79b21 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 3 Sep 2022 20:18:54 +0200 Subject: [PATCH 49/52] Missing break --- soh/soh/Enhancements/randomizer/randomizer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5856ab0c5..4b734279a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -841,6 +841,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { } else if (it.value() == "Off") { gSaveContext.randoSettings[index].value = 2; } + break; case RSK_STARTING_MAPS_COMPASSES: if(it.value() == "Start With") { gSaveContext.randoSettings[index].value = 0; From 8d033c67664368849ab9993607c3f96487374817 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 3 Sep 2022 20:29:45 +0200 Subject: [PATCH 50/52] Update settings.cpp --- soh/soh/Enhancements/randomizer/3drando/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 94093f833..634dc4250 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2561,7 +2561,7 @@ namespace Settings { MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]); - // RANDOTODO: Implement ammo drops entirely. Currently only "On" (index 0) or "On + Bombchus" (index 1) is implemented. + // RANDOTODO: Implement disabling ammo drops. Currently only "On" (index 0) or "On + Bombchus" (index 1) is implemented. AmmoDrops.SetSelectedIndex(cvarSettings[RSK_ENABLE_BOMBCHU_DROPS]); BombchusInLogic.SetSelectedIndex(cvarSettings[RSK_BOMBCHUS_IN_LOGIC]); From 6cd8d6ca3af976c51dde0957ed85bb441902b3d8 Mon Sep 17 00:00:00 2001 From: aMannus Date: Sat, 3 Sep 2022 20:48:00 +0200 Subject: [PATCH 51/52] Clean up bool --- soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c index f6f37e489..5e3992fc1 100644 --- a/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c +++ b/soh/src/overlays/actors/ovl_En_Kakasi2/z_en_kakasi2.c @@ -118,9 +118,9 @@ void func_80A90264(EnKakasi2* this, GlobalContext* globalCtx) { this->unk_194++; - bool skipScarecrow = - (CVar_GetS32("gSkipScarecrow", 0) && gSaveContext.scarecrowSpawnSongSet && globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY) || - (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_SCARECROWS_SONG) && globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY); + bool skipScarecrow = globalCtx->msgCtx.ocarinaAction == OCARINA_ACTION_FREE_PLAY && + ((CVar_GetS32("gSkipScarecrow", 0) && gSaveContext.scarecrowSpawnSongSet) || + (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SKIP_SCARECROWS_SONG))); if ((BREG(1) != 0) || skipScarecrow && (this->actor.xzDistToPlayer < this->maxSpawnDistance.x) && (fabsf(player->actor.world.pos.y - this->actor.world.pos.y) < this->maxSpawnDistance.y)) { From 77a5d03019c59196587f656b7ee069ae0a033566 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Sat, 3 Sep 2022 15:46:33 -0500 Subject: [PATCH 52/52] Hook into file delete and clear notes --- libultraship/libultraship/Hooks.h | 1 + soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp | 6 +++++- soh/soh/SaveManager.cpp | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/libultraship/libultraship/Hooks.h b/libultraship/libultraship/Hooks.h index f9cd8b4ba..fd6c049bc 100644 --- a/libultraship/libultraship/Hooks.h +++ b/libultraship/libultraship/Hooks.h @@ -32,4 +32,5 @@ namespace Ship { DEFINE_HOOK(GfxInit, void()); DEFINE_HOOK(ExitGame, void()); DEFINE_HOOK(LoadFile, void(uint32_t fileNum)); + DEFINE_HOOK(DeleteFile, void(uint32_t fileNum)); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 36b5593ea..5b52047ab 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -930,7 +930,11 @@ void InitItemTracker() { buttonsPressed = cont_pad; }); Ship::RegisterHook([](uint32_t fileNum) { - const char* initialTrackerNotes = CVar_GetString(("gItemTrackerNotes" + std::to_string(gSaveContext.fileNum)).c_str(), ""); + const char* initialTrackerNotes = CVar_GetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), ""); strcpy(itemTrackerNotes.Data, initialTrackerNotes); }); + Ship::RegisterHook([](uint32_t fileNum) { + CVar_SetString(("gItemTrackerNotes" + std::to_string(fileNum)).c_str(), ""); + SohImGui::RequestCvarSaveOnNextTick(); + }); } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 8de0b0f18..3305f1d70 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -1592,6 +1592,7 @@ extern "C" void Save_CopyFile(int from, int to) { extern "C" void Save_DeleteFile(int fileNum) { SaveManager::Instance->DeleteZeldaFile(fileNum); + Ship::ExecuteHooks(fileNum); } extern "C" bool Save_Exist(int fileNum) {