New Features: - Added Coordinate Calibration - manually calibrate click positions for unsupported resolutions, UI scales, or custom Windows DPI settings via addon options - Calibration values are saved persistently and applied globally to all click sequences UI Improvements: - Moved "Current template" indicator inside the Templates tab - also resolves window stretching on certain resolutions - Added hint below delay settings to suggest calibration if clicks miss Technical Changes: - Fixed implicit size_t to int conversion warning in template list rendering
253 lines
No EOL
9.4 KiB
C++
253 lines
No EOL
9.4 KiB
C++
#include <Windows.h>
|
|
#include <string>
|
|
#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;
|
|
|
|
// Ultrawide 5120x1440
|
|
if (g_nexusLink->Width == 5120 && g_nexusLink->Height == 1440) {
|
|
if (uiScale >= 0.89f && uiScale <= 0.91f) {
|
|
dpiScaleX = 2.814f;
|
|
dpiScaleY = 0.888f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 5120x1440: APPLIED SMALL UI OFFSET");
|
|
}
|
|
else if (uiScale >= 1.09f && uiScale <= 1.15f) {
|
|
dpiScaleX = 2.746f;
|
|
dpiScaleY = 1.104f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 5120x1440: APPLIED LARGE UI OFFSET");
|
|
}
|
|
else if (uiScale >= 1.21f && uiScale <= 1.25f) {
|
|
dpiScaleX = 2.713f;
|
|
dpiScaleY = 1.208f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 5120x1440: APPLIED LARGER UI OFFSET");
|
|
}
|
|
else {
|
|
dpiScaleX = 2.779f;
|
|
dpiScaleY = 1.000f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 5120x1440: APPLIED NORMAL UI OFFSET");
|
|
}
|
|
}
|
|
// Ultrawide 3440x1440
|
|
else if (g_nexusLink->Width == 3440 && g_nexusLink->Height == 1440) {
|
|
if (uiScale >= 0.89f && uiScale <= 0.91f) {
|
|
dpiScaleX = 1.810f;
|
|
dpiScaleY = 0.892f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 3440x1440: APPLIED SMALL UI OFFSET");
|
|
}
|
|
else if (uiScale >= 1.09f && uiScale <= 1.15f) {
|
|
dpiScaleX = 1.741f;
|
|
dpiScaleY = 1.104f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 3440x1440: APPLIED LARGE UI OFFSET");
|
|
}
|
|
else if (uiScale >= 1.21f && uiScale <= 1.25f) {
|
|
dpiScaleX = 1.708f;
|
|
dpiScaleY = 1.212f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 3440x1440: APPLIED LARGER UI OFFSET");
|
|
}
|
|
else {
|
|
dpiScaleX = 1.773f;
|
|
dpiScaleY = 0.992f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 3440x1440: APPLIED NORMAL UI OFFSET");
|
|
}
|
|
}
|
|
else if (g_nexusLink->Width == 3840 && g_nexusLink->Height == 2160) {
|
|
if (uiScale >= 0.89f && uiScale <= 0.91f) {
|
|
dpiScaleX = 2.052f;
|
|
dpiScaleY = 0.908f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "4K 3840x2160: APPLIED SMALL UI OFFSET");
|
|
}
|
|
else if (uiScale >= 1.09f && uiScale <= 1.15f) {
|
|
dpiScaleX = 1.985f;
|
|
dpiScaleY = 1.130f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "4K 3840x2160: APPLIED LARGE UI OFFSET");
|
|
}
|
|
else if (uiScale >= 1.21f && uiScale <= 1.25f) {
|
|
dpiScaleX = 1.952f;
|
|
dpiScaleY = 1.233f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "4K 3840x2160: APPLIED LARGER UI OFFSET");
|
|
}
|
|
else {
|
|
dpiScaleX = 2.0f;
|
|
dpiScaleY = 1.0f;
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "4K 3840x2160: APPLIED NORMAL UI OFFSET");
|
|
}
|
|
}
|
|
else {
|
|
dpiScaleX = (float)g_nexusLink->Width / 1920.0f;
|
|
dpiScaleY = 1.0f;
|
|
|
|
char normalBuffer[150];
|
|
sprintf_s(normalBuffer, "NORMAL MONITOR: Width=%d, Height=%d, scaleX=%.3f",
|
|
g_nexusLink->Width, g_nexusLink->Height, dpiScaleX);
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", normalBuffer);
|
|
}
|
|
|
|
int scaledForResolutionX = (int)(baseX * dpiScaleX);
|
|
int scaledForResolutionY = (int)(baseY * dpiScaleY);
|
|
|
|
int finalX = scaledForResolutionX;
|
|
int finalY = scaledForResolutionY;
|
|
|
|
if (!(g_nexusLink->Width == 5120 && g_nexusLink->Height == 1440) &&
|
|
!(g_nexusLink->Width == 3440 && g_nexusLink->Height == 1440) &&
|
|
!(g_nexusLink->Width == 3840 && g_nexusLink->Height == 2160)) {
|
|
if (uiScale >= 0.89f && uiScale <= 0.91f) {
|
|
finalX = scaledForResolutionX - (int)(scaledForResolutionX * 0.029f);
|
|
finalY = scaledForResolutionY - (int)(scaledForResolutionY * 0.103f);
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "APPLIED SMALL UI OFFSET");
|
|
}
|
|
else if (uiScale >= 1.09f && uiScale <= 1.15f) {
|
|
finalX = scaledForResolutionX - (int)(scaledForResolutionX * 0.053f);
|
|
finalY = scaledForResolutionY + (int)(scaledForResolutionY * 0.095f);
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", "APPLIED LARGE UI OFFSET");
|
|
}
|
|
else if (uiScale >= 1.21f && uiScale <= 1.25f) {
|
|
finalX = scaledForResolutionX - (int)(scaledForResolutionX * 0.097f);
|
|
finalY = scaledForResolutionY + (int)(scaledForResolutionY * 0.206f);
|
|
}
|
|
}
|
|
|
|
*scaledX = finalX;
|
|
*scaledY = finalY;
|
|
}
|
|
else {
|
|
g_api->Log(ELogLevel_WARNING, "GolemHelper", "GetScaledCoordinates - Nexus data not available");
|
|
|
|
int screenWidth = GetSystemMetrics(SM_CXSCREEN);
|
|
float dpiScale = (float)screenWidth / 1920.0f;
|
|
|
|
*scaledX = (int)(baseX * dpiScale);
|
|
*scaledY = baseY;
|
|
}
|
|
}
|
|
|
|
void CoordinateUtils::DebugMousePosition() {
|
|
if (!g_api) return;
|
|
|
|
POINT mousePos;
|
|
GetCursorPos(&mousePos);
|
|
|
|
if (g_nexusLink && g_nexusLink->Width > 0 && g_nexusLink->Height > 0) {
|
|
float uiScale = g_nexusLink->Scaling;
|
|
float dpiScale = (float)g_nexusLink->Width / 1920.0f;
|
|
float finalScaleX = uiScale * dpiScale;
|
|
|
|
int baseX = (int)(mousePos.x / finalScaleX);
|
|
int baseY = mousePos.y;
|
|
|
|
g_state.debugCounter++;
|
|
|
|
char buffer[450];
|
|
sprintf_s(buffer, "=== DEBUG #%d === Resolution: %dx%d | Mouse: %d,%d | Base coords: %d,%d | Interface Size: %.2f | DPI Scale: %.3f | Final ScaleX: %.3f",
|
|
g_state.debugCounter, g_nexusLink->Width, g_nexusLink->Height,
|
|
mousePos.x, mousePos.y, baseX, baseY, uiScale, dpiScale, finalScaleX);
|
|
g_api->Log(ELogLevel_INFO, "GolemHelper", buffer);
|
|
}
|
|
else {
|
|
g_api->Log(ELogLevel_WARNING, "GolemHelper", "Cannot debug - Nexus data not available");
|
|
}
|
|
}
|
|
|
|
void CoordinateUtils::ClickAtScaled(int baseX, int baseY, int delay) {
|
|
if (g_mumbleData && !g_mumbleData->Context.IsGameFocused) {
|
|
if (g_api) {
|
|
g_api->Log(ELogLevel_WARNING, "GolemHelper", "Sequence stopped - Game lost focus");
|
|
}
|
|
return;
|
|
}
|
|
|
|
HWND gameWindow = GetForegroundWindow();
|
|
if (!gameWindow) return;
|
|
|
|
int scaledX, scaledY;
|
|
GetScaledCoordinates(baseX, baseY, &scaledX, &scaledY);
|
|
|
|
LPARAM lParam = MAKELPARAM(scaledX, scaledY);
|
|
SendMessage(gameWindow, WM_LBUTTONDOWN, MK_LBUTTON, lParam);
|
|
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;
|
|
} |