summaryrefslogtreecommitdiff
path: root/mm/2s2h/Rando
diff options
context:
space:
mode:
Diffstat (limited to 'mm/2s2h/Rando')
-rw-r--r--mm/2s2h/Rando/ExcludedChecks.cpp47
-rw-r--r--mm/2s2h/Rando/Logic/GeneratePools.cpp30
-rw-r--r--mm/2s2h/Rando/Menu.cpp246
-rw-r--r--mm/2s2h/Rando/Rando.h3
4 files changed, 251 insertions, 75 deletions
diff --git a/mm/2s2h/Rando/ExcludedChecks.cpp b/mm/2s2h/Rando/ExcludedChecks.cpp
new file mode 100644
index 000000000..c359a9f1f
--- /dev/null
+++ b/mm/2s2h/Rando/ExcludedChecks.cpp
@@ -0,0 +1,47 @@
+#include "Rando.h"
+#include "2s2h/Rando/StaticData/StaticData.h"
+#include <libultraship/libultraship.h>
+#include <libultraship/bridge/consolevariablebridge.h>
+
+namespace Rando {
+
+std::vector<RandoCheckId> GetExcludedChecksFromConfig() {
+ auto allConfig = Ship::Context::GetRawInstance()->GetConfig()->GetNestedJson();
+ std::vector<RandoCheckId> excludedChecks;
+
+ if (allConfig.find("CVars") != allConfig.end() && allConfig["CVars"].is_object() &&
+ allConfig["CVars"].find("gRando") != allConfig["CVars"].end() && allConfig["CVars"]["gRando"].is_object() &&
+ allConfig["CVars"]["gRando"].find("ExcludedChecks") != allConfig["CVars"]["gRando"].end()) {
+
+ if (allConfig["CVars"]["gRando"]["ExcludedChecks"].is_array()) {
+ auto excludedChecksStrings = allConfig["CVars"]["gRando"]["ExcludedChecks"].get<std::vector<std::string>>();
+ for (auto& checkName : excludedChecksStrings) {
+ auto randoCheckId = Rando::StaticData::GetCheckIdFromName(checkName.c_str());
+ if (randoCheckId > RC_UNKNOWN && randoCheckId < RC_MAX) {
+ excludedChecks.push_back(randoCheckId);
+ }
+ }
+ } else if (allConfig["CVars"]["gRando"]["ExcludedChecks"].is_string()) {
+ CVarClear("gRando.ExcludedChecks");
+ Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
+ }
+ }
+
+ std::sort(excludedChecks.begin(), excludedChecks.end());
+ return excludedChecks;
+}
+
+void SetExcludedChecksInConfig(std::vector<RandoCheckId>& excludedChecks) {
+ auto excludedChecksJson = nlohmann::json::array();
+
+ for (auto& randoCheckId : excludedChecks) {
+ if (randoCheckId > RC_UNKNOWN && randoCheckId < RC_MAX) {
+ excludedChecksJson.push_back(Rando::StaticData::Checks[randoCheckId].name);
+ }
+ }
+
+ Ship::Context::GetRawInstance()->GetConfig()->SetBlock("CVars.gRando.ExcludedChecks", excludedChecksJson);
+ Ship::Context::GetRawInstance()->GetConfig()->Save();
+}
+
+} // namespace Rando
diff --git a/mm/2s2h/Rando/Logic/GeneratePools.cpp b/mm/2s2h/Rando/Logic/GeneratePools.cpp
index 08dcd6fe5..8a5195a8c 100644
--- a/mm/2s2h/Rando/Logic/GeneratePools.cpp
+++ b/mm/2s2h/Rando/Logic/GeneratePools.cpp
@@ -1,7 +1,6 @@
#include "Logic.h"
#include "Rando/MiscBehavior/ClockShuffle.h"
#include <libultraship/bridge/consolevariablebridge.h>
-#include <sstream>
extern "C" {
#include "variables.h"
@@ -17,13 +16,7 @@ void GeneratePools(RandoSaveInfo& saveInfo, std::vector<RandoCheckId>& checkPool
std::vector<RandoItemId> computedStartingItems = Rando::GetComputedStartingItems(saveInfo);
startingItems.insert(startingItems.end(), computedStartingItems.begin(), computedStartingItems.end());
- 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));
- }
+ std::vector<RandoCheckId> excludedChecks = Rando::GetExcludedChecksFromConfig();
// First loop through all regions and add checks/items to the pool
for (auto& [randoRegionId, randoRegion] : Rando::Logic::Regions) {
@@ -143,17 +136,20 @@ void GeneratePools(RandoSaveInfo& saveInfo, std::vector<RandoCheckId>& checkPool
}
}
- // When a check is skipped, we still want to add it's vanilla item to the pool, but we don't add the check.
- // Mark it as skipped and set it to junk. These leaves an inbalance in the pools that will get sorted
- // automatically if there is enough space.
+ // Excluded checks are always left out of the check pool, but what happens to them depends on what their
+ // vanilla item is worth. A check whose vanilla item is junk (grass, pots, snowballs...) has nothing worth
+ // preserving, so it stays unshuffled and behaves exactly like it does in vanilla, and its item never enters
+ // the item pool. Every other check keeps its item in the pool and is marked as skipped with junk in its
+ // place. That leaves an inbalance in the pools that will get sorted automatically if there is enough space.
if (saveInfo.randoSaveOptions[RO_LOGIC] != RO_LOGIC_VANILLA) {
- auto it = std::find(excludedChecks.begin(), excludedChecks.end(), randoCheckId);
- if (it != excludedChecks.end()) {
- itemPool.push_back(randoStaticCheck.randoItemId);
+ if (std::binary_search(excludedChecks.begin(), excludedChecks.end(), randoCheckId)) {
+ if (Rando::StaticData::Items[randoStaticCheck.randoItemId].randoItemType != RITYPE_JUNK) {
+ itemPool.push_back(randoStaticCheck.randoItemId);
- saveInfo.randoSaveChecks[randoCheckId].shuffled = true;
- saveInfo.randoSaveChecks[randoCheckId].randoItemId = RI_JUNK;
- saveInfo.randoSaveChecks[randoCheckId].skipped = true;
+ saveInfo.randoSaveChecks[randoCheckId].shuffled = true;
+ saveInfo.randoSaveChecks[randoCheckId].randoItemId = RI_JUNK;
+ saveInfo.randoSaveChecks[randoCheckId].skipped = true;
+ }
continue;
}
}
diff --git a/mm/2s2h/Rando/Menu.cpp b/mm/2s2h/Rando/Menu.cpp
index 08b248d16..0b4e969ff 100644
--- a/mm/2s2h/Rando/Menu.cpp
+++ b/mm/2s2h/Rando/Menu.cpp
@@ -67,7 +67,6 @@ std::vector<int32_t> incompatibleWithVanilla = {
// clang-format on
std::vector<RandoCheckId> checkExclusionList;
-bool isExcludedInitialized = false;
namespace BenGui {
extern std::shared_ptr<Rando::CheckTracker::CheckTrackerWindow> mRandoCheckTrackerWindow;
@@ -150,29 +149,94 @@ void SortExcludedChecks() {
}
void SaveExcludedChecks() {
- std::string excludedString = "";
SortExcludedChecks();
-
- for (auto& data : checkExclusionList) {
- excludedString += std::to_string(data);
- excludedString += ",";
- }
- CVarSetString("gRando.ExcludedChecks", excludedString.c_str());
+ Rando::SetExcludedChecksInConfig(checkExclusionList);
Ship::Context::GetRawInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
ShipInit::Init("gRando.ExcludedChecks");
}
void LoadExcludedChecks() {
- std::string checksList = CVarGetString("gRando.ExcludedChecks", "");
+ checkExclusionList = Rando::GetExcludedChecksFromConfig();
+}
+static RegisterShipInitFunc loadExcludedChecksInit(LoadExcludedChecks, { "gRando.ExcludedChecks" });
+
+struct CuratedCheckGroup {
+ const char* label;
+ const char* description;
+ std::vector<std::pair<RandoCheckId, RandoCheckId>> ranges;
+};
+
+// clang-format off
+std::vector<CuratedCheckGroup> curatedCheckGroups = {
+ {
+ "Cow Grotto Grass",
+ "Every blade of grass in the Great Bay Coast and Termina Field cow grottos.",
+ {
+ { RC_GREAT_BAY_COAST_COW_GROTTO_GRASS_01, RC_GREAT_BAY_COAST_COW_GROTTO_GRASS_72 },
+ { RC_TERMINA_FIELD_COW_GROTTO_GRASS_01, RC_TERMINA_FIELD_COW_GROTTO_GRASS_72 },
+ },
+ },
+ {
+ "Termina Field Grass",
+ "Every blade of grass in Termina Field itself. The grottos within it are unaffected.",
+ {
+ { RC_TERMINA_FIELD_GRASS_01, RC_TERMINA_FIELD_GRASS_216 },
+ },
+ },
+ {
+ "Common Exclusions",
+ "Minigames and side content that take a lot of time or a lot of luck to finish:",
+ {
+ { RC_BENEATH_THE_GRAVEYARD_DAMPE_CHEST, RC_BENEATH_THE_GRAVEYARD_DAMPE_CHEST },
+ { RC_CLOCK_TOWN_EAST_HONEY_DARLING_ALL_DAYS, RC_CLOCK_TOWN_EAST_HONEY_DARLING_ALL_DAYS },
+ { RC_CLOCK_TOWN_EAST_SHOOTING_GALLERY_PERFECT_SCORE, RC_CLOCK_TOWN_EAST_SHOOTING_GALLERY_PERFECT_SCORE },
+ { RC_SWAMP_SHOOTING_GALLERY_PERFECT_SCORE, RC_SWAMP_SHOOTING_GALLERY_PERFECT_SCORE },
+ { RC_DEKU_PLAYGROUND_ALL_DAYS, RC_DEKU_PLAYGROUND_ALL_DAYS },
+ { RC_DEKU_SHRINE_MASK_OF_SCENTS, RC_DEKU_SHRINE_MASK_OF_SCENTS },
+ { RC_GREAT_BAY_COAST_FISHERMAN_MINIGAME, RC_GREAT_BAY_COAST_FISHERMAN_MINIGAME },
+ { RC_MOON_FIERCE_DEITY_MASK, RC_MOON_FIERCE_DEITY_MASK },
+ { RC_MOUNTAIN_VILLAGE_FROG_CHOIR, RC_MOUNTAIN_VILLAGE_FROG_CHOIR },
+ { RC_STOCK_POT_INN_COUPLES_MASK, RC_STOCK_POT_INN_COUPLES_MASK },
+ { RC_WATERFALL_RAPIDS_BEAVER_RACE_02, RC_WATERFALL_RAPIDS_BEAVER_RACE_02 },
+ { RC_PINNACLE_ROCK_REUNITE_SEAHORSE, RC_PINNACLE_ROCK_REUNITE_SEAHORSE },
+ },
+ },
+};
+// clang-format on
+
+const std::vector<std::vector<RandoCheckId>>& GetCuratedGroupChecks() {
+ static std::vector<std::vector<RandoCheckId>> curatedGroupChecks;
+ if (curatedGroupChecks.empty()) {
+ for (auto& curatedCheckGroup : curatedCheckGroups) {
+ std::vector<RandoCheckId> groupChecks;
+ for (auto& [firstCheckId, lastCheckId] : curatedCheckGroup.ranges) {
+ for (int32_t checkId = firstCheckId; checkId <= lastCheckId; checkId++) {
+ if (Rando::StaticData::Checks.contains((RandoCheckId)checkId)) {
+ groupChecks.push_back((RandoCheckId)checkId);
+ }
+ }
+ }
+ std::sort(groupChecks.begin(), groupChecks.end());
+ curatedGroupChecks.push_back(groupChecks);
+ }
+ }
+ return curatedGroupChecks;
+}
- if (checksList != "") {
- std::string word;
- std::istringstream stream(checksList);
- while (std::getline(stream, word, ',')) {
- checkExclusionList.push_back((RandoCheckId)std::stoi(word));
+void SetCuratedGroupExcluded(const std::vector<RandoCheckId>& groupChecks, bool excluded) {
+ if (excluded) {
+ for (RandoCheckId randoCheckId : groupChecks) {
+ auto it = std::lower_bound(checkExclusionList.begin(), checkExclusionList.end(), randoCheckId);
+ if (it == checkExclusionList.end() || *it != randoCheckId) {
+ checkExclusionList.insert(it, randoCheckId);
+ }
}
+ } else {
+ std::erase_if(checkExclusionList, [&](const RandoCheckId& randoCheckId) {
+ return std::binary_search(groupChecks.begin(), groupChecks.end(), randoCheckId);
+ });
}
- SortExcludedChecks();
+ SaveExcludedChecks();
}
static int checksInPool = 0;
@@ -180,8 +244,10 @@ static int itemsInPool = 0;
static int junkInPool = 0;
static int balanceStatus = 0; // 0 = Able to balance, 1 = Unlikely to balance, 2 = Unable to balance
static std::set<RandoItemId> setOfItemsInPool;
+static std::set<RandoCheckId> setOfChecksInPool;
void RefreshMetrics() {
setOfItemsInPool.clear();
+ setOfChecksInPool.clear();
RandoSaveInfo randoSaveInfo;
std::vector<RandoCheckId> checkPool;
std::vector<RandoItemId> itemPool;
@@ -199,6 +265,9 @@ void RefreshMetrics() {
checksInPool = checkPool.size();
itemsInPool = itemPool.size();
junkInPool = 0;
+ for (auto& check : checkPool) {
+ setOfChecksInPool.insert(check);
+ }
for (auto& item : itemPool) {
setOfItemsInPool.insert(item);
if (Rando::StaticData::Items[item].randoItemType == RITYPE_JUNK) {
@@ -253,6 +322,7 @@ static RegisterShipInitFunc refreshMetricsInit(RefreshMetrics, {
"gRando.Options.RO_SHUFFLE_BARREL_DROPS",
"gRando.Options.RO_SHUFFLE_BOSS_REMAINS",
"gRando.Options.RO_SHUFFLE_BOSS_SOULS",
+ "gRando.Options.RO_SHUFFLE_BUTTERFLIES",
"gRando.Options.RO_SHUFFLE_COWS",
"gRando.Options.RO_SHUFFLE_CRATE_DROPS",
"gRando.Options.RO_SHUFFLE_ENEMY_DROPS",
@@ -275,6 +345,7 @@ static RegisterShipInitFunc refreshMetricsInit(RefreshMetrics, {
"gRando.Options.RO_SHUFFLE_SONG_SUN",
"gRando.Options.RO_SHUFFLE_SWIM",
"gRando.Options.RO_SHUFFLE_TINGLE_SHOPS",
+ "gRando.Options.RO_SHUFFLE_TREE_DROPS",
"gRando.Options.RO_SHUFFLE_TYCOON_WALLET",
"gRando.Options.RO_SHUFFLE_TRIFORCE_PIECES",
"gRando.Options.RO_SKULLTULA_TOKENS_MAX",
@@ -1099,6 +1170,68 @@ static void DrawFilterWithButton(ImGuiTextFilter& filter, const char* placeholde
}
}
+static void DrawCuratedCheckGroups(UIWidgets::Colors menuThemeColor) {
+ struct CuratedGroupButton {
+ std::string label;
+ std::string tooltip;
+ const std::vector<RandoCheckId>* checks;
+ bool allExcluded;
+ bool disabled;
+ };
+
+ const auto& curatedGroupChecks = GetCuratedGroupChecks();
+ std::vector<CuratedGroupButton> curatedGroupButtons;
+ for (size_t i = 0; i < curatedCheckGroups.size(); i++) {
+ const auto& groupChecks = curatedGroupChecks[i];
+ bool allExcluded =
+ !groupChecks.empty() && std::all_of(groupChecks.begin(), groupChecks.end(), [](RandoCheckId randoCheckId) {
+ return std::binary_search(checkExclusionList.begin(), checkExclusionList.end(), randoCheckId);
+ });
+ bool anyInPool = std::any_of(groupChecks.begin(), groupChecks.end(), [](RandoCheckId randoCheckId) {
+ return setOfChecksInPool.contains(randoCheckId);
+ });
+
+ std::string tooltip = curatedCheckGroups[i].description;
+ if (groupChecks.size() <= 12) {
+ for (RandoCheckId randoCheckId : groupChecks) {
+ tooltip += "\n- " + Rando::StaticData::CheckNames[randoCheckId];
+ }
+ }
+ tooltip +=
+ allExcluded ? "\n\nClick to stop excluding these checks." : "\n\nClick to exclude all of these checks.";
+
+ curatedGroupButtons.push_back({
+ std::string(curatedCheckGroups[i].label) + " (" + std::to_string(groupChecks.size()) + ")",
+ tooltip,
+ &groupChecks,
+ allExcluded,
+ !anyInPool && !allExcluded,
+ });
+ }
+
+ ImGui::SeparatorText("Curated Groups");
+ f32 windowRight = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
+ for (size_t i = 0; i < curatedGroupButtons.size(); i++) {
+ auto& curatedGroupButton = curatedGroupButtons[i];
+ if (Button(curatedGroupButton.label.c_str(),
+ ButtonOptions({ { .tooltip = curatedGroupButton.tooltip.c_str(),
+ .disabled = curatedGroupButton.disabled,
+ .disabledTooltip = "These checks are not shuffled by the current settings" } })
+ .Size(Sizes::Inline)
+ .Color(curatedGroupButton.allExcluded ? Colors::Orange : menuThemeColor))) {
+ SetCuratedGroupExcluded(*curatedGroupButton.checks, !curatedGroupButton.allExcluded);
+ }
+
+ if (i + 1 < curatedGroupButtons.size()) {
+ f32 nextButtonRight = ImGui::GetItemRectMax().x + ImGui::GetStyle().ItemSpacing.x +
+ CalcButtonWidth(curatedGroupButtons[i + 1].label.c_str());
+ if (nextButtonRight < windowRight) {
+ ImGui::SameLine();
+ }
+ }
+ }
+}
+
static void DrawCheckFilterTab() {
if (CVarGetInteger(Rando::StaticData::Options[RO_LOGIC].cvar, RO_LOGIC_GLITCHLESS) >= RO_LOGIC_VANILLA) {
ImGui::TextColored(UIWidgets::ColorValues.at(UIWidgets::Colors::Red),
@@ -1111,22 +1244,24 @@ static void DrawCheckFilterTab() {
bool excludeFiltered = false;
bool removeFiltered = false;
bool removeAllChecks = false;
- if (!isExcludedInitialized) {
- LoadExcludedChecks();
- isExcludedInitialized = true;
- }
+ RandoCheckId checkToExclude = RC_UNKNOWN;
+ RandoCheckId checkToRestore = RC_UNKNOWN;
+
+ DrawCuratedCheckGroups(menuThemeColor);
f32 columnWidth = ImGui::GetContentRegionAvail().x / 2 - (ImGui::GetStyle().ItemSpacing.x * 2);
- ImGui::BeginChild("randoIncludedChecks", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y));
- ImGui::SeparatorText("Normal Checks");
+ ImGui::BeginChild("randoIncludedChecks", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y),
+ ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
+ ImGui::SeparatorText("Shuffled Checks");
static ImGuiTextFilter includedFilter;
- const char* leftButtonLabel = includedFilter.IsActive() ? "Junk Filtered" : "Junk All";
+ const char* leftButtonLabel = includedFilter.IsActive() ? "Exclude Filtered" : "Exclude All";
f32 availableWidth = ImGui::GetContentRegionAvail().x;
- DrawFilterWithButton(includedFilter, "Normal Search", leftButtonLabel, availableWidth, menuThemeColor,
+ DrawFilterWithButton(includedFilter, "Shuffled Search", leftButtonLabel, availableWidth, menuThemeColor,
excludeFiltered, excludeAllChecks, 30.0f, 24.0f, 6.0f, 18.0f);
- if (ImGui::BeginTable("Normal Checks", 1)) {
+ ImGui::BeginChild("randoIncludedChecksList", ImVec2(0, 0));
+ if (ImGui::BeginTable("Shuffled Checks", 1)) {
ImGui::TableNextColumn();
for (auto& includedChecks : Rando::StaticData::Checks) {
@@ -1134,11 +1269,11 @@ static void DrawCheckFilterTab() {
continue;
}
- if (!includedFilter.PassFilter(Rando::StaticData::CheckNames[includedChecks.first].c_str())) {
+ if (!setOfChecksInPool.contains(includedChecks.first)) {
continue;
}
- if (std::binary_search(checkExclusionList.begin(), checkExclusionList.end(), includedChecks.first)) {
+ if (!includedFilter.PassFilter(Rando::StaticData::CheckNames[includedChecks.first].c_str())) {
continue;
}
@@ -1151,74 +1286,68 @@ static void DrawCheckFilterTab() {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,
ImGui::IsItemHovered() ? IM_COL32(255, 255, 0, 128) : IM_COL32(255, 255, 255, 0));
if (ImGui::IsItemClicked()) {
- auto it = std::lower_bound(checkExclusionList.begin(), checkExclusionList.end(), includedChecks.first);
- if (it == checkExclusionList.end() || *it != includedChecks.first) {
- checkExclusionList.insert(it, includedChecks.first);
- SaveExcludedChecks();
- }
+ checkToExclude = includedChecks.first;
}
ImGui::TableNextColumn();
}
ImGui::EndTable();
}
ImGui::EndChild();
+ ImGui::EndChild();
ImGui::SameLine();
- ImGui::BeginChild("randoExcludedChecks", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y));
- ImGui::SeparatorText("Forced Junk Checks");
+ ImGui::BeginChild("randoExcludedChecks", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y),
+ ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
+ ImGui::SeparatorText("Excluded Checks");
static ImGuiTextFilter excludedFilter;
const char* rightButtonLabel = excludedFilter.IsActive() ? "Remove Filtered" : "Remove All";
f32 rightAvailableWidth = ImGui::GetContentRegionAvail().x;
- DrawFilterWithButton(excludedFilter, "Junk Search", rightButtonLabel, rightAvailableWidth, menuThemeColor,
+ DrawFilterWithButton(excludedFilter, "Excluded Search", rightButtonLabel, rightAvailableWidth, menuThemeColor,
removeFiltered, removeAllChecks, 30.0f, 24.0f, 6.0f, 18.0f);
- if (ImGui::BeginTable("Forced Junk Checks", 1)) {
+ ImGui::BeginChild("randoExcludedChecksList", ImVec2(0, 0));
+ if (ImGui::BeginTable("Excluded Checks", 1)) {
ImGui::TableNextColumn();
- for (auto it = checkExclusionList.begin(); it != checkExclusionList.end();) {
- if (!excludedFilter.PassFilter(Rando::StaticData::CheckNames[*it].c_str())) {
- ++it;
+ for (RandoCheckId randoCheckId : checkExclusionList) {
+ if (!excludedFilter.PassFilter(Rando::StaticData::CheckNames[randoCheckId].c_str())) {
continue;
}
- ImGui::Text("%s", Rando::StaticData::CheckNames[*it].c_str());
+ ImGui::Text("%s", Rando::StaticData::CheckNames[randoCheckId].c_str());
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,
ImGui::IsItemHovered() ? IM_COL32(255, 255, 0, 128) : IM_COL32(255, 255, 255, 0));
if (ImGui::IsItemClicked()) {
- it = checkExclusionList.erase(it);
- SaveExcludedChecks();
- } else {
- ++it;
+ checkToRestore = randoCheckId;
}
ImGui::TableNextColumn();
}
ImGui::EndTable();
}
ImGui::EndChild();
+ ImGui::EndChild();
- // Junk all checks
- if (excludeAllChecks) {
- checkExclusionList.clear();
- checkExclusionList.reserve(Rando::StaticData::Checks.size());
- for (auto& includedChecks : Rando::StaticData::Checks) {
- if (includedChecks.first != RC_UNKNOWN) {
- checkExclusionList.push_back(includedChecks.first);
- }
+ if (checkToExclude != RC_UNKNOWN) {
+ auto it = std::lower_bound(checkExclusionList.begin(), checkExclusionList.end(), checkToExclude);
+ if (it == checkExclusionList.end() || *it != checkToExclude) {
+ checkExclusionList.insert(it, checkToExclude);
+ SaveExcludedChecks();
}
- SortExcludedChecks();
+ }
+
+ if (checkToRestore != RC_UNKNOWN) {
+ std::erase(checkExclusionList, checkToRestore);
SaveExcludedChecks();
- includedFilter.Clear();
- excludeAllChecks = false;
}
- // Junk filtered checks
- if (excludeFiltered) {
+ if (excludeAllChecks || excludeFiltered) {
for (auto& includedChecks : Rando::StaticData::Checks) {
- if (includedChecks.first == RC_UNKNOWN) {
+ if (!setOfChecksInPool.contains(includedChecks.first)) {
continue;
}
- if (!includedFilter.PassFilter(Rando::StaticData::CheckNames[includedChecks.first].c_str())) {
+ if (excludeFiltered &&
+ !includedFilter.PassFilter(Rando::StaticData::CheckNames[includedChecks.first].c_str())) {
continue;
}
@@ -1229,6 +1358,7 @@ static void DrawCheckFilterTab() {
}
SaveExcludedChecks();
includedFilter.Clear();
+ excludeAllChecks = false;
excludeFiltered = false;
}
diff --git a/mm/2s2h/Rando/Rando.h b/mm/2s2h/Rando/Rando.h
index 1c7aa6297..80df71535 100644
--- a/mm/2s2h/Rando/Rando.h
+++ b/mm/2s2h/Rando/Rando.h
@@ -41,6 +41,9 @@ std::vector<RandoItemId> GetSariaPriorityItemsFromConfig();
void SetSariaPriorityItemsInConfig(std::vector<RandoItemId>& priorityItems);
std::vector<RandoItemId> GetSariaPriorityItemCandidates();
+std::vector<RandoCheckId> GetExcludedChecksFromConfig();
+void SetExcludedChecksInConfig(std::vector<RandoCheckId>& excludedChecks);
+
std::vector<RandoCheckId> FindMultiItemPlacement(RandoItemId randoItemId);
} // namespace Rando