diff options
| author | Caladius <Caladius@users.noreply.github.com> | 2025-10-15 12:35:42 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-15 12:35:42 -0400 |
| commit | d53bdbb239016df5abd0edd04bbcc294ce94269f (patch) | |
| tree | 286d44bfce03abf2b0dc264ed5dd87920340be8e | |
| parent | dfcc80e38a6678e5c058d108574e22c75711ad5f (diff) | |
[Rando] Excluding Checks from Seed (#1069)
* Operational Check Exclusion List. needs logic help.
* Add Search filter and Clear All
* shemantics
* Fix build errors
* Clear out unsused code.
* Better =/
* This works now, just debug boot to warp seems to be finnicky.
* clang
* Fix Logic Generation and Regeneration.
* Feedback Fixes
* Updates
* Fix Logic Generation and restrict for specific Logic Types.
* Update Glitchless Logic
* Update rest of Logics
| -rw-r--r-- | mm/2s2h/Rando/Logic/GlitchlessLogic.cpp | 12 | ||||
| -rw-r--r-- | mm/2s2h/Rando/Logic/NearlyNoLogic.cpp | 17 | ||||
| -rw-r--r-- | mm/2s2h/Rando/Logic/NoLogic.cpp | 20 | ||||
| -rw-r--r-- | mm/2s2h/Rando/Menu.cpp | 162 | ||||
| -rw-r--r-- | mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp | 25 |
5 files changed, 223 insertions, 13 deletions
diff --git a/mm/2s2h/Rando/Logic/GlitchlessLogic.cpp b/mm/2s2h/Rando/Logic/GlitchlessLogic.cpp index b22f1a140..338733c4e 100644 --- a/mm/2s2h/Rando/Logic/GlitchlessLogic.cpp +++ b/mm/2s2h/Rando/Logic/GlitchlessLogic.cpp @@ -96,7 +96,17 @@ void ApplyGlitchlessLogicToSaveContext(std::unordered_map<RandoCheckId, bool>& c RandoItemId randoItemId; - if (isShuffled) { + if (RANDO_SAVE_CHECKS[randoCheckId].skipped) { + uint32_t index = 0; + for (auto& item : itemPool) { + if (Rando::StaticData::Items[item].randoItemType == RITYPE_JUNK) { + randoItemId = item; + itemPool.erase(itemPool.begin() + index); + break; + } + index++; + } + } else if (isShuffled) { randoItemId = itemPool.back(); itemPool.pop_back(); diff --git a/mm/2s2h/Rando/Logic/NearlyNoLogic.cpp b/mm/2s2h/Rando/Logic/NearlyNoLogic.cpp index 788e94df3..c1af5a468 100644 --- a/mm/2s2h/Rando/Logic/NearlyNoLogic.cpp +++ b/mm/2s2h/Rando/Logic/NearlyNoLogic.cpp @@ -48,8 +48,21 @@ void ApplyNearlyNoLogicToSaveContext(std::unordered_map<RandoCheckId, bool>& che continue; } - RandoItemId randoItemId = itemPool.back(); - itemPool.pop_back(); + RandoItemId randoItemId = RI_NONE; + if (RANDO_SAVE_CHECKS[randoCheckId].skipped) { + uint32_t index = 0; + for (auto& item : itemPool) { + if (Rando::StaticData::Items[item].randoItemType == RITYPE_JUNK) { + randoItemId = item; + itemPool.erase(itemPool.begin() + index); + break; + } + index++; + } + } else { + randoItemId = itemPool.back(); + itemPool.pop_back(); + } RANDO_SAVE_CHECKS[randoCheckId].shuffled = true; RANDO_SAVE_CHECKS[randoCheckId].randoItemId = randoItemId; diff --git a/mm/2s2h/Rando/Logic/NoLogic.cpp b/mm/2s2h/Rando/Logic/NoLogic.cpp index 0b4559299..e820c9176 100644 --- a/mm/2s2h/Rando/Logic/NoLogic.cpp +++ b/mm/2s2h/Rando/Logic/NoLogic.cpp @@ -10,6 +10,21 @@ namespace Rando { namespace Logic { void ApplyNoLogicToSaveContext(std::unordered_map<RandoCheckId, bool>& checkPool, std::vector<RandoItemId>& itemPool) { + std::vector<RandoItemId> junkPool; + for (auto& [randoCheckId, _] : checkPool) { + if (RANDO_SAVE_CHECKS[randoCheckId].skipped) { + uint32_t index = 0; + for (auto& item : itemPool) { + if (Rando::StaticData::Items[item].randoItemType == RITYPE_JUNK) { + junkPool.push_back(item); + itemPool.erase(itemPool.begin() + index); + break; + } + index++; + } + } + } + for (size_t i = 0; i < itemPool.size(); i++) { std::swap(itemPool[i], itemPool[Ship_Random(0, itemPool.size() - 1)]); } @@ -20,6 +35,11 @@ void ApplyNoLogicToSaveContext(std::unordered_map<RandoCheckId, bool>& checkPool } RANDO_SAVE_CHECKS[randoCheckId].shuffled = true; + if (RANDO_SAVE_CHECKS[randoCheckId].skipped == true) { + RANDO_SAVE_CHECKS[randoCheckId].randoItemId = junkPool.back(); + junkPool.pop_back(); + continue; + } RANDO_SAVE_CHECKS[randoCheckId].randoItemId = itemPool.back(); itemPool.pop_back(); } diff --git a/mm/2s2h/Rando/Menu.cpp b/mm/2s2h/Rando/Menu.cpp index 4612d4aa1..3cbf76f23 100644 --- a/mm/2s2h/Rando/Menu.cpp +++ b/mm/2s2h/Rando/Menu.cpp @@ -39,6 +39,9 @@ std::vector<int32_t> incompatibleWithVanilla = { RO_PLENTIFUL_ITEMS, }; +std::vector<RandoCheckId> checkExclusionList; +bool isExcludedInitialized = false; + namespace BenGui { extern std::shared_ptr<Rando::CheckTracker::CheckTrackerWindow> mRandoCheckTrackerWindow; extern std::shared_ptr<Rando::CheckTracker::SettingsWindow> mRandoCheckTrackerSettingsWindow; @@ -94,6 +97,35 @@ bool IncompatibleWithLogicSetting(int32_t option) { return false; } +void SortExcludedChecks() { + std::sort(checkExclusionList.begin(), checkExclusionList.end()); +} + +void SaveExcludedChecks() { + std::string excludedString = ""; + SortExcludedChecks(); + + for (auto& data : checkExclusionList) { + excludedString += std::to_string(data).c_str(); + excludedString += ","; + } + CVarSetString("gRando.ExcludedChecks", excludedString.c_str()); +} + +void LoadExcludedChecks() { + std::vector<RandoCheckId> sortedExclusionList; + std::string checksList = CVarGetString("gRando.ExcludedChecks", ""); + + if (checksList != "") { + std::string word; + std::istringstream stream(checksList); + while (std::getline(stream, word, ',')) { + checkExclusionList.push_back((RandoCheckId)std::stoi(word)); + } + } + SortExcludedChecks(); +} + static void DrawGeneralTab() { ImGui::BeginChild("randoSettings"); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 1, 1, 0.5f)); @@ -191,11 +223,11 @@ static void DrawLogicConditionsTab() { ImGui::EndChild(); } -static void DrawLocationsTab() { +static void DrawShufflesTab() { f32 columnWidth = ImGui::GetContentRegionAvail().x / 3 - (ImGui::GetStyle().ItemSpacing.x * 2); f32 halfHeight = ImGui::GetContentRegionAvail().y / 2 - (ImGui::GetStyle().ItemSpacing.y * 2); ImGui::SeparatorText("Shuffle Options"); - ImGui::BeginChild("randoLocationsColumn1", ImVec2(columnWidth, halfHeight)); + ImGui::BeginChild("randoShufflesColumn1", ImVec2(columnWidth, halfHeight)); CVarCheckbox("Shuffle Songs", "gPlaceholderBool", CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }).DefaultValue(true)); CVarCheckbox("Shuffle Owl Statues", Rando::StaticData::Options[RO_SHUFFLE_OWL_STATUES].cvar); @@ -216,7 +248,7 @@ static void DrawLocationsTab() { .DefaultValue(STRAY_FAIRY_SCATTERED_TOTAL)); ImGui::EndChild(); ImGui::SameLine(); - ImGui::BeginChild("randoLocationsColumn2", ImVec2(columnWidth, halfHeight)); + ImGui::BeginChild("randoShufflesColumn2", ImVec2(columnWidth, halfHeight)); CVarCheckbox("Shuffle Pot Drops", Rando::StaticData::Options[RO_SHUFFLE_POT_DROPS].cvar); CVarCheckbox("Shuffle Crate Drops", Rando::StaticData::Options[RO_SHUFFLE_CRATE_DROPS].cvar); CVarCheckbox("Shuffle Barrel Drops", Rando::StaticData::Options[RO_SHUFFLE_BARREL_DROPS].cvar); @@ -230,11 +262,7 @@ static void DrawLocationsTab() { CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } })); ImGui::EndChild(); ImGui::SameLine(); - ImGui::BeginChild("randoLocationsColumn3", ImVec2(columnWidth, halfHeight)); - ImGui::EndChild(); - ImGui::BeginChild("randoLocationsExclusions", ImVec2(0, 0)); - ImGui::SeparatorText("Exclusions"); - ImGui::TextWrapped("These checks will be guaranteed junk items, and marked as skipped in the check tracker."); + ImGui::BeginChild("randoShufflesColumn3", ImVec2(columnWidth, halfHeight)); ImGui::EndChild(); } @@ -402,6 +430,117 @@ static void DrawItemsTab() { ImGui::EndChild(); } +static void DrawLocationsTab() { + if (CVarGetInteger(Rando::StaticData::Options[RO_LOGIC].cvar, RO_LOGIC_GLITCHLESS) >= RO_LOGIC_FRENCH_VANILLA) { + ImGui::TextColored(UIWidgets::ColorValues.at(UIWidgets::Colors::Red), + "This setting is not compatible with French Vanilla or Vanilla Logic."); + return; + } + + auto menuThemeColor = UIWidgets::Colors(CVarGetInteger("gSettings.Menu.Theme", LightBlue)); + bool clearExcluded = false; + if (!isExcludedInitialized) { + LoadExcludedChecks(); + isExcludedInitialized = true; + } + + f32 columnWidth = ImGui::GetContentRegionAvail().x / 2 - (ImGui::GetStyle().ItemSpacing.x * 2); + ImGui::BeginChild("randoIncludedChecks", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y)); + ImGui::SeparatorText("Included Checks"); + + static ImGuiTextFilter includedFilter; + UIWidgets::PushStyleCombobox(menuThemeColor); + + includedFilter.Draw("##filter", ImGui::GetContentRegionAvail().x - 5.0f); + UIWidgets::PopStyleCombobox(); + if (!includedFilter.IsActive()) { + ImGui::SameLine(18.0f); + ImGui::Text("Included Search"); + } + + if (ImGui::BeginTable("Included Checks", 1)) { + ImGui::TableNextColumn(); + + for (auto& includedChecks : Rando::StaticData::Checks) { + if (includedChecks.first == RC_UNKNOWN) { + continue; + } + + if (!includedFilter.PassFilter( + convertEnumToReadableName(Rando::StaticData::Checks[includedChecks.first].name).c_str())) { + continue; + } + + auto it = std::find(checkExclusionList.begin(), checkExclusionList.end(), includedChecks.first); + if (it != checkExclusionList.end()) { + continue; + } + + ImGui::BeginGroup(); + ImGui::Text("%s", convertEnumToReadableName(Rando::StaticData::Checks[includedChecks.first].name).c_str()); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(ImGui::GetContentRegionAvail().x, 0)); + ImGui::EndGroup(); + + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, + ImGui::IsItemHovered() ? IM_COL32(255, 255, 0, 128) : IM_COL32(255, 255, 255, 0)); + if (ImGui::IsItemClicked()) { + checkExclusionList.push_back(includedChecks.first); + SaveExcludedChecks(); + } + ImGui::TableNextColumn(); + } + ImGui::EndTable(); + } + ImGui::EndChild(); + ImGui::SameLine(); + ImGui::BeginChild("randoExcludedChecks", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y)); + ImGui::SeparatorText("Forced Junk Checks"); + + static ImGuiTextFilter excludedFilter; + UIWidgets::PushStyleCombobox(menuThemeColor); + excludedFilter.Draw("##filter", ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize("Clear All").x - 30.0f); + if (!excludedFilter.IsActive()) { + ImGui::SameLine(18.0f); + ImGui::Text("Excluded Search"); + } + ImGui::SameLine(ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize("Clear All").x - 24.0f); + if (ImGui::Button("Clear All")) { + clearExcluded = true; + } + UIWidgets::PopStyleCombobox(); + + if (ImGui::BeginTable("Excluded Checks", 1)) { + ImGui::TableNextColumn(); + int16_t index = 0; + for (auto& excludedChecks : checkExclusionList) { + if (!excludedFilter.PassFilter( + convertEnumToReadableName(Rando::StaticData::Checks[excludedChecks].name).c_str())) { + continue; + } + + ImGui::Text("%s", convertEnumToReadableName(Rando::StaticData::Checks[excludedChecks].name).c_str()); + + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, + ImGui::IsItemHovered() ? IM_COL32(255, 255, 0, 128) : IM_COL32(255, 255, 255, 0)); + if (ImGui::IsItemClicked()) { + checkExclusionList.erase(checkExclusionList.begin() + index); + SaveExcludedChecks(); + } + index++; + ImGui::TableNextColumn(); + } + ImGui::EndTable(); + } + ImGui::EndChild(); + + if (clearExcluded) { + checkExclusionList.clear(); + SaveExcludedChecks(); + clearExcluded = false; + } +} + static void DrawHintsTab() { f32 columnWidth = ImGui::GetContentRegionAvail().x / 3 - (ImGui::GetStyle().ItemSpacing.x * 2); f32 halfHeight = ImGui::GetContentRegionAvail().y / 2 - (ImGui::GetStyle().ItemSpacing.y * 2); @@ -457,12 +596,15 @@ void Rando::RegisterMenu() { mBenMenu->AddWidget(path, "Logic/Conditions", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawLogicConditionsTab(); }); + mBenMenu->AddSidebarEntry("Rando", "Shuffle Options", 1); + path.sidebarName = "Shuffle Options"; + mBenMenu->AddWidget(path, "Locations", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawShufflesTab(); }); mBenMenu->AddSidebarEntry("Rando", "Locations", 1); - path.sidebarName = "Locations"; - mBenMenu->AddWidget(path, "Locations", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawLocationsTab(); }); mBenMenu->AddSidebarEntry("Rando", "Items", 1); path.sidebarName = "Items"; mBenMenu->AddWidget(path, "Items", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawItemsTab(); }); + path.sidebarName = "Locations"; + mBenMenu->AddWidget(path, "Locations", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawLocationsTab(); }); mBenMenu->AddSidebarEntry("Rando", "Hints", 1); path.sidebarName = "Hints"; mBenMenu->AddWidget(path, "Hints", WIDGET_CUSTOM).CustomFunction([](WidgetInfo& info) { DrawHintsTab(); }); diff --git a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp index 85d101dd1..668f5e7ba 100644 --- a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp +++ b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp @@ -105,6 +105,15 @@ void Rando::MiscBehavior::OnFileCreate(s16 fileNum) { std::unordered_map<RandoCheckId, bool> checkPool; std::vector<RandoItemId> itemPool; + // Create Excluded Checks List to eliminate excluded checks from the pool + std::vector<RandoCheckId> excludedChecks; + std::string excludedChecksList = CVarGetString("gRando.ExcludedChecks", ""); + std::string word; + std::istringstream stream(excludedChecksList); + while (std::getline(stream, word, ',')) { + excludedChecks.push_back((RandoCheckId)std::stoi(word)); + } + // First loop through all regions and add checks/items to the pool for (auto& [randoRegionId, randoRegion] : Rando::Logic::Regions) { for (auto& [randoCheckId, _] : randoRegion.checks) { @@ -203,6 +212,22 @@ void Rando::MiscBehavior::OnFileCreate(s16 fileNum) { } } + // Skip checks that have been excluded in the Locations menu and add their vanilla item to the + // pool except if Logic is set to Vanilla or French Vanilla. + if (RANDO_SAVE_OPTIONS[RO_LOGIC] <= RO_LOGIC_NEARLY_NO_LOGIC) { + auto it = std::find(excludedChecks.begin(), excludedChecks.end(), randoCheckId); + if (it != excludedChecks.end()) { + RandoItemId vanillaItem = Rando::StaticData::Checks[randoCheckId].randoItemId; + itemPool.push_back(vanillaItem); + + RANDO_SAVE_CHECKS[randoCheckId].randoItemId = RI_JUNK; + RANDO_SAVE_CHECKS[randoCheckId].skipped = true; + + checkPool.insert({ randoCheckId, true }); + continue; + } + } + checkPool.insert({ randoCheckId, true }); itemPool.push_back(randoStaticCheck.randoItemId); } |
