diff --git a/libultraship/libultraship/Console.cpp b/libultraship/libultraship/Console.cpp index 83737e7387..efc13ca2ca 100644 --- a/libultraship/libultraship/Console.cpp +++ b/libultraship/libultraship/Console.cpp @@ -15,9 +15,9 @@ namespace Ship { std::map BindingToggle; static bool HelpCommand(const std::vector&) { - INFO("SoH Commands:"); + SohImGui::console->SendInfoMessage("SoH Commands:"); for (const auto& cmd : SohImGui::console->Commands) { - INFO("%s", (" - " + cmd.first).c_str()); + SohImGui::console->SendInfoMessage(" - " + cmd.first); } return CMD_SUCCESS; } @@ -45,7 +45,7 @@ namespace Ship { std::ostringstream imploded; std::copy(args.begin() + 2, args.end(), std::ostream_iterator(imploded, delim)); Bindings[k] = imploded.str(); - INFO("Binding '%s' to %s", args[1].c_str(), Bindings[k].c_str()); + SohImGui::console->SendInfoMessage("Binding '%s' to %s", args[1].c_str(), Bindings[k].c_str()); break; } } @@ -61,7 +61,7 @@ namespace Ship { if (toLowerCase(args[1]) == toLowerCase(key)) { BindingToggle[k] = args[2]; - INFO("Binding toggle '%s' to %s", args[1].c_str(), BindingToggle[k].c_str()); + SohImGui::console->SendInfoMessage("Binding toggle '%s' to %s", args[1].c_str(), BindingToggle[k].c_str()); break; } } @@ -159,29 +159,39 @@ namespace Ship { // Renders top bar filters if (ImGui::Button("Clear")) this->Log[this->selected_channel].clear(); - ImGui::SameLine(); - ImGui::SetNextItemWidth(150); - if (ImGui::BeginCombo("##channel", this->selected_channel.c_str())) { - for (const auto& channel : log_channels) { - const bool is_selected = (channel == std::string(this->selected_channel)); - if (ImGui::Selectable(channel.c_str(), is_selected)) - this->selected_channel = channel; - if (is_selected) ImGui::SetItemDefaultFocus(); + + if (CVar_GetS32("gSinkEnabled", 0)) { + ImGui::SameLine(); + ImGui::SetNextItemWidth(150); + if (ImGui::BeginCombo("##channel", this->selected_channel.c_str())) { + for (const auto& channel : log_channels) { + const bool is_selected = (channel == std::string(this->selected_channel)); + if (ImGui::Selectable(channel.c_str(), is_selected)) + this->selected_channel = channel; + if (is_selected) ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); } - ImGui::EndCombo(); + } else { + this->selected_channel = "Console"; } ImGui::SameLine(); ImGui::SetNextItemWidth(150); - if (ImGui::BeginCombo("##level", this->level_filter.c_str())) { - for (const auto& filter : priority_filters) { - const bool is_selected = (filter == std::string(this->level_filter)); - if (ImGui::Selectable(filter.c_str(), is_selected)) - { - this->level_filter = filter; - if (is_selected) ImGui::SetItemDefaultFocus(); + + if (this->selected_channel != "Console") { + if (ImGui::BeginCombo("##level", spdlog::level::to_string_view(this->level_filter).data())) { + for (const auto& priority_filter : priority_filters) { + const bool is_selected = priority_filter == this->level_filter; + if (ImGui::Selectable(spdlog::level::to_string_view(priority_filter).data(), is_selected)) + { + this->level_filter = priority_filter; + if (is_selected) ImGui::SetItemDefaultFocus(); + } } + ImGui::EndCombo(); } - ImGui::EndCombo(); + } else { + this->level_filter = spdlog::level::trace; } ImGui::SameLine(); ImGui::PushItemWidth(-1); @@ -203,7 +213,7 @@ namespace Ship { for (int i = 0; i < static_cast(channel.size()); i++) { ConsoleLine line = channel[i]; if (!this->filter.empty() && line.text.find(this->filter) == std::string::npos) continue; - if (this->level_filter != NULLSTR && line.priority != (std::find(priority_filters.begin(), priority_filters.end(), this->level_filter) - priority_filters.begin()) - 1) continue; + if (this->level_filter > line.priority) continue; std::string id = line.text + "##" + std::to_string(i); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); @@ -226,54 +236,56 @@ namespace Ship { ImGui::SetScrollHereY(1.0f); ImGui::EndChild(); - // Renders input textfield - constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit | - ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; - ImGui::PushItemWidth(-53); - if (ImGui::InputTextWithHint("##CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) { - input_focus = true; - if (this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ') - this->Dispatch(std::string(this->InputBuffer)); - memset(this->InputBuffer, 0, MAX_BUFFER_SIZE); - } - - if (this->CMDHint != NULLSTR) { - if (ImGui::IsItemFocused()) { - ImGui::SetNextWindowPos(ImVec2(pos.x, pos.y + size.y)); - ImGui::SameLine(); - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextUnformatted(this->CMDHint.c_str()); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); + if (this->selected_channel == "Console") { + // Renders input textfield + constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit | + ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; + ImGui::PushItemWidth(-53); + if (ImGui::InputTextWithHint("##CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) { + input_focus = true; + if (this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ') + this->Dispatch(std::string(this->InputBuffer)); + memset(this->InputBuffer, 0, MAX_BUFFER_SIZE); } - } - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 50); - if (ImGui::Button("Submit") && !input_focus && this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ') { - this->Dispatch(std::string(this->InputBuffer)); - memset(this->InputBuffer, 0, MAX_BUFFER_SIZE); - } + if (this->CMDHint != NULLSTR) { + if (ImGui::IsItemFocused()) { + ImGui::SetNextWindowPos(ImVec2(pos.x, pos.y + size.y)); + ImGui::SameLine(); + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(this->CMDHint.c_str()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + } - ImGui::SetItemDefaultFocus(); - if (input_focus) ImGui::SetKeyboardFocusHere(-1); - ImGui::PopItemWidth(); + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 50); + if (ImGui::Button("Submit") && !input_focus && this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ') { + this->Dispatch(std::string(this->InputBuffer)); + memset(this->InputBuffer, 0, MAX_BUFFER_SIZE); + } + + ImGui::SetItemDefaultFocus(); + if (input_focus) ImGui::SetKeyboardFocusHere(-1); + ImGui::PopItemWidth(); + } ImGui::End(); } void Console::Dispatch(const std::string& line) { this->CMDHint = NULLSTR; this->History.push_back(line); - this->Log[this->selected_channel].push_back({ "> " + line }); + SendInfoMessage("> " + line); const std::vector cmd_args = StringHelper::Split(line, " "); if (this->Commands.contains(cmd_args[0])) { const CommandEntry entry = this->Commands[cmd_args[0]]; if (!entry.handler(cmd_args) && !entry.arguments.empty()) - this->Log[this->selected_channel].push_back({ "[SOH] Usage: " + cmd_args[0] + " " + BuildUsage(entry), ERROR_LVL }); + SendErrorMessage("[SOH] Usage: " + cmd_args[0] + " " + BuildUsage(entry)); return; } - this->Log[this->selected_channel].push_back({ "[SOH] Command not found", ERROR_LVL }); + SendErrorMessage("[SOH] Command not found"); } int Console::CallbackStub(ImGuiInputTextCallbackData* data) { @@ -325,13 +337,39 @@ namespace Ship { return 0; } - void Console::Append(const std::string& channel, Priority priority, const char* fmt, ...) { - char buf[1024]; - va_list args; - va_start(args, fmt); + void Console::Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, va_list args) { + char buf[2048]; vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); buf[IM_ARRAYSIZE(buf) - 1] = 0; - va_end(args); this->Log[channel].push_back({ std::string(buf), priority }); } + + void Console::Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + Append(channel, priority, fmt, args); + va_end(args); + } + + void Console::SendInfoMessage(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + Append("Console", spdlog::level::info, fmt, args); + va_end(args); + } + + void Console::SendErrorMessage(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + Append("Console", spdlog::level::err, fmt, args); + va_end(args); + } + + void Console::SendInfoMessage(const std::string& str) { + Append("Console", spdlog::level::info, str.c_str()); + } + + void Console::SendErrorMessage(const std::string& str) { + Append("Console", spdlog::level::err, str.c_str()); + } } \ No newline at end of file diff --git a/libultraship/libultraship/Console.h b/libultraship/libultraship/Console.h index a174450e16..00ca518e26 100644 --- a/libultraship/libultraship/Console.h +++ b/libultraship/libultraship/Console.h @@ -6,12 +6,11 @@ #include #include "Lib/ImGui/imgui.h" +#define NOGDI +#define WIN32_LEAN_AND_MEAN +#include "spdlog/spdlog.h" namespace Ship { - #define LOG(msg, ...) SohImGui::console->Append("Main", Ship::Priority::LOG_LVL, msg, ##__VA_ARGS__) - #define INFO(msg, ...) SohImGui::console->Append("Main", Ship::Priority::INFO_LVL, msg, ##__VA_ARGS__) - #define WARNING(msg, ...) SohImGui::console->Append("Main", Ship::Priority::WARNING_LVL, msg, ##__VA_ARGS__) - #define ERROR(msg, ...) SohImGui::console->Append("Main", Ship::Priority::ERROR_LVL, msg, ##__VA_ARGS__) #define CMD_SUCCESS true #define CMD_FAILED false #define MAX_BUFFER_SIZE 255 @@ -19,13 +18,6 @@ namespace Ship { typedef std::function args)> CommandHandler; - enum Priority { - INFO_LVL, - LOG_LVL, - WARNING_LVL, - ERROR_LVL - }; - enum class ArgumentType { TEXT, NUMBER, PLAYER_POS, PLAYER_ROT }; @@ -44,23 +36,29 @@ namespace Ship { struct ConsoleLine { std::string text; - Priority priority = Priority::INFO_LVL; - std::string channel = "Main"; + spdlog::level::level_enum priority = spdlog::level::info; + std::string channel = "Console"; }; class Console { int selectedId = -1; std::vector selectedEntries; std::string filter; - std::string level_filter = NULLSTR; - std::vector log_channels = { "Main", "SoH Logging" }; - std::vector priority_filters = { "None", "Info", "Log", "Warning", "Error" }; + spdlog::level::level_enum level_filter = spdlog::level::trace; + std::vector log_channels = { "Console", "Logs" }; + std::vector priority_filters = { spdlog::level::off, spdlog::level::critical, spdlog::level::err, spdlog::level::warn, spdlog::level::info, spdlog::level::debug, spdlog::level::trace }; std::vector priority_colors = { - ImVec4(1.0f, 1.0f, 1.0f, 1.0f), - ImVec4(0.2f, 1.0f, 0.2f, 1.0f), - ImVec4(0.9f, 0.8f, 0.4f, 0.01f), - ImVec4(1.0f, 0.2f, 0.2f, 1.0f) + ImVec4(0.8f, 0.8f, 0.8f, 1.0f), // TRACE + ImVec4(0.9f, 0.9f, 0.9f, 1.0f), // DEBUG + ImVec4(1.0f, 1.0f, 1.0f, 1.0f), // INFO + ImVec4(1.0f, 0.875f, 0.125f, 1.0f), // WARN + ImVec4(0.65f, 0.18f, 0.25, 1.0f), // ERROR + ImVec4(0.95f, 0.11f, 0.25, 1.0f), // CRITICAL + ImVec4(0.0f, 0.0f, 0.0f, 0.0f) // OFF }; + protected: + void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, va_list args); + public: std::map> Log; std::map Commands; @@ -71,13 +69,17 @@ namespace Ship { char* InputBuffer = nullptr; bool OpenAutocomplete = false; int HistoryIndex = -1; - std::string selected_channel = "Main"; + std::string selected_channel = "Console"; bool opened = false; void Init(); void Update(); void Draw(); - void Append(const std::string& channel, Priority priority, const char* fmt, ...) IM_FMTARGS(4); void Dispatch(const std::string& line); static int CallbackStub(ImGuiInputTextCallbackData* data); + void SendInfoMessage(const char* fmt, ...); + void SendErrorMessage(const char* fmt, ...); + void SendInfoMessage(const std::string& str); + void SendErrorMessage(const std::string& str); + void Append(const std::string& channel, spdlog::level::level_enum priority, const char* fmt, ...); }; } \ No newline at end of file diff --git a/libultraship/libultraship/Cutscene.cpp b/libultraship/libultraship/Cutscene.cpp index a1e2421ebb..79b42b3f10 100644 --- a/libultraship/libultraship/Cutscene.cpp +++ b/libultraship/libultraship/Cutscene.cpp @@ -1,4 +1,5 @@ #include "Cutscene.h" +#include "spdlog/spdlog.h" enum class CutsceneCommands { @@ -511,9 +512,7 @@ void Ship::CutsceneV0::ParseFileBinary(BinaryReader* reader, Resource* res) return; } default: -#ifdef _DEBUG - printf("CutsceneV0: Unknown command %x\n", commandId); -#endif + SPDLOG_TRACE("CutsceneV0: Unknown command {}\n", commandId); // error? break; } diff --git a/libultraship/libultraship/GameOverlay.cpp b/libultraship/libultraship/GameOverlay.cpp index 00bab575fb..8fe028667e 100644 --- a/libultraship/libultraship/GameOverlay.cpp +++ b/libultraship/libultraship/GameOverlay.cpp @@ -4,7 +4,6 @@ #include "File.h" #include "Archive.h" #include "ResourceMgr.h" -#include "Console.h" #include "ImGuiImpl.h" #include "Lib/ImGui/imgui_internal.h" #include "Utils/StringHelper.h" @@ -209,24 +208,25 @@ namespace Ship { if (args[1] == "add") { if (!overlay->RegisteredOverlays.contains(key)) { overlay->RegisteredOverlays[key] = new Overlay({ OverlayType::TEXT, ImStrdup(key), -1.0f }); - INFO("Added overlay: %s ", key); + SPDLOG_INFO("Added overlay: {} ", key); + SohImGui::console->SendInfoMessage("Added overlay: %s", key); } else { - ERROR("Overlay already exists: %s", key); + SPDLOG_ERROR("Overlay already exists: {}", key); } } else if (args[1] == "remove") { if (overlay->RegisteredOverlays.contains(key)) { overlay->RegisteredOverlays.erase(key); - INFO("Removed overlay: %s ", key); + SPDLOG_INFO("Removed overlay: {} ", key); } else { - ERROR("Overlay not found: %s ", key); + SPDLOG_ERROR("Overlay not found: {}", key); } } } else { - ERROR("CVar %s does not exist", args[2].c_str()); + SPDLOG_ERROR("CVar {} does not exist", args[2].c_str()); } return CMD_SUCCESS; diff --git a/libultraship/libultraship/GlobalCtx2.cpp b/libultraship/libultraship/GlobalCtx2.cpp index 4d6046de39..c5597d7c9e 100644 --- a/libultraship/libultraship/GlobalCtx2.cpp +++ b/libultraship/libultraship/GlobalCtx2.cpp @@ -90,12 +90,20 @@ namespace Ship { // Setup Logging spdlog::init_thread_pool(8192, 1); auto SohConsoleSink = std::make_shared(); - auto ConsoleSink = std::make_shared(); - auto FileSink = std::make_shared(logPath, 1024 * 1024 * 10, 10); SohConsoleSink->set_level(spdlog::level::trace); +#if defined(__linux__) + auto ConsoleSink = std::make_shared(); ConsoleSink->set_level(spdlog::level::trace); +#endif + auto FileSink = std::make_shared(logPath, 1024 * 1024 * 10, 10); FileSink->set_level(spdlog::level::trace); - std::vector Sinks{ ConsoleSink, FileSink, SohConsoleSink }; + std::vector Sinks{ +#if defined(__linux__) + ConsoleSink, +#endif + FileSink, + SohConsoleSink + }; Logger = std::make_shared(GetName(), Sinks.begin(), Sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block); GetLogger()->set_level(spdlog::level::trace); GetLogger()->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%@] [%l] %v"); diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp index 93f30455c5..b95073fd18 100644 --- a/libultraship/libultraship/ImGuiImpl.cpp +++ b/libultraship/libultraship/ImGuiImpl.cpp @@ -1530,7 +1530,7 @@ namespace SohImGui { 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)) { - INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]); + SPDLOG_INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]); CVar_SetS32("gSwitchPerfMode", sId); Switch::ApplyOverclock(); needs_save = true; @@ -1752,6 +1752,14 @@ namespace SohImGui { needs_save = true; customWindows["Item Tracker"].enabled = CVar_GetS32("gItemTrackerEnabled", 0); } + InsertPadding(); + if (ImGui::Button(GetWindowButtonText("Item Tracker Settings", CVar_GetS32("gItemTrackerSettingsEnabled", 0)).c_str(), buttonSize)) + { + bool currentValue = CVar_GetS32("gItemTrackerSettingsEnabled", 0); + CVar_SetS32("gItemTrackerSettingsEnabled", !currentValue); + needs_save = true; + customWindows["Item Tracker Settings"].enabled = CVar_GetS32("gItemTrackerSettingsEnabled", 0); + } ImGui::PopStyleVar(3); ImGui::PopStyleColor(1); 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 7b5da63fde..65e98610aa 100644 --- a/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h +++ b/libultraship/libultraship/Lib/spdlog/include/spdlog/sinks/sohconsole_sink.h @@ -31,47 +31,24 @@ public: {} protected: - void sink_it_(const details::log_msg &msg) override - { - const Ship::Priority priority = convert_to_soh(msg.level); + void sink_it_(const details::log_msg &msg) override { memory_buf_t formatted; - if (use_raw_msg_) - { + if (use_raw_msg_) { details::fmt_helper::append_string_view(msg.payload, formatted); } - else - { + else { base_sink::formatter_->format(msg, formatted); } formatted.push_back('\0'); - const char *msg_output = formatted.data(); - if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->opened) - SohImGui::console->Append("SoH Logging", priority, "%s", msg_output); + const char* msg_output = formatted.data(); + if (CVar_GetS32("gSinkEnabled", 0) && SohImGui::console->opened) { + SohImGui::console->Append("Logs", msg.level, "%s", msg_output); + } } void flush_() override {} private: - static Ship::Priority convert_to_soh(spdlog::level::level_enum level) - { - switch (level) { - case spdlog::level::trace: - return Ship::Priority::INFO_LVL; - case spdlog::level::debug: - return Ship::Priority::LOG_LVL; - case spdlog::level::info: - return Ship::Priority::LOG_LVL; - case spdlog::level::warn: - return Ship::Priority::WARNING_LVL; - case spdlog::level::err: - return Ship::Priority::ERROR_LVL; - case spdlog::level::critical: - return Ship::Priority::ERROR_LVL; - default: - break; - } - return Ship::Priority::LOG_LVL; - } std::string tag_; bool use_raw_msg_; diff --git a/libultraship/libultraship/Resource.cpp b/libultraship/libultraship/Resource.cpp index 3de83ed3f2..cbeedb44bb 100644 --- a/libultraship/libultraship/Resource.cpp +++ b/libultraship/libultraship/Resource.cpp @@ -1,6 +1,7 @@ #include "Resource.h" #include "DisplayList.h" #include "ResourceMgr.h" +#include "spdlog/spdlog.h" #include "Utils/BinaryReader.h" #include "Lib/tinyxml2/tinyxml2.h" #include "Lib/Fast3D/U64/PR/ultra64/gbi.h" @@ -56,9 +57,7 @@ namespace Ship patches.clear(); -#if _DEBUG if (file != nullptr) - printf("Deconstructor called on file %s\n", file->path.c_str()); -#endif + SPDLOG_TRACE("Deconstructor called on file %s\n", file->path.c_str()); } } \ No newline at end of file diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 5342374f0c..3048602c4a 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -174,6 +174,7 @@ source_group("Header Files\\soh\\Enhancements\\debugger" FILES ${Header_Files__s set(Header_Files__soh__Enhancements__randomizer "soh/Enhancements/randomizer/randomizer.h" "soh/Enhancements/randomizer/randomizer_item_tracker.h" + "soh/Enhancements/randomizer/adult_trade_shuffle.h" ) source_group("Header Files\\soh\\Enhancements\\randomizer" FILES ${Header_Files__soh__Enhancements__randomizer}) @@ -266,6 +267,7 @@ source_group("Source Files\\soh\\Enhancements\\debugger" FILES ${Source_Files__s set(Source_Files__soh__Enhancements__randomizer "soh/Enhancements/randomizer/randomizer.cpp" "soh/Enhancements/randomizer/randomizer_item_tracker.cpp" + "soh/Enhancements/randomizer/adult_trade_shuffle.c" ) source_group("Source Files\\soh\\Enhancements\\randomizer" FILES ${Source_Files__soh__Enhancements__randomizer}) diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 9e78487dba..3a409a7056 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -253,6 +253,41 @@ typedef enum { /* 0xA2 */ ITEM_BOTTLE_WITH_BUGS, /* 0xA3 */ ITEM_BOTTLE_WITH_POE, /* 0xA4 */ ITEM_BOTTLE_WITH_BIG_POE, + /* 0xA5 */ ITEM_GERUDO_FORTRESS_SMALL_KEY, + /* 0xA6 */ ITEM_FOREST_TEMPLE_SMALL_KEY, + /* 0xA7 */ ITEM_FIRE_TEMPLE_SMALL_KEY, + /* 0xA8 */ ITEM_WATER_TEMPLE_SMALL_KEY, + /* 0xA9 */ ITEM_SPIRIT_TEMPLE_SMALL_KEY, + /* 0xAA */ ITEM_SHADOW_TEMPLE_SMALL_KEY, + /* 0xAB */ ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY, + /* 0xAC */ ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY, + /* 0xAD */ ITEM_GANONS_CASTLE_SMALL_KEY, + /* 0xAE */ ITEM_FOREST_TEMPLE_BOSS_KEY, + /* 0xAF */ ITEM_FIRE_TEMPLE_BOSS_KEY, + /* 0xB0 */ ITEM_WATER_TEMPLE_BOSS_KEY, + /* 0xB1 */ ITEM_SPIRIT_TEMPLE_BOSS_KEY, + /* 0xB2 */ ITEM_SHADOW_TEMPLE_BOSS_KEY, + /* 0xB3 */ ITEM_GANONS_CASTLE_BOSS_KEY, + /* 0xB4 */ ITEM_DEKU_TREE_MAP, + /* 0xB5 */ ITEM_DODONGOS_CAVERN_MAP, + /* 0xB6 */ ITEM_JABU_JABUS_BELLY_MAP, + /* 0xB7 */ ITEM_FOREST_TEMPLE_MAP, + /* 0xB8 */ ITEM_FIRE_TEMPLE_MAP, + /* 0xB9 */ ITEM_WATER_TEMPLE_MAP, + /* 0xBA */ ITEM_SPIRIT_TEMPLE_MAP, + /* 0xBB */ ITEM_SHADOW_TEMPLE_MAP, + /* 0xBC */ ITEM_BOTTOM_OF_THE_WELL_MAP, + /* 0xBD */ ITEM_ICE_CAVERN_MAP, + /* 0xBE */ ITEM_DEKU_TREE_COMPASS, + /* 0xBF */ ITEM_DODONGOS_CAVERN_COMPASS, + /* 0xC0 */ ITEM_JABU_JABUS_BELLY_COMPASS, + /* 0xC1 */ ITEM_FOREST_TEMPLE_COMPASS, + /* 0xC2 */ ITEM_FIRE_TEMPLE_COMPASS, + /* 0xC3 */ ITEM_WATER_TEMPLE_COMPASS, + /* 0xC4 */ ITEM_SPIRIT_TEMPLE_COMPASS, + /* 0xC5 */ ITEM_SHADOW_TEMPLE_COMPASS, + /* 0xC6 */ ITEM_BOTTOM_OF_THE_WELL_COMPASS, + /* 0xC7 */ ITEM_ICE_CAVERN_COMPASS, /* 0xFC */ ITEM_LAST_USED = 0xFC, /* 0xFE */ ITEM_NONE_FE = 0xFE, /* 0xFF */ ITEM_NONE = 0xFF @@ -397,39 +432,78 @@ typedef enum { /* 0x82 */ GI_MEDALLION_SHADOW, /* 0x83 */ GI_MEDALLION_SPIRIT, - /* 0x81 */ GI_STONE_KOKIRI, - /* 0x82 */ GI_STONE_GORON, - /* 0x83 */ GI_STONE_ZORA, + /* 0x84 */ GI_STONE_KOKIRI, + /* 0x85 */ GI_STONE_GORON, + /* 0x86 */ GI_STONE_ZORA, - /* 0x81 */ GI_ZELDAS_LULLABY, - /* 0x82 */ GI_SUNS_SONG, - /* 0x83 */ GI_EPONAS_SONG, - /* 0x81 */ GI_SONG_OF_STORMS, - /* 0x82 */ GI_SONG_OF_TIME, - /* 0x83 */ GI_SARIAS_SONG, + /* 0x87 */ GI_ZELDAS_LULLABY, + /* 0x88 */ GI_SUNS_SONG, + /* 0x89 */ GI_EPONAS_SONG, + /* 0x8A */ GI_SONG_OF_STORMS, + /* 0x8B */ GI_SONG_OF_TIME, + /* 0x8C */ GI_SARIAS_SONG, - /* 0x81 */ GI_MINUET_OF_FOREST, - /* 0x82 */ GI_BOLERO_OF_FIRE, - /* 0x83 */ GI_SERENADE_OF_WATER, - /* 0x81 */ GI_NOCTURNE_OF_SHADOW, - /* 0x82 */ GI_REQUIEM_OF_SPIRIT, - /* 0x83 */ GI_PRELUDE_OF_LIGHT, + /* 0x8D */ GI_MINUET_OF_FOREST, + /* 0x8E */ GI_BOLERO_OF_FIRE, + /* 0x8F */ GI_SERENADE_OF_WATER, + /* 0x90 */ GI_NOCTURNE_OF_SHADOW, + /* 0x91 */ GI_REQUIEM_OF_SPIRIT, + /* 0x92 */ GI_PRELUDE_OF_LIGHT, - GI_SINGLE_MAGIC, - GI_DOUBLE_MAGIC, - GI_DOUBLE_DEFENSE, + /* 0x93 */ GI_SINGLE_MAGIC, + /* 0x94 */ GI_DOUBLE_MAGIC, + /* 0x95 */ GI_DOUBLE_DEFENSE, - GI_BOTTLE_WITH_RED_POTION, - GI_BOTTLE_WITH_GREEN_POTION, - GI_BOTTLE_WITH_BLUE_POTION, - GI_BOTTLE_WITH_FAIRY, - GI_BOTTLE_WITH_FISH, - GI_BOTTLE_WITH_BLUE_FIRE, - GI_BOTTLE_WITH_BUGS, - GI_BOTTLE_WITH_POE, - GI_BOTTLE_WITH_BIG_POE, + /* 0x96 */ GI_BOTTLE_WITH_RED_POTION, + /* 0x97 */ GI_BOTTLE_WITH_GREEN_POTION, + /* 0x98 */ GI_BOTTLE_WITH_BLUE_POTION, + /* 0x99 */ GI_BOTTLE_WITH_FAIRY, + /* 0x9A */ GI_BOTTLE_WITH_FISH, + /* 0x9B */ GI_BOTTLE_WITH_BLUE_FIRE, + /* 0x9C */ GI_BOTTLE_WITH_BUGS, + /* 0x9D */ GI_BOTTLE_WITH_POE, + /* 0x9E */ GI_BOTTLE_WITH_BIG_POE, - /* 0x84 */ GI_MAX + /* 0x9F */ GI_GERUDO_FORTRESS_SMALL_KEY, + /* 0xA0 */ GI_FOREST_TEMPLE_SMALL_KEY, + /* 0xA1 */ GI_FIRE_TEMPLE_SMALL_KEY, + /* 0xA2 */ GI_WATER_TEMPLE_SMALL_KEY, + /* 0xA3 */ GI_SPIRIT_TEMPLE_SMALL_KEY, + /* 0xA4 */ GI_SHADOW_TEMPLE_SMALL_KEY, + /* 0xA5 */ GI_BOTTOM_OF_THE_WELL_SMALL_KEY, + /* 0xA6 */ GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY, + /* 0xA7 */ GI_GANONS_CASTLE_SMALL_KEY, + + /* 0xA8 */ GI_FOREST_TEMPLE_BOSS_KEY, + /* 0xA9 */ GI_FIRE_TEMPLE_BOSS_KEY, + /* 0xAA */ GI_WATER_TEMPLE_BOSS_KEY, + /* 0xAB */ GI_SPIRIT_TEMPLE_BOSS_KEY, + /* 0xAC */ GI_SHADOW_TEMPLE_BOSS_KEY, + /* 0xAD */ GI_GANONS_CASTLE_BOSS_KEY, + + /* 0xAE */ GI_DEKU_TREE_MAP, + /* 0xAF */ GI_DODONGOS_CAVERN_MAP, + /* 0xB0 */ GI_JABU_JABUS_BELLY_MAP, + /* 0xB1 */ GI_FOREST_TEMPLE_MAP, + /* 0xB2 */ GI_FIRE_TEMPLE_MAP, + /* 0xB3 */ GI_WATER_TEMPLE_MAP, + /* 0xB4 */ GI_SPIRIT_TEMPLE_MAP, + /* 0xB5 */ GI_SHADOW_TEMPLE_MAP, + /* 0xB6 */ GI_BOTTOM_OF_THE_WELL_MAP, + /* 0xB7 */ GI_ICE_CAVERN_MAP, + + /* 0xB8 */ GI_DEKU_TREE_COMPASS, + /* 0xB9 */ GI_DODONGOS_CAVERN_COMPASS, + /* 0xBA */ GI_JABU_JABUS_BELLY_COMPASS, + /* 0xBB */ GI_FOREST_TEMPLE_COMPASS, + /* 0xBC */ GI_FIRE_TEMPLE_COMPASS, + /* 0xBD */ GI_WATER_TEMPLE_COMPASS, + /* 0xBE */ GI_SPIRIT_TEMPLE_COMPASS, + /* 0xBF */ GI_SHADOW_TEMPLE_COMPASS, + /* 0xC0 */ GI_BOTTOM_OF_THE_WELL_COMPASS, + /* 0xC1 */ GI_ICE_CAVERN_COMPASS, + + /* 0xAE */ GI_MAX } GetItemID; typedef enum { diff --git a/soh/include/z64player.h b/soh/include/z64player.h index 2f2ac1008d..33ae4c6d9f 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -13,7 +13,7 @@ typedef struct { /* 0x04 */ u16 objectId; } GetItemEntry; // size = 0x06 -extern GetItemEntry sGetItemTable[160]; +extern GetItemEntry sGetItemTable[195]; typedef enum { /* 0 */ PLAYER_SWORD_NONE, diff --git a/soh/include/z64save.h b/soh/include/z64save.h index b6069475e2..9da18f72ef 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -175,7 +175,7 @@ typedef struct { /* 0x1422 */ s16 sunsSongState; // controls the effects of suns song /* 0x1424 */ s16 healthAccumulator; RandoSetting randoSettings[300]; - ItemLocationRando itemLocations[500]; + ItemLocationRando itemLocations[RC_MAX]; HintLocationRando hintLocations[50]; char childAltarText[250]; char adultAltarText[750]; @@ -186,6 +186,7 @@ typedef struct { u8 trialsDone[6]; u8 cowsMilked[10]; u8 temporaryWeapon; + u16 adultTradeItems; } SaveContext; // size = 0x1428 typedef enum { diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index d7dd089914..8a42bef956 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -118,6 +118,7 @@ bool CustomMessageManager::ClearMessageTable(std::string tableID) { } auto& messageTable = foundMessageTable->second; messageTable.clear(); + return true; } bool CustomMessageManager::AddCustomMessageTable(std::string tableID) { diff --git a/soh/soh/Enhancements/debugconsole.cpp b/soh/soh/Enhancements/debugconsole.cpp index b50c8c9d67..203e5521ac 100644 --- a/soh/soh/Enhancements/debugconsole.cpp +++ b/soh/soh/Enhancements/debugconsole.cpp @@ -34,12 +34,12 @@ extern GlobalContext* gGlobalCtx; static bool ActorSpawnHandler(const std::vector& args) { if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) { - ERROR("Not enough arguments passed to actorspawn"); + SohImGui::console->SendErrorMessage("Not enough arguments passed to actorspawn"); return CMD_FAILED; } if (gGlobalCtx == nullptr) { - ERROR("GlobalCtx == nullptr"); + SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } @@ -75,7 +75,7 @@ static bool ActorSpawnHandler(const std::vector& args) { 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) { - ERROR("Failed to spawn actor. Actor_Spawn returned NULL"); + SohImGui::console->SendErrorMessage("Failed to spawn actor. Actor_Spawn returned NULL"); return CMD_FAILED; } return CMD_SUCCESS; @@ -84,14 +84,13 @@ static bool ActorSpawnHandler(const std::vector& args) { static bool KillPlayerHandler([[maybe_unused]] const std::vector&) { gSaveContext.health = 0; - - INFO("[SOH] You've met with a terrible fate, haven't you?"); + SohImGui::console->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?"); return CMD_SUCCESS; } static bool SetPlayerHealthHandler(const std::vector& args) { if (args.size() != 2) { - ERROR("[SOH] Unexpected arguments passed"); + SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -100,18 +99,18 @@ static bool SetPlayerHealthHandler(const std::vector& args) { try { health = std::stoi(args[1]); } catch (std::invalid_argument const& ex) { - ERROR("[SOH] Health value must be an integer."); + SohImGui::console->SendErrorMessage("[SOH] Health value must be an integer."); return CMD_FAILED; } if (health < 0) { - ERROR("[SOH] Health value must be a positive integer"); + SohImGui::console->SendErrorMessage("[SOH] Health value must be a positive integer"); return CMD_SUCCESS; } gSaveContext.health = health * 0x10; - INFO("[SOH] Player health updated to %d", health); + SohImGui::console->SendInfoMessage("[SOH] Player health updated to %d", health); return CMD_SUCCESS; } @@ -133,31 +132,32 @@ static bool RuppeHandler(const std::vector& args) { rupeeAmount = std::stoi(args[1]); } catch (std::invalid_argument const& ex) { - ERROR("[SOH] Rupee count must be an integer."); + SohImGui::console->SendErrorMessage("[SOH] Rupee count must be an integer."); return CMD_FAILED; } if (rupeeAmount < 0) { - ERROR("[SOH] Rupee count must be positive"); + SohImGui::console->SendErrorMessage("[SOH] Rupee count must be positive"); return CMD_FAILED; } gSaveContext.rupees = rupeeAmount; - INFO("Set rupee count to %u", rupeeAmount); + SohImGui::console->SendInfoMessage("Set rupee count to %u", rupeeAmount); return CMD_SUCCESS; } static bool SetPosHandler(const std::vector args) { if (gGlobalCtx == nullptr) { - ERROR("GlobalCtx == nullptr"); + SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } Player* player = GET_PLAYER(gGlobalCtx); if (args.size() == 1) { - INFO("Player position is [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y, + SohImGui::console->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; } @@ -168,14 +168,15 @@ static bool SetPosHandler(const std::vector args) { player->actor.world.pos.y = std::stof(args[2]); player->actor.world.pos.z = std::stof(args[3]); - INFO("Set player position to [ %.2f, %.2f, %.2f ]", player->actor.world.pos.x, player->actor.world.pos.y, + SohImGui::console->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; } static bool ResetHandler(std::vector args) { if (gGlobalCtx == nullptr) { - ERROR("GlobalCtx == nullptr"); + SohImGui::console->SendErrorMessage("GlobalCtx == nullptr"); return CMD_FAILED; } @@ -196,7 +197,7 @@ const static std::map ammoItems{ static bool AmmoHandler(const std::vector& args) { if (args.size() != 3) { - ERROR("[SOH] Unexpected arguments passed"); + SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -205,19 +206,19 @@ static bool AmmoHandler(const std::vector& args) { try { count = std::stoi(args[2]); } catch (std::invalid_argument const& ex) { - ERROR("Ammo count must be an integer"); + SohImGui::console->SendErrorMessage("Ammo count must be an integer"); return CMD_FAILED; } if (count < 0) { - ERROR("Ammo count must be positive"); + SohImGui::console->SendErrorMessage("Ammo count must be positive"); return CMD_FAILED; } const auto& it = ammoItems.find(args[1]); if (it == ammoItems.end()) { - ERROR("Invalid item passed"); + SohImGui::console->SendErrorMessage("Invalid item passed"); return CMD_FAILED; } @@ -239,7 +240,7 @@ const static std::map bottleItems{ static bool BottleHandler(const std::vector& args) { if (args.size() != 3) { - ERROR("[SOH] Unexpected arguments passed"); + SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -247,19 +248,19 @@ static bool BottleHandler(const std::vector& args) { try { slot = std::stoi(args[2]); } catch (std::invalid_argument const& ex) { - ERROR("[SOH] Bottle slot must be an integer."); + SohImGui::console->SendErrorMessage("[SOH] Bottle slot must be an integer."); return CMD_FAILED; } if ((slot < 1) || (slot > 4)) { - ERROR("Invalid slot passed"); + SohImGui::console->SendErrorMessage("Invalid slot passed"); return CMD_FAILED; } const auto& it = bottleItems.find(args[1]); if (it == bottleItems.end()) { - ERROR("Invalid item passed"); + SohImGui::console->SendErrorMessage("Invalid item passed"); return CMD_FAILED; } @@ -271,7 +272,7 @@ static bool BottleHandler(const std::vector& args) { static bool BHandler(const std::vector& args) { if (args.size() != 2) { - ERROR("[SOH] Unexpected arguments passed"); + SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -281,7 +282,7 @@ static bool BHandler(const std::vector& args) { static bool ItemHandler(const std::vector& args) { if (args.size() != 3) { - ERROR("[SOH] Unexpected arguments passed"); + SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -292,7 +293,7 @@ static bool ItemHandler(const std::vector& args) { static bool EntranceHandler(const std::vector& args) { if (args.size() != 2) { - ERROR("[SOH] Unexpected arguments passed"); + SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } @@ -301,11 +302,11 @@ static bool EntranceHandler(const std::vector& args) { try { entrance = std::stoi(args[1], nullptr, 16); } catch (std::invalid_argument const& ex) { - ERROR("[SOH] Entrance value must be a Hex number."); + SohImGui::console->SendErrorMessage("[SOH] Entrance value must be a Hex number."); return CMD_FAILED; } - gGlobalCtx->nextEntranceIndex = entrance; + gGlobalCtx->nextEntranceIndex = entrance; gGlobalCtx->sceneLoadFlag = 0x14; gGlobalCtx->fadeTransition = 11; gSaveContext.nextTransition = 11; @@ -317,10 +318,10 @@ static bool SaveStateHandler(const std::vector& args) { switch (rtn) { case SaveStateReturn::SUCCESS: - INFO("[SOH] Saved state to slot %u", slot); + SohImGui::console->SendInfoMessage("[SOH] Saved state to slot %u", slot); return CMD_SUCCESS; case SaveStateReturn::FAIL_WRONG_GAMESTATE: - ERROR("[SOH] Can not save a state outside of \"GamePlay\""); + SohImGui::console->SendErrorMessage("[SOH] Can not save a state outside of \"GamePlay\""); return CMD_FAILED; } @@ -332,16 +333,16 @@ static bool LoadStateHandler(const std::vector& args) { switch (rtn) { case SaveStateReturn::SUCCESS: - INFO("[SOH] Loaded state from slot %u", slot); + SohImGui::console->SendInfoMessage("[SOH] Loaded state from slot (%u)", slot); return CMD_SUCCESS; case SaveStateReturn::FAIL_INVALID_SLOT: - ERROR("[SOH] Invalid State Slot Number (%u)", slot); + SohImGui::console->SendErrorMessage("[SOH] Invalid State Slot Number (%u)", slot); return CMD_FAILED; case SaveStateReturn::FAIL_STATE_EMPTY: - ERROR("[SOH] State Slot (%u) is empty", slot); + SohImGui::console->SendErrorMessage("[SOH] State Slot (%u) is empty", slot); return CMD_FAILED; case SaveStateReturn::FAIL_WRONG_GAMESTATE: - ERROR("[SOH] Can not load a state outside of \"GamePlay\""); + SohImGui::console->SendErrorMessage("[SOH] Can not load a state outside of \"GamePlay\""); return CMD_FAILED; } @@ -349,7 +350,7 @@ static bool LoadStateHandler(const std::vector& args) { static bool StateSlotSelectHandler(const std::vector& args) { if (args.size() != 2) { - ERROR("[SOH] Unexpected arguments passed"); + SohImGui::console->SendErrorMessage("[SOH] Unexpected arguments passed"); return CMD_FAILED; } int slot; @@ -357,17 +358,18 @@ static bool StateSlotSelectHandler(const std::vector& args) { try { slot = std::stoi(args[1], nullptr, 10); } catch (std::invalid_argument const& ex) { - ERROR("[SOH] SaveState slot value must be a number."); + SohImGui::console->SendErrorMessage("[SOH] SaveState slot value must be a number."); return CMD_FAILED; } if (slot < 0) { - ERROR("[SOH] Invalid slot passed. Slot must be between 0 and 2"); + SohImGui::console->SendErrorMessage("[SOH] Invalid slot passed. Slot must be between 0 and 2"); return CMD_FAILED; } OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot); - INFO("[SOH] Slot %u selected", OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot()); + SohImGui::console->SendInfoMessage("[SOH] Slot %u selected", + OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot()); return CMD_SUCCESS; } @@ -427,7 +429,7 @@ static bool SetCVarHandler(const std::vector& args) { CVar_Save(); - //INFO("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z); + //SohImGui::console->SendInfoMessage("[SOH] Updated player position to [ %.2f, %.2f, %.2f ]", pos.x, pos.y, pos.z); return CMD_SUCCESS; } @@ -441,17 +443,17 @@ static bool GetCVarHandler(const std::vector& args) { if (cvar != nullptr) { if (cvar->type == CVarType::S32) - INFO("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32); + SohImGui::console->SendInfoMessage("[SOH] Variable %s is %i", args[1].c_str(), cvar->value.valueS32); else if (cvar->type == CVarType::Float) - INFO("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); + SohImGui::console->SendInfoMessage("[SOH] Variable %s is %f", args[1].c_str(), cvar->value.valueFloat); else if (cvar->type == CVarType::String) - INFO("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); + SohImGui::console->SendInfoMessage("[SOH] Variable %s is %s", args[1].c_str(), cvar->value.valueStr); else if (cvar->type == CVarType::RGBA) - INFO("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA); + SohImGui::console->SendInfoMessage("[SOH] Variable %s is %08X", args[1].c_str(), cvar->value.valueRGBA); } else { - INFO("[SOH] Could not find variable %s", args[1].c_str()); + SohImGui::console->SendInfoMessage("[SOH] Could not find variable %s", args[1].c_str()); } diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 48c9c46959..90e4ca0ff6 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 "../libultraship/ImGuiImpl.h" #include "ImGuiHelpers.h" @@ -14,6 +15,7 @@ extern "C" { #include "variables.h" #include "functions.h" #include "macros.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" extern GlobalContext* gGlobalCtx; #include "textures/icon_item_static/icon_item_static.h" @@ -525,6 +527,24 @@ void DrawInfoTab() { ImGui::PopItemWidth(); } +void DrawBGSItemFlag(uint8_t itemID) { + const ItemMapEntry& slotEntry = itemMapping[itemID]; + ImGui::Image(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1)); + ImGui::SameLine(); + int tradeIndex = itemID - ITEM_POCKET_EGG; + bool hasItem = (gSaveContext.adultTradeItems & (1 << tradeIndex)) != 0; + ImGui::Checkbox(("##adultTradeFlag" + std::to_string(itemID)).c_str(), &hasItem); + if (hasItem) { + gSaveContext.adultTradeItems |= (1 << tradeIndex); + if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_NONE) { + INV_CONTENT(ITEM_TRADE_ADULT) = ITEM_POCKET_EGG + tradeIndex; + } + } else { + gSaveContext.adultTradeItems &= ~(1 << tradeIndex); + Inventory_ReplaceItem(gGlobalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetNextAdultTradeItem()); + } +} + void DrawInventoryTab() { static bool restrictToValid = true; @@ -596,6 +616,17 @@ void DrawInventoryTab() { if (ImGui::ImageButton(SohImGui::GetTextureByName(slotEntry.name), ImVec2(32.0f, 32.0f), ImVec2(0, 0), ImVec2(1, 1), 0)) { 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) && + selectedIndex == SLOT_TRADE_ADULT) { + if (slotEntry.id == ITEM_NONE) { + gSaveContext.adultTradeItems = 0; + } else if (slotEntry.id >= ITEM_POCKET_EGG && slotEntry.id <= ITEM_CLAIM_CHECK) { + uint32_t tradeID = slotEntry.id - ITEM_POCKET_EGG; + gSaveContext.adultTradeItems |= tradeID; + } + } ImGui::CloseCurrentPopup(); } SetLastItemHoverText(SohUtils::GetItemName(slotEntry.id)); @@ -632,6 +663,16 @@ void DrawInventoryTab() { ImGui::PopID(); } } + + // Trade quest flags are only used when shuffling the trade sequence, so + // don't show this if it isn't needed. + if (gSaveContext.n64ddFlag && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_ADULT_TRADE) + && ImGui::TreeNode("Adult trade quest items")) { + for (int i = ITEM_POCKET_EGG; i <= ITEM_CLAIM_CHECK; i++) { + DrawBGSItemFlag(i); + } + ImGui::TreePop(); + } } // Draw a flag bitfield as an grid of checkboxes diff --git a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp index 51be29bdf2..144759e294 100644 --- a/soh/soh/Enhancements/randomizer/3drando/entrance.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/entrance.cpp @@ -156,7 +156,7 @@ static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::ve //Entrances shouldn't connect to their own scene, fail in this situation if (entrance->GetParentRegion()->scene != "" && entrance->GetParentRegion()->scene == target->GetConnectedRegion()->scene) { auto message = "Entrance " + entrance->GetName() + " attempted to connect with own scene target " + target->to_string() + ". Connection failed.\n"; - SPDLOG_INFO(message); + SPDLOG_DEBUG(message); return false; } @@ -168,7 +168,7 @@ static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::ve //Change connections between an entrance and a target assumed entrance, in order to test the connections afterwards if necessary static void ChangeConnections(Entrance* entrance, Entrance* targetEntrance) { auto message = "Attempting to connect " + entrance->GetName() + " to " + targetEntrance->to_string() + "\n"; - SPDLOG_INFO(message); + SPDLOG_DEBUG(message); entrance->Connect(targetEntrance->Disconnect()); entrance->SetReplacement(targetEntrance->GetReplacement()); if (entrance->GetReverse() != nullptr /*&& entrances aren't decoupled*/) { @@ -208,7 +208,7 @@ static void ConfirmReplacement(Entrance* entrance, Entrance* targetEntrance) { static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vector& alreadyChecked) { if (entrance == nullptr) { - SPDLOG_INFO("Entrance is nullptr in EntranceUnreachableAs()"); + SPDLOG_DEBUG("Entrance is nullptr in EntranceUnreachableAs()"); return true; } @@ -247,7 +247,7 @@ static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vectorHasAccess() && !AreaTable(KAKARIKO_VILLAGE)->HasAccess()) { - SPDLOG_INFO("Invalid starting area\n"); + SPDLOG_DEBUG("Invalid starting area\n"); return false; } // Check that a region where time passes is always reachable as both ages without having collected any items if (!Areas::HasTimePassAccess(AGE_CHILD) || !Areas::HasTimePassAccess(AGE_ADULT)) { - SPDLOG_INFO("Time passing is not guaranteed as both ages\n"); + SPDLOG_DEBUG("Time passing is not guaranteed as both ages\n"); return false; } // The player should be able to get back to ToT after going through time, without having collected any items // This is important to ensure that the player never loses access to the pedestal after going through time if (Settings::ResolvedStartingAge == AGE_CHILD && !AreaTable(TEMPLE_OF_TIME)->Adult()) { - SPDLOG_INFO("Path to Temple of Time as adult is not guaranteed\n"); + SPDLOG_DEBUG("Path to Temple of Time as adult is not guaranteed\n"); return false; } else if (Settings::ResolvedStartingAge == AGE_ADULT && !AreaTable(TEMPLE_OF_TIME)->Child()) { - SPDLOG_INFO("Path to Temple of Time as child is not guaranteed\n"); + SPDLOG_DEBUG("Path to Temple of Time as child is not guaranteed\n"); return false; } } @@ -353,11 +353,11 @@ static bool ValidateWorld(Entrance* entrancePlaced) { // This is important to ensure that players can never lock their only bottles by filling them with Big Poes they can't sell if (checkPoeCollectorAccess) { if (!AreaTable(MARKET_GUARD_HOUSE)->Adult()) { - SPDLOG_INFO("Big Poe Shop access is not guarenteed as adult\n"); + SPDLOG_DEBUG("Big Poe Shop access is not guarenteed as adult\n"); return false; } } - SPDLOG_INFO("All Locations NOT REACHABLE\n"); + SPDLOG_DEBUG("All Locations NOT REACHABLE\n"); return false; } return true; @@ -476,7 +476,7 @@ static void ShuffleEntrancePool(std::vector& entrancePool, std::vecto } if (retries <= 0) { - SPDLOG_INFO("Entrance placement attempt count exceeded. Restarting randomization completely"); + SPDLOG_DEBUG("Entrance placement attempt count exceeded. Restarting randomization completely"); entranceShuffleFailure = true; } } @@ -840,7 +840,7 @@ void CreateEntranceOverrides() { if (noRandomEntrances) { return; } - SPDLOG_INFO("\nCREATING ENTRANCE OVERRIDES\n"); + SPDLOG_DEBUG("\nCREATING ENTRANCE OVERRIDES\n"); auto allShuffleableEntrances = GetShuffleableEntrances(EntranceType::All, false); for (Entrance* entrance : allShuffleableEntrances) { @@ -851,7 +851,7 @@ void CreateEntranceOverrides() { } auto message = "Setting " + entrance->to_string() + "\n"; - SPDLOG_INFO(message); + SPDLOG_DEBUG(message); int16_t originalIndex = entrance->GetIndex(); int16_t destinationIndex = entrance->GetReverse()->GetIndex(); @@ -868,9 +868,9 @@ void CreateEntranceOverrides() { }); message = "\tOriginal: " + std::to_string(originalIndex) + "\n"; - SPDLOG_INFO(message); + SPDLOG_DEBUG(message); message = "\tReplacement " + std::to_string(replacementIndex) + "\n"; - SPDLOG_INFO(message); + SPDLOG_DEBUG(message); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index b9cf755182..14bf594c2e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -420,7 +420,7 @@ std::vector GetAccessibleLocations(const std::vector& allowe if (!Location(loc)->IsAddedToPool()) { allLocationsReachable = false; auto message = "Location " + Location(loc)->GetName() + " not reachable\n"; - SPDLOG_INFO(message); + SPDLOG_DEBUG(message); #ifndef ENABLE_DEBUG break; #endif @@ -567,17 +567,17 @@ static void AssumedFill(const std::vector& items, const std::vector allowedLocations.size()) { printf("\x1b[2;2HERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS"); - SPDLOG_INFO("Items:\n"); + SPDLOG_DEBUG("Items:\n"); for (const uint32_t item : items) { - SPDLOG_INFO("\t"); - SPDLOG_INFO(ItemTable(item).GetName().GetEnglish()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\t"); + SPDLOG_DEBUG(ItemTable(item).GetName().GetEnglish()); + SPDLOG_DEBUG("\n"); } - SPDLOG_INFO("\nAllowed Locations:\n"); + SPDLOG_DEBUG("\nAllowed Locations:\n"); for (const uint32_t loc : allowedLocations) { - SPDLOG_INFO("\t"); - SPDLOG_INFO(Location(loc)->GetName()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\t"); + SPDLOG_DEBUG(Location(loc)->GetName()); + SPDLOG_DEBUG("\n"); } placementFailure = true; return; @@ -627,9 +627,9 @@ static void AssumedFill(const std::vector& items, const std::vector& items, const std::vector& possibleHintLocations) { //return if there aren't any hintable locations or gossip stones available if (possibleHintLocations.empty()) { - SPDLOG_INFO("\tNO LOCATIONS TO HINT\n\n"); + SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n"); return; } uint32_t hintedLocation = RandomElement(possibleHintLocations); const std::vector accessibleGossipStones = GetAccessibleGossipStones(hintedLocation); - SPDLOG_INFO("\tLocation: "); - SPDLOG_INFO(Location(hintedLocation)->GetName()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tLocation: "); + SPDLOG_DEBUG(Location(hintedLocation)->GetName()); + SPDLOG_DEBUG("\n"); - SPDLOG_INFO("\tItem: "); - SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tItem: "); + SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish()); + SPDLOG_DEBUG("\n"); if (accessibleGossipStones.empty()) { - SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n"); + SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n"); return; } @@ -235,9 +235,9 @@ static void CreateLocationHint(const std::vector& possibleHintLocation Text prefix = Hint(PREFIX).GetText(); Text finalHint = prefix + locationHintText + " #"+itemHintText+"#."; - SPDLOG_INFO("\tMessage: "); - SPDLOG_INFO(finalHint.english); - SPDLOG_INFO("\n\n"); + SPDLOG_DEBUG("\tMessage: "); + SPDLOG_DEBUG(finalHint.english); + SPDLOG_DEBUG("\n\n"); AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED}); } @@ -258,24 +258,24 @@ static void CreateWothHint(uint8_t* remainingDungeonWothHints) { // If no more locations can be hinted at for woth, then just try to get another hint if (possibleHintLocations.empty()) { - SPDLOG_INFO("\tNO LOCATIONS TO HINT\n\n"); + SPDLOG_DEBUG("\tNO LOCATIONS TO HINT\n\n"); return; } uint32_t hintedLocation = RandomElement(possibleHintLocations); - SPDLOG_INFO("\tLocation: "); - SPDLOG_INFO(Location(hintedLocation)->GetName()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tLocation: "); + SPDLOG_DEBUG(Location(hintedLocation)->GetName()); + SPDLOG_DEBUG("\n"); - SPDLOG_INFO("\tItem: "); - SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tItem: "); + SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish()); + SPDLOG_DEBUG("\n"); // get an accessible gossip stone const std::vector gossipStoneLocations = GetAccessibleGossipStones(hintedLocation); if (gossipStoneLocations.empty()) { - SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n"); + SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n"); return; } Location(hintedLocation)->SetAsHinted(); @@ -293,9 +293,9 @@ static void CreateWothHint(uint8_t* remainingDungeonWothHints) { locationText = GetHintRegion(parentRegion)->GetHint().GetText(); } Text finalWothHint = Hint(PREFIX).GetText() + "#" + locationText + "#" + Hint(WAY_OF_THE_HERO).GetText(); - SPDLOG_INFO("\tMessage: "); - SPDLOG_INFO(finalWothHint.english); - SPDLOG_INFO("\n\n"); + SPDLOG_DEBUG("\tMessage: "); + SPDLOG_DEBUG(finalWothHint.english); + SPDLOG_DEBUG("\n\n"); AddHint(finalWothHint, gossipStone, { QM_LBLUE }); } @@ -312,18 +312,18 @@ static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vectorGetName()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tLocation: "); + SPDLOG_DEBUG(Location(hintedLocation)->GetName()); + SPDLOG_DEBUG("\n"); - SPDLOG_INFO("\tItem: "); - SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tItem: "); + SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish()); + SPDLOG_DEBUG("\n"); // get an accessible gossip stone const std::vector gossipStoneLocations = GetAccessibleGossipStones(hintedLocation); if (gossipStoneLocations.empty()) { - SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n"); + SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n"); return; } Location(hintedLocation)->SetAsHinted(); @@ -341,9 +341,9 @@ static void CreateBarrenHint(uint8_t* remainingDungeonBarrenHints, std::vectorGetName()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tLocation: "); + SPDLOG_DEBUG(Location(hintedLocation)->GetName()); + SPDLOG_DEBUG("\n"); - SPDLOG_INFO("\tItem: "); - SPDLOG_INFO(Location(hintedLocation)->GetPlacedItemName().GetEnglish()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tItem: "); + SPDLOG_DEBUG(Location(hintedLocation)->GetPlacedItemName().GetEnglish()); + SPDLOG_DEBUG("\n"); //get an acessible gossip stone const std::vector gossipStoneLocations = GetAccessibleGossipStones(hintedLocation); if (gossipStoneLocations.empty()) { - SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n"); + SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n"); return; } Location(hintedLocation)->SetAsHinted(); @@ -387,16 +387,16 @@ static void CreateRandomLocationHint(const bool goodItem = false) { uint32_t parentRegion = Location(hintedLocation)->GetParentRegionKey(); Text locationText = AreaTable(parentRegion)->GetHint().GetText(); Text finalHint = Hint(PREFIX).GetText()+"#"+locationText+"# "+Hint(HOARDS).GetText()+" #"+itemText+"#."; - SPDLOG_INFO("\tMessage: "); - SPDLOG_INFO(finalHint.english); - SPDLOG_INFO("\n\n"); + SPDLOG_DEBUG("\tMessage: "); + SPDLOG_DEBUG(finalHint.english); + SPDLOG_DEBUG("\n\n"); AddHint(finalHint, gossipStone, {QM_GREEN, QM_RED}); } else { Text locationText = GetHintRegion(Location(hintedLocation)->GetParentRegionKey())->GetHint().GetText(); Text finalHint = Hint(PREFIX).GetText()+"#"+itemText+"# "+Hint(CAN_BE_FOUND_AT).GetText()+" #"+locationText+"#."; - SPDLOG_INFO("\tMessage: "); - SPDLOG_INFO(finalHint.english); - SPDLOG_INFO("\n\n"); + SPDLOG_DEBUG("\tMessage: "); + SPDLOG_DEBUG(finalHint.english); + SPDLOG_DEBUG("\n\n"); AddHint(finalHint, gossipStone, {QM_RED, QM_GREEN}); } } @@ -411,15 +411,15 @@ static void CreateJunkHint() { LogicReset(); const std::vector gossipStones = GetAccessibleLocations(gossipStoneLocations); if (gossipStones.empty()) { - SPDLOG_INFO("\tNO GOSSIP STONES TO PLACE HINT\n\n"); + SPDLOG_DEBUG("\tNO GOSSIP STONES TO PLACE HINT\n\n"); return; } uint32_t gossipStone = RandomElement(gossipStones); Text hint = junkHint.GetText(); - SPDLOG_INFO("\tMessage: "); - SPDLOG_INFO(hint.english); - SPDLOG_INFO("\n\n"); + SPDLOG_DEBUG("\tMessage: "); + SPDLOG_DEBUG(hint.english); + SPDLOG_DEBUG("\n\n"); AddHint(hint, gossipStone, {QM_PINK}); } @@ -711,7 +711,7 @@ void CreateAllHints() { CreateGanonText(); CreateAltarText(); - SPDLOG_INFO("\nNOW CREATING HINTS\n"); + SPDLOG_DEBUG("\nNOW CREATING HINTS\n"); const HintSetting& hintSetting = hintSettingTable[Settings::HintDistribution.Value()]; uint8_t remainingDungeonWothHints = hintSetting.dungeonsWothLimit; @@ -768,9 +768,9 @@ void CreateAllHints() { barrenDungeons.push_back(barrenRegion); } } - SPDLOG_INFO("\nBarren Dungeons:\n"); + SPDLOG_DEBUG("\nBarren Dungeons:\n"); for (std::string barrenDungeon : barrenDungeons) { - SPDLOG_INFO(barrenDungeon + "\n"); + SPDLOG_DEBUG(barrenDungeon + "\n"); } //Get list of all woth dungeons @@ -783,9 +783,9 @@ void CreateAllHints() { wothDungeons.push_back(wothRegion); } } - SPDLOG_INFO("\nWoth Dungeons:\n"); + SPDLOG_DEBUG("\nWoth Dungeons:\n"); for (std::string wothDungeon : wothDungeons) { - SPDLOG_INFO(wothDungeon + "\n"); + SPDLOG_DEBUG(wothDungeon + "\n"); } //Set DungeonInfo array for each dungeon @@ -827,9 +827,9 @@ void CreateAllHints() { //get a random hint type from the remaining hints HintType type = RandomElement(remainingHintTypes, true); - SPDLOG_INFO("Attempting to make hint of type: "); - SPDLOG_INFO(hintTypeNames[static_cast(type)]); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("Attempting to make hint of type: "); + SPDLOG_DEBUG(hintTypeNames[static_cast(type)]); + SPDLOG_DEBUG("\n"); //create the appropriate hint for the type if (type == HintType::Woth) { diff --git a/soh/soh/Enhancements/randomizer/3drando/item.hpp b/soh/soh/Enhancements/randomizer/3drando/item.hpp index a424dbf2b8..dbfb695b1e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/item.hpp @@ -103,11 +103,11 @@ public: return false; } - if ((type == ITEMTYPE_BOSSKEY && getItemId != 0x9A) && (BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) { + if ((type == ITEMTYPE_BOSSKEY && getItemId != 0xAD) && (BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) { return false; } //Ganons Castle Boss Key - if (getItemId == 0x9A && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) { + if (getItemId == 0xAD && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) { return false; } diff --git a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp index 6b12d3aac4..213b62f0ac 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_location.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_location.cpp @@ -1470,11 +1470,11 @@ void GenerateLocationPool() { void PlaceItemInLocation(uint32_t locKey, uint32_t item, bool applyEffectImmediately /*= false*/, bool setHidden /*= false*/) { auto loc = Location(locKey); - SPDLOG_INFO("\n"); - SPDLOG_INFO(ItemTable(item).GetName().GetEnglish()); - SPDLOG_INFO(" placed at "); - SPDLOG_INFO(loc->GetName()); - SPDLOG_INFO("\n\n"); + SPDLOG_DEBUG("\n"); + SPDLOG_DEBUG(ItemTable(item).GetName().GetEnglish()); + SPDLOG_DEBUG(" placed at "); + SPDLOG_DEBUG(loc->GetName()); + SPDLOG_DEBUG("\n\n"); if (applyEffectImmediately || Settings::Logic.Is(LOGIC_NONE) || Settings::Logic.Is(LOGIC_VANILLA)) { ItemTable(item).ApplyEffect(); @@ -1561,7 +1561,7 @@ void AddExcludedOptions() { } void CreateItemOverrides() { - SPDLOG_INFO("NOW CREATING OVERRIDES\n\n"); + SPDLOG_DEBUG("NOW CREATING OVERRIDES\n\n"); for (uint32_t locKey : allLocations) { auto loc = Location(locKey); ItemOverride_Value val = ItemTable(loc->GetPlaceduint32_t()).Value(); @@ -1573,18 +1573,18 @@ void CreateItemOverrides() { .key = loc->Key(), .value = val, }); - SPDLOG_INFO("\tScene: "); - SPDLOG_INFO(std::to_string(loc->Key().scene)); - SPDLOG_INFO("\tType: "); - SPDLOG_INFO(std::to_string(loc->Key().type)); - SPDLOG_INFO("\tFlag: "); - SPDLOG_INFO(std::to_string(loc->Key().flag)); - SPDLOG_INFO("\t"); - SPDLOG_INFO(loc->GetName()); - SPDLOG_INFO(": "); - SPDLOG_INFO(loc->GetPlacedItemName().GetEnglish()); - SPDLOG_INFO("\n"); + SPDLOG_DEBUG("\tScene: "); + SPDLOG_DEBUG(std::to_string(loc->Key().scene)); + SPDLOG_DEBUG("\tType: "); + SPDLOG_DEBUG(std::to_string(loc->Key().type)); + SPDLOG_DEBUG("\tFlag: "); + SPDLOG_DEBUG(std::to_string(loc->Key().flag)); + SPDLOG_DEBUG("\t"); + SPDLOG_DEBUG(loc->GetName()); + SPDLOG_DEBUG(": "); + SPDLOG_DEBUG(loc->GetPlacedItemName().GetEnglish()); + SPDLOG_DEBUG("\n"); } - SPDLOG_INFO("Overrides Created: "); - SPDLOG_INFO(std::to_string(overrides.size())); + 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 e128da21cd..ec03a0ebd6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -1184,6 +1184,6 @@ void GenerateItemPool() { } void AddJunk() { - SPDLOG_INFO("HAD TO PLACE EXTRA JUNK "); + SPDLOG_DEBUG("HAD TO PLACE EXTRA JUNK "); AddItemToMainPool(GetPendingJunkItem()); } diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp index 7a0c16def9..f7699b7541 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp @@ -26,13 +26,13 @@ Menu* currentMenu; } // namespace void PrintTopScreen() { - SPDLOG_INFO("\x1b[2;11H%sOcarina of Time 3D Randomizer%s", CYAN, RESET); - SPDLOG_INFO("\x1b[3;18H%s%s-%s%s", CYAN, RANDOMIZER_VERSION, COMMIT_NUMBER, RESET); - SPDLOG_INFO("\x1b[4;10HA/B/D-pad: Navigate Menu\n"); - SPDLOG_INFO(" Select: Exit to Homebrew Menu\n"); - SPDLOG_INFO(" Y: New Random Seed\n"); - SPDLOG_INFO(" X: Input Custom Seed\n"); - SPDLOG_INFO("\x1b[11;7HCurrent Seed: %s", Settings::seed.c_str()); + SPDLOG_DEBUG("\x1b[2;11H%sOcarina of Time 3D Randomizer%s", CYAN, RESET); + SPDLOG_DEBUG("\x1b[3;18H%s%s-%s%s", CYAN, RANDOMIZER_VERSION, COMMIT_NUMBER, RESET); + SPDLOG_DEBUG("\x1b[4;10HA/B/D-pad: Navigate Menu\n"); + SPDLOG_DEBUG(" Select: Exit to Homebrew Menu\n"); + SPDLOG_DEBUG(" Y: New Random Seed\n"); + SPDLOG_DEBUG(" X: Input Custom Seed\n"); + SPDLOG_DEBUG("\x1b[11;7HCurrent Seed: %s", Settings::seed.c_str()); } void MenuInit() { @@ -526,7 +526,7 @@ std::string GenerateRandomizer(std::unordered_map if (ret == -1) { // Failed to generate after 5 tries printf("\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be " "successful."); - SPDLOG_INFO("\nRANDOMIZATION FAILED COMPLETELY. PLZ FIX\n"); + SPDLOG_DEBUG("\nRANDOMIZATION FAILED COMPLETELY. PLZ FIX\n"); return ""; } else { printf("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret); diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 1f8d4437fc..4a136b9cb6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2537,6 +2537,8 @@ namespace Settings { ShuffleGerudoToken.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD]); ShuffleFrogSongRupees.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_FROG_SONG_RUPEES]); + ShuffleAdultTradeQuest.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_ADULT_TRADE]); + // the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina" StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]); @@ -2544,14 +2546,7 @@ namespace Settings { StartingDekuShield.SetSelectedIndex(cvarSettings[RSK_STARTING_DEKU_SHIELD]); StartingKokiriSword.SetSelectedIndex(cvarSettings[RSK_STARTING_KOKIRI_SWORD]); - if(cvarSettings[RSK_STARTING_MAPS_COMPASSES]) { - // "Start With" is index 0 - MapsAndCompasses.SetSelectedIndex(0); - } else { - // We don't support maps/compasses outside of their own dungeon yet - // "Own Dungeon" is index 2 - MapsAndCompasses.SetSelectedIndex(2); - } + MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]); StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]); StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]); @@ -2563,6 +2558,9 @@ namespace Settings { ItemPoolValue.SetSelectedIndex(cvarSettings[RSK_ITEM_POOL]); IceTrapValue.SetSelectedIndex(cvarSettings[RSK_ICE_TRAPS]); + Keysanity.SetSelectedIndex(cvarSettings[RSK_KEYSANITY]); + GerudoKeys.SetSelectedIndex(cvarSettings[RSK_GERUDO_KEYS]); + BossKeysanity.SetSelectedIndex(cvarSettings[RSK_BOSS_KEYSANITY]); GanonsBossKey.SetSelectedIndex(cvarSettings[RSK_GANONS_BOSS_KEY]); NumRequiredCuccos.SetSelectedIndex(cvarSettings[RSK_CUCCO_COUNT]); @@ -2572,6 +2570,8 @@ namespace Settings { SkipTowerEscape.SetSelectedIndex(cvarSettings[RSK_SKIP_TOWER_ESCAPE]); + CompleteMaskQuest.SetSelectedIndex(cvarSettings[RSK_COMPLETE_MASK_QUEST]); + NightGSExpectSuns.SetSelectedIndex(cvarSettings[RSK_SKULLS_SUNS_SONG]); // RANDOTODO implement chest shuffle with keysanity diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index 1ecd4230cc..91271b74b0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -347,7 +347,8 @@ static void WriteSettings(const bool printAll = false) { setting->GetName() == "Cuccos to return" || setting->GetName() == "Skip Epona Race" || setting->GetName() == "Skip Tower Escape" || - setting->GetName() == "Skip Child Stealth") { + setting->GetName() == "Skip Child Stealth" || + setting->GetName() == "Complete Mask Quest") { std::string settingName = menu->name + ":" + setting->GetName(); jsonData["settings"][settingName] = setting->GetSelectedOptionText(); } diff --git a/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c new file mode 100644 index 0000000000..1bddf0c2f2 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.c @@ -0,0 +1,33 @@ +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "functions.h" +#include "variables.h" +#include "macros.h" + +void Randomizer_ConsumeAdultTradeItem(GlobalContext* globalCtx, u8 itemId) { + gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(itemId); + Inventory_ReplaceItem(globalCtx, itemId, Randomizer_GetNextAdultTradeItem()); +} + +u8 Randomizer_GetNextAdultTradeItem() { + const u8 numTradeItems = ITEM_CLAIM_CHECK - ITEM_POCKET_EGG + 1; + u8 currentTradeItemIndex = INV_CONTENT(ITEM_TRADE_ADULT) - ITEM_POCKET_EGG; + for (int i = 0; i < numTradeItems; i++) { + u8 tradeIndex = (currentTradeItemIndex + i + 1) % numTradeItems; + if (gSaveContext.adultTradeItems & (1 << tradeIndex)) { + return ITEM_POCKET_EGG + tradeIndex; + } + } + return ITEM_NONE; +} + +u8 Randomizer_GetPrevAdultTradeItem() { + const u8 numTradeItems = ITEM_CLAIM_CHECK - ITEM_POCKET_EGG + 1; + u8 currentTradeItemIndex = INV_CONTENT(ITEM_TRADE_ADULT) - ITEM_POCKET_EGG; + for (int i = 0; i < numTradeItems; i++) { + u8 tradeIndex = (currentTradeItemIndex - i - 1 + numTradeItems) % numTradeItems; + if (gSaveContext.adultTradeItems & (1 << tradeIndex)) { + return ITEM_POCKET_EGG + tradeIndex; + } + } + return ITEM_NONE; +} diff --git a/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h new file mode 100644 index 0000000000..c5199e50a4 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/adult_trade_shuffle.h @@ -0,0 +1,12 @@ +#ifndef Z_ADULT_TRADE_SHUFFLE_H +#define Z_ADULT_TRADE_SHUFFLE_H + +#include + +#define ADULT_TRADE_FLAG(itemId) (1 << (itemId - ITEM_POCKET_EGG)) + +void Randomizer_ConsumeAdultTradeItem(GlobalContext* globalCtx, u8 itemId); +u8 Randomizer_GetNextAdultTradeItem(); +u8 Randomizer_GetPrevAdultTradeItem(); + +#endif diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b897775649..5ffe540ad6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1005,6 +1005,41 @@ std::unordered_map itemIdToModel = { { GI_NONE, GID_MAXIMUM }, { GI_MEDALLION_LIGHT, GID_MEDALLION_LIGHT }, { GI_SINGLE_MAGIC, GID_MAGIC_SMALL }, { GI_DOUBLE_MAGIC, GID_MAGIC_LARGE }, + { GI_GERUDO_FORTRESS_SMALL_KEY, GID_KEY_SMALL }, + { GI_FOREST_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_FIRE_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_WATER_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_SPIRIT_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_SHADOW_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_BOTTOM_OF_THE_WELL_SMALL_KEY, GID_KEY_SMALL }, + { GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY, GID_KEY_SMALL }, + { GI_GANONS_CASTLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_FOREST_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, + { GI_FIRE_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, + { GI_WATER_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, + { GI_SPIRIT_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, + { GI_SHADOW_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, + { GI_GANONS_CASTLE_BOSS_KEY, GID_KEY_BOSS }, + { GI_DEKU_TREE_MAP, GID_DUNGEON_MAP }, + { GI_DODONGOS_CAVERN_MAP, GID_DUNGEON_MAP }, + { GI_JABU_JABUS_BELLY_MAP, GID_DUNGEON_MAP }, + { GI_FOREST_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_FIRE_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_WATER_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_SPIRIT_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_SHADOW_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_BOTTOM_OF_THE_WELL_MAP, GID_DUNGEON_MAP }, + { GI_ICE_CAVERN_MAP, GID_DUNGEON_MAP }, + { GI_DEKU_TREE_COMPASS, GID_COMPASS }, + { GI_DODONGOS_CAVERN_COMPASS, GID_COMPASS }, + { GI_JABU_JABUS_BELLY_COMPASS, GID_COMPASS }, + { GI_FOREST_TEMPLE_COMPASS, GID_COMPASS }, + { GI_FIRE_TEMPLE_COMPASS, GID_COMPASS }, + { GI_WATER_TEMPLE_COMPASS, GID_COMPASS }, + { GI_SPIRIT_TEMPLE_COMPASS, GID_COMPASS }, + { GI_SHADOW_TEMPLE_COMPASS, GID_COMPASS }, + { GI_BOTTOM_OF_THE_WELL_COMPASS, GID_COMPASS }, + { GI_ICE_CAVERN_COMPASS, GID_COMPASS }, { GI_ICE_TRAP, GID_RUPEE_GOLD }, { GI_ICE_TRAP, GID_MAXIMUM }, { GI_TEXT_0, GID_MAXIMUM } }; @@ -1408,10 +1443,14 @@ std::unordered_map SpoilerfileSettingNameToEn { "Open Settings:Trial Count", RSK_TRIAL_COUNT }, { "Shuffle Settings:Shuffle Cows", RSK_SHUFFLE_COWS }, { "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS }, + { "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE }, { "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD }, { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, { "Shuffle Dungeon Items:Start with Maps/Compasses", RSK_STARTING_MAPS_COMPASSES }, + { "Shuffle Dungeon Items:Small Keys", RSK_KEYSANITY }, + { "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 }, { "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS }, { "Misc Settings:Hint Clarity", RSK_HINT_CLARITY }, @@ -1423,7 +1462,8 @@ std::unordered_map SpoilerfileSettingNameToEn { "Timesaver Settings:Big Poe Target Count", RSK_BIG_POE_COUNT }, { "Timesaver Settings:Skip Child Stealth", RSK_SKIP_CHILD_STEALTH }, { "Timesaver Settings:Skip Epona Race", RSK_SKIP_EPONA_RACE }, - { "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE } + { "Timesaver Settings:Skip Tower Escape", RSK_SKIP_TOWER_ESCAPE }, + { "Timesaver Settings:Complete Mask Quest", RSK_COMPLETE_MASK_QUEST }, }; s32 Randomizer::GetItemIDFromGetItemID(s32 getItemId) { @@ -1639,7 +1679,11 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { gSaveContext.randoSettings[index].value = std::stoi(numericValueString); break; case RSK_SHUFFLE_COWS: + case RSK_SHUFFLE_ADULT_TRADE: case RSK_RANDOM_TRIALS: + case RSK_STARTING_DEKU_SHIELD: + case RSK_STARTING_KOKIRI_SWORD: + case RSK_COMPLETE_MASK_QUEST: if(it.value() == "Off") { gSaveContext.randoSettings[index].value = 0; } else if(it.value() == "On") { @@ -1647,24 +1691,18 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { } break; case RSK_STARTING_MAPS_COMPASSES: - if(it.value() == "Own Dungeon") { - gSaveContext.randoSettings[index].value = 0; - } else if (it.value() == "Start With") { - gSaveContext.randoSettings[index].value = 1; - } - break; - case RSK_STARTING_DEKU_SHIELD: - if(it.value() == "Off") { + if(it.value() == "Start With") { gSaveContext.randoSettings[index].value = 0; - } else if(it.value() == "On") { - gSaveContext.randoSettings[index].value = 1; - } - break; - case RSK_STARTING_KOKIRI_SWORD: - if(it.value() == "Off") { - gSaveContext.randoSettings[index].value = 0; - } else if(it.value() == "On") { + } else if(it.value() == "Vanilla") { gSaveContext.randoSettings[index].value = 1; + } else if(it.value() == "Own Dungeon") { + gSaveContext.randoSettings[index].value = 2; + } else if(it.value() == "Any Dungeon") { + gSaveContext.randoSettings[index].value = 3; + } else if(it.value() == "Overworld") { + gSaveContext.randoSettings[index].value = 4; + } else if(it.value() == "Anywhere") { + gSaveContext.randoSettings[index].value = 5; } break; case RSK_STARTING_OCARINA: @@ -1705,13 +1743,49 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { gSaveContext.randoSettings[index].value = 3; } break; - case RSK_GANONS_BOSS_KEY: - if(it.value() == "Start with") { + case RSK_KEYSANITY: + if(it.value() == "Start With") { gSaveContext.randoSettings[index].value = 0; } else if(it.value() == "Vanilla") { gSaveContext.randoSettings[index].value = 1; - } else if(it.value() == "Own dungeon") { + } else if(it.value() == "Own Dungeon") { gSaveContext.randoSettings[index].value = 2; + } else if(it.value() == "Any Dungeon") { + gSaveContext.randoSettings[index].value = 3; + } else if(it.value() == "Overworld") { + gSaveContext.randoSettings[index].value = 4; + } else if(it.value() == "Anywhere") { + gSaveContext.randoSettings[index].value = 5; + } + break; + case RSK_BOSS_KEYSANITY: + if(it.value() == "Start With") { + gSaveContext.randoSettings[index].value = 0; + } else if(it.value() == "Vanilla") { + gSaveContext.randoSettings[index].value = 1; + } else if(it.value() == "Own Dungeon") { + gSaveContext.randoSettings[index].value = 2; + } else if(it.value() == "Any Dungeon") { + gSaveContext.randoSettings[index].value = 3; + } else if(it.value() == "Overworld") { + gSaveContext.randoSettings[index].value = 4; + } else if(it.value() == "Anywhere") { + gSaveContext.randoSettings[index].value = 5; + } + break; + case RSK_GANONS_BOSS_KEY: + if(it.value() == "Vanilla") { + gSaveContext.randoSettings[index].value = 0; + } else if(it.value() == "Own dungeon") { + gSaveContext.randoSettings[index].value = 1; + } else if(it.value() == "Start with") { + gSaveContext.randoSettings[index].value = 2; + } else if(it.value() == "Any Dungeon") { + gSaveContext.randoSettings[index].value = 3; + } else if(it.value() == "Overworld") { + gSaveContext.randoSettings[index].value = 4; + } else if(it.value() == "Anywhere") { + gSaveContext.randoSettings[index].value = 5; } break; case RSK_SKIP_CHILD_ZELDA: @@ -2228,50 +2302,79 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_PRELUDE_OF_LIGHT: return GI_PRELUDE_OF_LIGHT; - // todo implement dungeon-specific maps/compasses case RG_DEKU_TREE_MAP: + return GI_DEKU_TREE_MAP; case RG_DODONGOS_CAVERN_MAP: + return GI_DODONGOS_CAVERN_MAP; case RG_JABU_JABUS_BELLY_MAP: + return GI_JABU_JABUS_BELLY_MAP; case RG_FOREST_TEMPLE_MAP: + return GI_FOREST_TEMPLE_MAP; case RG_FIRE_TEMPLE_MAP: + return GI_FIRE_TEMPLE_MAP; case RG_WATER_TEMPLE_MAP: + return GI_WATER_TEMPLE_MAP; case RG_SPIRIT_TEMPLE_MAP: + return GI_SPIRIT_TEMPLE_MAP; case RG_SHADOW_TEMPLE_MAP: + return GI_SHADOW_TEMPLE_MAP; case RG_BOTTOM_OF_THE_WELL_MAP: + return GI_BOTTOM_OF_THE_WELL_MAP; case RG_ICE_CAVERN_MAP: - return GI_MAP; + return GI_ICE_CAVERN_MAP; case RG_DEKU_TREE_COMPASS: + return GI_DEKU_TREE_COMPASS; case RG_DODONGOS_CAVERN_COMPASS: + return GI_DODONGOS_CAVERN_COMPASS; case RG_JABU_JABUS_BELLY_COMPASS: + return GI_JABU_JABUS_BELLY_COMPASS; case RG_FOREST_TEMPLE_COMPASS: + return GI_FOREST_TEMPLE_COMPASS; case RG_FIRE_TEMPLE_COMPASS: + return GI_FIRE_TEMPLE_COMPASS; case RG_WATER_TEMPLE_COMPASS: + return GI_WATER_TEMPLE_COMPASS; case RG_SPIRIT_TEMPLE_COMPASS: + return GI_SPIRIT_TEMPLE_COMPASS; case RG_SHADOW_TEMPLE_COMPASS: + return GI_SHADOW_TEMPLE_COMPASS; case RG_BOTTOM_OF_THE_WELL_COMPASS: + return GI_BOTTOM_OF_THE_WELL_COMPASS; case RG_ICE_CAVERN_COMPASS: - return GI_COMPASS; + return GI_ICE_CAVERN_COMPASS; - // todo implement dungeon-specific keys/keyrings case RG_FOREST_TEMPLE_BOSS_KEY: + return GI_FOREST_TEMPLE_BOSS_KEY; case RG_FIRE_TEMPLE_BOSS_KEY: + return GI_FIRE_TEMPLE_BOSS_KEY; case RG_WATER_TEMPLE_BOSS_KEY: + return GI_WATER_TEMPLE_BOSS_KEY; case RG_SPIRIT_TEMPLE_BOSS_KEY: + return GI_SPIRIT_TEMPLE_BOSS_KEY; case RG_SHADOW_TEMPLE_BOSS_KEY: + return GI_SHADOW_TEMPLE_BOSS_KEY; case RG_GANONS_CASTLE_BOSS_KEY: - return GI_KEY_BOSS; + return GI_GANONS_CASTLE_BOSS_KEY; case RG_FOREST_TEMPLE_SMALL_KEY: + return GI_FOREST_TEMPLE_SMALL_KEY; case RG_FIRE_TEMPLE_SMALL_KEY: + return GI_FIRE_TEMPLE_SMALL_KEY; case RG_WATER_TEMPLE_SMALL_KEY: + return GI_WATER_TEMPLE_SMALL_KEY; case RG_SPIRIT_TEMPLE_SMALL_KEY: + return GI_SPIRIT_TEMPLE_SMALL_KEY; case RG_SHADOW_TEMPLE_SMALL_KEY: + return GI_SHADOW_TEMPLE_SMALL_KEY; case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + return GI_BOTTOM_OF_THE_WELL_SMALL_KEY; case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + return GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY; case RG_GERUDO_FORTRESS_SMALL_KEY: + return GI_GERUDO_FORTRESS_SMALL_KEY; case RG_GANONS_CASTLE_SMALL_KEY: - return GI_KEY_SMALL; + return GI_GANONS_CASTLE_SMALL_KEY; // todo test this with keys in own dungeon case RG_TREASURE_GAME_SMALL_KEY: @@ -3430,11 +3533,12 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVar_GetS32("gRandomizeShuffleKokiriSword", 0) || CVar_GetS32("gRandomizeStartingKokiriSword", 0); cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVar_GetS32("gRandomizeStartingDekuShield", 0); - cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 0); + cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 2); cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0); cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0); cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 0); cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0); + cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); // if we skip child zelda, we start with zelda's letter, and malon starts @@ -3449,7 +3553,10 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVar_GetS32("gRandomizeGossipStoneHints", 1); cvarSettings[RSK_HINT_CLARITY] = CVar_GetS32("gRandomizeHintClarity", 2); cvarSettings[RSK_HINT_DISTRIBUTION] = CVar_GetS32("gRandomizeHintDistribution", 1); - cvarSettings[RSK_GANONS_BOSS_KEY] = CVar_GetS32("gRandomizeShuffleGanonBossKey", 0); + cvarSettings[RSK_KEYSANITY] = CVar_GetS32("gRandomizeKeysanity", 2); + cvarSettings[RSK_GERUDO_KEYS] = CVar_GetS32("gRandomizeGerudoKeys", 0); + cvarSettings[RSK_BOSS_KEYSANITY] = CVar_GetS32("gRandomizeBossKeysanity", 2); + cvarSettings[RSK_GANONS_BOSS_KEY] = CVar_GetS32("gRandomizeShuffleGanonBossKey", 1); cvarSettings[RSK_STARTING_CONSUMABLES] = CVar_GetS32("gRandomizeStartingConsumables", 0); cvarSettings[RSK_FULL_WALLETS] = CVar_GetS32("gRandomizeFullWallets", 0); @@ -3474,6 +3581,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_SKULLS_SUNS_SONG] = CVar_GetS32("gRandomizeGsExpectSunsSong", 0); @@ -3540,17 +3648,11 @@ void DrawRandoEditor(bool& open) { const char* randoShuffleAdultTrade[2] = { "Off", "On" }; // Shuffle Dungeon Items Settings - const char* randoShuffleMapsAndCompasses[6] = { "Own Dungeon", "Any Dungeon", "Overworld", - "Anywhere", "Start with", "Vanilla" }; - const char* randoShuffleSmallKeys[6] = { "Own Dungeon", "Any Dungeon", "Overworld", - "Anywhere", "Start with", "Vanilla" }; + const char* randoShuffleMapsAndCompasses[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }; + const char* randoShuffleSmallKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }; const char* randoShuffleGerudoFortressKeys[4] = { "Vanilla", "Any Dungeon", "Overworld", "Anywhere" }; - const char* randoShuffleBossKeys[6] = { "Own Dungeon", "Any Dungeon", "Overworld", - "Anywhere", "Start with", "Vanilla" }; - // const char* randoShuffleGanonsBossKey[12] = { "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere", - // "LACS Vanilla", "LACS Medallions", "LACS Stones", "LACS Rewards", - // "LACS Dungeons", "LACS Tokens", "Start with", "Vanilla" }; - const char* randoShuffleGanonsBossKey[3] = {"Vanilla", "Own dungeon", "Start with"}; + const char* randoShuffleBossKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }; + 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)" }; @@ -3963,6 +4065,20 @@ void DrawRandoEditor(bool& open) { 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"); @@ -4060,22 +4176,90 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); PaddedSeparator(); - // RANDOTODO implement ganon's boss key outside of ganon's castle + // 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." + ); + 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." + ); + 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." + ); + SohImGui::EnhancementCombobox("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2); + PaddedSeparator(); + // Ganon's Boss Key ImGui::Text(Settings::GanonsBossKey.GetName().c_str()); InsertHelpHoverText( - "Vanilla - Key will appear in the vanilla location.\n" + "Vanilla - Ganon's Boss Key will appear in the vanilla location.\n" "\n" - "Own dungeon - Key can appear anywhere inside Ganon's Castle.\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, 3, - 0); + SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1); PaddedSeparator(); // Start with Maps & Compasses - SohImGui::EnhancementCheckbox(Settings::MapsAndCompasses.GetName().c_str(), "gRandomizeStartingMapsCompasses"); + 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." + ); + SohImGui::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2); ImGui::PopItemWidth(); ImGui::EndTable(); @@ -4156,6 +4340,13 @@ void DrawRandoEditor(bool& open) { 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." + ); // COLUMN 2 - HINT SETTINGS ImGui::TableNextColumn(); @@ -4457,6 +4648,45 @@ void Randomizer::CreateCustomMessages() { "You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!"), GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_POE, ITEM_POE, "You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this..."), + + GIMESSAGE_UNTRANSLATED(GI_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yThieves Hideout &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %gForest Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rFire Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %bWater Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %ySpirit Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pShadow Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pBottom of the &Well %wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yGerudo Training Grounds &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!"), + + GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %gForest Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rFire Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %bWater Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %ySpirit Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %pShadow Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rGanon's Castle &%wBoss Key!"), + + GIMESSAGE_UNTRANSLATED(GI_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, "You found the %gDeku Tree &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %rDodongo's Cavern &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, "You found the %bJabu Jabu's Belly &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %gForest Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %rFire Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %bWater Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %ySpirit Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %pShadow Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, "You found the %pBottom of the &Well %wMap!"), + GIMESSAGE_UNTRANSLATED(GI_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %cIce Cavern &%wMap!"), + + GIMESSAGE_UNTRANSLATED(GI_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, "You found the %rDodongo's Cavern &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, "You found the %bJabu Jabu's Belly &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %gForest Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %rFire Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %bWater Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %ySpirit Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %pShadow Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS, "You found the %pBottom of the &Well %wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_ICE_CAVERN_COMPASS, ITEM_COMPASS, "You found the %cIce Cavern &%wCompass!"), }; CreateGetItemMessages(getItemMessages); CreateScrubMessages(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 5aa89fbcaf..3f0da52b7a 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -10,6 +10,7 @@ typedef struct { } Sprite; typedef enum { + RC_UNKNOWN_CHECK, RC_LINKS_POCKET, RC_QUEEN_GOHMA, RC_KING_DODONGO, @@ -752,7 +753,7 @@ typedef enum { RC_ZR_NEAR_DOMAIN_GOSSIP_STONE, RC_ZR_NEAR_GROTTOS_GOSSIP_STONE, RC_ZR_OPEN_GROTTO_GOSSIP_STONE, - RC_UNKNOWN_CHECK + RC_MAX } RandomizerCheck; // based on https://github.com/TestRunnerSRL/OoT-Randomizer/blob/e337d7f603b91a6bacb618fb32cc7fd70ed9ffca/ItemList.py @@ -971,7 +972,7 @@ typedef enum { RSK_STARTING_DEKU_SHIELD, RSK_STARTING_KOKIRI_SWORD, RSK_SHUFFLE_KOKIRI_SWORD, - RSK_STARTING_MAPS_COMPASSES, //RANDOTODO more options for this, rn it's just start with or own dungeon + RSK_STARTING_MAPS_COMPASSES, RSK_SHUFFLE_DUNGEON_REWARDS, RSK_SHUFFLE_SONGS, RSK_SHUFFLE_TOKENS, @@ -984,6 +985,9 @@ typedef enum { RSK_GOSSIP_STONE_HINTS, RSK_HINT_CLARITY, RSK_HINT_DISTRIBUTION, + RSK_KEYSANITY, + RSK_GERUDO_KEYS, + RSK_BOSS_KEYSANITY, RSK_GANONS_BOSS_KEY, RSK_SKIP_CHILD_STEALTH, RSK_SKIP_CHILD_ZELDA, @@ -1001,5 +1005,7 @@ typedef enum { RSK_BIG_POE_COUNT, RSK_SKIP_EPONA_RACE, RSK_SKIP_TOWER_ESCAPE, - RSK_SKULLS_SUNS_SONG + RSK_COMPLETE_MASK_QUEST, + RSK_SKULLS_SUNS_SONG, + RSK_SHUFFLE_ADULT_TRADE } RandomizerSettingKey; diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 4d312daffd..70c16fd80f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -230,18 +230,12 @@ typedef struct { } std::unordered_map equipTrackerMap = { - ITEM_TRACKER_MAP_ENTRY(ITEM_SWORD_KOKIRI, 0), - ITEM_TRACKER_MAP_ENTRY(ITEM_SWORD_MASTER, 1), - ITEM_TRACKER_MAP_ENTRY(ITEM_SWORD_BGS, 2), - ITEM_TRACKER_MAP_ENTRY(ITEM_SWORD_BROKEN, 3), - ITEM_TRACKER_MAP_ENTRY(ITEM_SHIELD_DEKU, 4), - ITEM_TRACKER_MAP_ENTRY(ITEM_SHIELD_HYLIAN, 5), - ITEM_TRACKER_MAP_ENTRY(ITEM_SHIELD_MIRROR, 6), - ITEM_TRACKER_MAP_ENTRY(ITEM_TUNIC_KOKIRI, 8), - ITEM_TRACKER_MAP_ENTRY(ITEM_TUNIC_GORON, 9), - ITEM_TRACKER_MAP_ENTRY(ITEM_TUNIC_ZORA, 10), - ITEM_TRACKER_MAP_ENTRY(ITEM_BOOTS_KOKIRI, 12), - ITEM_TRACKER_MAP_ENTRY(ITEM_BOOTS_IRON, 13), + ITEM_TRACKER_MAP_ENTRY(ITEM_SWORD_KOKIRI, 0), ITEM_TRACKER_MAP_ENTRY(ITEM_SWORD_MASTER, 1), + ITEM_TRACKER_MAP_ENTRY(ITEM_SWORD_BGS, 2), ITEM_TRACKER_MAP_ENTRY(ITEM_SWORD_BROKEN, 3), + ITEM_TRACKER_MAP_ENTRY(ITEM_SHIELD_DEKU, 4), ITEM_TRACKER_MAP_ENTRY(ITEM_SHIELD_HYLIAN, 5), + ITEM_TRACKER_MAP_ENTRY(ITEM_SHIELD_MIRROR, 6), ITEM_TRACKER_MAP_ENTRY(ITEM_TUNIC_KOKIRI, 8), + ITEM_TRACKER_MAP_ENTRY(ITEM_TUNIC_GORON, 9), ITEM_TRACKER_MAP_ENTRY(ITEM_TUNIC_ZORA, 10), + ITEM_TRACKER_MAP_ENTRY(ITEM_BOOTS_KOKIRI, 12), ITEM_TRACKER_MAP_ENTRY(ITEM_BOOTS_IRON, 13), ITEM_TRACKER_MAP_ENTRY(ITEM_BOOTS_HOVER, 14), }; @@ -256,18 +250,12 @@ void DrawEquip(uint32_t itemId) { } std::unordered_map questTrackerMap = { - ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_FOREST, 0), - ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_FIRE, 1), - ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_WATER, 2), - ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_SPIRIT, 3), - ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_SHADOW, 4), - ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_LIGHT, 5), - ITEM_TRACKER_MAP_ENTRY(QUEST_KOKIRI_EMERALD, 18), - ITEM_TRACKER_MAP_ENTRY(QUEST_GORON_RUBY, 19), - ITEM_TRACKER_MAP_ENTRY(QUEST_ZORA_SAPPHIRE, 20), - ITEM_TRACKER_MAP_ENTRY(QUEST_STONE_OF_AGONY, 21), - ITEM_TRACKER_MAP_ENTRY(QUEST_GERUDO_CARD, 22), - ITEM_TRACKER_MAP_ENTRY(QUEST_SKULL_TOKEN, 23), + ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_FOREST, 0), ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_FIRE, 1), + ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_WATER, 2), ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_SPIRIT, 3), + ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_SHADOW, 4), ITEM_TRACKER_MAP_ENTRY(QUEST_MEDALLION_LIGHT, 5), + ITEM_TRACKER_MAP_ENTRY(QUEST_KOKIRI_EMERALD, 18), ITEM_TRACKER_MAP_ENTRY(QUEST_GORON_RUBY, 19), + ITEM_TRACKER_MAP_ENTRY(QUEST_ZORA_SAPPHIRE, 20), ITEM_TRACKER_MAP_ENTRY(QUEST_STONE_OF_AGONY, 21), + ITEM_TRACKER_MAP_ENTRY(QUEST_GERUDO_CARD, 22), ITEM_TRACKER_MAP_ENTRY(QUEST_SKULL_TOKEN, 23), }; @@ -404,6 +392,10 @@ std::unordered_map itemTrackerMap = { ITEM_TRACKER_MAP_ENTRY(ITEM_MAGIC_LARGE, 0), ITEM_TRACKER_MAP_ENTRY(ITEM_WALLET_ADULT, 0), ITEM_TRACKER_MAP_ENTRY(ITEM_WALLET_GIANT, 0), + ITEM_TRACKER_MAP_ENTRY(ITEM_DUNGEON_MAP, 0), + ITEM_TRACKER_MAP_ENTRY(ITEM_COMPASS, 0), + ITEM_TRACKER_MAP_ENTRY(ITEM_KEY_SMALL, 0), + ITEM_TRACKER_MAP_ENTRY(ITEM_KEY_BOSS, 0) }; void DrawItem(uint32_t itemId) { @@ -691,39 +683,74 @@ void DrawBottle(uint32_t itemId, uint32_t bottleSlot) { SetLastItemHoverText(SohUtils::GetItemName(entry.id)); }; +void DrawDungeonItem(uint32_t itemId, uint32_t scene) { + const ItemTrackerMapEntry& entry = itemTrackerMap[itemId]; + uint32_t bitMask = 1 << (entry.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential + int iconSize = CVar_GetS32("gRandoTrackIconSize", 0); + bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[scene]) != 0; + ImGui::BeginGroup(); + ImGui::Image(SohImGui::GetTextureByName(hasItem ? entry.name : entry.nameFaded), ImVec2(iconSize, iconSize), + ImVec2(0, 0), ImVec2(1, 1)); + + ImVec2 p = ImGui::GetCursorScreenPos(); + int estimatedTextWidth = 10; + int estimatedTextHeight = 10; + ImGui::SetCursorScreenPos(ImVec2(p.x - 5 + (iconSize / 2) - estimatedTextWidth, p.y - estimatedTextHeight)); + + if (itemId == ITEM_KEY_SMALL) { + if (gSaveContext.inventory.dungeonKeys[scene] == 0) { + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(155, 155, 155, 255)); + ImGui::Text("%i", gSaveContext.inventory.dungeonKeys[scene]); + ImGui::PopStyleColor(); + } + else { + ImGui::Text("%i", gSaveContext.inventory.dungeonKeys[scene]); + } + } + ImGui::EndGroup(); + + SetLastItemHoverText(SohUtils::GetItemName(entry.id)); +} + typedef struct { uint8_t id; std::string name; std::string nameFaded; } ItemTrackerUpgradeEntry; -#define ITEM_TRACKER_UPGRADE_ENTRY(id) { id, #id, #id "_Faded" } +#define ITEM_TRACKER_UPGRADE_ENTRY(id) \ + { id, #id, #id "_Faded" } std::unordered_map> upgradeTrackerMap = { - {UPG_STRENGTH, { - ITEM_TRACKER_UPGRADE_ENTRY(ITEM_BRACELET), - ITEM_TRACKER_UPGRADE_ENTRY(ITEM_GAUNTLETS_SILVER), - ITEM_TRACKER_UPGRADE_ENTRY(ITEM_GAUNTLETS_GOLD), - }}, - {UPG_SCALE, { - ITEM_TRACKER_UPGRADE_ENTRY(ITEM_SCALE_SILVER), - ITEM_TRACKER_UPGRADE_ENTRY(ITEM_SCALE_GOLDEN), - }}, - {UPG_QUIVER, { + { UPG_STRENGTH, + { + ITEM_TRACKER_UPGRADE_ENTRY(ITEM_BRACELET), + ITEM_TRACKER_UPGRADE_ENTRY(ITEM_GAUNTLETS_SILVER), + ITEM_TRACKER_UPGRADE_ENTRY(ITEM_GAUNTLETS_GOLD), + } }, + { UPG_SCALE, + { + ITEM_TRACKER_UPGRADE_ENTRY(ITEM_SCALE_SILVER), + ITEM_TRACKER_UPGRADE_ENTRY(ITEM_SCALE_GOLDEN), + } }, + { UPG_QUIVER, + { ITEM_TRACKER_UPGRADE_ENTRY(ITEM_QUIVER_30), ITEM_TRACKER_UPGRADE_ENTRY(ITEM_QUIVER_40), ITEM_TRACKER_UPGRADE_ENTRY(ITEM_QUIVER_50), - }}, - {UPG_BULLET_BAG, { + } }, + { UPG_BULLET_BAG, + { ITEM_TRACKER_UPGRADE_ENTRY(ITEM_BULLET_BAG_30), ITEM_TRACKER_UPGRADE_ENTRY(ITEM_BULLET_BAG_40), ITEM_TRACKER_UPGRADE_ENTRY(ITEM_BULLET_BAG_50), - }}, - {UPG_BOMB_BAG, { + } }, + { UPG_BOMB_BAG, + { ITEM_TRACKER_UPGRADE_ENTRY(ITEM_BOMB_BAG_20), ITEM_TRACKER_UPGRADE_ENTRY(ITEM_BOMB_BAG_30), ITEM_TRACKER_UPGRADE_ENTRY(ITEM_BOMB_BAG_40), - }}, + } }, }; @@ -731,13 +758,12 @@ void DrawUpgrade(int32_t categoryId) { int iconSize = CVar_GetS32("gRandoTrackIconSize", 0); if (CUR_UPG_VALUE(categoryId) == 0) { const ItemTrackerUpgradeEntry& entry = upgradeTrackerMap[categoryId][0]; - ImGui::Image(SohImGui::GetTextureByName(entry.nameFaded), ImVec2(iconSize, iconSize), - ImVec2(0, 0), ImVec2(1, 1)); + ImGui::Image(SohImGui::GetTextureByName(entry.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), + ImVec2(1, 1)); 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)); + ImGui::Image(SohImGui::GetTextureByName(entry.name), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); SetLastItemHoverText(SohUtils::GetItemName(entry.id)); } } @@ -749,234 +775,620 @@ typedef struct { ImVec4 color; } ItemTrackerSongEntry; -#define ITEM_TRACKER_SONG_ENTRY(id) \ - { \ - id, { \ - id, #id, #id "_Faded" \ - } \ +#define ITEM_TRACKER_SONG_ENTRY(id) \ + { \ + id, { \ + id, #id, #id "_Faded" \ + } \ } // Maps song ids to info for use in ImGui std::unordered_map songTrackerMap = { - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_LULLABY), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_EPONA), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SARIA), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SUN), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_TIME), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_STORMS), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_MINUET), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_BOLERO), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SERENADE), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_REQUIEM), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_NOCTURNE), - ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_PRELUDE), + ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_LULLABY), ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_EPONA), + ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SARIA), ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SUN), + ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_TIME), ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_STORMS), + ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_MINUET), ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_BOLERO), + ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SERENADE), ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_REQUIEM), + ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_NOCTURNE), ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_PRELUDE), }; -#define VANILLA_ITEM_TRACKER_SONG_ENTRY(id) \ - { \ - id, { \ - id, #id "_Vanilla", #id "_Vanilla_Faded" \ - } \ +#define VANILLA_ITEM_TRACKER_SONG_ENTRY(id) \ + { \ + id, { \ + id, #id "_Vanilla", #id "_Vanilla_Faded" \ + } \ } // Maps song ids to info for use in ImGui std::unordered_map vanillaSongTrackerMap = { - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_LULLABY), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_EPONA), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SARIA), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SUN), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_TIME), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_STORMS), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_MINUET), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_BOLERO), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SERENADE), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_REQUIEM), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_NOCTURNE), - VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_PRELUDE), + VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_LULLABY), VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_EPONA), + VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SARIA), VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SUN), + VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_TIME), VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_STORMS), + VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_MINUET), VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_BOLERO), + VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_SERENADE), VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_REQUIEM), + VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_NOCTURNE), VANILLA_ITEM_TRACKER_SONG_ENTRY(QUEST_SONG_PRELUDE), }; void DrawSong(int32_t songId) { int iconSize = CVar_GetS32("gRandoTrackIconSize", 0); - const ItemTrackerSongEntry& entry = CVar_GetS32("gItemTrackeSongColor", 0) ? - songTrackerMap[songId] : - vanillaSongTrackerMap[songId]; + const ItemTrackerSongEntry& entry = + CVar_GetS32("gItemTrackeSongColor", 0) ? songTrackerMap[songId] : vanillaSongTrackerMap[songId]; uint32_t bitMask = 1 << entry.id; 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)); + 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)); } -void DrawItemTracker(bool& open) { - if (!open) { - CVar_SetS32("gItemTrackerEnabled", 0); - return; +// Theme 1 Original Tracker style +void DrawFloatingInventory(int Icon_Cells_Size, int Icon_Spacing) { + ImGui::BeginGroup(); + DrawItem(ITEM_STICK); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawItem(ITEM_NUT); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawItem(ITEM_BOMB); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawItem(ITEM_BOW); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawItem(ITEM_ARROW_FIRE); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawItem(ITEM_DINS_FIRE); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawItem(ITEM_SLINGSHOT); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawItem(ITEM_OCARINA_FAIRY); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawItem(ITEM_BOMBCHU); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawItem(ITEM_HOOKSHOT); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawItem(ITEM_ARROW_ICE); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawItem(ITEM_FARORES_WIND); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawItem(ITEM_BOOMERANG); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawItem(ITEM_LENS); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawItem(ITEM_BEAN); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawItem(ITEM_HAMMER); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawItem(ITEM_ARROW_LIGHT); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawItem(ITEM_NAYRUS_LOVE); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawBottle(ITEM_BOTTLE, 0); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawBottle(ITEM_BOTTLE, 1); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawBottle(ITEM_BOTTLE, 2); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawBottle(ITEM_BOTTLE, 3); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawItem(ITEM_POCKET_EGG); // ADULT TRADE + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawItem(ITEM_MASK_KEATON); // CHILD TRADE + ImGui::EndGroup(); +} +void DrawFloatingEquipsQuestUpgradeStones(int Icon_Cells_Size, int Icon_Spacing) { + ImGui::BeginGroup(); + DrawEquip(ITEM_SWORD_KOKIRI); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawEquip(ITEM_SWORD_MASTER); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawEquip(ITEM_SWORD_BGS); // PURPLE TODO: CHECK IF BGS OR BROKEN SWORD TO DISPLAY + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawQuest(QUEST_STONE_OF_AGONY); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawQuest(QUEST_GERUDO_CARD); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawQuest(QUEST_SKULL_TOKEN); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawEquip(ITEM_SHIELD_DEKU); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawEquip(ITEM_SHIELD_HYLIAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawEquip(ITEM_SHIELD_MIRROR); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawUpgrade(UPG_STRENGTH); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawUpgrade(UPG_SCALE); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawItem(ITEM_WALLET_ADULT); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawEquip(ITEM_TUNIC_KOKIRI); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawEquip(ITEM_TUNIC_GORON); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawEquip(ITEM_TUNIC_ZORA); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawItem(ITEM_HEART_CONTAINER); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawItem(ITEM_MAGIC_SMALL); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawEquip(ITEM_BOOTS_KOKIRI); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawEquip(ITEM_BOOTS_IRON); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawEquip(ITEM_BOOTS_HOVER); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawQuest(QUEST_KOKIRI_EMERALD); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawQuest(QUEST_GORON_RUBY); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawQuest(QUEST_ZORA_SAPPHIRE); + ImGui::EndGroup(); +} +void DrawFloatingTokens(int Icon_Cells_Size, int Icon_Spacing) { + ImGui::BeginGroup(); + if (CVar_GetS32("gItemTrackerTheme", 0) == 0 || !CVar_GetS32("gItemTrackerMedallionsPlacement", 0)) { + DrawQuest(QUEST_MEDALLION_FOREST); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawQuest(QUEST_MEDALLION_FIRE); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawQuest(QUEST_MEDALLION_WATER); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawQuest(QUEST_MEDALLION_SPIRIT); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawQuest(QUEST_MEDALLION_SHADOW); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawQuest(QUEST_MEDALLION_LIGHT); + } else if (CVar_GetS32("gItemTrackerTheme", 0) != 0 && CVar_GetS32("gItemTrackerMedallionsPlacement", 0)) { + ImGui::BeginGroup(); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 1); + DrawQuest(QUEST_MEDALLION_LIGHT); + ImGui::EndGroup(); + ImGui::BeginGroup(); + DrawQuest(QUEST_MEDALLION_SHADOW); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawQuest(QUEST_MEDALLION_FOREST); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::EndGroup(); + ImGui::BeginGroup(); + DrawQuest(QUEST_MEDALLION_SPIRIT); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawQuest(QUEST_MEDALLION_FIRE); + ImGui::EndGroup(); + ImGui::BeginGroup(); + ImGui::NewLine(); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 1); + DrawQuest(QUEST_MEDALLION_WATER); + ImGui::EndGroup(); } + ImGui::EndGroup(); +} - ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); - static uint32_t ccc = 0xFF000000; - ImVec4 color = ImGui::ColorConvertU32ToFloat4(ccc); +void DrawFloatingSongs(int Icon_Cells_Size, int Icon_Spacing) { + ImGui::BeginGroup(); + DrawSong(QUEST_SONG_LULLABY); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawSong(QUEST_SONG_EPONA); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawSong(QUEST_SONG_SARIA); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawSong(QUEST_SONG_SUN); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawSong(QUEST_SONG_TIME); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawSong(QUEST_SONG_STORMS); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawSong(QUEST_SONG_MINUET); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawSong(QUEST_SONG_BOLERO); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawSong(QUEST_SONG_SERENADE); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawSong(QUEST_SONG_REQUIEM); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawSong(QUEST_SONG_NOCTURNE); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawSong(QUEST_SONG_PRELUDE); + ImGui::EndGroup(); +} - ImGui::PushStyleColor(ImGuiCol_WindowBg, color); - if (!ImGui::Begin("Item Tracker", &open, ImGuiWindowFlags_NoFocusOnAppearing)) { - ImGui::PopStyleColor(); - ImGui::End(); - return; +// Theme 2 per cells elements +void DrawFloatingEquipments(int Icon_Cells_Size, int Icon_Spacing) { + ImGui::BeginGroup(); + DrawEquip(ITEM_SWORD_KOKIRI); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawEquip(ITEM_SWORD_MASTER); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawEquip(ITEM_SWORD_BGS); // PURPLE TODO: CHECK IF BGS OR BROKEN SWORD TO DISPLAY + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawEquip(ITEM_SHIELD_DEKU); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawEquip(ITEM_SHIELD_HYLIAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawEquip(ITEM_SHIELD_MIRROR); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawEquip(ITEM_TUNIC_KOKIRI); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawEquip(ITEM_TUNIC_GORON); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawEquip(ITEM_TUNIC_ZORA); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawEquip(ITEM_BOOTS_KOKIRI); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawEquip(ITEM_BOOTS_IRON); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawEquip(ITEM_BOOTS_HOVER); + ImGui::EndGroup(); +} + +void DrawFloatingUpgrades(int Icon_Cells_Size, int Icon_Spacing) { + ImGui::BeginGroup(); + DrawUpgrade(UPG_STRENGTH); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawUpgrade(UPG_SCALE); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawItem(ITEM_WALLET_ADULT); + ImGui::EndGroup(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + Icon_Spacing); + ImGui::BeginGroup(); + DrawItem(ITEM_HEART_CONTAINER); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawItem(ITEM_MAGIC_SMALL); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + ImGui::EndGroup(); +} + +void DrawFloatingQuest(int Icon_Cells_Size, int Icon_Spacing) { + ImGui::BeginGroup(); + DrawQuest(QUEST_STONE_OF_AGONY); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawQuest(QUEST_GERUDO_CARD); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawQuest(QUEST_SKULL_TOKEN); + ImGui::EndGroup(); +} + +void DrawFloatingStones(int Icon_Cells_Size, int Icon_Spacing) { + ImGui::BeginGroup(); + DrawQuest(QUEST_KOKIRI_EMERALD); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawQuest(QUEST_GORON_RUBY); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawQuest(QUEST_ZORA_SAPPHIRE); + ImGui::EndGroup(); +} + +void DrawFloatingDungeons(int Icon_Cells_Size, int Icon_Spacing) { + if (CVar_GetS32("gItemTrackerDisplayDungeonItems", 0)) { + ImGui::BeginGroup(); + if (CVar_GetS32("gItemTrackerDisplayMapsAndCompasses", 0)) { + ImGui::Text("DEKU"); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + ImGui::Text("DCVN"); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + ImGui::Text("JABU"); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + ImGui::Text("FRST"); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + ImGui::Text("FIRE"); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + ImGui::Text("WATR"); + } + else { + ImGui::Text("FRST"); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + ImGui::Text("FIRE"); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + ImGui::Text("WATR"); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + ImGui::Text("SPRT"); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + ImGui::Text("SHDW"); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + ImGui::Text("GANON"); + } + ImGui::EndGroup(); + if (CVar_GetS32("gItemTrackerDisplayMapsAndCompasses", 0)) { + ImGui::BeginGroup(); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_YDAN); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_DDAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_BDAN); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_BMORI1); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_HIDAN); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_MIZUSIN); + ImGui::EndGroup(); + ImGui::BeginGroup(); + DrawDungeonItem(ITEM_COMPASS, SCENE_YDAN); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawDungeonItem(ITEM_COMPASS, SCENE_DDAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawDungeonItem(ITEM_COMPASS, SCENE_BDAN); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawDungeonItem(ITEM_COMPASS, SCENE_BMORI1); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawDungeonItem(ITEM_COMPASS, SCENE_HIDAN); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawDungeonItem(ITEM_COMPASS, SCENE_MIZUSIN); + ImGui::EndGroup(); + } + // SMALL KEYS FOR DEKU TREE TO WATER TEMPLE + ImGui::BeginGroup(); + if (CVar_GetS32("gItemTrackerDisplayMapsAndCompasses", 0)) { + ImGui::NewLine(); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_BMORI1); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_HIDAN); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_MIZUSIN); + ImGui::EndGroup(); + // BOSS KEYS FOR DEKU TREE TO WATER TEMPLE + ImGui::BeginGroup(); + ImGui::NewLine(); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_BMORI1); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_HIDAN); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_MIZUSIN); + } else { + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_BMORI1); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing ); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_HIDAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_MIZUSIN); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_JYASINZOU); + ImGui::SameLine(Icon_Cells_Size *4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_HAKADAN); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_GANON); + ImGui::EndGroup(); + // BOSS KEYS FOR FOREST TO GANON + ImGui::BeginGroup(); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_BMORI1); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_HIDAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_MIZUSIN); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_JYASINZOU); + ImGui::SameLine(Icon_Cells_Size *4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_HAKADAN); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_GANON); + } + ImGui::EndGroup(); + ImGui::BeginGroup(); + if (CVar_GetS32("gItemTrackerDisplayMapsAndCompasses", 0)) { + ImGui::Text("SPRT"); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + ImGui::Text("SHDW"); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + ImGui::Text("BOTW"); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + ImGui::Text("ICE"); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + ImGui::Text("GTG"); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + ImGui::Text("GANON"); + } else { + ImGui::Text("BOTW"); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + ImGui::Text("HIDE"); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + ImGui::Text("GTG"); + } + ImGui::EndGroup(); + if (CVar_GetS32("gItemTrackerDisplayMapsAndCompasses", 0)) { + ImGui::BeginGroup(); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_JYASINZOU); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_HAKADAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_HAKADANCH); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawDungeonItem(ITEM_DUNGEON_MAP, SCENE_ICE_DOUKUTO); + ImGui::SameLine(Icon_Cells_Size * 4); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 4); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_MEN); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_GANON); + ImGui::EndGroup(); + ImGui::BeginGroup(); + DrawDungeonItem(ITEM_COMPASS, SCENE_JYASINZOU); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawDungeonItem(ITEM_COMPASS, SCENE_HAKADAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawDungeonItem(ITEM_COMPASS, SCENE_HAKADANCH); + ImGui::SameLine(Icon_Cells_Size * 3); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 3); + DrawDungeonItem(ITEM_COMPASS, SCENE_ICE_DOUKUTO); + ImGui::SameLine(Icon_Cells_Size * 5); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 5); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_GANONTIKA); + ImGui::EndGroup(); + } + ImGui::BeginGroup(); + if (CVar_GetS32("gItemTrackerDisplayMapsAndCompasses", 0)) { + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_JYASINZOU); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_HAKADAN); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_HAKADANCH); + ImGui::EndGroup(); + ImGui::BeginGroup(); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_JYASINZOU); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawDungeonItem(ITEM_KEY_BOSS, SCENE_HAKADAN); + } else { + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_HAKADANCH); + ImGui::SameLine(Icon_Cells_Size); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_GERUDOWAY); + ImGui::SameLine(Icon_Cells_Size * 2); + ImGui::SetCursorPosX(ImGui::GetCursorPosX() + Icon_Spacing * 2); + DrawDungeonItem(ITEM_KEY_SMALL, SCENE_MEN); + } + ImGui::EndGroup(); } +} - if (ImGui::BeginTabBar("Item Tracker", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { - int spacingX = CVar_GetS32("gRandoTrackIconSpacingX", 0); - int spacingY = CVar_GetS32("gRandoTrackIconSpacingY", 0); - - if (ImGui::BeginTabItem("Item Tracker")) { - - ImGui::BeginGroup(); - DrawItem(ITEM_STICK); - ImGui::SameLine(spacingX); - DrawItem(ITEM_NUT); - ImGui::SameLine(spacingX * 2); - DrawItem(ITEM_BOMB); - ImGui::SameLine(spacingX * 3); - DrawItem(ITEM_BOW); - ImGui::SameLine(spacingX * 4); - DrawItem(ITEM_ARROW_FIRE); - ImGui::SameLine(spacingX * 5); - DrawItem(ITEM_DINS_FIRE); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawItem(ITEM_SLINGSHOT); - ImGui::SameLine(spacingX); - DrawItem(ITEM_OCARINA_FAIRY); - ImGui::SameLine(spacingX * 2); - DrawItem(ITEM_BOMBCHU); - ImGui::SameLine(spacingX * 3); - DrawItem(ITEM_HOOKSHOT); - ImGui::SameLine(spacingX * 4); - DrawItem(ITEM_ARROW_ICE); - ImGui::SameLine(spacingX * 5); - DrawItem(ITEM_FARORES_WIND); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawItem(ITEM_BOOMERANG); - ImGui::SameLine(spacingX); - DrawItem(ITEM_LENS); - ImGui::SameLine(spacingX * 2); - DrawItem(ITEM_BEAN); - ImGui::SameLine(spacingX * 3); - DrawItem(ITEM_HAMMER); - ImGui::SameLine(spacingX * 4); - DrawItem(ITEM_ARROW_LIGHT); - ImGui::SameLine(spacingX * 5); - DrawItem(ITEM_NAYRUS_LOVE); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawBottle(ITEM_BOTTLE, 0); - ImGui::SameLine(spacingX); - DrawBottle(ITEM_BOTTLE, 1); - ImGui::SameLine(spacingX * 2); - DrawBottle(ITEM_BOTTLE, 2); - ImGui::SameLine(spacingX * 3); - DrawBottle(ITEM_BOTTLE, 3); - ImGui::SameLine(spacingX * 4); - DrawItem(ITEM_POCKET_EGG); // ADULT TRADE - ImGui::SameLine(spacingX * 5); - DrawItem(ITEM_MASK_KEATON); // CHILD TRADE - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawEquip(ITEM_SWORD_KOKIRI); - ImGui::SameLine(spacingX); - DrawEquip(ITEM_SWORD_MASTER); - ImGui::SameLine(spacingX * 2); - DrawEquip(ITEM_SWORD_BGS); // PURPLE TODO: CHECK IF BGS OR BROKEN SWORD TO DISPLAY - ImGui::SameLine(spacingX * 3); - DrawQuest(QUEST_STONE_OF_AGONY); - ImGui::SameLine(spacingX * 4); - DrawQuest(QUEST_GERUDO_CARD); - ImGui::SameLine(spacingX * 5); - DrawQuest(QUEST_SKULL_TOKEN); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawEquip(ITEM_SHIELD_DEKU); - ImGui::SameLine(spacingX); - DrawEquip(ITEM_SHIELD_HYLIAN); - ImGui::SameLine(spacingX * 2); - DrawEquip(ITEM_SHIELD_MIRROR); - ImGui::SameLine(spacingX * 3); - DrawUpgrade(UPG_STRENGTH); - ImGui::SameLine(spacingX * 4); - DrawUpgrade(UPG_SCALE); - ImGui::SameLine(spacingX * 5); - DrawItem(ITEM_WALLET_ADULT); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawEquip(ITEM_TUNIC_KOKIRI); - ImGui::SameLine(spacingX); - DrawEquip(ITEM_TUNIC_GORON); - ImGui::SameLine(spacingX * 2); - DrawEquip(ITEM_TUNIC_ZORA); - ImGui::SameLine(spacingX * 3); - //ImGui::Dummy(ImVec2(spacingX + 48.0f, spacingY)); - DrawItem(ITEM_HEART_CONTAINER); - ImGui::SameLine(spacingX * 4); - DrawItem(ITEM_MAGIC_SMALL); - ImGui::SameLine(spacingX * 5); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawEquip(ITEM_BOOTS_KOKIRI); - ImGui::SameLine(spacingX); - DrawEquip(ITEM_BOOTS_IRON); - ImGui::SameLine(spacingX * 2); - DrawEquip(ITEM_BOOTS_HOVER); - ImGui::SameLine(spacingX * 3); - DrawQuest(QUEST_KOKIRI_EMERALD); - ImGui::SameLine(spacingX * 4); - DrawQuest(QUEST_GORON_RUBY); - ImGui::SameLine(spacingX * 5); - DrawQuest(QUEST_ZORA_SAPPHIRE); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawQuest(QUEST_MEDALLION_FOREST); - ImGui::SameLine(spacingX); - DrawQuest(QUEST_MEDALLION_FIRE); - ImGui::SameLine(spacingX * 2); - DrawQuest(QUEST_MEDALLION_WATER); - ImGui::SameLine(spacingX * 3); - DrawQuest(QUEST_MEDALLION_SPIRIT); - ImGui::SameLine(spacingX * 4); - DrawQuest(QUEST_MEDALLION_SHADOW); - ImGui::SameLine(spacingX * 5); - DrawQuest(QUEST_MEDALLION_LIGHT); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawSong(QUEST_SONG_LULLABY); - ImGui::SameLine(spacingX); - DrawSong(QUEST_SONG_EPONA); - ImGui::SameLine(spacingX * 2); - DrawSong(QUEST_SONG_SARIA); - ImGui::SameLine(spacingX * 3); - DrawSong(QUEST_SONG_SUN); - ImGui::SameLine(spacingX * 4); - DrawSong(QUEST_SONG_TIME); - ImGui::SameLine(spacingX * 5); - DrawSong(QUEST_SONG_STORMS); - ImGui::EndGroup(); - ImGui::BeginGroup(); - DrawSong(QUEST_SONG_MINUET); - ImGui::SameLine(spacingX); - DrawSong(QUEST_SONG_BOLERO); - ImGui::SameLine(spacingX * 2); - DrawSong(QUEST_SONG_SERENADE); - ImGui::SameLine(spacingX * 3); - DrawSong(QUEST_SONG_REQUIEM); - ImGui::SameLine(spacingX * 4); - DrawSong(QUEST_SONG_NOCTURNE); - ImGui::SameLine(spacingX * 5); - DrawSong(QUEST_SONG_PRELUDE); - ImGui::EndGroup(); - - // Item Tracker Custom Notes area - if (CVar_GetS32("gItemTrackerNotes", 0)) { - ImGui::BeginGroup(); +void DrawFloatingNotes(int Icon_Cells_Size, int Icon_Spacing) { + if (CVar_GetS32("gItemTrackerNotes", 0)) { + ImGui::BeginGroup(); struct ItemTrackerNotes { static int TrackerNotesResizeCallback(ImGuiInputTextCallbackData* data) { if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) { @@ -1003,51 +1415,235 @@ void DrawItemTracker(bool& open) { } ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput); ImGui::EndGroup(); - } - - ImGui::EndTabItem(); - } - - if (ImGui::BeginTabItem("Options")) { - int minimalSpacingX; - if (CVar_GetS32("gItemTrackerAmmoDisplay", 0) == 1) { - minimalSpacingX = 48; - } 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::EnhancementCheckbox("Personal notes space", "gItemTrackerNotes"); - SohImGui::Tooltip("Adds a textbox under the item tracker to keep your own notes in"); - SohImGui::EnhancementSliderInt("Icon size : %dpx", "##ITEMTRACKERICONSIZE", "gRandoTrackIconSize", 32, 128, ""); - - SohImGui::EnhancementSliderInt("X spacing : %dpx", "##ITEMTRACKERSPACINGX", "gRandoTrackIconSpacingX", minimalSpacingX, 256, - ""); - // SohImGui::EnhancementSliderInt("Y Spacing : %dpx", "##ITEMTRACKERSPACINGY", "gRandoTrackIconSpacingY", 0, - // 16, ""); - ImGui::Text("Chroma Key"); - - auto flags = ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_NoLabel; - - if (ImGui::ColorEdit4("ColorTest", (float*)&color, flags)) { - ccc = ImGui::ColorConvertFloat4ToU32(color); - } - - - // ImVec4 colors = ImColor::HSV(0.39f, 0.00f, 0.63f, 0.11f); - // //ImGui::ColorEdit4("TrackerBackgroundColor", colors, ImGuiColorEditFlags_DisplayHSV); - // ImGui::PushStyleColor(ImGuiCol_WindowBg, color); - // ImGui::PopStyleColor(); - // */ - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); } +} + +// Windowing stuff +ImVec4 ChromaKeyBackground = { 0, 0, 0, 1 }; // Float value, 1 = 255 in rgb value. +void BeginFloatingWindows(std::string UniqueName) { + ImGuiWindowFlags FloatingWndFlags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoScrollWithMouse | + ImGuiWindowFlags_NoScrollbar; + if (!CVar_GetS32("gItemTrackerHudEditMode", 0)) { + FloatingWndFlags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar; + } + ImGui::PushStyleColor(ImGuiCol_WindowBg, ChromaKeyBackground); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::Begin(UniqueName.c_str(), nullptr, FloatingWndFlags); +} +void EndFloatingWindows() { + ImGui::PopStyleColor(); ImGui::PopStyleColor(); ImGui::End(); } -void InitItemTracker() { - SohImGui::AddWindow("Randomizer", "Item Tracker", DrawItemTracker); +void DrawItemTracker(bool& open) { + if (!open) { + CVar_SetS32("gItemTrackerEnabled", 0); + return; + } + int Icon_Cells_Size = CVar_GetS32("gRandoTrackIconSize", 0); + int Icon_Spacing = CVar_GetS32("gRandoTrackIconSpacing", 0); + + if (CVar_GetS32("gItemTrackerEnabled", 0)) { + int ImGui_DefaultMargin = 0; + if (CVar_GetS32("gItemTrackerTheme", 0) == 0) { // One block tracker, original tracker style + BeginFloatingWindows("ItemTracker_Theme_0_Grouped"); + DrawFloatingInventory(Icon_Cells_Size, Icon_Spacing); + DrawFloatingEquipsQuestUpgradeStones(Icon_Cells_Size, Icon_Spacing); + DrawFloatingTokens(Icon_Cells_Size, Icon_Spacing); + DrawFloatingSongs(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + if (CVar_GetS32("gItemTrackerDisplayDungeonItems", 0)) { + BeginFloatingWindows("ItemTracker_Theme_0_Dungeons"); + DrawFloatingDungeons(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + } + + if (CVar_GetS32("gItemTrackerNotes", 0)) { + BeginFloatingWindows("ItemTracker_Theme_0_Notes"); + DrawFloatingNotes(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + } + } else if (CVar_GetS32("gItemTrackerTheme", 0) == 1) { // Per groups elements N.1 + BeginFloatingWindows("ItemTracker_Theme_1_Inventory"); + DrawFloatingInventory(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_1_Stuffs"); + DrawFloatingEquipsQuestUpgradeStones(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_1_Tokens"); + DrawFloatingTokens(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_1_Songs"); + DrawFloatingSongs(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + if (CVar_GetS32("gItemTrackerDisplayDungeonItems", 0)) { + BeginFloatingWindows("ItemTracker_Theme_1_Dungeons"); + DrawFloatingDungeons(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + } + + if (CVar_GetS32("gItemTrackerNotes", 0)) { + BeginFloatingWindows("ItemTracker_Theme_1_Notes"); + DrawFloatingNotes(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + } + } else if (CVar_GetS32("gItemTrackerTheme", 0) == 2) { // Per groups elements N.2 + BeginFloatingWindows("ItemTracker_Theme_2_Inventory"); + DrawFloatingInventory(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_2_Equips"); + DrawFloatingEquipments(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_2_Upgrade"); + DrawFloatingUpgrades(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_2_Quest"); + DrawFloatingQuest(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_2_Stones"); + DrawFloatingStones(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_2_Tokens"); + DrawFloatingTokens(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + BeginFloatingWindows("ItemTracker_Theme_2_Song"); + DrawFloatingSongs(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + + if (CVar_GetS32("gItemTrackerDisplayDungeonItems", 0)) { + BeginFloatingWindows("ItemTracker_Theme_2_Dungeons"); + DrawFloatingDungeons(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + } + + if (CVar_GetS32("gItemTrackerNotes", 0)) { + BeginFloatingWindows("ItemTracker_Theme_2_Notes"); + DrawFloatingNotes(Icon_Cells_Size, Icon_Spacing); + EndFloatingWindows(); + } + } + } +} + +void DrawItemTrackerOptions(bool& open) { + if (!open) { + CVar_SetS32("gItemTrackerSettingsEnabled", 0); + return; + } + + ImGui::SetNextWindowSize(ImVec2(240, 285), ImGuiCond_FirstUseEver); + + if (!ImGui::Begin("Item Tracker Settings", &open, ImGuiWindowFlags_NoFocusOnAppearing)) { + ImGui::End(); + return; + } + + 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", 25, 128, "", 32, + true); + SohImGui::EnhancementSliderInt("Icon margins : %dpx", "##ITEMTRACKERSPACING", "gRandoTrackIconSpacing", -5, 50, "", + 0, true); + // SohImGui::EnhancementSliderInt("X spacing : %dpx", "##ITEMTRACKERSPACINGX", "gRandoTrackIconSpacingX", 0, 256, + // ""); SohImGui::EnhancementSliderInt("Y Spacing : %dpx", "##ITEMTRACKERSPACINGY", "gRandoTrackIconSpacingY", 0, + // 255, ""); + + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Text("Chroma Key"); + auto flags = ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_NoLabel; + ImGui::ColorEdit4("Chroma Key Selection", (float*)&ChromaKeyBackground, flags); + + const char* ItemsTrackerTheme[3] = { "One Block", "Grouped style n.1", "Grouped style n.2" }; + ImGui::Text("Using theme :"); + SohImGui::EnhancementCombobox("gItemTrackerTheme", ItemsTrackerTheme, 3, 0); + SohImGui::EnhancementCheckbox("Edit mode HUD", "gItemTrackerHudEditMode"); + std::string ResetButtonName = "Reset \""; + ResetButtonName += ItemsTrackerTheme[CVar_GetS32("gItemTrackerTheme", 0)]; + ResetButtonName += "\" theme"; + if (ImGui::Button(ResetButtonName.c_str())) { + ImVec2 OriginPosition = { + ImGui::GetMainViewport()->GetWorkCenter().x - 100, + ImGui::GetMainViewport()->GetWorkCenter().y - 220, + }; + CVar_SetS32("gRandoTrackIconSize", 32); + CVar_SetS32("gRandoTrackIconSpacing", 0); + if (CVar_GetS32("gItemTrackerTheme", 0) == 0) { // One block tracker, original tracker style + ImVec2 Default_Pos_Wnd_0 = { OriginPosition.x, OriginPosition.y }; + ImGui::SetWindowPos("ItemTracker_Theme_0_Grouped", Default_Pos_Wnd_0); + ImVec2 Default_Pos_Wnd_1 = { OriginPosition.x, OriginPosition.y + 175}; + ImGui::SetWindowPos("ItemTracker_Theme_0_Dungeons", Default_Pos_Wnd_1); + ImVec2 Default_Pos_Wnd_2 = { OriginPosition.x + 100, OriginPosition.y}; + ImGui::SetWindowPos("ItemTracker_Theme_0_Notes", Default_Pos_Wnd_2); + } else if (CVar_GetS32("gItemTrackerTheme", 0) == 1) { // Per groups elements N.1 + ImVec2 Default_Pos_Wnd_0 = { OriginPosition.x, OriginPosition.y }; + ImGui::SetWindowPos("ItemTracker_Theme_1_Inventory", Default_Pos_Wnd_0); + ImVec2 Default_Pos_Wnd_1 = { OriginPosition.x, OriginPosition.y + 175 }; + ImGui::SetWindowPos("ItemTracker_Theme_1_Stuffs", Default_Pos_Wnd_1); + ImVec2 Default_Pos_Wnd_2 = { OriginPosition.x, OriginPosition.y + 340 }; + ImGui::SetWindowPos("ItemTracker_Theme_1_Tokens", Default_Pos_Wnd_2); + ImVec2 Default_Pos_Wnd_3 = { OriginPosition.x + 5, OriginPosition.y + 380 }; + ImGui::SetWindowPos("ItemTracker_Theme_1_Songs", Default_Pos_Wnd_3); + ImVec2 Default_Pos_Wnd_4 = { OriginPosition.x + 100, OriginPosition.y + 175}; + ImGui::SetWindowPos("ItemTracker_Theme_1_Dungeons", Default_Pos_Wnd_4); + ImVec2 Default_Pos_Wnd_5 = { OriginPosition.x - 100, OriginPosition.y}; + ImGui::SetWindowPos("ItemTracker_Theme_1_Notes", Default_Pos_Wnd_5); + } else if (CVar_GetS32("gItemTrackerTheme", 0) == 2) { // Per groups elements N.2 + ImVec2 Default_Pos_Wnd_0 = { OriginPosition.x, OriginPosition.y }; + ImGui::SetWindowPos("ItemTracker_Theme_2_Inventory", Default_Pos_Wnd_0); + ImVec2 Default_Pos_Wnd_1 = { OriginPosition.x, OriginPosition.y + 175 }; + ImGui::SetWindowPos("ItemTracker_Theme_2_Equips", Default_Pos_Wnd_1); + ImVec2 Default_Pos_Wnd_2 = { OriginPosition.x + 100, OriginPosition.y + 170 }; + ImGui::SetWindowPos("ItemTracker_Theme_2_Upgrade", Default_Pos_Wnd_2); + ImVec2 Default_Pos_Wnd_3 = { OriginPosition.x + 100, OriginPosition.y + 250 }; + ImGui::SetWindowPos("ItemTracker_Theme_2_Quest", Default_Pos_Wnd_3); + ImVec2 Default_Pos_Wnd_4 = { OriginPosition.x + 100, OriginPosition.y + 290 }; + ImGui::SetWindowPos("ItemTracker_Theme_2_Stones", Default_Pos_Wnd_4); + ImVec2 Default_Pos_Wnd_5 = { OriginPosition.x, OriginPosition.y + 330 }; + ImGui::SetWindowPos("ItemTracker_Theme_2_Tokens", Default_Pos_Wnd_5); + ImVec2 Default_Pos_Wnd_6 = { OriginPosition.x, OriginPosition.y + 368 }; + ImGui::SetWindowPos("ItemTracker_Theme_2_Song", Default_Pos_Wnd_6); + ImVec2 Default_Pos_Wnd_7 = { OriginPosition.x - 100, OriginPosition.y}; + ImGui::SetWindowPos("ItemTracker_Theme_2_Dungeons", Default_Pos_Wnd_7); + ImVec2 Default_Pos_Wnd_8 = { OriginPosition.x - 100, OriginPosition.y + 170}; + ImGui::SetWindowPos("ItemTracker_Theme_2_Notes", Default_Pos_Wnd_8); + } + } + SohImGui::EnhancementCheckbox("Alternative medallions display", "gItemTrackerMedallionsPlacement"); + SohImGui::Tooltip("Will display medallions into a placement that will be from the Quest Menu"); + + SohImGui::EnhancementCheckbox("Key Tracker", "gItemTrackerDisplayDungeonItems"); + + if (CVar_GetS32("gItemTrackerDisplayDungeonItems", 0)) { + SohImGui::EnhancementCheckbox("Map and Compass Tracker", "gItemTrackerDisplayMapsAndCompasses"); + } + + // SohImGui::EnhancementCheckbox("Personal notes space", "gItemTrackerNotes"); + // SohImGui::Tooltip("Adds a textbox under the item tracker to keep your own notes in"); + // TODO: FIX THE NOTES SPACE SIZE ON FLOATING WINDOW, DISABLED UNTIL FIXED + + ImGui::End(); +} + +void InitItemTracker() { + CVar_RegisterS32("gRandoTrackIconSize", 32); + SohImGui::AddWindow("Randomizer", "Item Tracker", DrawItemTracker); + SohImGui::AddWindow("Randomizer", "Item Tracker Settings", DrawItemTrackerOptions); } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index fa3ff4e88e..30a559fb7d 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -88,6 +88,8 @@ void SaveManager::LoadRandomizerVersion1() { for (int i = 0; i < ARRAY_COUNT(gSaveContext.ganonText); i++) { SaveManager::Instance->LoadData("gt" + std::to_string(i), gSaveContext.ganonText[i]); } + + SaveManager::Instance->LoadData("adultTradeItems", gSaveContext.adultTradeItems); } void SaveManager::SaveRandomizer() { @@ -130,6 +132,8 @@ void SaveManager::SaveRandomizer() { for (int i = 0; i < ARRAY_COUNT(gSaveContext.ganonText); i++) { SaveManager::Instance->SaveData("gt" + std::to_string(i), gSaveContext.ganonText[i]); } + + SaveManager::Instance->SaveData("adultTradeItems", gSaveContext.adultTradeItems); } void SaveManager::Init() { diff --git a/soh/src/code/z_game_over.c b/soh/src/code/z_game_over.c index 86ba7c6e14..bb4be8711c 100644 --- a/soh/src/code/z_game_over.c +++ b/soh/src/code/z_game_over.c @@ -33,19 +33,21 @@ void GameOver_Update(GlobalContext* globalCtx) { gSaveContext.eventInf[1] &= ~1; // search inventory for spoiling items and revert if necessary - for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { - if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) { - INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; + if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) { + for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { + if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) { + INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; - // search c buttons for the found spoiling item and revert if necessary - for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { - if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { - gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; - Interface_LoadItemIcon1(globalCtx, j); + // search c buttons for the found spoiling item and revert if necessary + for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { + if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { + gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + Interface_LoadItemIcon1(globalCtx, j); + } } } } - } + } // restore "temporary B" to the B Button if not a sword item if (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI && diff --git a/soh/src/code/z_kankyo.c b/soh/src/code/z_kankyo.c index 7fd9a7480f..140f5f8325 100644 --- a/soh/src/code/z_kankyo.c +++ b/soh/src/code/z_kankyo.c @@ -4,6 +4,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/gameplay_field_keep/gameplay_field_keep.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" typedef enum { /* 0 */ LENS_FLARE_CIRCLE0, @@ -2048,6 +2049,21 @@ void Environment_PlaySceneSequence(GlobalContext* globalCtx) { Audio_SetEnvReverb(globalCtx->roomCtx.curRoom.echo); } +bool HatchPocketEgg(GlobalContext* globalCtx) { + if (!gSaveContext.n64ddFlag) { + return Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO); + } + + if (!(gSaveContext.adultTradeItems & ADULT_TRADE_FLAG(ITEM_POCKET_EGG))) { + return 0; + } + + gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(ITEM_POCKET_EGG); + gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(ITEM_POCKET_CUCCO); + Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO); + return 1; +} + // updates bgm/sfx and other things as the day progresses void func_80075B44(GlobalContext* globalCtx) { switch (globalCtx->envCtx.unk_E0) { @@ -2101,7 +2117,7 @@ void func_80075B44(GlobalContext* globalCtx) { gSaveContext.dogIsLost = true; func_80078884(NA_SE_EV_CHICKEN_CRY_M); if ((Inventory_ReplaceItem(globalCtx, ITEM_WEIRD_EGG, ITEM_CHICKEN) || - Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO)) && + HatchPocketEgg(globalCtx)) && globalCtx->csCtx.state == 0 && !Player_InCsMode(globalCtx)) { Message_StartTextbox(globalCtx, 0x3066, NULL); } diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 24211c5907..a7f1a6c78c 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -3,6 +3,7 @@ #include "textures/parameter_static/parameter_static.h" #include "textures/do_action_static/do_action_static.h" #include "textures/icon_item_static/icon_item_static.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #ifdef _MSC_VER #include @@ -1750,29 +1751,6 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { } return ITEM_NONE; } else if (item == ITEM_KEY_SMALL) { - // Small key exceptions for rando. - if (gSaveContext.n64ddFlag) { - if (globalCtx->sceneNum == 10) { // ganon's tower -> ganon's castle - if (gSaveContext.inventory.dungeonKeys[13] < 0) { - gSaveContext.inventory.dungeonKeys[13] = 1; - return ITEM_NONE; - } else { - gSaveContext.inventory.dungeonKeys[13]++; - return ITEM_NONE; - } - } - - if (globalCtx->sceneNum == 92) { // Desert Colossus -> Spirit Temple. - if (gSaveContext.inventory.dungeonKeys[6] < 0) { - gSaveContext.inventory.dungeonKeys[6] = 1; - return ITEM_NONE; - } else { - gSaveContext.inventory.dungeonKeys[6]++; - return ITEM_NONE; - } - } - } - if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1; return ITEM_NONE; @@ -1780,6 +1758,100 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]++; return ITEM_NONE; } + } else if ( + (item >= ITEM_GERUDO_FORTRESS_SMALL_KEY && item <= ITEM_GANONS_CASTLE_SMALL_KEY) || + (item >= ITEM_FOREST_TEMPLE_BOSS_KEY && item <= ITEM_GANONS_CASTLE_BOSS_KEY) || + (item >= ITEM_DEKU_TREE_MAP && item <= ITEM_ICE_CAVERN_MAP) || + (item >= ITEM_DEKU_TREE_COMPASS && item <= ITEM_ICE_CAVERN_COMPASS) + ) { + int mapIndex = gSaveContext.mapIndex; + switch (item) { + case ITEM_DEKU_TREE_MAP: + case ITEM_DEKU_TREE_COMPASS: + mapIndex = SCENE_YDAN; + break; + case ITEM_DODONGOS_CAVERN_MAP: + case ITEM_DODONGOS_CAVERN_COMPASS: + mapIndex = SCENE_DDAN; + break; + case ITEM_JABU_JABUS_BELLY_MAP: + case ITEM_JABU_JABUS_BELLY_COMPASS: + mapIndex = SCENE_BDAN; + break; + case ITEM_FOREST_TEMPLE_MAP: + case ITEM_FOREST_TEMPLE_COMPASS: + case ITEM_FOREST_TEMPLE_SMALL_KEY: + case ITEM_FOREST_TEMPLE_BOSS_KEY: + mapIndex = SCENE_BMORI1; + break; + case ITEM_FIRE_TEMPLE_MAP: + case ITEM_FIRE_TEMPLE_COMPASS: + case ITEM_FIRE_TEMPLE_SMALL_KEY: + case ITEM_FIRE_TEMPLE_BOSS_KEY: + mapIndex = SCENE_HIDAN; + break; + case ITEM_WATER_TEMPLE_MAP: + case ITEM_WATER_TEMPLE_COMPASS: + case ITEM_WATER_TEMPLE_SMALL_KEY: + case ITEM_WATER_TEMPLE_BOSS_KEY: + mapIndex = SCENE_MIZUSIN; + break; + case ITEM_SPIRIT_TEMPLE_MAP: + case ITEM_SPIRIT_TEMPLE_COMPASS: + case ITEM_SPIRIT_TEMPLE_SMALL_KEY: + case ITEM_SPIRIT_TEMPLE_BOSS_KEY: + mapIndex = SCENE_JYASINZOU; + break; + case ITEM_SHADOW_TEMPLE_MAP: + case ITEM_SHADOW_TEMPLE_COMPASS: + case ITEM_SHADOW_TEMPLE_SMALL_KEY: + case ITEM_SHADOW_TEMPLE_BOSS_KEY: + mapIndex = SCENE_HAKADAN; + break; + case ITEM_BOTTOM_OF_THE_WELL_MAP: + case ITEM_BOTTOM_OF_THE_WELL_COMPASS: + case ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY: + mapIndex = SCENE_HAKADANCH; + break; + case ITEM_ICE_CAVERN_MAP: + case ITEM_ICE_CAVERN_COMPASS: + mapIndex = SCENE_ICE_DOUKUTO; + break; + case ITEM_GANONS_CASTLE_BOSS_KEY: + mapIndex = SCENE_GANON; + break; + case ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + mapIndex = SCENE_MEN; + break; + case ITEM_GERUDO_FORTRESS_SMALL_KEY: + mapIndex = SCENE_GERUDOWAY; + break; + case ITEM_GANONS_CASTLE_SMALL_KEY: + mapIndex = SCENE_GANONTIKA; + break; + } + + if ((item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY)) { + if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { + gSaveContext.inventory.dungeonKeys[mapIndex] = 1; + return ITEM_NONE; + } else { + gSaveContext.inventory.dungeonKeys[mapIndex]++; + return ITEM_NONE; + } + } else { + int bitmask; + if ((item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP)) { + bitmask = gBitFlags[2]; + } else if ((item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS)) { + bitmask = gBitFlags[1]; + } else { + bitmask = gBitFlags[0]; + } + + gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask; + return ITEM_NONE; + } } else if ((item == ITEM_QUIVER_30) || (item == ITEM_BOW)) { if (CUR_UPG_VALUE(UPG_QUIVER) == 0) { Inventory_ChangeUpgrade(UPG_QUIVER, 1); @@ -2164,6 +2236,10 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { gSaveContext.itemGetInf[1] |= 0x8000; } + if (item >= ITEM_POCKET_EGG) { + gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item); + } + temp = INV_CONTENT(item); INV_CONTENT(item) = item; @@ -2289,6 +2365,13 @@ u8 Item_CheckObtainability(u8 item) { } else { return ITEM_NONE; } + } else if ( + (item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY) || + (item >= ITEM_FOREST_TEMPLE_BOSS_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY) || + (item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP) || + (item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS) + ) { + return ITEM_NONE; } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { return ITEM_NONE; } else if (item == ITEM_KEY_SMALL) { diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 8aa46ceb43..65eb588121 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -416,6 +416,95 @@ void GiveLinkDungeonReward(GetItemID getItemId) { } } +void GiveLinkDungeonItem(GetItemID getItemId) { + int mapIndex; + + switch (getItemId) { + case GI_DEKU_TREE_MAP: + case GI_DEKU_TREE_COMPASS: + mapIndex = SCENE_YDAN; + break; + case GI_DODONGOS_CAVERN_MAP: + case GI_DODONGOS_CAVERN_COMPASS: + mapIndex = SCENE_DDAN; + break; + case GI_JABU_JABUS_BELLY_MAP: + case GI_JABU_JABUS_BELLY_COMPASS: + mapIndex = SCENE_BDAN; + break; + case GI_FOREST_TEMPLE_MAP: + case GI_FOREST_TEMPLE_COMPASS: + case GI_FOREST_TEMPLE_SMALL_KEY: + case GI_FOREST_TEMPLE_BOSS_KEY: + mapIndex = SCENE_BMORI1; + break; + case GI_FIRE_TEMPLE_MAP: + case GI_FIRE_TEMPLE_COMPASS: + case GI_FIRE_TEMPLE_SMALL_KEY: + case GI_FIRE_TEMPLE_BOSS_KEY: + mapIndex = SCENE_HIDAN; + break; + case GI_WATER_TEMPLE_MAP: + case GI_WATER_TEMPLE_COMPASS: + case GI_WATER_TEMPLE_SMALL_KEY: + case GI_WATER_TEMPLE_BOSS_KEY: + mapIndex = SCENE_MIZUSIN; + break; + case GI_SPIRIT_TEMPLE_MAP: + case GI_SPIRIT_TEMPLE_COMPASS: + case GI_SPIRIT_TEMPLE_SMALL_KEY: + case GI_SPIRIT_TEMPLE_BOSS_KEY: + mapIndex = SCENE_JYASINZOU; + break; + case GI_SHADOW_TEMPLE_MAP: + case GI_SHADOW_TEMPLE_COMPASS: + case GI_SHADOW_TEMPLE_SMALL_KEY: + case GI_SHADOW_TEMPLE_BOSS_KEY: + mapIndex = SCENE_HAKADAN; + break; + case GI_BOTTOM_OF_THE_WELL_MAP: + case GI_BOTTOM_OF_THE_WELL_COMPASS: + case GI_BOTTOM_OF_THE_WELL_SMALL_KEY: + mapIndex = SCENE_HAKADANCH; + break; + case GI_ICE_CAVERN_MAP: + case GI_ICE_CAVERN_COMPASS: + mapIndex = SCENE_ICE_DOUKUTO; + break; + case GI_GANONS_CASTLE_BOSS_KEY: + mapIndex = SCENE_GANON; + break; + case GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + mapIndex = SCENE_MEN; + break; + case GI_GERUDO_FORTRESS_SMALL_KEY: + mapIndex = SCENE_GERUDOWAY; + break; + case GI_GANONS_CASTLE_SMALL_KEY: + mapIndex = SCENE_GANONTIKA; + break; + } + + if ((getItemId >= GI_GERUDO_FORTRESS_SMALL_KEY) && (getItemId <= GI_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 >= GI_DEKU_TREE_MAP) && (getItemId <= GI_ICE_CAVERN_MAP)) { + bitmask = gBitFlags[2]; + } else if ((getItemId >= GI_DEKU_TREE_COMPASS) && (getItemId <= GI_ICE_CAVERN_COMPASS)) { + bitmask = gBitFlags[1]; + } else { + bitmask = gBitFlags[0]; + } + + gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask; + } +} + void GiveLinksPocketMedallion() { GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LINKS_POCKET, RG_NONE); @@ -563,13 +652,15 @@ void Sram_OpenSave() { gSaveContext.equips.equipment |= 2; } - for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) { - INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; + if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) { + for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) { + INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; - for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { - if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { - gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { + if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { + gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + } } } } @@ -687,11 +778,12 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; } - if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES)) { + // "Start with" == 0 for Maps and Compasses + if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == 0) { uint32_t mapBitMask = 1 << 1; uint32_t compassBitMask = 1 << 2; uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask; - for(int scene = 0; scene <= 9; scene++) { + for(int scene = SCENE_YDAN; scene <= SCENE_ICE_DOUKUTO; scene++) { gSaveContext.inventory.dungeonItems[scene] |= startingDungeonItemsBitMask; } } @@ -788,6 +880,13 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { GiveLinkMagic(giid); } else if (giid == GI_DOUBLE_DEFENSE) { GiveLinkDoubleDefense(); + } else if ( + (giid >= GI_GERUDO_FORTRESS_SMALL_KEY && giid <= GI_GANONS_CASTLE_SMALL_KEY) || + (giid >= GI_FOREST_TEMPLE_BOSS_KEY && giid <= GI_GANONS_CASTLE_BOSS_KEY) || + (giid >= GI_DEKU_TREE_MAP && giid <= GI_ICE_CAVERN_MAP) || + (giid >= GI_DEKU_TREE_COMPASS && giid <= GI_ICE_CAVERN_COMPASS) + ) { + GiveLinkDungeonItem(giid); } else { s32 iid = Randomizer_GetItemIDFromGetItemID(giid); if (iid != -1) INV_CONTENT(iid) = iid; @@ -814,9 +913,31 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { GiveLinkRupees(9001); } - // For Ganon's boss key "Start With" is 0 - if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 0) { - gSaveContext.inventory.dungeonItems[10] |= 1; + // "Start with" == 0 for Keysanity + if(Randomizer_GetSettingValue(RSK_KEYSANITY) == 0) { + // TODO: If master quest there are different key counts + gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = 5; // Forest + gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = 8; // Fire + gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] = 6; // Water + gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 5; // Spirit + gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] = 5; // Shadow + gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] = 2; // BotW + gSaveContext.inventory.dungeonKeys[SCENE_MEN] = 9; // GTG + gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = 2; // Ganon + } + + // "Start with" == 0 for Boss Kesanity + if(Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == 0) { + gSaveContext.inventory.dungeonItems[SCENE_BMORI1] |= 1; // Forest + gSaveContext.inventory.dungeonItems[SCENE_HIDAN] |= 1; // Fire + gSaveContext.inventory.dungeonItems[SCENE_MIZUSIN] |= 1; // Water + gSaveContext.inventory.dungeonItems[SCENE_JYASINZOU] |= 1; // Spirit + gSaveContext.inventory.dungeonItems[SCENE_HAKADAN] |= 1; // Shadow + } + + // "Start with" == 2 for Ganon's Boss Key + if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 2) { + gSaveContext.inventory.dungeonItems[SCENE_GANON] |= 1; } HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT)); @@ -878,6 +999,21 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { GiveLinkGerudoCard(); } } + + // shuffle adult trade quest + if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) { + gSaveContext.adultTradeItems = 0; + } + + // complete mask quest + if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) { + gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask + gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask + gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask + gSaveContext.itemGetInf[3] |= 0x800; // bunny hood related + gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth + gSaveContext.eventChkInf[8] |= 0x8000; // sold all masks + } } Save_SaveFile(); diff --git a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c index 14e193f36e..97e58b30a2 100644 --- a/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c +++ b/soh/src/overlays/actors/ovl_En_Ds/z_en_ds.c @@ -6,6 +6,7 @@ #include "z_en_ds.h" #include "objects/object_ds/object_ds.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -91,7 +92,12 @@ void EnDs_GiveOddPotion(EnDs* this, GlobalContext* globalCtx) { this->actionFunc = EnDs_DisplayOddPotionText; gSaveContext.timer2State = 0; } else { - func_8002F434(&this->actor, globalCtx, GI_ODD_POTION, 10000.0f, 50.0f); + u32 itemId = GI_ODD_POTION; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_MUSHROOM); + } + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f); } } @@ -99,7 +105,12 @@ void EnDs_TalkAfterBrewOddPotion(EnDs* this, GlobalContext* globalCtx) { if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(globalCtx)) { Message_CloseTextbox(globalCtx); this->actionFunc = EnDs_GiveOddPotion; - func_8002F434(&this->actor, globalCtx, GI_ODD_POTION, 10000.0f, 50.0f); + u32 itemId = GI_ODD_POTION; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_ODD_MUSHROOM, GI_ODD_POTION); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_MUSHROOM); + } + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f); } } @@ -120,7 +131,7 @@ void EnDs_BrewOddPotion2(EnDs* this, GlobalContext* globalCtx) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion3; - this->brewTimer = 60; + this->brewTimer = gSaveContext.n64ddFlag ? 0 : 60; Flags_UnsetSwitch(globalCtx, 0x3F); } } @@ -130,7 +141,7 @@ void EnDs_BrewOddPotion1(EnDs* this, GlobalContext* globalCtx) { this->brewTimer -= 1; } else { this->actionFunc = EnDs_BrewOddPotion2; - this->brewTimer = 20; + this->brewTimer = gSaveContext.n64ddFlag ? 0 : 20; } Math_StepToF(&this->unk_1E4, 1.0f, 0.01f); @@ -144,7 +155,7 @@ void EnDs_OfferOddPotion(EnDs* this, GlobalContext* globalCtx) { switch (globalCtx->msgCtx.choiceIndex) { case 0: // yes this->actionFunc = EnDs_BrewOddPotion1; - this->brewTimer = 60; + this->brewTimer = gSaveContext.n64ddFlag ? 0 : 60; Flags_SetSwitch(globalCtx, 0x3F); globalCtx->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index e1179fe1b1..c510902210 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -3,6 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_oF1d_map/object_oF1d_map.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5) @@ -961,9 +962,17 @@ void EnGo_GetItem(EnGo* this, GlobalContext* globalCtx) { } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { getItemId = GI_CLAIM_CHECK; + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_EYEDROPS); + } } if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) { getItemId = GI_PRESCRIPTION; + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SWORD_BROKEN); + } } } diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 22c19f5f09..97a6fd3a82 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -3,6 +3,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_oF1d_map/object_oF1d_map.h" #include "soh/frame_interpolation.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5) @@ -652,7 +653,12 @@ s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { if (Message_ShouldAdvance(globalCtx)) { if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) { if (globalCtx->msgCtx.choiceIndex == 0) { - EnGo2_GetItem(this, globalCtx, GI_PRESCRIPTION); + u32 getItemId = GI_PRESCRIPTION; + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_BROKEN_SWORD, GI_PRESCRIPTION); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SWORD_BROKEN); + } + EnGo2_GetItem(this, globalCtx, getItemId); this->actionFunc = EnGo2_SetupGetItem; return 2; } @@ -1847,12 +1853,14 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) { this->actor.flags &= ~ACTOR_FLAG_0; this->actor.shape.rot.y += 0x5B0; this->unk_26E = 1; - this->animTimer = this->skelAnime.endFrame + 60.0f + 60.0f; // eyeDrops animation timer + this->animTimer = gSaveContext.n64ddFlag ? 0 : (this->skelAnime.endFrame + 60.0f + 60.0f); // eyeDrops animation timer this->eyeMouthTexState = 2; this->unk_20C = 0; this->goronState++; func_800F483C(0x28, 5); - OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM); + if (!gSaveContext.n64ddFlag) { + OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM); + } break; case 1: if (DECR(this->animTimer)) { @@ -1879,7 +1887,12 @@ void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) { this->unk_26E = 2; this->skelAnime.playSpeed = 0.0f; this->skelAnime.curFrame = this->skelAnime.endFrame; - EnGo2_GetItem(this, globalCtx, GI_CLAIM_CHECK); + u32 getItemId = GI_CLAIM_CHECK; + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_EYEDROPS, GI_CLAIM_CHECK); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_EYEDROPS); + } + EnGo2_GetItem(this, globalCtx, getItemId); this->actionFunc = EnGo2_SetupGetItem; this->goronState = 0; } diff --git a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c index efdbbdef8d..3fe2c98516 100644 --- a/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c +++ b/soh/src/overlays/actors/ovl_En_Hs/z_en_hs.c @@ -7,6 +7,7 @@ #include "z_en_hs.h" #include "vt.h" #include "objects/object_hs/object_hs.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -78,7 +79,14 @@ void EnHs_Init(Actor* thisx, GlobalContext* globalCtx) { // "chicken shop (adult era)" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコの店(大人の時) \n" VT_RST); func_80A6E3A0(this, func_80A6E9AC); - if (gSaveContext.itemGetInf[3] & 1) { + bool shouldDespawn; + bool tradedMushroom = gSaveContext.itemGetInf[3] & 1; + if (gSaveContext.n64ddFlag) { + shouldDespawn = tradedMushroom && !(gSaveContext.adultTradeItems & ADULT_TRADE_FLAG(ITEM_COJIRO)); + } else { + shouldDespawn = tradedMushroom; + } + if (shouldDespawn) { // "chicken shop closed" osSyncPrintf(VT_FGCOL(CYAN) " ヒヨコ屋閉店 \n" VT_RST); Actor_Kill(&this->actor); @@ -127,7 +135,9 @@ void func_80A6E5EC(EnHs* this, GlobalContext* globalCtx) { void func_80A6E630(EnHs* this, GlobalContext* globalCtx) { if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) { - func_80088AA0(180); + if (!gSaveContext.n64ddFlag) { + func_80088AA0(180); + } func_80A6E3A0(this, func_80A6E6B0); gSaveContext.eventInf[1] &= ~1; } @@ -156,7 +166,12 @@ void func_80A6E740(EnHs* this, GlobalContext* globalCtx) { this->actor.parent = NULL; func_80A6E3A0(this, func_80A6E630); } else { - func_8002F434(&this->actor, globalCtx, GI_ODD_MUSHROOM, 10000.0f, 50.0f); + s32 itemId = GI_ODD_MUSHROOM; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_COJIRO); + } + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f); } this->unk_2A8 |= 1; @@ -167,7 +182,12 @@ void func_80A6E7BC(EnHs* this, GlobalContext* globalCtx) { switch (globalCtx->msgCtx.choiceIndex) { case 0: func_80A6E3A0(this, func_80A6E740); - func_8002F434(&this->actor, globalCtx, GI_ODD_MUSHROOM, 10000.0f, 50.0f); + s32 itemId = GI_ODD_MUSHROOM; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_COJIRO, GI_ODD_MUSHROOM); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_COJIRO); + } + func_8002F434(&this->actor, globalCtx, itemId, 10000.0f, 50.0f); break; case 1: Message_ContinueTextbox(globalCtx, 0x10B4); diff --git a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c index 50dc8d1d99..4b9bc1f2b3 100644 --- a/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c +++ b/soh/src/overlays/actors/ovl_En_Ko/z_en_ko.c @@ -10,6 +10,7 @@ #include "objects/object_km1/object_km1.h" #include "objects/object_kw1/object_kw1.h" #include "vt.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4) @@ -1216,7 +1217,12 @@ void func_80A99504(EnKo* this, GlobalContext* globalCtx) { this->actor.parent = NULL; this->actionFunc = func_80A99560; } else { - func_8002F434(&this->actor, globalCtx, GI_SAW, 120.0f, 10.0f); + s32 itemId = GI_SAW; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_LW_TRADE_ODD_POTION, GI_SAW); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_ODD_POTION); + } + func_8002F434(&this->actor, globalCtx, itemId, 120.0f, 10.0f); } } diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index cda6e476df..25bc987abb 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -6,6 +6,7 @@ #include "z_en_kz.h" #include "objects/object_kz/object_kz.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -465,6 +466,7 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) { if (gSaveContext.n64ddFlag) { if (this->isTrading) { getItemId = Randomizer_GetItemIdFromKnownCheck(RC_ZD_TRADE_PRESCRIPTION, GI_FROG); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_PRESCRIPTION); Flags_SetTreasure(globalCtx, 0x1F); } else { getItemId = Randomizer_GetItemIdFromKnownCheck(RC_ZD_KING_ZORA_THAWED, GI_TUNIC_ZORA); @@ -480,7 +482,7 @@ void EnKz_SetupGetItem(EnKz* this, GlobalContext* globalCtx) { void EnKz_StartTimer(EnKz* this, GlobalContext* globalCtx) { if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_FROG && !gSaveContext.n64ddFlag) { func_80088AA0(180); // start timer2 with 3 minutes gSaveContext.eventInf[1] &= ~1; } diff --git a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c index f42e095223..dd853ac06d 100644 --- a/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c +++ b/soh/src/overlays/actors/ovl_En_Mk/z_en_mk.c @@ -6,6 +6,7 @@ #include "z_en_mk.h" #include "objects/object_mk/object_mk.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4) @@ -93,17 +94,29 @@ void func_80AACA94(EnMk* this, GlobalContext* globalCtx) { if (Actor_HasParent(&this->actor, globalCtx) != 0) { this->actor.parent = NULL; this->actionFunc = func_80AACA40; - func_80088AA0(240); - gSaveContext.eventInf[1] &= ~1; + if (!gSaveContext.n64ddFlag) { + func_80088AA0(240); + gSaveContext.eventInf[1] &= ~1; + } } else { - func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f); + s32 getItemID = GI_EYEDROPS; + if (gSaveContext.n64ddFlag) { + getItemID = Randomizer_GetItemIdFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_FROG); + } + func_8002F434(&this->actor, globalCtx, getItemID, 10000.0f, 50.0f); } } void func_80AACB14(EnMk* this, GlobalContext* globalCtx) { if (Actor_TextboxIsClosing(&this->actor, globalCtx)) { this->actionFunc = func_80AACA94; - func_8002F434(&this->actor, globalCtx, GI_EYEDROPS, 10000.0f, 50.0f); + s32 getItemID = GI_EYEDROPS; + if (gSaveContext.n64ddFlag) { + getItemID = Randomizer_GetItemIdFromKnownCheck(RC_LH_TRADE_FROG, GI_EYEDROPS); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_FROG); + } + func_8002F434(&this->actor, globalCtx, getItemID, 10000.0f, 50.0f); } } @@ -129,7 +142,7 @@ void func_80AACC04(EnMk* this, GlobalContext* globalCtx) { if (this->timer > 0) { this->timer--; } else { - this->timer = 16; + this->timer = gSaveContext.n64ddFlag ? 0 : 16; this->actionFunc = func_80AACBAC; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); @@ -142,7 +155,7 @@ void func_80AACCA0(EnMk* this, GlobalContext* globalCtx) { this->timer--; this->actor.shape.rot.y += 0x800; } else { - this->timer = 120; + this->timer = gSaveContext.n64ddFlag ? 0 : 120; this->actionFunc = func_80AACC04; Animation_Change(&this->skelAnime, &object_mk_Anim_000724, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000724), ANIMMODE_LOOP, -4.0f); @@ -158,7 +171,7 @@ void func_80AACD48(EnMk* this, GlobalContext* globalCtx) { this->actionFunc = func_80AACCA0; globalCtx->msgCtx.msgMode = MSGMODE_PAUSED; player->exchangeItemId = EXCH_ITEM_NONE; - this->timer = 16; + this->timer = gSaveContext.n64ddFlag ? 0 : 16; Animation_Change(&this->skelAnime, &object_mk_Anim_000D88, 1.0f, 0.0f, Animation_GetLastFrame(&object_mk_Anim_000D88), ANIMMODE_LOOP, -4.0f); this->flags &= ~2; diff --git a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c index c31f2b923f..23584cc196 100644 --- a/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c +++ b/soh/src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.c @@ -3,6 +3,7 @@ #include "objects/object_os_anime/object_os_anime.h" #include "overlays/actors/ovl_En_Niw/z_en_niw.h" #include "vt.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4) @@ -454,8 +455,13 @@ void func_80ABAC00(EnNiwLady* this, GlobalContext* globalCtx) { if (LINK_IS_ADULT) { getItemId = !(gSaveContext.itemGetInf[2] & 0x1000) ? GI_POCKET_EGG : GI_COJIRO; - if (gSaveContext.n64ddFlag && getItemId == GI_POCKET_EGG) { - getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); + if (gSaveContext.n64ddFlag) { + if (getItemId == GI_POCKET_EGG) { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_ANJU_AS_ADULT, GI_POCKET_EGG); + } else { + getItemId = Randomizer_GetItemIdFromKnownCheck(RC_KAK_TRADE_POCKET_CUCCO, GI_COJIRO); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_POCKET_CUCCO); + } } } func_8002F434(&this->actor, globalCtx, getItemId, 200.0f, 100.0f); diff --git a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c index 425e07421d..c6ca4cad71 100644 --- a/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c +++ b/soh/src/overlays/actors/ovl_En_Toryo/z_en_toryo.c @@ -6,6 +6,7 @@ #include "z_en_toryo.h" #include "objects/object_toryo/object_toryo.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3) @@ -313,7 +314,12 @@ void func_80B20768(EnToryo* this, GlobalContext* globalCtx) { this->actor.parent = NULL; this->unk_1E4 = 5; } else { - func_8002F434(&this->actor, globalCtx, GI_SWORD_BROKEN, 100.0f, 10.0f); + s32 itemId = GI_SWORD_BROKEN; + if (gSaveContext.n64ddFlag) { + itemId = Randomizer_GetItemIdFromKnownCheck(RC_GV_TRADE_SAW, GI_SWORD_BROKEN); + Randomizer_ConsumeAdultTradeItem(globalCtx, ITEM_SAW); + } + func_8002F434(&this->actor, globalCtx, itemId, 100.0f, 10.0f); } return; } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index eac49315db..cf682a45c1 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -656,6 +656,45 @@ GetItemEntry sGetItemTable[] = { GET_ITEM(ITEM_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + + GET_ITEM(ITEM_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + + GET_ITEM(ITEM_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + + GET_ITEM(ITEM_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM_NONE, GET_ITEM_NONE, }; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 675fc11917..fe57289fac 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -1,5 +1,7 @@ #include "z_kaleido_scope.h" #include "textures/parameter_static/parameter_static.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" +#include "soh/Enhancements/randomizer/randomizerTypes.h" u8 gAmmoItems[] = { ITEM_STICK, ITEM_NUT, ITEM_BOMB, ITEM_BOW, ITEM_NONE, ITEM_NONE, ITEM_SLINGSHOT, ITEM_NONE, @@ -10,6 +12,7 @@ static s16 sEquipState = 0; static s16 sEquipAnimTimer = 0; static s16 sEquipMoveTimer = 10; bool gSelectingMask; +bool gSelectingAdultTrade; static s16 sAmmoVtxOffset[] = { 0, 2, 4, 6, 99, 99, 8, 99, 10, 99, 99, 99, 99, 99, 12, @@ -109,7 +112,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { pauseCtx->nameColorSet = 0; if ((pauseCtx->state == 6) && (pauseCtx->unk_1E4 == 0) && (pauseCtx->pageIndex == PAUSE_ITEM)) { - moveCursorResult = 0 || gSelectingMask; + moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade; oldCursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM]; cursorItem = pauseCtx->cursorItem[PAUSE_ITEM]; @@ -283,7 +286,7 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { if (pauseCtx->cursorSpecialPos == 0) { if (cursorItem != PAUSE_ITEM_NONE) { if ((ABS(pauseCtx->stickRelY) > 30) || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DDOWN | BTN_DUP))) { - moveCursorResult = 0 || gSelectingMask; + moveCursorResult = 0 || gSelectingMask || gSelectingAdultTrade; cursorPoint = pauseCtx->cursorPoint[PAUSE_ITEM]; cursorY = pauseCtx->cursorY[PAUSE_ITEM]; @@ -385,6 +388,24 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) { } gSelectingMask = cursorSlot == SLOT_TRADE_CHILD; } + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE) && + cursorSlot == SLOT_TRADE_ADULT && CHECK_BTN_ALL(input->press.button, BTN_A)) { + Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + gSelectingAdultTrade = !gSelectingAdultTrade; + } + if (gSelectingAdultTrade) { + pauseCtx->cursorColorSet = 8; + if (((pauseCtx->stickRelX > 30 || pauseCtx->stickRelY > 30) || + dpad && CHECK_BTN_ANY(input->press.button, BTN_DRIGHT | BTN_DUP))) { + Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + Inventory_ReplaceItem(globalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetNextAdultTradeItem()); + } else if (((pauseCtx->stickRelX < -30 || pauseCtx->stickRelY < -30) || + dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DDOWN))) { + Audio_PlaySoundGeneral(NA_SE_SY_CURSOR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + Inventory_ReplaceItem(globalCtx, INV_CONTENT(ITEM_TRADE_ADULT), Randomizer_GetPrevAdultTradeItem()); + } + gSelectingAdultTrade = cursorSlot == SLOT_TRADE_ADULT; + } u16 buttonsToCheck = BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT; if (CVar_GetS32("gDpadEquips", 0) && (!CVar_GetS32("gDpadPauseName", 0) || CHECK_BTN_ALL(input->cur.button, BTN_CUP))) { buttonsToCheck |= BTN_DUP | BTN_DDOWN | BTN_DLEFT | BTN_DRIGHT; @@ -510,6 +531,7 @@ void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s Input* input = &globalCtx->state.input[0]; PauseContext* pauseCtx = &globalCtx->pauseCtx; gSelectingMask = false; + gSelectingAdultTrade = false; if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) { pauseCtx->equipTargetCBtn = 0;