diff --git a/GolemHelper/Automation/CoordinateUtils.cpp b/GolemHelper/Automation/CoordinateUtils.cpp index a1184e7..3b23a9b 100644 --- a/GolemHelper/Automation/CoordinateUtils.cpp +++ b/GolemHelper/Automation/CoordinateUtils.cpp @@ -2,10 +2,17 @@ #include #include "CoordinateUtils.h" #include "../Common/Globals.h" +#include "../Config/ConfigManager.h" void CoordinateUtils::GetScaledCoordinates(int baseX, int baseY, int* scaledX, int* scaledY) { if (!g_api) return; + if (g_state.hasCalibration) { + *scaledX = (int)(baseX * g_state.calibratedScaleX); + *scaledY = (int)(baseY * g_state.calibratedScaleY); + return; + } + if (g_nexusLink && g_nexusLink->Width > 0 && g_nexusLink->Height > 0) { float uiScale = g_nexusLink->Scaling; float dpiScaleX, dpiScaleY; @@ -173,4 +180,74 @@ void CoordinateUtils::ClickAtScaled(int baseX, int baseY, int delay) { Sleep(10); SendMessage(gameWindow, WM_LBUTTONUP, 0, lParam); Sleep(delay); +} + +void CoordinateUtils::StartCalibration() { + g_state.calibrationMode = true; + g_state.showUI = false; + + if (g_api) { + g_api->Log(ELogLevel_INFO, "GolemHelper", + "Calibration started - interact with the Boon Console and click 'Adjust Self'"); + } +} + +void CoordinateUtils::CaptureCalibrationPoint() { + POINT mousePos; + GetCursorPos(&mousePos); + + const float REF_BASE_X = 830.0f; + const float REF_BASE_Y = 262.0f; + + g_state.calibratedScaleX = mousePos.x / REF_BASE_X; + g_state.calibratedScaleY = mousePos.y / REF_BASE_Y; + g_state.hasCalibration = true; + g_state.calibrationMode = false; + + ConfigManager::SaveCustomDelaySettings(); + + if (g_api) { + char buffer[256]; + sprintf_s(buffer, + "Calibration saved: click=(%ld, %ld) scaleX=%.4f scaleY=%.4f", + mousePos.x, mousePos.y, + g_state.calibratedScaleX, g_state.calibratedScaleY); + g_api->Log(ELogLevel_INFO, "GolemHelper", buffer); + g_api->UI.SendAlert("Calibration saved!"); + } +} + +void CoordinateUtils::ResetCalibration() { + g_state.hasCalibration = false; + g_state.calibrationMode = false; + g_state.calibratedScaleX = 1.0f; + g_state.calibratedScaleY = 1.0f; + + ConfigManager::SaveCustomDelaySettings(); + + if (g_api) { + g_api->Log(ELogLevel_INFO, "GolemHelper", "Calibration reset - back to auto-scaling"); + g_api->UI.SendAlert("Calibration reset to default"); + } +} + +void CoordinateUtils::UpdateCalibrationCapture() { + if (!g_state.calibrationMode) return; + + if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) { + g_state.calibrationMode = false; + if (g_api) g_api->UI.SendAlert("Calibration cancelled"); + return; + } + + static bool s_wasPressed = false; + bool isPressed = (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0; + + if (isPressed && !s_wasPressed) { + if (g_mumbleData && g_mumbleData->Context.IsGameFocused) { + CaptureCalibrationPoint(); + } + } + + s_wasPressed = isPressed; } \ No newline at end of file diff --git a/GolemHelper/Automation/CoordinateUtils.h b/GolemHelper/Automation/CoordinateUtils.h index c89cbc1..60b687b 100644 --- a/GolemHelper/Automation/CoordinateUtils.h +++ b/GolemHelper/Automation/CoordinateUtils.h @@ -5,4 +5,9 @@ public: static void GetScaledCoordinates(int baseX, int baseY, int* scaledX, int* scaledY); static void DebugMousePosition(); static void ClickAtScaled(int baseX, int baseY, int delay = 25); + + static void StartCalibration(); + static void CaptureCalibrationPoint(); + static void ResetCalibration(); + static void UpdateCalibrationCapture(); }; \ No newline at end of file diff --git a/GolemHelper/Common/Types.h b/GolemHelper/Common/Types.h index 8a2a9b1..52e2285 100644 --- a/GolemHelper/Common/Types.h +++ b/GolemHelper/Common/Types.h @@ -155,6 +155,12 @@ struct GolemHelperState { bool quickAccessVisible = false; unsigned int lastMapID = 0; + // Calibration + bool calibrationMode = false; + bool hasCalibration = false; + float calibratedScaleX = 1.0f; + float calibratedScaleY = 1.0f; + std::vector templates; int selectedTemplateIndex = -1; int lastUserTemplateIndex = -1; diff --git a/GolemHelper/Config/ConfigManager.cpp b/GolemHelper/Config/ConfigManager.cpp index dc6268b..9704326 100644 --- a/GolemHelper/Config/ConfigManager.cpp +++ b/GolemHelper/Config/ConfigManager.cpp @@ -24,6 +24,9 @@ void ConfigManager::SaveCustomDelaySettings() { configFile << "alwaysHideIcon=" << (g_state.alwaysHideIcon ? "1" : "0") << std::endl; configFile << "autoShowHideUI=" << (g_state.autoShowHideUI ? "1" : "0") << std::endl; configFile << "alwaysLoadLastSettings=" << (g_state.alwaysLoadLastSettings ? "1" : "0") << std::endl; + configFile << "hasCalibration=" << (g_state.hasCalibration ? "1" : "0") << std::endl; + configFile << "calibratedScaleX=" << g_state.calibratedScaleX << std::endl; + configFile << "calibratedScaleY=" << g_state.calibratedScaleY << std::endl; configFile.close(); @@ -84,6 +87,23 @@ void ConfigManager::LoadCustomDelaySettings() { else if (key == "alwaysLoadLastSettings") { g_state.alwaysLoadLastSettings = (value == "1"); } + else if (key == "hasCalibration") { + g_state.hasCalibration = (value == "1"); + } + else if (key == "calibratedScaleX") { + try { + float v = std::stof(value); + if (v > 0.1f && v < 10.0f) g_state.calibratedScaleX = v; + } + catch (...) {} + } + else if (key == "calibratedScaleY") { + try { + float v = std::stof(value); + if (v > 0.1f && v < 10.0f) g_state.calibratedScaleY = v; + } + catch (...) {} + } } configFile.close(); diff --git a/GolemHelper/GolemHelper.cpp b/GolemHelper/GolemHelper.cpp index ba247d3..7d2bd6e 100644 --- a/GolemHelper/GolemHelper.cpp +++ b/GolemHelper/GolemHelper.cpp @@ -40,7 +40,7 @@ void Load(AddonAPI* aApi) { MapUtils::UpdateQuickAccessVisibility(); - g_api->Log(ELogLevel_INFO, "GolemHelper", "=== GolemHelper v1.6.0.0 Loaded ==="); + g_api->Log(ELogLevel_INFO, "GolemHelper", "=== GolemHelper v1.7.0.0 Loaded ==="); g_api->Log(ELogLevel_INFO, "GolemHelper", "GolemHelper addon loaded successfully!"); } @@ -67,7 +67,7 @@ extern "C" __declspec(dllexport) AddonDefinition* GetAddonDef() { def.Signature = -424248; def.APIVersion = NEXUS_API_VERSION; def.Name = "GolemHelper"; - def.Version = { 1, 6, 0, 0 }; + def.Version = { 1, 7, 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/UI/UIManager.cpp b/GolemHelper/UI/UIManager.cpp index 93d9df1..b414803 100644 --- a/GolemHelper/UI/UIManager.cpp +++ b/GolemHelper/UI/UIManager.cpp @@ -5,11 +5,14 @@ #include "../Config/ConfigManager.h" #include "../Utils/MapUtils.h" #include "../Config/TemplateManager.h" +#include "../Automation/CoordinateUtils.h" #include "../Dependencies/imgui/imgui.h" void UIManager::RenderUI() { MapUtils::UpdateQuickAccessVisibility(); + CoordinateUtils::UpdateCalibrationCapture(); + if (!g_state.showUI) return; ImGui::SetNextWindowSize(ImVec2(450, 600), ImGuiCond_FirstUseEver); @@ -17,7 +20,7 @@ void UIManager::RenderUI() { if (ImGui::Begin("GolemHelper", &g_state.showUI, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::TextColored(ImVec4(0.2f, 0.8f, 1.0f, 1.0f), "GolemHelper v1.6.0.0"); + ImGui::TextColored(ImVec4(0.2f, 0.8f, 1.0f, 1.0f), "GolemHelper v1.7.0.0"); ImGui::Separator(); if (ImGui::BeginTabBar("GolemHelperTabs", ImGuiTabBarFlags_None)) { @@ -28,46 +31,6 @@ void UIManager::RenderUI() { } if (ImGui::BeginTabItem("Templates")) { - ImGui::SameLine(); - ImGui::SetCursorPosX(ImGui::GetWindowWidth() - 130); - - 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.skipBurning == g_state.skipBurning && - temp.skipConfusion == g_state.skipConfusion && - temp.skipSlow == g_state.skipSlow && - temp.addImmobilize == g_state.addImmobilize && - temp.addBlind == g_state.addBlind && - temp.fiveBleedingStacks == g_state.fiveBleedingStacks && - temp.hitboxType == g_state.hitboxType && - temp.addResistance == g_state.addResistance && - temp.addStability == g_state.addStability && - temp.skipAegis == g_state.skipAegis) { - currentTemplateName = temp.name; - foundMatchingTemplate = true; - break; - } - } - - ImGui::Text("Current: "); - ImGui::SameLine(); - if (foundMatchingTemplate) { - std::string truncatedName = currentTemplateName; - if (truncatedName.length() > 8) { - truncatedName = truncatedName.substr(0, 6) + ".."; - } - ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "%s", truncatedName.c_str()); - } - else { - ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "None"); - } - RenderTemplatesTab(); ImGui::EndTabItem(); } @@ -264,6 +227,7 @@ void UIManager::RenderSettingsTab() { ImGui::Spacing(); ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.2f, 1.0f), "Increase delays if clicks fail"); + ImGui::TextColored(ImVec4(0.8f, 0.8f, 0.2f, 1.0f), "or calibrate in Options"); if (oldStepDelay != g_state.stepDelay || oldInitialDelay != g_state.initialDelay) { ConfigManager::SaveCustomDelaySettings(); @@ -329,6 +293,41 @@ void UIManager::RenderSettingsTab() { } void UIManager::RenderTemplatesTab() { + + 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.skipBurning == g_state.skipBurning && + temp.skipConfusion == g_state.skipConfusion && + temp.skipSlow == g_state.skipSlow && + temp.addImmobilize == g_state.addImmobilize && + temp.addBlind == g_state.addBlind && + temp.fiveBleedingStacks == g_state.fiveBleedingStacks && + temp.hitboxType == g_state.hitboxType && + temp.addResistance == g_state.addResistance && + temp.addStability == g_state.addStability && + temp.skipAegis == g_state.skipAegis) { + currentTemplateName = temp.name; + foundMatchingTemplate = true; + break; + } + } + + ImGui::Spacing(); + ImGui::Text("Current: "); + ImGui::SameLine(); + if (foundMatchingTemplate) { + 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"); + } + ImGui::Separator(); ImGui::Spacing(); if (ImGui::Button("Apply Boons", ImVec2(110, 0))) { @@ -407,7 +406,7 @@ void UIManager::RenderTemplatesTab() { } ImGui::SetNextItemWidth(170); - if (ImGui::Combo("##templateList", ¤tUserIndex, userTemplateNames.data(), userTemplateNames.size())) { + if (ImGui::Combo("##templateList", ¤tUserIndex, userTemplateNames.data(), (int)userTemplateNames.size())) { g_state.selectedTemplateIndex = userTemplateIndices[currentUserIndex]; g_state.lastUserTemplateIndex = userTemplateIndices[currentUserIndex]; } @@ -535,7 +534,7 @@ void UIManager::RenderTemplatesTab() { TemplateManager::LoadTemplate(templateIndex); g_state.selectedTemplateIndex = -1; } - if (i < 2) ImGui::SameLine(0, 5);; + if (i < 2) ImGui::SameLine(0, 5); } } @@ -556,7 +555,7 @@ void UIManager::RenderTemplatesTab() { TemplateManager::LoadTemplate(templateIndex); g_state.selectedTemplateIndex = -1; } - if (i == 3) ImGui::SameLine(0, 5);; + if (i == 3) ImGui::SameLine(0, 5); } } } @@ -588,4 +587,54 @@ void UIManager::RenderOptions() { } ImGui::Checkbox("Enable debug mode", &g_state.debugMode); + + 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("Coordinate Calibration")) { + + ImGui::Spacing(); + + if (g_state.calibrationMode) { + ImGui::TextColored(ImVec4(1.0f, 0.85f, 0.0f, 1.0f), "! Calibration active !"); + ImGui::Spacing(); + ImGui::TextWrapped("1. Interact with the Boon Console (press F)"); + ImGui::TextWrapped("2. Hover your mouse over the middle of \"Adjust Self\" and click."); + ImGui::Spacing(); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "The addon window is hidden."); + ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "Press ESC to cancel."); + } + else { + if (g_state.hasCalibration) { + ImGui::TextColored(ImVec4(0.2f, 1.0f, 0.4f, 1.0f), "Status: Calibrated"); + ImGui::Text("scaleX: %.4f scaleY: %.4f", + g_state.calibratedScaleX, g_state.calibratedScaleY); + } + else { + ImGui::TextColored(ImVec4(0.75f, 0.75f, 0.75f, 1.0f), "Status: Auto-scaling (default)"); + } + + ImGui::Spacing(); + + if (ImGui::Button("Calibrate", ImVec2(120, 0))) { + CoordinateUtils::StartCalibration(); + } + + if (g_state.hasCalibration) { + ImGui::SameLine(0, 6); + if (ImGui::Button("Reset to Default", ImVec2(120, 0))) { + CoordinateUtils::ResetCalibration(); + } + } + + ImGui::Spacing(); + ImGui::TextDisabled("Interact with the Boon Console, then hover over"); + ImGui::TextDisabled("the middle of \"Adjust Self\" and click."); + } + + ImGui::Spacing(); + } + ImGui::PopStyleColor(2); } \ No newline at end of file