diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp index 07bb809ac..de6c20be0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp @@ -16,6 +16,7 @@ #include "debug.hpp" #include #include "../../randomizer/randomizerTypes.h" +#include namespace { bool seedChanged; @@ -512,16 +513,16 @@ void PrintOptionDescription() { } std::string GenerateRandomizer(std::unordered_map cvarSettings, std::set excludedLocations, - std::string seedInput) { + std::string seedString) { srand(time(NULL)); // if a blank seed was entered, make a random one - if (seedInput.empty()) { + if (seedString.empty()) { Settings::seed = rand() & 0xFFFFFFFF; - } else if (seedInput.rfind("seed_testing_count", 0) == 0 && seedInput.length() > 18) { + } else if (seedString.rfind("seed_testing_count", 0) == 0 && seedString.length() > 18) { int count; try { - count = std::stoi(seedInput.substr(18), nullptr); + count = std::stoi(seedString.substr(18), nullptr); } catch (std::invalid_argument &e) { count = 1; } catch (std::out_of_range &e) { @@ -531,8 +532,10 @@ std::string GenerateRandomizer(std::unordered_map return ""; } else { try { - int seed = std::stoi(seedInput, nullptr); + uint32_t seedHash = boost::hash_32{}(seedString); + int seed = seedHash & 0xFFFFFFFF; Settings::seed = seed; + Settings::seedString = seedString; } catch (...) { return ""; } diff --git a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp index c8fb8ab39..b57ac9774 100644 --- a/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/rando_main.cpp @@ -12,7 +12,7 @@ #define TICKS_PER_SEC 268123480.0 void RandoMain::GenerateRando(std::unordered_map cvarSettings, std::set excludedLocations, - std::string seedInput) { + std::string seedString) { HintTable_Init(); ItemTable_Init(); LocationTable_Init(); @@ -20,7 +20,7 @@ void RandoMain::GenerateRando(std::unordered_map cvarS // std::string settingsFileName = "./randomizer/latest_settings.json"; // CVarSetString("gLoadedPreset", settingsFileName.c_str()); - std::string fileName = Ship::Window::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, seedInput).c_str()); + std::string fileName = Ship::Window::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, seedString).c_str()); CVarSetString("gSpoilerLog", fileName.c_str()); CVarSave(); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index d087324b4..d32e96ab7 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -23,6 +23,7 @@ namespace Settings { std::string hash; std::string version = RANDOMIZER_VERSION "-" COMMIT_NUMBER; std::array hashIconIndexes; + std::string seedString; bool skipChildZelda = false; diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.hpp b/soh/soh/Enhancements/randomizer/3drando/settings.hpp index e6bd4e785..aef944db6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.hpp @@ -891,6 +891,7 @@ void UpdateSettings(std::unordered_map cvarSettin extern std::string version; extern std::array hashIconIndexes; extern std::string hash; + extern std::string seedString; extern bool skipChildZelda; diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index a7541c3e0..d33ccf9a2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -775,7 +775,7 @@ const char* SpoilerLog_Write(int language) { jsonData.clear(); jsonData["_version"] = (char*) gBuildVersion; - jsonData["_seed"] = Settings::seed; + jsonData["_seed"] = Settings::seedString; // Write Hash int index = 0; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 58c9ce46d..dff443f34 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -26,6 +26,7 @@ #include #include "draw.h" #include "rando_hash.h" +#include extern "C" uint32_t ResourceMgr_IsGameMasterQuest(); extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum); @@ -39,7 +40,7 @@ std::multimap, RandomizerCheckObject> checkFromActorMu std::set excludedLocations; u8 generated; -char* seedInputBuffer; +char* seedString; const std::string Randomizer::getItemMessageTableID = "Randomizer"; const std::string Randomizer::hintMessageTableID = "RandomizerHints"; @@ -2949,8 +2950,6 @@ void GenerateRandomizerImgui(std::string seed = "") { RandoMain::GenerateRando(cvarSettings, excludedLocations, seed); - memset(seedInputBuffer, 0, MAX_SEED_BUFFER_SIZE); - CVarSetInteger("gRandoGenerating", 0); CVarSave(); CVarLoad(); @@ -3049,27 +3048,28 @@ void DrawRandoEditor(bool& open) { DrawPresetSelector(PRESET_TYPE_RANDOMIZER); UIWidgets::Spacer(0); - - ImGui::Text("Seed"); - if (ImGui::InputText("##RandomizerSeed", seedInputBuffer, MAX_SEED_BUFFER_SIZE, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterNumbers)) { - uint32_t seedInput; - ImGui::DataTypeApplyFromText(seedInputBuffer, ImGuiDataType_U32, &seedInput, "%u"); - strncpy(seedInputBuffer, std::to_string(seedInput).c_str(), MAX_SEED_BUFFER_SIZE); - } - UIWidgets::Tooltip("Leaving this field blank will use a random seed value automatically\nSeed range is 0 - 4,294,967,295"); - ImGui::SameLine(); - if (ImGui::Button("New Seed")) { - strncpy(seedInputBuffer, std::to_string(rand() & 0xFFFFFFFF).c_str(), MAX_SEED_BUFFER_SIZE); - } - UIWidgets::Tooltip("Creates a new random seed value to be used when generating a randomizer"); - ImGui::SameLine(); - if (ImGui::Button("Clear Seed")) { - memset(seedInputBuffer, 0, MAX_SEED_BUFFER_SIZE); + UIWidgets::EnhancementCheckbox("Manual seed entry", "gRandoManualSeedEntry", false, ""); + if (CVarGetInteger("gRandoManualSeedEntry", 0)) { + ImGui::Text("Seed"); + ImGui::InputText("##RandomizerSeed", seedString, MAX_SEED_STRING_SIZE, ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterAlphaNum); + UIWidgets::Tooltip( + "Characters from a-z, A-Z, and 0-9 are supported.\n" + "Character limit is 1023, after which the seed will be truncated.\n" + ); + ImGui::SameLine(); + if (ImGui::Button("New Seed")) { + strncpy(seedString, std::to_string(rand() & 0xFFFFFFFF).c_str(), MAX_SEED_STRING_SIZE); + } + UIWidgets::Tooltip("Creates a new random seed value to be used when generating a randomizer"); + ImGui::SameLine(); + if (ImGui::Button("Clear Seed")) { + memset(seedString, 0, MAX_SEED_STRING_SIZE); + } } UIWidgets::Spacer(0); - if (ImGui::Button("Generate Randomizer")) { - GenerateRandomizer(seedInputBuffer); + if (ImGui::Button("Generate Randomizer")) { + GenerateRandomizer(CVarGetInteger("gRandoManualSeedEntry", 0) ? seedString : std::to_string(rand() & 0xFFFFFFFF).c_str()); } UIWidgets::Spacer(0); @@ -5305,7 +5305,7 @@ void InitRandoItemTable() { void InitRando() { SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor); Randomizer::CreateCustomMessages(); - seedInputBuffer = (char*)calloc(MAX_SEED_BUFFER_SIZE, sizeof(char)); + seedString = (char*)calloc(MAX_SEED_STRING_SIZE, sizeof(char)); InitRandoItemTable(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index a8c97858f..b6da344e7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -12,7 +12,7 @@ #include #include "soh/Enhancements/item-tables/ItemTableTypes.h" -#define MAX_SEED_BUFFER_SIZE 11 // digits for uint32 +#define MAX_SEED_STRING_SIZE 1024 #define NUM_NAVI_MESSAGES 19 #define NUM_ICE_TRAP_MESSAGES 23 #define NUM_GORON_MESSAGES 9 diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index 3295bf2c8..4cb5b1012 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -22,6 +22,15 @@ namespace UIWidgets { } return 1; } + + static int FilterAlphaNum(ImGuiInputTextCallbackData* data) { + const char* alphanum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWYZ0123456789"; + if (data->EventChar < 256 && strchr(alphanum, (char)data->EventChar)) { + return 0; + } + return 1; + } + }; // MARK: - Enums