Merge branch 'develop' into aManchipelago
This commit is contained in:
@@ -1,17 +1,32 @@
|
||||
#include "mod_menu.h"
|
||||
#include <ship/utils/StringHelper.h>
|
||||
#include <libultraship/classes.h>
|
||||
#include "soh/SohGui/SohGui.hpp"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/resource/type/Skeleton.h"
|
||||
#include <map>
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
|
||||
#include <libultraship/classes.h>
|
||||
#include <ship/utils/StringHelper.h>
|
||||
|
||||
#include "mod_menu.h"
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include "soh/resource/type/Skeleton.h"
|
||||
#include "soh/SohGui/MenuTypes.h"
|
||||
#include "soh/SohGui/SohMenu.h"
|
||||
#include "soh/SohGui/SohGui.hpp"
|
||||
|
||||
std::vector<std::string> enabledModFiles;
|
||||
std::vector<std::string> disabledModFiles;
|
||||
std::vector<std::string> unsupportedFiles;
|
||||
std::map<std::string, std::filesystem::path> filePaths;
|
||||
static int dragSourceIndex = -1;
|
||||
static int dragTargetIndex = -1;
|
||||
|
||||
#define CVAR_ENABLED_MODS_NAME CVAR_GENERAL("EnabledMods")
|
||||
namespace SohGui {
|
||||
extern std::shared_ptr<SohMenu> mSohMenu;
|
||||
}
|
||||
|
||||
static WidgetInfo enableModsWidget;
|
||||
static WidgetInfo tabHotkeyWidget;
|
||||
|
||||
#define CVAR_ENABLED_MODS_NAME CVAR_SETTING("EnabledMods")
|
||||
#define CVAR_ENABLED_MODS_DEFAULT ""
|
||||
#define CVAR_ENABLED_MODS_VALUE CVarGetString(CVAR_ENABLED_MODS_NAME, CVAR_ENABLED_MODS_DEFAULT)
|
||||
|
||||
@@ -42,6 +57,42 @@ void SetEnabledModsCVarValue() {
|
||||
CVarSetString(CVAR_ENABLED_MODS_NAME, s.c_str());
|
||||
}
|
||||
|
||||
void AfterModChange() {
|
||||
// disabled mods are always sorted
|
||||
std::sort(disabledModFiles.begin(), disabledModFiles.end(), [](const std::string& a, const std::string& b) {
|
||||
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(),
|
||||
[](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); });
|
||||
});
|
||||
}
|
||||
|
||||
void ModsPostDragAndDrop() {
|
||||
if (dragTargetIndex != -1) {
|
||||
std::string file = enabledModFiles[dragSourceIndex];
|
||||
enabledModFiles.erase(enabledModFiles.begin() + dragSourceIndex);
|
||||
enabledModFiles.insert(enabledModFiles.begin() + dragTargetIndex, file);
|
||||
dragTargetIndex = dragSourceIndex = -1;
|
||||
AfterModChange();
|
||||
}
|
||||
}
|
||||
|
||||
void ModsHandleDragAndDrop(std::vector<std::string>& objectList, int targetIndex, const std::string& itemName,
|
||||
ImGuiDragDropFlags flags = ImGuiDragDropFlags_SourceAllowNullID) {
|
||||
if (ImGui::BeginDragDropSource(flags)) {
|
||||
ImGui::SetDragDropPayload("DragMove", &targetIndex, sizeof(uint32_t));
|
||||
ImGui::Text("Move %s", itemName.c_str());
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
if (ImGui::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DragMove")) {
|
||||
IM_ASSERT(payload->DataSize == sizeof(uint32_t));
|
||||
dragSourceIndex = *(const int*)payload->Data;
|
||||
dragTargetIndex = targetIndex;
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> GetEnabledModsFromCVar() {
|
||||
std::string enabledModsCVarValue = CVAR_ENABLED_MODS_VALUE;
|
||||
return StringHelper::Split(enabledModsCVarValue, SEPARATOR);
|
||||
@@ -55,58 +106,71 @@ std::shared_ptr<Ship::ArchiveManager> GetArchiveManager() {
|
||||
return Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager();
|
||||
}
|
||||
|
||||
void UpdateModFiles(bool init = false) {
|
||||
if (init) {
|
||||
bool IsValidExtension(std::string extension) {
|
||||
if (
|
||||
#ifdef INCLUDE_MPQ_SUPPORT
|
||||
// .mpq doesn't make sense to support because all tools to make such mods output OTR
|
||||
StringHelper::IEquals(extension, ".otr") /*|| StringHelper::IEquals(extension, ".mpq")*/ ||
|
||||
#endif
|
||||
// .zip needs to be excluded because mods are most often distributed in zip archives
|
||||
// and thus could contain .otr/o2r files
|
||||
StringHelper::IEquals(extension, ".o2r") /*|| StringHelper::IEquals(extension, ".zip")*/) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UpdateModFiles(bool init = false, bool reset = false) {
|
||||
if (init || reset) {
|
||||
enabledModFiles.clear();
|
||||
enabledModFiles = GetEnabledModsFromCVar();
|
||||
}
|
||||
disabledModFiles.clear();
|
||||
std::vector<std::string> enabledMods = GetEnabledModsFromCVar();
|
||||
unsupportedFiles.clear();
|
||||
filePaths.clear();
|
||||
std::string modsPath = Ship::Context::LocateFileAcrossAppDirs("mods", appShortName);
|
||||
bool changed = false;
|
||||
if (modsPath.length() > 0 && std::filesystem::exists(modsPath)) {
|
||||
std::vector<std::filesystem::path> enabledFiles;
|
||||
if (std::filesystem::is_directory(modsPath)) {
|
||||
for (const std::filesystem::directory_entry& p : std::filesystem::recursive_directory_iterator(
|
||||
modsPath, std::filesystem::directory_options::follow_directory_symlink)) {
|
||||
std::string extension = p.path().extension().string();
|
||||
if (
|
||||
#ifndef EXCLUDE_MPQ_SUPPORT
|
||||
StringHelper::IEquals(extension, ".otr") || StringHelper::IEquals(extension, ".mpq") ||
|
||||
#endif
|
||||
StringHelper::IEquals(extension, ".o2r") || StringHelper::IEquals(extension, ".zip")) {
|
||||
std::string path = p.path().generic_string();
|
||||
bool shouldBeEnabled = std::find(enabledMods.begin(), enabledMods.end(), path) != enabledMods.end();
|
||||
|
||||
if (shouldBeEnabled) {
|
||||
if (init) {
|
||||
enabledModFiles.push_back(path);
|
||||
GetArchiveManager()->AddArchive(path);
|
||||
}
|
||||
if (p.is_directory()) {
|
||||
continue;
|
||||
}
|
||||
std::string filename =
|
||||
p.path().filename().generic_string().substr(0, p.path().filename().generic_string().rfind("."));
|
||||
std::string extension = p.path().extension().generic_string();
|
||||
if (!IsValidExtension(extension)) {
|
||||
continue;
|
||||
}
|
||||
bool enabled =
|
||||
std::find(enabledModFiles.begin(), enabledModFiles.end(), filename) != enabledModFiles.end();
|
||||
if (!enabled) {
|
||||
enabledModFiles.push_back(filename);
|
||||
changed = true;
|
||||
}
|
||||
filePaths.emplace(filename, p.path());
|
||||
}
|
||||
if (init) {
|
||||
std::vector<std::string> enabledTemp(enabledModFiles);
|
||||
for (std::string mod : enabledTemp) {
|
||||
if (filePaths.contains(mod)) {
|
||||
GetArchiveManager()->AddArchive(filePaths.at(mod).generic_string());
|
||||
} else {
|
||||
disabledModFiles.push_back(path);
|
||||
enabledModFiles.erase(std::find(enabledModFiles.begin(), enabledModFiles.end(), mod));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
SetEnabledModsCVarValue();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void gfx_texture_cache_clear();
|
||||
|
||||
void AfterModChange() {
|
||||
SetEnabledModsCVarValue();
|
||||
// TODO: runtime changes
|
||||
/*
|
||||
gfx_texture_cache_clear();
|
||||
SOH::SkeletonPatcher::ClearSkeletons();
|
||||
*/
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
||||
|
||||
// disabled mods are always sorted
|
||||
std::sort(disabledModFiles.begin(), disabledModFiles.end(), [](const std::string& a, const std::string& b) {
|
||||
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end(),
|
||||
[](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); });
|
||||
});
|
||||
}
|
||||
|
||||
void EnableMod(std::string file) {
|
||||
disabledModFiles.erase(std::find(disabledModFiles.begin(), disabledModFiles.end(), file));
|
||||
enabledModFiles.insert(enabledModFiles.begin(), file);
|
||||
@@ -139,39 +203,30 @@ void DrawMods(bool enabled) {
|
||||
bool madeAnyChange = false;
|
||||
int switchFromIndex = -1;
|
||||
int switchToIndex = -1;
|
||||
uint32_t index = 0;
|
||||
|
||||
for (int i = 0; i < selectedModFiles.size(); i += 1) {
|
||||
for (int i = selectedModFiles.size() - 1; i >= 0; i--) {
|
||||
std::string file = selectedModFiles[i];
|
||||
if (UIWidgets::StateButton((file + "_left_right").c_str(), enabled ? ICON_FA_ARROW_LEFT : ICON_FA_ARROW_RIGHT,
|
||||
ImVec2(25, 25), UIWidgets::ButtonOptions().Color(THEME_COLOR))) {
|
||||
if (enabled) {
|
||||
DisableMod(file);
|
||||
} else {
|
||||
EnableMod(file);
|
||||
}
|
||||
if (enabled) {
|
||||
ImGui::BeginGroup();
|
||||
}
|
||||
// if (UIWidgets::StateButton((file + "_left_right").c_str(), enabled ? ICON_FA_ARROW_RIGHT :
|
||||
// ICON_FA_ARROW_LEFT,
|
||||
// ImVec2(25, 25), UIWidgets::ButtonOptions().Color(THEME_COLOR))) {
|
||||
// if (enabled) {
|
||||
// DisableMod(file);
|
||||
// } else {
|
||||
// EnableMod(file);
|
||||
// }
|
||||
// }
|
||||
|
||||
// it's not relevant to reorder disabled mods
|
||||
if (enabled) {
|
||||
ImGui::SameLine();
|
||||
if (i == 0) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
if (UIWidgets::StateButton((file + "_up").c_str(), ICON_FA_ARROW_UP, ImVec2(25, 25),
|
||||
UIWidgets::ButtonOptions().Color(THEME_COLOR))) {
|
||||
madeAnyChange = true;
|
||||
switchFromIndex = i;
|
||||
switchToIndex = i - 1;
|
||||
}
|
||||
if (i == 0) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
// ImGui::SameLine();
|
||||
if (i == selectedModFiles.size() - 1) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
if (UIWidgets::StateButton((file + "_down").c_str(), ICON_FA_ARROW_DOWN, ImVec2(25, 25),
|
||||
if (UIWidgets::StateButton((file + "_up").c_str(), ICON_FA_ARROW_UP, ImVec2(25, 25),
|
||||
UIWidgets::ButtonOptions().Color(THEME_COLOR))) {
|
||||
madeAnyChange = true;
|
||||
switchFromIndex = i;
|
||||
@@ -180,9 +235,31 @@ void DrawMods(bool enabled) {
|
||||
if (i == selectedModFiles.size() - 1) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (i == 0) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
if (UIWidgets::StateButton((file + "_down").c_str(), ICON_FA_ARROW_DOWN, ImVec2(25, 25),
|
||||
UIWidgets::ButtonOptions().Color(THEME_COLOR))) {
|
||||
madeAnyChange = true;
|
||||
switchFromIndex = i;
|
||||
switchToIndex = i - 1;
|
||||
}
|
||||
if (i == 0) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
DrawModInfo(file);
|
||||
DrawModInfo(filePaths.at(file).filename().generic_string());
|
||||
if (enabled) {
|
||||
ImGui::EndGroup();
|
||||
ModsHandleDragAndDrop(selectedModFiles, i, file);
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
ModsPostDragAndDrop();
|
||||
}
|
||||
|
||||
if (madeAnyChange) {
|
||||
@@ -191,22 +268,61 @@ void DrawMods(bool enabled) {
|
||||
}
|
||||
}
|
||||
|
||||
void ModMenuWindow::DrawElement() {
|
||||
ImGui::BeginDisabled(CVarGetInteger(CVAR_SETTING("DisableChanges"), 0));
|
||||
bool editing = false;
|
||||
|
||||
const ImVec4 yellow = ImVec4(1, 1, 0, 1);
|
||||
void ModMenuWindow::DrawElement() {
|
||||
SohGui::mSohMenu->MenuDrawItem(enableModsWidget, 200, THEME_COLOR);
|
||||
ImGui::SameLine();
|
||||
SohGui::mSohMenu->MenuDrawItem(tabHotkeyWidget, 200, THEME_COLOR);
|
||||
|
||||
ImGui::TextColored(
|
||||
yellow, "Mods are currently not reloaded at runtime.\nClose and re-open Ship for the changes to take effect.");
|
||||
UIWidgets::ColorValues.at(UIWidgets::Colors::Yellow),
|
||||
"Mods are currently not reloaded at runtime. Close and re-open Ship for the changes to take effect.\n"
|
||||
"Drag ordering for the enabled list is available.\nMod priority is top to bottom. They override mods listed "
|
||||
"below them.");
|
||||
|
||||
if (UIWidgets::Button("Update", UIWidgets::ButtonOptions().Size(ImVec2(250.0f, 0.0f)).Color(THEME_COLOR))) {
|
||||
UpdateModFiles();
|
||||
// if (UIWidgets::Button(
|
||||
// "Update", UIWidgets::ButtonOptions({ { .disabled = editing, .disabledTooltip = "Currently editing..." }
|
||||
// })
|
||||
// .Size(UIWidgets::Sizes::Inline)
|
||||
// .Color(THEME_COLOR))) {
|
||||
// UpdateModFiles();
|
||||
// }
|
||||
// ImGui::SameLine();
|
||||
if (UIWidgets::Button("Edit",
|
||||
UIWidgets::ButtonOptions({ { .disabled = editing, .disabledTooltip = "Already editing..." } })
|
||||
.Size(UIWidgets::Sizes::Inline)
|
||||
.Color(THEME_COLOR))) {
|
||||
editing = true;
|
||||
}
|
||||
UIWidgets::Tooltip("Re-check the mods folder for new files");
|
||||
|
||||
if (editing) {
|
||||
ImGui::SameLine();
|
||||
if (UIWidgets::Button("Cancel", UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline))) {
|
||||
editing = false;
|
||||
UpdateModFiles(false, true);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (UIWidgets::Button("Apply & Close",
|
||||
UIWidgets::ButtonOptions().Size(UIWidgets::Sizes::Inline).Color(THEME_COLOR))) {
|
||||
SohGui::RegisterPopup("Apply & Close",
|
||||
"Application currently requires a restart. Save the mod info and close SoH?", "Close",
|
||||
"Cancel", [&]() {
|
||||
// TODO: runtime changes
|
||||
SetEnabledModsCVarValue();
|
||||
// TODO: runtime changes
|
||||
/*
|
||||
gfx_texture_cache_clear();
|
||||
SOH::SkeletonPatcher::ClearSkeletons();
|
||||
*/
|
||||
Ship::Context::GetInstance()->GetConsoleVariables()->Save();
|
||||
Ship::Context::GetInstance()->GetWindow()->Close();
|
||||
});
|
||||
}
|
||||
}
|
||||
ImGui::BeginDisabled(!editing);
|
||||
if (ImGui::BeginTable("tableMods", 2, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) {
|
||||
ImGui::TableSetupColumn("Disabled Mods", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||
ImGui::TableSetupColumn("Enabled Mods", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||
// ImGui::TableSetupColumn("Disabled Mods", ImGuiTableColumnFlags_WidthStretch, 200.0f);
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
ImGui::TableHeadersRow();
|
||||
ImGui::PopItemFlag();
|
||||
@@ -214,26 +330,52 @@ void ModMenuWindow::DrawElement() {
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (ImGui::BeginChild("Disabled Mods", ImVec2(0, -8))) {
|
||||
DrawMods(false);
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
if (ImGui::BeginChild("Enabled Mods", ImVec2(0, -8))) {
|
||||
DrawMods(true);
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
/*ImGui::TableNextColumn();
|
||||
|
||||
if (ImGui::BeginChild("Disabled Mods", ImVec2(0, -8))) {
|
||||
DrawMods(false);
|
||||
|
||||
ImGui::EndChild();
|
||||
}*/
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
void ModMenuWindow::InitElement() {
|
||||
UpdateModFiles(true);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterModMenuWidgets() {
|
||||
enableModsWidget = { .name = "Enable Mods", .type = WidgetType::WIDGET_CVAR_CHECKBOX };
|
||||
enableModsWidget.CVar(CVAR_SETTING("AltAssets"))
|
||||
.RaceDisable(false)
|
||||
.Options(UIWidgets::CheckboxOptions({ { .disabledTooltip = "Temporarily disabled while editing mods list." } })
|
||||
.Color(THEME_COLOR)
|
||||
.Tooltip("Toggle mods. For graphics mods, this means toggling between default and mod graphics.")
|
||||
.DefaultValue(true))
|
||||
.PreFunc([&](WidgetInfo& info) {
|
||||
auto options = std::static_pointer_cast<UIWidgets::CheckboxOptions>(info.options);
|
||||
options->disabled = editing;
|
||||
});
|
||||
SohGui::mSohMenu->AddSearchWidget({ enableModsWidget, "Settings", "Mod Menu", "Top", "alternat assets" });
|
||||
|
||||
tabHotkeyWidget = { .name = "Mods Tab Hotkey", .type = WidgetType::WIDGET_CVAR_CHECKBOX };
|
||||
tabHotkeyWidget.CVar(CVAR_SETTING("Mods.AlternateAssetsHotkey"))
|
||||
.RaceDisable(false)
|
||||
.Options(UIWidgets::CheckboxOptions()
|
||||
.Color(THEME_COLOR)
|
||||
.Tooltip("Allows pressing the Tab key to toggle mods")
|
||||
.DefaultValue(true));
|
||||
SohGui::mSohMenu->AddSearchWidget(
|
||||
{ enableModsWidget, "Settings", "Mod Menu", "Top", "alternat assets tab hotkey" });
|
||||
}
|
||||
|
||||
static RegisterMenuInitFunc menuInitFunc(RegisterModMenuWidgets);
|
||||
|
||||
@@ -227,9 +227,10 @@ uint8_t StonesRequiredBySettings() {
|
||||
}
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
|
||||
stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).Get() });
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
|
||||
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 6) });
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) &&
|
||||
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
|
||||
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 6) });
|
||||
}
|
||||
return stones;
|
||||
@@ -247,12 +248,12 @@ uint8_t MedallionsRequiredBySettings() {
|
||||
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 3;
|
||||
}
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
|
||||
medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get() });
|
||||
medallions = std::max(medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get());
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
|
||||
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 3) });
|
||||
medallions = std::max(medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 3));
|
||||
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) &&
|
||||
ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
|
||||
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3) });
|
||||
medallions = std::max(medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3));
|
||||
}
|
||||
return medallions;
|
||||
}
|
||||
@@ -264,7 +265,7 @@ uint8_t TokensRequiredBySettings() {
|
||||
tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get();
|
||||
}
|
||||
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
|
||||
tokens = std::max<uint8_t>({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get() });
|
||||
tokens = std::max<uint8_t>(tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
@@ -255,11 +255,14 @@ void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) {
|
||||
return;
|
||||
|
||||
if (flagType == FLAG_GS_TOKEN &&
|
||||
Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF))
|
||||
Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) {
|
||||
Rando::Context::GetInstance()->GetItemLocation(rc)->SetCheckStatus(RCSHOW_COLLECTED);
|
||||
return;
|
||||
}
|
||||
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
|
||||
if (rc != RC_HF_OCARINA_OF_TIME_ITEM) {
|
||||
if (loc == nullptr || loc->HasObtained() || loc->GetPlacedRandomizerGet() == RG_NONE)
|
||||
Rando::Context::GetInstance()->GetItemLocation(rc)->SetCheckStatus(RCSHOW_COLLECTED);
|
||||
return;
|
||||
}
|
||||
SPDLOG_INFO("Queuing RC: {}", static_cast<uint32_t>(rc));
|
||||
|
||||
@@ -2116,9 +2116,8 @@ void RegisterItemTrackerWidgets() {
|
||||
hookshotIdentWidget.CVar(CVAR_SETTING("FreeLook.Enabled"))
|
||||
.Options(CheckboxOptions()
|
||||
.Color(THEME_COLOR)
|
||||
.Tooltip("Shows an 'H' or an 'L' to more easiely distinguish between Hookshot and Longshot."));
|
||||
SohGui::mSohMenu->AddSearchWidget(
|
||||
{ hookshotIdentWidget, "Settings", "Controls", "Camera Controls", "longshot icon" });
|
||||
.Tooltip("Shows an 'H' or an 'L' to more easily distinguish between Hookshot and Longshot."));
|
||||
SohGui::mSohMenu->AddSearchWidget({ hookshotIdentWidget, "Randomizer", "Item Tracker", "General Settings" });
|
||||
}
|
||||
|
||||
static RegisterMenuInitFunc menuInitFunc(RegisterItemTrackerWidgets);
|
||||
|
||||
@@ -300,7 +300,7 @@ void OTRGlobals::Initialize() {
|
||||
|
||||
// tell LUS to reserve 3 SoH specific threads (Game, Audio, Save)
|
||||
context->InitResourceManager(OTRFiles, {}, 3);
|
||||
prevAltAssets = CVarGetInteger(CVAR_SETTING("AltAssets"), 0);
|
||||
prevAltAssets = CVarGetInteger(CVAR_SETTING("AltAssets"), 1);
|
||||
context->GetResourceManager()->SetAltAssetsEnabled(prevAltAssets);
|
||||
|
||||
auto controlDeck = std::make_shared<LUS::ControlDeck>(std::vector<CONTROLLERBUTTONS_T>({
|
||||
@@ -1483,7 +1483,7 @@ extern "C" void Graph_StartFrame() {
|
||||
#endif
|
||||
case KbScancode::LUS_KB_TAB: {
|
||||
if (CVarGetInteger(CVAR_SETTING("Mods.AlternateAssetsHotkey"), 1)) {
|
||||
CVarSetInteger(CVAR_SETTING("AltAssets"), !CVarGetInteger(CVAR_SETTING("AltAssets"), 0));
|
||||
CVarSetInteger(CVAR_SETTING("AltAssets"), !CVarGetInteger(CVAR_SETTING("AltAssets"), 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1571,7 +1571,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
|
||||
}
|
||||
}
|
||||
|
||||
bool curAltAssets = CVarGetInteger(CVAR_SETTING("AltAssets"), 0);
|
||||
bool curAltAssets = CVarGetInteger(CVAR_SETTING("AltAssets"), 1);
|
||||
if (prevAltAssets != curAltAssets) {
|
||||
prevAltAssets = curAltAssets;
|
||||
Ship::Context::GetInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets);
|
||||
|
||||
@@ -537,12 +537,6 @@ void SohMenu::AddMenuEnhancements() {
|
||||
path.column = SECTION_COLUMN_1;
|
||||
|
||||
AddWidget(path, "Mods", WIDGET_SEPARATOR_TEXT);
|
||||
AddWidget(path, "Use Alternate Assets", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_SETTING("AltAssets"))
|
||||
.RaceDisable(false)
|
||||
.Options(CheckboxOptions().Tooltip(
|
||||
"Toggle between standard assets and alternate assets. Usually mods will indicate if "
|
||||
"this setting has to be used or not."));
|
||||
AddWidget(path, "Disable Bomb Billboarding", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_ENHANCEMENT("DisableBombBillboarding"))
|
||||
.RaceDisable(false)
|
||||
@@ -1908,15 +1902,6 @@ void SohMenu::AddMenuEnhancements() {
|
||||
.CVar(timer.timeEnable)
|
||||
.Callback([](WidgetInfo& info) { TimeDisplayUpdateDisplayOptions(); });
|
||||
}
|
||||
|
||||
// Mod Menu
|
||||
path.sidebarName = "Mod Menu";
|
||||
AddSidebarEntry("Enhancements", path.sidebarName, 1);
|
||||
AddWidget(path, "Popout Mod Menu Window", WIDGET_WINDOW_BUTTON)
|
||||
.CVar(CVAR_WINDOW("ModMenu"))
|
||||
.WindowName("Mod Menu")
|
||||
.HideInSearch(true)
|
||||
.Options(WindowButtonOptions().Tooltip("Enables the separate Mod Menu Window."));
|
||||
}
|
||||
|
||||
} // namespace SohGui
|
||||
|
||||
@@ -178,11 +178,6 @@ void SohMenu::AddMenuSettings() {
|
||||
.RaceDisable(false)
|
||||
.Options(CheckboxOptions().Tooltip(
|
||||
"Search input box gets autofocus when visible. Does not affect using other widgets."));
|
||||
AddWidget(path, "Alt Assets Tab hotkey", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_SETTING("Mods.AlternateAssetsHotkey"))
|
||||
.RaceDisable(false)
|
||||
.Options(
|
||||
CheckboxOptions().Tooltip("Allows pressing the Tab key to toggle alternate assets").DefaultValue(true));
|
||||
AddWidget(path, "Open App Files Folder", WIDGET_BUTTON)
|
||||
.RaceDisable(false)
|
||||
.Callback([](WidgetInfo& info) {
|
||||
@@ -505,6 +500,15 @@ void SohMenu::AddMenuSettings() {
|
||||
});
|
||||
})
|
||||
.Options(ButtonOptions().Tooltip("Displays a test notification."));
|
||||
|
||||
// Mod Menu
|
||||
path.sidebarName = "Mod Menu";
|
||||
AddSidebarEntry("Settings", path.sidebarName, 1);
|
||||
AddWidget(path, "Popout Mod Menu Window", WIDGET_WINDOW_BUTTON)
|
||||
.CVar(CVAR_WINDOW("ModMenu"))
|
||||
.WindowName("Mod Menu")
|
||||
.HideInSearch(true)
|
||||
.Options(WindowButtonOptions().Tooltip("Enables the separate Mod Menu Window."));
|
||||
}
|
||||
|
||||
} // namespace SohGui
|
||||
|
||||
@@ -1503,7 +1503,7 @@ std::vector<Migration> version3Migrations = {
|
||||
{ MigrationAction::Rename, "gOpenMenuBar", "gSettings.OpenMenuBar" },
|
||||
{ MigrationAction::Rename, "gRandomizeSkipChildStealth", "gRandoSettings.SkipChildStealth" },
|
||||
{ MigrationAction::Rename, "gRandomizeExcludedLocations", "gRandoSettings.ExcludedLocations" },
|
||||
{ MigrationAction::Rename, "gAltAssets", "gEnhancements.AltAssets" },
|
||||
{ MigrationAction::Rename, "gAltAssets", "gSettings.AltAssets" },
|
||||
{ MigrationAction::Rename, "gMSAAValue", "gSettings.MSAAValue" },
|
||||
{ MigrationAction::Rename, "gInternalResolution", "gSettings.InternalResolution" },
|
||||
{ MigrationAction::Rename, "gTextureFilter", "gSettings.TextureFilter" },
|
||||
|
||||
Reference in New Issue
Block a user