diff --git a/GolemHelper/Automation/AutomationLogic.cpp b/GolemHelper/Automation/AutomationLogic.cpp index 69cfbec..e23aa77 100644 --- a/GolemHelper/Automation/AutomationLogic.cpp +++ b/GolemHelper/Automation/AutomationLogic.cpp @@ -33,7 +33,7 @@ bool AutomationLogic::ShouldSkipGolemStep(int stepIndex) { } void AutomationLogic::ApplyHealerBoons() { - if (!g_api || !g_state.boonsEnabled || !g_state.enabled) return; + if (!g_api || !g_state.enabled) return; bool uiWasVisible = g_state.showUI; if (uiWasVisible) { @@ -99,7 +99,7 @@ void AutomationLogic::ApplyHealerBoons() { } void AutomationLogic::ApplyAllBoons() { - if (!g_api || !g_state.boonsEnabled || !g_state.enabled) return; + if (!g_api || !g_state.enabled) return; if (g_state.environmentDamage) { ApplyHealerBoons(); @@ -119,8 +119,16 @@ void AutomationLogic::ApplyAllBoons() { mode = "Alac DPS"; } + std::string advancedBoons = ""; + if (g_state.showBoonAdvanced && (g_state.addResistance || g_state.addStability)) { + advancedBoons = " + "; + if (g_state.addResistance) advancedBoons += "Resistance "; + if (g_state.addStability) advancedBoons += "Stability "; + advancedBoons.pop_back(); + } + char startBuffer[300]; - sprintf_s(startBuffer, "Starting boon sequence (20 steps) - Mode: %s", mode.c_str()); + sprintf_s(startBuffer, "Starting boon sequence (20 steps) - Mode: %s%s", mode.c_str(), advancedBoons.c_str()); g_api->Log(ELogLevel_INFO, "GolemHelper", startBuffer); try { @@ -136,8 +144,23 @@ void AutomationLogic::ApplyAllBoons() { continue; } - int delay = (i == 19) ? 50 : g_state.stepDelay; + if (i == 9) { + CoordinateUtils::ClickAtScaled(g_coords.boonStepX[i], g_coords.boonStepY[i], g_state.stepDelay); + if (g_state.showBoonAdvanced && g_state.addResistance) { + g_api->Log(ELogLevel_INFO, "GolemHelper", "Adding Resistance"); + CoordinateUtils::ClickAtScaled(g_coords.resistanceX, g_coords.resistanceY, g_state.stepDelay); + } + + if (g_state.showBoonAdvanced && g_state.addStability) { + g_api->Log(ELogLevel_INFO, "GolemHelper", "Adding Stability"); + CoordinateUtils::ClickAtScaled(g_coords.stabilityX, g_coords.stabilityY, g_state.stepDelay); + } + + continue; + } + + int delay = (i == 19) ? 50 : g_state.stepDelay; CoordinateUtils::ClickAtScaled(g_coords.boonStepX[i], g_coords.boonStepY[i], delay); } } @@ -153,7 +176,7 @@ void AutomationLogic::ApplyAllBoons() { } void AutomationLogic::ApplyGolemSettings() { - if (!g_api || !g_state.golemEnabled || !g_state.enabled) return; + if (!g_api || !g_state.enabled) return; bool uiWasVisible = g_state.showUI; if (uiWasVisible) { diff --git a/GolemHelper/Common/Types.h b/GolemHelper/Common/Types.h index 218b94c..098168d 100644 --- a/GolemHelper/Common/Types.h +++ b/GolemHelper/Common/Types.h @@ -1,5 +1,7 @@ #pragma once #include "../Dependencies/mumble/mumble.h" +#include +#include enum HitboxType { HITBOX_SMALL = 0, @@ -13,10 +15,38 @@ enum EnvironmentDamageLevel { ENV_EXTREME = 2 }; +struct GolemTemplate { + std::string name; + bool isQuickDps; + bool isAlacDps; + bool environmentDamage; + EnvironmentDamageLevel envDamageLevel; + bool skipSlow; + bool skipBurning; + bool fiveBleedingStacks; + HitboxType hitboxType; + bool isDefaultTemplate; + bool addResistance; + bool addStability; + + GolemTemplate() : + name("Unnamed Template"), + isQuickDps(false), + isAlacDps(false), + environmentDamage(false), + envDamageLevel(ENV_MILD), + skipSlow(false), + skipBurning(false), + fiveBleedingStacks(false), + hitboxType(HITBOX_SMALL), + isDefaultTemplate(false), + addResistance(false), + addStability(false) { + } +}; + struct GolemHelperState { bool enabled = false; - bool boonsEnabled = true; - bool golemEnabled = true; bool isQuickDps = false; bool isAlacDps = false; bool environmentDamage = false; @@ -29,6 +59,10 @@ struct GolemHelperState { bool showUI = false; bool showAdvanced = false; bool showTimingSettings = false; + bool showBoonAdvanced = false; + bool addResistance = false; + bool addStability = false; + bool alwaysHideIcon = false; int debugCounter = 0; int initialDelay = 390; @@ -36,6 +70,11 @@ struct GolemHelperState { bool quickAccessVisible = false; unsigned int lastMapID = 0; + + std::vector templates; + int selectedTemplateIndex = -1; + int lastUserTemplateIndex = -1; + char newTemplateName[64] = ""; }; struct MenuCoordinates { @@ -68,4 +107,9 @@ struct MenuCoordinates { int healerStepY[10] = { 262, 352, 352, 262, 262, 500, 450, 450, 305, 262 }; + + int resistanceX = 830; + int resistanceY = 354; + int stabilityX = 830; + int stabilityY = 400; }; \ No newline at end of file diff --git a/GolemHelper/Config/ConfigManager.cpp b/GolemHelper/Config/ConfigManager.cpp index 49e74f7..ddfae79 100644 --- a/GolemHelper/Config/ConfigManager.cpp +++ b/GolemHelper/Config/ConfigManager.cpp @@ -21,12 +21,13 @@ void ConfigManager::SaveCustomDelaySettings() { configFile << "[GolemHelper]" << std::endl; configFile << "initialDelay=" << g_state.initialDelay << std::endl; configFile << "stepDelay=" << g_state.stepDelay << std::endl; + configFile << "alwaysHideIcon=" << (g_state.alwaysHideIcon ? "1" : "0") << std::endl; configFile.close(); - char logBuffer[250]; - sprintf_s(logBuffer, "Delay settings saved: initialDelay=%dms, stepDelay=%dms", - g_state.initialDelay, g_state.stepDelay); + char logBuffer[300]; + sprintf_s(logBuffer, "Settings saved: initialDelay=%dms, stepDelay=%dms, alwaysHideIcon=%s", + g_state.initialDelay, g_state.stepDelay, g_state.alwaysHideIcon ? "true" : "false"); g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); } @@ -69,13 +70,16 @@ void ConfigManager::LoadCustomDelaySettings() { g_state.stepDelay = delay; } } + else if (key == "alwaysHideIcon") { + g_state.alwaysHideIcon = (value == "1"); + } } configFile.close(); - char logBuffer[250]; - sprintf_s(logBuffer, "Delay settings loaded: initialDelay=%dms, stepDelay=%dms", - g_state.initialDelay, g_state.stepDelay); + char logBuffer[300]; + sprintf_s(logBuffer, "Settings loaded: initialDelay=%dms, stepDelay=%dms, alwaysHideIcon=%s", + g_state.initialDelay, g_state.stepDelay, g_state.alwaysHideIcon ? "true" : "false"); g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); } diff --git a/GolemHelper/Config/TemplateManager.cpp b/GolemHelper/Config/TemplateManager.cpp new file mode 100644 index 0000000..f3c516e --- /dev/null +++ b/GolemHelper/Config/TemplateManager.cpp @@ -0,0 +1,294 @@ +#include +#include +#include +#include +#include +#include "TemplateManager.h" +#include "../Common/Globals.h" +#include "../Utils/FileUtils.h" + +void TemplateManager::LoadTemplates() { + if (!g_api) return; + + CreateDefaultTemplates(); + + std::string templatePath = FileUtils::GetAddonPath() + "\\templates.cfg"; + + try { + std::ifstream file(templatePath); + if (!file.is_open()) { + g_api->Log(ELogLevel_INFO, "GolemHelper", "No user templates file found"); + SaveTemplates(); + return; + } + + std::string line; + GolemTemplate currentTemplate; + bool inTemplate = false; + + while (std::getline(file, line)) { + if (line.empty() || line[0] == '#') continue; + + if (line.find("[Template]") == 0) { + if (inTemplate && !currentTemplate.name.empty()) { + g_state.templates.push_back(currentTemplate); + } + currentTemplate = GolemTemplate(); + inTemplate = true; + continue; + } + + if (!inTemplate) continue; + + size_t equalPos = line.find('='); + if (equalPos == std::string::npos) continue; + + std::string key = line.substr(0, equalPos); + std::string value = line.substr(equalPos + 1); + + if (key == "name") { + currentTemplate.name = value; + } + else if (key == "isQuickDps") { + currentTemplate.isQuickDps = (value == "1"); + } + else if (key == "isAlacDps") { + currentTemplate.isAlacDps = (value == "1"); + } + else if (key == "environmentDamage") { + currentTemplate.environmentDamage = (value == "1"); + } + else if (key == "envDamageLevel") { + currentTemplate.envDamageLevel = (EnvironmentDamageLevel)std::stoi(value); + } + else if (key == "skipSlow") { + currentTemplate.skipSlow = (value == "1"); + } + else if (key == "skipBurning") { + currentTemplate.skipBurning = (value == "1"); + } + else if (key == "fiveBleedingStacks") { + currentTemplate.fiveBleedingStacks = (value == "1"); + } + else if (key == "hitboxType") { + currentTemplate.hitboxType = (HitboxType)std::stoi(value); + } + else if (key == "addResistance") { + currentTemplate.addResistance = (value == "1"); + } + else if (key == "addStability") { + currentTemplate.addStability = (value == "1"); + } + } + + if (inTemplate && !currentTemplate.name.empty()) { + g_state.templates.push_back(currentTemplate); + } + + file.close(); + + int userTemplateCount = 0; + for (const auto& temp : g_state.templates) { + if (!temp.isDefaultTemplate) userTemplateCount++; + } + + char logBuffer[150]; + sprintf_s(logBuffer, "Loaded %d user templates", userTemplateCount); + g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); + + } + catch (...) { + g_api->Log(ELogLevel_WARNING, "GolemHelper", "Failed to load user templates"); + } +} + +void TemplateManager::SaveTemplates() { + if (!g_api) return; + + std::string templatePath = FileUtils::GetAddonPath() + "\\templates.cfg"; + + try { + std::ofstream file(templatePath); + if (!file.is_open()) { + g_api->Log(ELogLevel_WARNING, "GolemHelper", "Could not create templates file"); + return; + } + + file << "# GolemHelper User Templates Configuration\n"; + + int savedCount = 0; + for (const auto& temp : g_state.templates) { + if (!temp.isDefaultTemplate) { + file << "[Template]\n"; + file << "name=" << temp.name << "\n"; + file << "isQuickDps=" << (temp.isQuickDps ? "1" : "0") << "\n"; + file << "isAlacDps=" << (temp.isAlacDps ? "1" : "0") << "\n"; + file << "environmentDamage=" << (temp.environmentDamage ? "1" : "0") << "\n"; + file << "envDamageLevel=" << temp.envDamageLevel << "\n"; + file << "skipSlow=" << (temp.skipSlow ? "1" : "0") << "\n"; + file << "skipBurning=" << (temp.skipBurning ? "1" : "0") << "\n"; + file << "fiveBleedingStacks=" << (temp.fiveBleedingStacks ? "1" : "0") << "\n"; + file << "hitboxType=" << temp.hitboxType << "\n"; + file << "addResistance=" << (temp.addResistance ? "1" : "0") << "\n"; + file << "addStability=" << (temp.addStability ? "1" : "0") << "\n\n"; + savedCount++; + } + } + + file.close(); + + char logBuffer[150]; + sprintf_s(logBuffer, "Saved %d user templates", savedCount); + g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); + + } + catch (...) { + g_api->Log(ELogLevel_WARNING, "GolemHelper", "Failed to save templates"); + } +} + +void TemplateManager::SaveCurrentAsTemplate(const std::string& name) { + GolemTemplate newTemplate = CreateTemplateFromCurrentSettings(); + newTemplate.name = name; + + g_state.templates.push_back(newTemplate); + SaveTemplates(); + + if (g_api) { + char logBuffer[200]; + sprintf_s(logBuffer, "Template '%s' saved successfully", name.c_str()); + g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); + } +} + +void TemplateManager::LoadTemplate(int index) { + if (index < 0 || index >= g_state.templates.size()) return; + + ApplyTemplateToSettings(g_state.templates[index]); + + if (!g_state.templates[index].isDefaultTemplate) { + g_state.selectedTemplateIndex = index; + g_state.lastUserTemplateIndex = index; + } + + if (g_api) { + char logBuffer[200]; + sprintf_s(logBuffer, "Template '%s' loaded", g_state.templates[index].name.c_str()); + g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); + } +} + +void TemplateManager::DeleteTemplate(int index) { + if (index < 0 || index >= g_state.templates.size()) return; + + std::string templateName = g_state.templates[index].name; + g_state.templates.erase(g_state.templates.begin() + index); + + if (g_state.selectedTemplateIndex == index) { + g_state.selectedTemplateIndex = -1; + } + else if (g_state.selectedTemplateIndex > index) { + g_state.selectedTemplateIndex--; + } + + SaveTemplates(); + + if (g_api) { + char logBuffer[200]; + sprintf_s(logBuffer, "Template '%s' deleted", templateName.c_str()); + g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); + } +} + +void TemplateManager::RenameTemplate(int index, const std::string& newName) { + if (index < 0 || index >= g_state.templates.size()) return; + + std::string oldName = g_state.templates[index].name; + g_state.templates[index].name = newName; + SaveTemplates(); + + if (g_api) { + char logBuffer[300]; + sprintf_s(logBuffer, "Template renamed from '%s' to '%s'", oldName.c_str(), newName.c_str()); + g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); + } +} + +GolemTemplate TemplateManager::CreateTemplateFromCurrentSettings() { + GolemTemplate temp; + temp.isQuickDps = g_state.isQuickDps; + temp.isAlacDps = g_state.isAlacDps; + temp.environmentDamage = g_state.environmentDamage; + temp.envDamageLevel = g_state.envDamageLevel; + temp.skipSlow = g_state.skipSlow; + temp.skipBurning = g_state.skipBurning; + temp.fiveBleedingStacks = g_state.fiveBleedingStacks; + temp.hitboxType = g_state.hitboxType; + temp.addResistance = g_state.addResistance; + temp.addStability = g_state.addStability; + temp.isDefaultTemplate = false; + return temp; +} + +void TemplateManager::ApplyTemplateToSettings(const GolemTemplate& temp) { + g_state.isQuickDps = temp.isQuickDps; + g_state.isAlacDps = temp.isAlacDps; + g_state.environmentDamage = temp.environmentDamage; + g_state.envDamageLevel = temp.envDamageLevel; + g_state.skipSlow = temp.skipSlow; + g_state.skipBurning = temp.skipBurning; + g_state.fiveBleedingStacks = temp.fiveBleedingStacks; + g_state.hitboxType = temp.hitboxType; + g_state.addResistance = temp.addResistance; + g_state.addStability = temp.addStability; + + if (temp.isDefaultTemplate) { + g_state.showAdvanced = false; + g_state.showBoonAdvanced = false; + } + else { + if (temp.skipSlow || temp.skipBurning || temp.fiveBleedingStacks) { + g_state.showAdvanced = true; + } + if (temp.addResistance || temp.addStability) { + g_state.showBoonAdvanced = true; + } + } +} + +void TemplateManager::CreateDefaultTemplates() { + g_state.templates.clear(); + + GolemTemplate dps; + dps.name = "DPS"; + dps.isDefaultTemplate = true; + g_state.templates.push_back(dps); + + GolemTemplate quickDps; + quickDps.name = "Quick DPS"; + quickDps.isQuickDps = true; + quickDps.isDefaultTemplate = true; + g_state.templates.push_back(quickDps); + + GolemTemplate alacDps; + alacDps.name = "Alac DPS"; + alacDps.isAlacDps = true; + alacDps.isDefaultTemplate = true; + g_state.templates.push_back(alacDps); + + GolemTemplate qHeal; + qHeal.name = "qHeal"; + qHeal.isQuickDps = true; + qHeal.environmentDamage = true; + qHeal.envDamageLevel = ENV_MILD; + qHeal.isDefaultTemplate = true; + g_state.templates.push_back(qHeal); + + GolemTemplate aHeal; + aHeal.name = "aHeal"; + aHeal.isAlacDps = true; + aHeal.environmentDamage = true; + aHeal.envDamageLevel = ENV_MILD; + aHeal.isDefaultTemplate = true; + g_state.templates.push_back(aHeal); +} \ No newline at end of file diff --git a/GolemHelper/Config/TemplateManager.h b/GolemHelper/Config/TemplateManager.h new file mode 100644 index 0000000..4484c4b --- /dev/null +++ b/GolemHelper/Config/TemplateManager.h @@ -0,0 +1,15 @@ +#pragma once +#include "../Common/Types.h" + +class TemplateManager { +public: + static void LoadTemplates(); + static void SaveTemplates(); + static void SaveCurrentAsTemplate(const std::string& name); + static void LoadTemplate(int index); + static void DeleteTemplate(int index); + static void RenameTemplate(int index, const std::string& newName); + static GolemTemplate CreateTemplateFromCurrentSettings(); + static void ApplyTemplateToSettings(const GolemTemplate& temp); + static void CreateDefaultTemplates(); +}; \ No newline at end of file diff --git a/GolemHelper/GolemHelper.cpp b/GolemHelper/GolemHelper.cpp index 00d240b..4146d74 100644 --- a/GolemHelper/GolemHelper.cpp +++ b/GolemHelper/GolemHelper.cpp @@ -4,6 +4,7 @@ #include "Utils/FileUtils.h" #include "Utils/MapUtils.h" #include "Config/ConfigManager.h" +#include "Config/TemplateManager.h" #include "UI/UIManager.h" #include "Input/KeybindManager.h" #include "Dependencies/imgui/imgui.h" @@ -21,6 +22,7 @@ void Load(AddonAPI* aApi) { g_state.enabled = true; ConfigManager::LoadCustomDelaySettings(); + TemplateManager::LoadTemplates(); FileUtils::CopyResourceIcons(); g_api->Renderer.Register(ERenderType_Render, UIManager::RenderUI); @@ -33,7 +35,7 @@ void Load(AddonAPI* aApi) { MapUtils::UpdateQuickAccessVisibility(); - g_api->Log(ELogLevel_INFO, "GolemHelper", "=== GolemHelper v1.3.0.0 Loaded ==="); + g_api->Log(ELogLevel_INFO, "GolemHelper", "=== GolemHelper v1.4.0.0 Loaded ==="); g_api->Log(ELogLevel_INFO, "GolemHelper", "GolemHelper addon loaded successfully!"); } @@ -60,7 +62,7 @@ extern "C" __declspec(dllexport) AddonDefinition* GetAddonDef() { def.Signature = -424248; def.APIVersion = NEXUS_API_VERSION; def.Name = "GolemHelper"; - def.Version = { 1, 3, 0, 0 }; + def.Version = { 1, 4, 0, 0 }; def.Author = "Azrub"; def.Description = "Automates the process of setting optimal boon and golem configurations in the training area"; def.Load = Load; diff --git a/GolemHelper/GolemHelper.vcxproj b/GolemHelper/GolemHelper.vcxproj index acd3e43..5957deb 100644 --- a/GolemHelper/GolemHelper.vcxproj +++ b/GolemHelper/GolemHelper.vcxproj @@ -146,6 +146,7 @@ + @@ -168,6 +169,7 @@ + NotUsing NotUsing diff --git a/GolemHelper/GolemHelper.vcxproj.filters b/GolemHelper/GolemHelper.vcxproj.filters index 347d92d..640997b 100644 --- a/GolemHelper/GolemHelper.vcxproj.filters +++ b/GolemHelper/GolemHelper.vcxproj.filters @@ -111,6 +111,9 @@ Utils + + Config + @@ -161,6 +164,9 @@ Utils + + Config + diff --git a/GolemHelper/UI/UIManager.cpp b/GolemHelper/UI/UIManager.cpp index 84fbb43..24d5884 100644 --- a/GolemHelper/UI/UIManager.cpp +++ b/GolemHelper/UI/UIManager.cpp @@ -4,6 +4,7 @@ #include "../Common/Globals.h" #include "../Config/ConfigManager.h" #include "../Utils/MapUtils.h" +#include "../Config/TemplateManager.h" #include "../Dependencies/imgui/imgui.h" void UIManager::RenderUI() { @@ -11,196 +12,403 @@ void UIManager::RenderUI() { if (!g_state.showUI) return; - ImGui::SetNextWindowSize(ImVec2(400, 500), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(450, 600), ImGuiCond_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(50, 50), ImGuiCond_FirstUseEver); if (ImGui::Begin("GolemHelper", &g_state.showUI, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::TextColored(ImVec4(0.2f, 0.8f, 1.0f, 1.0f), "GolemHelper v1.3.0.0"); + ImGui::TextColored(ImVec4(0.2f, 0.8f, 1.0f, 1.0f), "GolemHelper v1.4.0.0"); ImGui::Separator(); - ImGui::Text("Status:"); - ImGui::SameLine(); - if (g_state.enabled) { - ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "ENABLED"); - } - else { - ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "DISABLED"); - } + if (ImGui::BeginTabBar("GolemHelperTabs", ImGuiTabBarFlags_None)) { - if (ImGui::Button(g_state.enabled ? "Disable GolemHelper" : "Enable GolemHelper", ImVec2(200, 0))) { - g_state.enabled = !g_state.enabled; - } - - ImGui::Spacing(); - ImGui::Separator(); - - ImGui::Text("Boon Configuration"); - ImGui::Checkbox("Enable Boons", &g_state.boonsEnabled); - - if (ImGui::Button("Apply Boons", ImVec2(150, 0))) { - if (g_state.enabled) { - g_api->InputBinds.Invoke("GolemHelper.ApplyBoons", false); - } - } - - ImGui::Text(g_state.environmentDamage ? "Healer Modes:" : "DPS Modes:"); - - if (g_state.environmentDamage) { - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f); - ImGui::RadioButton("Normal Mode", false); - ImGui::PopStyleVar(); - } - else { - if (ImGui::RadioButton("Normal Mode", !g_state.isQuickDps && !g_state.isAlacDps)) { - g_state.isQuickDps = false; - g_state.isAlacDps = false; - } - } - - if (ImGui::RadioButton(g_state.environmentDamage ? "qHeal (Skip Quickness)" : "Quick DPS (Skip Quickness)", g_state.isQuickDps)) { - g_state.isQuickDps = true; - g_state.isAlacDps = false; - } - - if (ImGui::RadioButton(g_state.environmentDamage ? "aHeal (Skip Alacrity)" : "Alac DPS (Skip Alacrity)", g_state.isAlacDps)) { - g_state.isQuickDps = false; - g_state.isAlacDps = true; - } - - ImGui::Spacing(); - ImGui::Text("Healer Bench:"); - - bool wasEnvironmentDamage = g_state.environmentDamage; - ImGui::Checkbox("Environment Damage", &g_state.environmentDamage); - - if (g_state.environmentDamage && !wasEnvironmentDamage) { - if (!g_state.isQuickDps && !g_state.isAlacDps) { - g_state.isQuickDps = true; - } - } - - if (g_state.environmentDamage) { - if (ImGui::RadioButton("Mild", g_state.envDamageLevel == ENV_MILD)) { - g_state.envDamageLevel = ENV_MILD; + if (ImGui::BeginTabItem("Settings")) { + RenderSettingsTab(); + ImGui::EndTabItem(); } - if (ImGui::RadioButton("Moderate", g_state.envDamageLevel == ENV_MODERATE)) { - g_state.envDamageLevel = ENV_MODERATE; + if (ImGui::BeginTabItem("Templates")) { + ImGui::SameLine(); + ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 160); + + std::string currentTemplateName = "None"; + bool foundMatchingTemplate = false; + + for (const auto& temp : g_state.templates) { + if (temp.isQuickDps == g_state.isQuickDps && + temp.isAlacDps == g_state.isAlacDps && + temp.environmentDamage == g_state.environmentDamage && + temp.envDamageLevel == g_state.envDamageLevel && + temp.skipSlow == g_state.skipSlow && + temp.skipBurning == g_state.skipBurning && + temp.fiveBleedingStacks == g_state.fiveBleedingStacks && + temp.hitboxType == g_state.hitboxType && + temp.addResistance == g_state.addResistance && + temp.addStability == g_state.addStability) { + currentTemplateName = temp.name; + foundMatchingTemplate = true; + break; + } + } + + ImGui::Text("Current: "); + ImGui::SameLine(); + if (foundMatchingTemplate) { + if (currentTemplateName.length() > 12) { + currentTemplateName = currentTemplateName.substr(0, 9) + "..."; + } + ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "%s", currentTemplateName.c_str()); + } + else { + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "None"); + } + + RenderTemplatesTab(); + ImGui::EndTabItem(); } - if (ImGui::RadioButton("Extreme", g_state.envDamageLevel == ENV_EXTREME)) { - g_state.envDamageLevel = ENV_EXTREME; - } + ImGui::EndTabBar(); } - - ImGui::Spacing(); - ImGui::Separator(); - - ImGui::Text("Golem Configuration"); - ImGui::Checkbox("Enable Golem Settings", &g_state.golemEnabled); - - if (ImGui::Button("Apply Golem Settings", ImVec2(150, 0))) { - if (g_state.enabled) { - g_api->InputBinds.Invoke("GolemHelper.ApplyGolem", false); - } - } - - ImGui::Text("Golem Hitbox:"); - - if (ImGui::RadioButton("Small (Benchmark Default)", g_state.hitboxType == HITBOX_SMALL)) { - g_state.hitboxType = HITBOX_SMALL; - } - - if (ImGui::RadioButton("Medium", g_state.hitboxType == HITBOX_MEDIUM)) { - g_state.hitboxType = HITBOX_MEDIUM; - } - - if (ImGui::RadioButton("Large", g_state.hitboxType == HITBOX_LARGE)) { - g_state.hitboxType = HITBOX_LARGE; - } - - ImGui::Spacing(); - ImGui::Text("Advanced:"); - - ImGui::Checkbox("Condition Settings", &g_state.showAdvanced); - - if (g_state.showAdvanced) { - ImGui::Checkbox("Skip Slow", &g_state.skipSlow); - ImGui::Checkbox("Skip Burning", &g_state.skipBurning); - ImGui::Checkbox("5 Bleeding Stacks", &g_state.fiveBleedingStacks); - } - - if (g_state.debugMode) { - ImGui::Spacing(); - ImGui::Separator(); - ImGui::Text("Display Info:"); - if (g_nexusLink && g_nexusLink->Width > 0 && g_nexusLink->Height > 0) { - ImGui::Text("Resolution: %dx%d", g_nexusLink->Width, g_nexusLink->Height); - ImGui::Text("UI Scale: %.2f", g_nexusLink->Scaling); - float dpiScale = (float)g_nexusLink->Width / 1920.0f; - ImGui::Text("DPI Scale: %.3f", dpiScale); - ImGui::Text("Debug samples: %d", g_state.debugCounter); - } - - ImGui::Spacing(); - ImGui::Text("Map Info:"); - unsigned int currentMapID = MapUtils::GetCurrentMapID(); - ImGui::Text("Current MapID: %u", currentMapID); - ImGui::Text("Is Training Area: %s", MapUtils::IsInTrainingArea() ? "YES" : "NO"); - ImGui::Text("QuickAccess Visible: %s", g_state.quickAccessVisible ? "YES" : "NO"); - } - - ImGui::Spacing(); - ImGui::Separator(); - - ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.3f, 0.5f, 0.7f, 0.8f)); - if (ImGui::CollapsingHeader("Set Custom Delays")) { - - int oldStepDelay = g_state.stepDelay; - int oldInitialDelay = g_state.initialDelay; - - ImGui::Text("Initial Delay (after F key):"); - ImGui::SetNextItemWidth(205); - ImGui::SliderInt("##initial", &g_state.initialDelay, 100, 1000, "%d ms"); - - ImGui::Text("Step Delay (between clicks):"); - ImGui::SetNextItemWidth(205); - ImGui::SliderInt("##step", &g_state.stepDelay, 100, 1000, "%d ms"); - - ImGui::Spacing(); - - if (ImGui::Button("Reset to Default", ImVec2(120, 0))) { - g_state.stepDelay = 290; - g_state.initialDelay = 390; - ConfigManager::SaveCustomDelaySettings(); - } - ImGui::SameLine(); - if (ImGui::Button("Slow Mode", ImVec2(80, 0))) { - g_state.stepDelay = 1000; - g_state.initialDelay = 600; - ConfigManager::SaveCustomDelaySettings(); - } - - ImGui::Spacing(); - ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.2f, 1.0f), "Increase delays if clicks fail"); - - if (oldStepDelay != g_state.stepDelay || oldInitialDelay != g_state.initialDelay) { - ConfigManager::SaveCustomDelaySettings(); - } - } - ImGui::PopStyleColor(2); } ImGui::End(); } +void UIManager::RenderSettingsTab() { + ImGui::Text("Boon Configuration"); + + if (ImGui::Button("Apply Boons", ImVec2(150, 0))) { + if (g_state.enabled) { + g_api->InputBinds.Invoke("GolemHelper.ApplyBoons", false); + } + } + + ImGui::Text(g_state.environmentDamage ? "Healer Modes:" : "DPS Modes:"); + + if (g_state.environmentDamage) { + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f); + ImGui::RadioButton("Normal Mode", false); + ImGui::PopStyleVar(); + } + else { + if (ImGui::RadioButton("Normal Mode", !g_state.isQuickDps && !g_state.isAlacDps)) { + g_state.isQuickDps = false; + g_state.isAlacDps = false; + } + } + + if (ImGui::RadioButton(g_state.environmentDamage ? "qHeal (Skip Quickness)" : "Quick DPS (Skip Quickness)", g_state.isQuickDps)) { + g_state.isQuickDps = true; + g_state.isAlacDps = false; + } + + if (ImGui::RadioButton(g_state.environmentDamage ? "aHeal (Skip Alacrity)" : "Alac DPS (Skip Alacrity)", g_state.isAlacDps)) { + g_state.isQuickDps = false; + g_state.isAlacDps = true; + } + + ImGui::Spacing(); + ImGui::Text("Advanced:"); + + if (g_state.environmentDamage) { + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6f); + ImGui::Checkbox("Boon Settings", &g_state.showBoonAdvanced); + g_state.showBoonAdvanced = false; + ImGui::PopStyleVar(); + } + else { + ImGui::Checkbox("Boon Settings", &g_state.showBoonAdvanced); + } + + if (g_state.showBoonAdvanced && !g_state.environmentDamage) { + ImGui::Checkbox("Add Resistance", &g_state.addResistance); + ImGui::Checkbox("Add Stability", &g_state.addStability); + } + + ImGui::Spacing(); + ImGui::Text("Healer Bench:"); + + bool wasEnvironmentDamage = g_state.environmentDamage; + ImGui::Checkbox("Environment Damage", &g_state.environmentDamage); + + if (g_state.environmentDamage && !wasEnvironmentDamage) { + if (!g_state.isQuickDps && !g_state.isAlacDps) { + g_state.isQuickDps = true; + } + } + + if (g_state.environmentDamage) { + if (ImGui::RadioButton("Mild", g_state.envDamageLevel == ENV_MILD)) { + g_state.envDamageLevel = ENV_MILD; + } + + if (ImGui::RadioButton("Moderate", g_state.envDamageLevel == ENV_MODERATE)) { + g_state.envDamageLevel = ENV_MODERATE; + } + + if (ImGui::RadioButton("Extreme", g_state.envDamageLevel == ENV_EXTREME)) { + g_state.envDamageLevel = ENV_EXTREME; + } + } + + ImGui::Spacing(); + ImGui::Separator(); + + ImGui::Text("Golem Configuration"); + + if (ImGui::Button("Apply Golem Settings", ImVec2(150, 0))) { + if (g_state.enabled) { + g_api->InputBinds.Invoke("GolemHelper.ApplyGolem", false); + } + } + + ImGui::Text("Golem Hitbox:"); + + if (ImGui::RadioButton("Small (Benchmark Default)", g_state.hitboxType == HITBOX_SMALL)) { + g_state.hitboxType = HITBOX_SMALL; + } + + if (ImGui::RadioButton("Medium", g_state.hitboxType == HITBOX_MEDIUM)) { + g_state.hitboxType = HITBOX_MEDIUM; + } + + if (ImGui::RadioButton("Large", g_state.hitboxType == HITBOX_LARGE)) { + g_state.hitboxType = HITBOX_LARGE; + } + + ImGui::Spacing(); + ImGui::Text("Advanced:"); + + ImGui::Checkbox("Condition Settings", &g_state.showAdvanced); + + if (g_state.showAdvanced) { + ImGui::Checkbox("Skip Slow", &g_state.skipSlow); + ImGui::Checkbox("Skip Burning", &g_state.skipBurning); + ImGui::Checkbox("5 Bleeding Stacks", &g_state.fiveBleedingStacks); + } + + if (g_state.debugMode) { + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Text("Display Info:"); + if (g_nexusLink && g_nexusLink->Width > 0 && g_nexusLink->Height > 0) { + ImGui::Text("Resolution: %dx%d", g_nexusLink->Width, g_nexusLink->Height); + ImGui::Text("UI Scale: %.2f", g_nexusLink->Scaling); + float dpiScale = (float)g_nexusLink->Width / 1920.0f; + ImGui::Text("DPI Scale: %.3f", dpiScale); + ImGui::Text("Debug samples: %d", g_state.debugCounter); + } + + ImGui::Spacing(); + ImGui::Text("Map Info:"); + unsigned int currentMapID = MapUtils::GetCurrentMapID(); + ImGui::Text("Current MapID: %u", currentMapID); + ImGui::Text("Is Training Area: %s", MapUtils::IsInTrainingArea() ? "YES" : "NO"); + ImGui::Text("QuickAccess Visible: %s", g_state.quickAccessVisible ? "YES" : "NO"); + } + + ImGui::Spacing(); + ImGui::Separator(); + + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.3f, 0.5f, 0.7f, 0.8f)); + if (ImGui::CollapsingHeader("Set Custom Delays")) { + + int oldStepDelay = g_state.stepDelay; + int oldInitialDelay = g_state.initialDelay; + + ImGui::Text("Initial Delay (after F key):"); + ImGui::SetNextItemWidth(205); + ImGui::SliderInt("##initial", &g_state.initialDelay, 100, 1000, "%d ms"); + + ImGui::Text("Step Delay (between clicks):"); + ImGui::SetNextItemWidth(205); + ImGui::SliderInt("##step", &g_state.stepDelay, 100, 1000, "%d ms"); + + ImGui::Spacing(); + + if (ImGui::Button("Reset to Default", ImVec2(120, 0))) { + g_state.stepDelay = 290; + g_state.initialDelay = 390; + ConfigManager::SaveCustomDelaySettings(); + } + ImGui::SameLine(); + if (ImGui::Button("Slow Mode", ImVec2(80, 0))) { + g_state.stepDelay = 1000; + g_state.initialDelay = 600; + ConfigManager::SaveCustomDelaySettings(); + } + + ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.2f, 1.0f), "Increase delays if clicks fail"); + + if (oldStepDelay != g_state.stepDelay || oldInitialDelay != g_state.initialDelay) { + ConfigManager::SaveCustomDelaySettings(); + } + } + ImGui::PopStyleColor(2); +} + +void UIManager::RenderTemplatesTab() { + ImGui::Text("Template Management"); + ImGui::Separator(); + + ImGui::Text("Save Current Settings:"); + ImGui::SetNextItemWidth(200); + ImGui::InputText("##templateName", g_state.newTemplateName, sizeof(g_state.newTemplateName)); + ImGui::SameLine(); + + if (ImGui::Button("Save Template")) { + if (strlen(g_state.newTemplateName) > 0) { + TemplateManager::SaveCurrentAsTemplate(std::string(g_state.newTemplateName)); + memset(g_state.newTemplateName, 0, sizeof(g_state.newTemplateName)); + } + } + + ImGui::Spacing(); + ImGui::Separator(); + + ImGui::Text("Available Templates:"); + + std::vector userTemplateIndices; + std::vector userTemplateNames; + + for (int i = 0; i < g_state.templates.size(); i++) { + if (!g_state.templates[i].isDefaultTemplate) { + userTemplateIndices.push_back(i); + userTemplateNames.push_back(g_state.templates[i].name.c_str()); + } + } + + if (userTemplateNames.empty()) { + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "No user templates saved"); + } + else { + int currentUserIndex = -1; + if (g_state.lastUserTemplateIndex >= 0) { + for (int i = 0; i < userTemplateIndices.size(); i++) { + if (userTemplateIndices[i] == g_state.lastUserTemplateIndex) { + currentUserIndex = i; + break; + } + } + } + + ImGui::SetNextItemWidth(200); + if (ImGui::Combo("##templateList", ¤tUserIndex, userTemplateNames.data(), userTemplateNames.size())) { + g_state.selectedTemplateIndex = userTemplateIndices[currentUserIndex]; + g_state.lastUserTemplateIndex = userTemplateIndices[currentUserIndex]; + } + + ImGui::SameLine(); + if (ImGui::Button("Load")) { + if (currentUserIndex >= 0 && currentUserIndex < userTemplateIndices.size()) { + TemplateManager::LoadTemplate(userTemplateIndices[currentUserIndex]); + } + } + + ImGui::SameLine(); + if (ImGui::Button("Delete")) { + if (currentUserIndex >= 0 && currentUserIndex < userTemplateIndices.size()) { + TemplateManager::DeleteTemplate(userTemplateIndices[currentUserIndex]); + g_state.selectedTemplateIndex = -1; + } + } + + if (g_state.lastUserTemplateIndex >= 0 && + g_state.lastUserTemplateIndex < g_state.templates.size()) { + + const auto& selectedTemplate = g_state.templates[g_state.lastUserTemplateIndex]; + + ImGui::Spacing(); + ImGui::Separator(); + ImGui::Text("%s", selectedTemplate.name.c_str()); + + std::string modeText = "Normal"; + if (selectedTemplate.isQuickDps) modeText = "Quick DPS"; + else if (selectedTemplate.isAlacDps) modeText = "Alac DPS"; + + if (selectedTemplate.environmentDamage) { + modeText += " + Env "; + switch (selectedTemplate.envDamageLevel) { + case ENV_MILD: modeText += "Mild"; break; + case ENV_MODERATE: modeText += "Moderate"; break; + case ENV_EXTREME: modeText += "Extreme"; break; + } + } + + ImGui::Text("Mode: %s", modeText.c_str()); + + const char* hitboxName = selectedTemplate.hitboxType == HITBOX_SMALL ? "Small" : + selectedTemplate.hitboxType == HITBOX_MEDIUM ? "Medium" : "Large"; + ImGui::Text("Hitbox: %s", hitboxName); + + if (selectedTemplate.skipSlow || selectedTemplate.skipBurning || selectedTemplate.fiveBleedingStacks) { + std::string conditions; + if (selectedTemplate.skipSlow) conditions += "Skip Slow, "; + if (selectedTemplate.skipBurning) conditions += "Skip Burning, "; + if (selectedTemplate.fiveBleedingStacks) conditions += "5 Bleeding, "; + if (!conditions.empty()) { + conditions.pop_back(); + conditions.pop_back(); + } + ImGui::Text("Conditions: %s", conditions.c_str()); + } + + if (selectedTemplate.addResistance || selectedTemplate.addStability) { + std::string boonSettings; + if (selectedTemplate.addResistance) boonSettings += "Resistance, "; + if (selectedTemplate.addStability) boonSettings += "Stability, "; + if (!boonSettings.empty()) { + boonSettings.pop_back(); + boonSettings.pop_back(); + } + ImGui::Text("Boon Settings: %s", boonSettings.c_str()); + } + } + } + + ImGui::Spacing(); + ImGui::Separator(); + + ImGui::Text("Quick Load:"); + + std::vector defaultNames = { "DPS", "Quick DPS", "Alac DPS", "qHeal", "aHeal" }; + + for (const std::string& name : defaultNames) { + int templateIndex = -1; + for (int i = 0; i < g_state.templates.size(); i++) { + if (g_state.templates[i].name == name && g_state.templates[i].isDefaultTemplate) { + templateIndex = i; + break; + } + } + + if (templateIndex >= 0) { + if (ImGui::Button(name.c_str(), ImVec2(80, 0))) { + TemplateManager::LoadTemplate(templateIndex); + g_state.selectedTemplateIndex = -1; + } + + if (name != "Alac DPS" && name != "aHeal") { + ImGui::SameLine(); + } + } + } +} + void UIManager::RenderOptions() { ImGui::Separator(); ImGui::Text("GolemHelper Settings"); - ImGui::Checkbox("Show UI by default", &g_state.showUI); + bool oldAlwaysHideIcon = g_state.alwaysHideIcon; + ImGui::Checkbox("Always Hide Icon", &g_state.alwaysHideIcon); + + if (oldAlwaysHideIcon != g_state.alwaysHideIcon) { + ConfigManager::SaveCustomDelaySettings(); + MapUtils::UpdateQuickAccessVisibility(); + } + ImGui::Checkbox("Enable debug mode", &g_state.debugMode); if (ImGui::Button("Reset all settings")) { @@ -214,12 +422,15 @@ void UIManager::RenderOptions() { g_state.hitboxType = HITBOX_SMALL; g_state.showAdvanced = false; g_state.showTimingSettings = false; + g_state.showBoonAdvanced = false; + g_state.addResistance = false; + g_state.addStability = false; g_state.stepDelay = 290; g_state.initialDelay = 390; - g_state.boonsEnabled = true; - g_state.golemEnabled = true; + g_state.alwaysHideIcon = false; ConfigManager::SaveCustomDelaySettings(); + MapUtils::UpdateQuickAccessVisibility(); } ImGui::Spacing(); @@ -260,4 +471,9 @@ void UIManager::RenderOptions() { ImGui::Text("- Step Delay: %d ms", g_state.stepDelay); ImGui::Text("- Initial Delay: %d ms", g_state.initialDelay); + + ImGui::Text("- Templates: %zu loaded", g_state.templates.size()); + if (g_state.selectedTemplateIndex >= 0 && g_state.selectedTemplateIndex < g_state.templates.size()) { + ImGui::Text("- Active Template: %s", g_state.templates[g_state.selectedTemplateIndex].name.c_str()); + } } \ No newline at end of file diff --git a/GolemHelper/UI/UIManager.h b/GolemHelper/UI/UIManager.h index 153ba7d..dfbf74e 100644 --- a/GolemHelper/UI/UIManager.h +++ b/GolemHelper/UI/UIManager.h @@ -4,4 +4,8 @@ class UIManager { public: static void RenderUI(); static void RenderOptions(); + +private: + static void RenderSettingsTab(); + static void RenderTemplatesTab(); }; \ No newline at end of file diff --git a/GolemHelper/Utils/MapUtils.cpp b/GolemHelper/Utils/MapUtils.cpp index a2ef426..e51292e 100644 --- a/GolemHelper/Utils/MapUtils.cpp +++ b/GolemHelper/Utils/MapUtils.cpp @@ -1,7 +1,4 @@ #include -#include -#include -#include #include "MapUtils.h" #include "../Common/Globals.h" @@ -20,10 +17,10 @@ unsigned int MapUtils::GetCurrentMapID() { void MapUtils::UpdateQuickAccessVisibility() { if (!g_api) return; - bool shouldBeVisible = IsInTrainingArea(); + bool shouldBeVisible = IsInTrainingArea() && !g_state.alwaysHideIcon; unsigned int currentMapID = GetCurrentMapID(); - if (currentMapID != g_state.lastMapID) { + if (currentMapID != g_state.lastMapID || g_state.quickAccessVisible != shouldBeVisible) { g_state.lastMapID = currentMapID; if (shouldBeVisible && !g_state.quickAccessVisible) { @@ -42,13 +39,14 @@ void MapUtils::UpdateQuickAccessVisibility() { g_api->Log(ELogLevel_INFO, "GolemHelper", buffer); } } - else if (!shouldBeVisible && g_state.quickAccessVisible) { + else if ((!shouldBeVisible || g_state.alwaysHideIcon) && g_state.quickAccessVisible) { g_api->QuickAccess.Remove("GolemHelper.ToggleUI"); g_state.quickAccessVisible = false; if (g_state.debugMode) { - char buffer[150]; - sprintf_s(buffer, sizeof(buffer), "QuickAccess icon REMOVED - MapID: %u (Not Training Area)", currentMapID); + const char* reason = g_state.alwaysHideIcon ? "Always Hide Icon enabled" : "Not Training Area"; + char buffer[200]; + sprintf_s(buffer, sizeof(buffer), "QuickAccess icon REMOVED - MapID: %u (%s)", currentMapID, reason); g_api->Log(ELogLevel_INFO, "GolemHelper", buffer); } }