Compare commits

...

7 commits

Author SHA1 Message Date
Azrub
39ca3d919b Release: v1.7.1.0
Finally self-hosted! Migrated from GitHub to my own Forgejo instance here. Full development history, all commits and tags are intact — nothing lost. Future updates will be distributed from here. Welcome to the new home of GolemHelper!
2026-04-15 01:09:51 +02:00
Azrub
d035d14587 Release v1.7.0.0
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
2026-04-02 00:53:28 +02:00
Azrub
a334cadd83 Release v1.6.0.0
New Features:

- Added "Remove and Respawn" button
- Added "Respawn" and "Remove and Respawn" buttons to Templates tab for quick access
- Added "Always Load Last Settings" option - automatically saves and restores your last used settings on startup

UI Improvements:

- Improved button spacing and layout consistency
2025-10-29 21:10:18 +01:00
Azrub
0faba02a60 Release v1.5.3.0
Added support for 3840x2160 monitor
2025-08-24 15:29:44 +02:00
Azrub
f6055f946c Release v1.5.2.0
Added Respawn Golem button
2025-08-12 12:13:11 +02:00
Azrub
98c51aa098 Release v1.5.1.0
New Features:

- Auto Show/Hide UI: New setting that automatically shows/hides the UI when entering/exiting Training Area

Technical Changes:

Architecture refactor; replaced coordinate arrays and magic numbers with enum-based system:

- NEW: MenuSequences.h - Centralized sequence definitions with clean logic
- REFACTORED: Types.h - Semantic enum structure mapping GW2 interface 1:1 (BOON_ALACRITY vs stepIndex == 13)
- REFACTORED: AutomationLogic.cpp - Eliminated all magic numbers, unified healer logic
- Improved maintainability
- Enhanced readability: Self-documenting code with meaningful names like GOLEM_SLOW instead of array indices
2025-08-08 03:56:11 +02:00
Azrub
54233f6ac1 Hotfix: restored deleted coordinate
Restored deleted coordinate
2025-08-06 05:41:08 +02:00
15 changed files with 934 additions and 243 deletions

View file

@ -2,18 +2,21 @@
#include <string> #include <string>
#include "AutomationLogic.h" #include "AutomationLogic.h"
#include "../Common/Globals.h" #include "../Common/Globals.h"
#include "../Common/MenuSequences.h"
#include "CoordinateUtils.h" #include "CoordinateUtils.h"
bool AutomationLogic::ShouldSkipBoonStep(int stepIndex) { bool AutomationLogic::ShouldSkipBoonStep(int stepIndex) {
if (g_state.isQuickDps && stepIndex == 14) { MenuOption step = MenuSequences::BOON_SEQUENCE[stepIndex];
if (g_state.isQuickDps && step == BOON_QUICKNESS) {
return true; return true;
} }
if (g_state.isAlacDps && (stepIndex == 13 || stepIndex == 18)) { if (g_state.isAlacDps && step == BOON_ALACRITY) {
return true; return true;
} }
if (g_state.showBoonAdvanced && g_state.skipAegis && stepIndex == 10) { if (g_state.showBoonAdvanced && g_state.skipAegis && step == BOON_AEGIS) {
return true; return true;
} }
@ -25,15 +28,17 @@ bool AutomationLogic::ShouldSkipGolemStep(int stepIndex) {
return false; return false;
} }
if (g_state.skipBurning && stepIndex == 7) { MenuOption step = MenuSequences::GOLEM_SEQUENCE[stepIndex];
if (g_state.skipBurning && step == GOLEM_BURNING) {
return true; return true;
} }
if (g_state.skipConfusion && stepIndex == 8) { if (g_state.skipConfusion && step == GOLEM_CONFUSION) {
return true; return true;
} }
if (g_state.skipSlow && stepIndex == 17) { if (g_state.skipSlow && step == GOLEM_SLOW) {
return true; return true;
} }
@ -50,10 +55,10 @@ void AutomationLogic::ApplyHealerBoons() {
std::string mode = "Healer Bench - "; std::string mode = "Healer Bench - ";
if (g_state.isQuickDps) { if (g_state.isQuickDps) {
mode += "Quick DPS (Healer provides Alacrity)"; mode += "Quick DPS";
} }
else if (g_state.isAlacDps) { else if (g_state.isAlacDps) {
mode += "Alac DPS (Healer provides Quickness)"; mode += "Alac DPS";
} }
mode += " + Environment "; mode += " + Environment ";
@ -71,27 +76,47 @@ void AutomationLogic::ApplyHealerBoons() {
g_api->GameBinds.InvokeAsync(EGameBinds_MiscInteract, 50); g_api->GameBinds.InvokeAsync(EGameBinds_MiscInteract, 50);
Sleep(g_state.initialDelay); Sleep(g_state.initialDelay);
if (g_state.isQuickDps) { bool alacrityCounted = false;
for (int i = 0; i < 10; i++) { for (int i = 0; i < MenuSequences::HEALER_QUICK_LENGTH; i++) {
CoordinateUtils::ClickAtScaled(g_coords.healerStepX[i], g_coords.healerStepY[i], g_state.stepDelay); MenuOption step = MenuSequences::HEALER_QUICK_SEQUENCE[i];
if (g_state.isAlacDps && step == BOON_ALACRITY) {
if (!alacrityCounted) {
auto quicknessCoord = g_coords.coords.find(BOON_QUICKNESS);
if (quicknessCoord != g_coords.coords.end()) {
CoordinateUtils::ClickAtScaled(
quicknessCoord->second.first,
quicknessCoord->second.second,
g_state.stepDelay
);
} }
alacrityCounted = true;
} }
else if (g_state.isAlacDps) { continue;
int alacStepY[9] = { 262, 352, 352, 305, 500, 450, 450, 305, 262 }; }
for (int i = 0; i < 9; i++) {
CoordinateUtils::ClickAtScaled(830, alacStepY[i], g_state.stepDelay); auto coordIt = g_coords.coords.find(step);
if (coordIt != g_coords.coords.end()) {
CoordinateUtils::ClickAtScaled(
coordIt->second.first,
coordIt->second.second,
g_state.stepDelay
);
} }
} }
int finalY; MenuOption envDamageOption;
switch (g_state.envDamageLevel) { switch (g_state.envDamageLevel) {
case ENV_MILD: finalY = 352; break; case ENV_MILD: envDamageOption = BOON_ENV_MILD; break;
case ENV_MODERATE: finalY = 305; break; case ENV_MODERATE: envDamageOption = BOON_ENV_MODERATE; break;
case ENV_EXTREME: finalY = 262; break; case ENV_EXTREME: envDamageOption = BOON_ENV_EXTREME; break;
default: finalY = 352; break; default: envDamageOption = BOON_ENV_MILD; break;
} }
CoordinateUtils::ClickAtScaled(830, finalY, 50); auto envCoord = g_coords.coords.find(envDamageOption);
if (envCoord != g_coords.coords.end()) {
CoordinateUtils::ClickAtScaled(envCoord->second.first, envCoord->second.second, 50);
}
} }
catch (...) { catch (...) {
g_api->Log(ELogLevel_WARNING, "GolemHelper", "Exception during healer boon sequence"); g_api->Log(ELogLevel_WARNING, "GolemHelper", "Exception during healer boon sequence");
@ -104,7 +129,7 @@ void AutomationLogic::ApplyHealerBoons() {
g_api->Log(ELogLevel_INFO, "GolemHelper", "Healer boon sequence completed!"); g_api->Log(ELogLevel_INFO, "GolemHelper", "Healer boon sequence completed!");
} }
void AutomationLogic::ApplyAllBoons() { void AutomationLogic::ApplyBoons() {
if (!g_api || !g_state.enabled) return; if (!g_api || !g_state.enabled) return;
if (g_state.environmentDamage) { if (g_state.environmentDamage) {
@ -142,31 +167,54 @@ void AutomationLogic::ApplyAllBoons() {
g_api->GameBinds.InvokeAsync(EGameBinds_MiscInteract, 50); g_api->GameBinds.InvokeAsync(EGameBinds_MiscInteract, 50);
Sleep(g_state.initialDelay); Sleep(g_state.initialDelay);
for (int i = 0; i < 20; i++) { for (int i = 0; i < MenuSequences::BOON_LENGTH; i++) {
if (g_coords.boonStepX[i] == 0 && g_coords.boonStepY[i] == 0) { int stepIndex = i;
MenuOption step = MenuSequences::BOON_SEQUENCE[i];
auto coordIt = g_coords.coords.find(step);
if (coordIt == g_coords.coords.end() ||
(coordIt->second.first == 0 && coordIt->second.second == 0)) {
continue; continue;
} }
if (ShouldSkipBoonStep(i)) { if (ShouldSkipBoonStep(stepIndex)) {
continue; continue;
} }
if (i == 9) { if (step == BOON_RESOLUTION) {
CoordinateUtils::ClickAtScaled(g_coords.boonStepX[i], g_coords.boonStepY[i], g_state.stepDelay); CoordinateUtils::ClickAtScaled(
coordIt->second.first,
coordIt->second.second,
g_state.stepDelay
);
if (g_state.showBoonAdvanced && g_state.addResistance) { if (g_state.showBoonAdvanced && g_state.addResistance) {
CoordinateUtils::ClickAtScaled(g_coords.resistanceX, g_coords.resistanceY, g_state.stepDelay); auto resistanceCoord = g_coords.coords.find(BOON_RESISTANCE);
if (resistanceCoord != g_coords.coords.end()) {
CoordinateUtils::ClickAtScaled(
resistanceCoord->second.first,
resistanceCoord->second.second,
g_state.stepDelay
);
}
} }
if (g_state.showBoonAdvanced && g_state.addStability) { if (g_state.showBoonAdvanced && g_state.addStability) {
CoordinateUtils::ClickAtScaled(g_coords.stabilityX, g_coords.stabilityY, g_state.stepDelay); auto stabilityCoord = g_coords.coords.find(BOON_STABILITY);
if (stabilityCoord != g_coords.coords.end()) {
CoordinateUtils::ClickAtScaled(
stabilityCoord->second.first,
stabilityCoord->second.second,
g_state.stepDelay
);
}
} }
continue; continue;
} }
int delay = (i == 19) ? 50 : g_state.stepDelay; int delay = (i == MenuSequences::BOON_LENGTH - 1) ? 50 : g_state.stepDelay;
CoordinateUtils::ClickAtScaled(g_coords.boonStepX[i], g_coords.boonStepY[i], delay); CoordinateUtils::ClickAtScaled(coordIt->second.first, coordIt->second.second, delay);
} }
} }
catch (...) { catch (...) {
@ -180,7 +228,7 @@ void AutomationLogic::ApplyAllBoons() {
g_api->Log(ELogLevel_INFO, "GolemHelper", "Boon sequence completed!"); g_api->Log(ELogLevel_INFO, "GolemHelper", "Boon sequence completed!");
} }
void AutomationLogic::ApplyGolemSettings() { void AutomationLogic::SpawnGolem() {
if (!g_api || !g_state.enabled) return; if (!g_api || !g_state.enabled) return;
bool uiWasVisible = g_state.showUI; bool uiWasVisible = g_state.showUI;
@ -205,56 +253,77 @@ void AutomationLogic::ApplyGolemSettings() {
} }
char startBuffer[400]; char startBuffer[400];
sprintf_s(startBuffer, "Starting golem settings sequence (24 steps) - Modifiers: %s, Hitbox: %s", modifiers.c_str(), hitbox); sprintf_s(startBuffer, "Starting golem settings sequence (25 steps) - Modifiers: %s, Hitbox: %s", modifiers.c_str(), hitbox);
g_api->Log(ELogLevel_INFO, "GolemHelper", startBuffer); g_api->Log(ELogLevel_INFO, "GolemHelper", startBuffer);
try { try {
g_api->GameBinds.InvokeAsync(EGameBinds_MiscInteract, 50); g_api->GameBinds.InvokeAsync(EGameBinds_MiscInteract, 50);
Sleep(g_state.initialDelay); Sleep(g_state.initialDelay);
for (int i = 0; i < 24; i++) { for (int i = 0; i < MenuSequences::GOLEM_LENGTH; i++) {
if (g_coords.golemStepX[i] == 0 && g_coords.golemStepY[i] == 0) { int stepIndex = i;
MenuOption step = MenuSequences::GOLEM_SEQUENCE[i];
auto coordIt = g_coords.coords.find(step);
if (coordIt == g_coords.coords.end() ||
(coordIt->second.first == 0 && coordIt->second.second == 0)) {
continue; continue;
} }
if (ShouldSkipGolemStep(i)) { if (ShouldSkipGolemStep(stepIndex)) {
continue; continue;
} }
int currentX = g_coords.golemStepX[i]; int currentX = coordIt->second.first;
int currentY = g_coords.golemStepY[i]; int currentY = coordIt->second.second;
if (i == 1) { if (step == GOLEM_HITBOX_SMALL) {
MenuOption hitboxOption;
switch (g_state.hitboxType) { switch (g_state.hitboxType) {
case HITBOX_SMALL: case HITBOX_SMALL: hitboxOption = GOLEM_HITBOX_SMALL; break;
currentY = 260; case HITBOX_MEDIUM: hitboxOption = GOLEM_HITBOX_MEDIUM; break;
break; case HITBOX_LARGE: hitboxOption = GOLEM_HITBOX_LARGE; break;
case HITBOX_MEDIUM: default: hitboxOption = GOLEM_HITBOX_SMALL; break;
currentY = 305; }
break;
case HITBOX_LARGE: auto hitboxCoord = g_coords.coords.find(hitboxOption);
currentY = 352; if (hitboxCoord != g_coords.coords.end()) {
break; currentX = hitboxCoord->second.first;
currentY = hitboxCoord->second.second;
} }
} }
int delay = (i == 23) ? 50 : g_state.stepDelay; int delay = (i == MenuSequences::GOLEM_LENGTH - 1) ? 50 : g_state.stepDelay;
if (i == 14) { if (step == GOLEM_CRIPPLE) {
CoordinateUtils::ClickAtScaled(currentX, currentY, delay); CoordinateUtils::ClickAtScaled(currentX, currentY, delay);
if (g_state.showAdvanced && g_state.addImmobilize) { if (g_state.showAdvanced && g_state.addImmobilize) {
CoordinateUtils::ClickAtScaled(g_coords.immobilizeX, g_coords.immobilizeY, g_state.stepDelay); auto immobilizeCoord = g_coords.coords.find(GOLEM_IMMOBILIZE);
if (immobilizeCoord != g_coords.coords.end()) {
CoordinateUtils::ClickAtScaled(
immobilizeCoord->second.first,
immobilizeCoord->second.second,
g_state.stepDelay
);
}
} }
continue; continue;
} }
if (i == 16) { if (step == GOLEM_COMBATAFFECTINGCONDITIONS) {
CoordinateUtils::ClickAtScaled(currentX, currentY, delay); CoordinateUtils::ClickAtScaled(currentX, currentY, delay);
if (g_state.showAdvanced && g_state.addBlind) { if (g_state.showAdvanced && g_state.addBlind) {
CoordinateUtils::ClickAtScaled(g_coords.blindX, g_coords.blindY, g_state.stepDelay); auto blindCoord = g_coords.coords.find(GOLEM_BLIND);
if (blindCoord != g_coords.coords.end()) {
CoordinateUtils::ClickAtScaled(
blindCoord->second.first,
blindCoord->second.second,
g_state.stepDelay
);
}
} }
continue; continue;
@ -262,7 +331,7 @@ void AutomationLogic::ApplyGolemSettings() {
CoordinateUtils::ClickAtScaled(currentX, currentY, delay); CoordinateUtils::ClickAtScaled(currentX, currentY, delay);
if (g_state.showAdvanced && g_state.fiveBleedingStacks && i == 6) { if (g_state.showAdvanced && g_state.fiveBleedingStacks && step == GOLEM_BLEEDING) {
for (int repeat = 0; repeat < 4; repeat++) { for (int repeat = 0; repeat < 4; repeat++) {
CoordinateUtils::ClickAtScaled(currentX, currentY, g_state.stepDelay); CoordinateUtils::ClickAtScaled(currentX, currentY, g_state.stepDelay);
} }
@ -277,5 +346,82 @@ void AutomationLogic::ApplyGolemSettings() {
g_state.showUI = true; g_state.showUI = true;
} }
g_api->Log(ELogLevel_INFO, "GolemHelper", "Golem settings sequence completed (24 steps)!"); g_api->Log(ELogLevel_INFO, "GolemHelper", "Golem settings sequence completed (25 steps)!");
}
void AutomationLogic::RespawnGolem() {
if (!g_api || !g_state.enabled) return;
bool uiWasVisible = g_state.showUI;
if (uiWasVisible) {
g_state.showUI = false;
}
g_api->Log(ELogLevel_INFO, "GolemHelper", "Starting golem respawn sequence (2 steps)");
try {
g_api->GameBinds.InvokeAsync(EGameBinds_MiscInteract, 50);
Sleep(g_state.initialDelay);
for (int i = 0; i < MenuSequences::GOLEM_RESPAWN_LENGTH; i++) {
MenuOption step = MenuSequences::GOLEM_RESPAWN[i];
auto coordIt = g_coords.coords.find(step);
if (coordIt == g_coords.coords.end() ||
(coordIt->second.first == 0 && coordIt->second.second == 0)) {
continue;
}
int delay = (i == MenuSequences::GOLEM_RESPAWN_LENGTH - 1) ? 50 : g_state.stepDelay;
CoordinateUtils::ClickAtScaled(coordIt->second.first, coordIt->second.second, delay);
}
}
catch (...) {
g_api->Log(ELogLevel_WARNING, "GolemHelper", "Exception during golem respawn sequence");
}
if (uiWasVisible) {
g_state.showUI = true;
}
g_api->Log(ELogLevel_INFO, "GolemHelper", "Golem respawn sequence completed!");
}
void AutomationLogic::RemoveAndRespawnGolem()
{
if (!g_api || !g_state.enabled) return;
bool uiWasVisible = g_state.showUI;
if (uiWasVisible) {
g_state.showUI = false;
}
g_api->Log(ELogLevel_INFO, "GolemHelper", "Starting golem remove and respawn sequence (3 steps)");
try {
g_api->GameBinds.InvokeAsync(EGameBinds_MiscInteract, 50);
Sleep(g_state.initialDelay);
for (int i = 0; i < MenuSequences::GOLEM_REMOVE_AND_RESPAWN_LENGTH; i++) {
MenuOption step = MenuSequences::GOLEM_REMOVE_AND_RESPAWN[i];
auto coordIt = g_coords.coords.find(step);
if (coordIt == g_coords.coords.end() ||
(coordIt->second.first == 0 && coordIt->second.second == 0)) {
continue;
}
int delay = (i == MenuSequences::GOLEM_REMOVE_AND_RESPAWN_LENGTH - 1) ? 50 : g_state.stepDelay;
CoordinateUtils::ClickAtScaled(coordIt->second.first, coordIt->second.second, delay);
}
}
catch (...) {
g_api->Log(ELogLevel_WARNING, "GolemHelper", "Exception during golem remove and respawn sequence");
}
if (uiWasVisible) {
g_state.showUI = true;
}
g_api->Log(ELogLevel_INFO, "GolemHelper", "Golem remove and respawn sequence completed!");
} }

View file

@ -4,7 +4,9 @@ class AutomationLogic {
public: public:
static bool ShouldSkipBoonStep(int stepIndex); static bool ShouldSkipBoonStep(int stepIndex);
static bool ShouldSkipGolemStep(int stepIndex); static bool ShouldSkipGolemStep(int stepIndex);
static void ApplyAllBoons(); static void ApplyBoons();
static void ApplyHealerBoons(); static void ApplyHealerBoons();
static void ApplyGolemSettings(); static void SpawnGolem();
static void RespawnGolem();
static void RemoveAndRespawnGolem();
}; };

View file

@ -2,10 +2,17 @@
#include <string> #include <string>
#include "CoordinateUtils.h" #include "CoordinateUtils.h"
#include "../Common/Globals.h" #include "../Common/Globals.h"
#include "../Config/ConfigManager.h"
void CoordinateUtils::GetScaledCoordinates(int baseX, int baseY, int* scaledX, int* scaledY) { void CoordinateUtils::GetScaledCoordinates(int baseX, int baseY, int* scaledX, int* scaledY) {
if (!g_api) return; 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) { if (g_nexusLink && g_nexusLink->Width > 0 && g_nexusLink->Height > 0) {
float uiScale = g_nexusLink->Scaling; float uiScale = g_nexusLink->Scaling;
float dpiScaleX, dpiScaleY; float dpiScaleX, dpiScaleY;
@ -56,6 +63,28 @@ void CoordinateUtils::GetScaledCoordinates(int baseX, int baseY, int* scaledX, i
g_api->Log(ELogLevel_INFO, "GolemHelper", "ULTRAWIDE 3440x1440: APPLIED NORMAL UI OFFSET"); 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 { else {
dpiScaleX = (float)g_nexusLink->Width / 1920.0f; dpiScaleX = (float)g_nexusLink->Width / 1920.0f;
dpiScaleY = 1.0f; dpiScaleY = 1.0f;
@ -73,7 +102,8 @@ void CoordinateUtils::GetScaledCoordinates(int baseX, int baseY, int* scaledX, i
int finalY = scaledForResolutionY; int finalY = scaledForResolutionY;
if (!(g_nexusLink->Width == 5120 && g_nexusLink->Height == 1440) && if (!(g_nexusLink->Width == 5120 && g_nexusLink->Height == 1440) &&
!(g_nexusLink->Width == 3440 && 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) { if (uiScale >= 0.89f && uiScale <= 0.91f) {
finalX = scaledForResolutionX - (int)(scaledForResolutionX * 0.029f); finalX = scaledForResolutionX - (int)(scaledForResolutionX * 0.029f);
finalY = scaledForResolutionY - (int)(scaledForResolutionY * 0.103f); finalY = scaledForResolutionY - (int)(scaledForResolutionY * 0.103f);
@ -151,3 +181,73 @@ void CoordinateUtils::ClickAtScaled(int baseX, int baseY, int delay) {
SendMessage(gameWindow, WM_LBUTTONUP, 0, lParam); SendMessage(gameWindow, WM_LBUTTONUP, 0, lParam);
Sleep(delay); 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;
}

View file

@ -5,4 +5,9 @@ public:
static void GetScaledCoordinates(int baseX, int baseY, int* scaledX, int* scaledY); static void GetScaledCoordinates(int baseX, int baseY, int* scaledX, int* scaledY);
static void DebugMousePosition(); static void DebugMousePosition();
static void ClickAtScaled(int baseX, int baseY, int delay = 25); static void ClickAtScaled(int baseX, int baseY, int delay = 25);
static void StartCalibration();
static void CaptureCalibrationPoint();
static void ResetCalibration();
static void UpdateCalibrationCapture();
}; };

View file

@ -0,0 +1,86 @@
#pragma once
#include "Types.h"
class MenuSequences {
public:
static constexpr MenuOption BOON_SEQUENCE[20] = {
BOON_ADJUSTSELF,
BOON_ADDBOONS,
BOON_OFFENSIVE,
BOON_MIGHT,
BOON_25MIGHT,
BOON_FURY,
BOON_RETURN1,
BOON_DEFENSIVE,
BOON_PROTECTION,
BOON_RESOLUTION,
BOON_AEGIS,
BOON_RETURN2,
BOON_UTILITY,
BOON_ALACRITY,
BOON_QUICKNESS,
BOON_REGENERATION,
BOON_SWIFTNESS,
BOON_VIGOR,
BOON_ALACRITY,
BOON_EXIT
};
static constexpr MenuOption HEALER_QUICK_SEQUENCE[10] = {
BOON_ADJUSTSELF,
BOON_ADDBOONS,
BOON_UTILITY,
BOON_ALACRITY,
BOON_ALACRITY,
BOON_RETURN3,
BOON_RETURN4,
BOON_GOBACK,
BOON_ADJUSTENVIRONMENT,
BOON_TOGGLEPULSINGARENADAMAGEON
};
static constexpr MenuOption GOLEM_SEQUENCE[25] = {
GOLEM_SPAWNAGOLEM,
GOLEM_HITBOX_SMALL,
GOLEM_AVERAGEENEMY,
GOLEM_ADDITIONALOPTIONS,
GOLEM_ADDCONDITIONS,
GOLEM_DAMAGEOVERTIMECONDITIONS,
GOLEM_BLEEDING,
GOLEM_BURNING,
GOLEM_CONFUSION,
GOLEM_POISON,
GOLEM_TORMENT,
GOLEM_GOBACK1,
GOLEM_MOBILITYAFFECTINGCONDITIONS,
GOLEM_CHILL,
GOLEM_CRIPPLE,
GOLEM_GOBACK2,
GOLEM_COMBATAFFECTINGCONDITIONS,
GOLEM_SLOW,
GOLEM_VULNERABILITY,
GOLEM_25VULNERABILITY,
GOLEM_GOBACK3,
GOLEM_WEAKNESS,
GOLEM_GOBACK4,
GOLEM_GOBACK5,
GOLEM_PLEASESPAWNMYGOLEM
};
static constexpr MenuOption GOLEM_RESPAWN[2] = {
GOLEM_RESPAWNMYPREVIOUSGOLEMINCARNATION,
GOLEM_EXIT
};
static constexpr MenuOption GOLEM_REMOVE_AND_RESPAWN[3] = {
GOLEM_REMOVEGOLEM,
GOLEM_RESPAWNMYPREVIOUSGOLEMINCARNATION,
GOLEM_EXIT
};
static constexpr int BOON_LENGTH = 20;
static constexpr int HEALER_QUICK_LENGTH = 10;
static constexpr int GOLEM_LENGTH = 25;
static constexpr int GOLEM_RESPAWN_LENGTH = 2;
static constexpr int GOLEM_REMOVE_AND_RESPAWN_LENGTH = 3;
};

View file

@ -2,6 +2,7 @@
#include "../Dependencies/mumble/mumble.h" #include "../Dependencies/mumble/mumble.h"
#include <vector> #include <vector>
#include <string> #include <string>
#include <map>
enum HitboxType { enum HitboxType {
HITBOX_SMALL = 0, HITBOX_SMALL = 0,
@ -15,6 +16,75 @@ enum EnvironmentDamageLevel {
ENV_EXTREME = 2 ENV_EXTREME = 2
}; };
enum MenuOption {
// === BOON MENU ===
BOON_ADJUSTSELF,
BOON_ADDBOONS,
BOON_OFFENSIVE,
BOON_MIGHT,
BOON_25MIGHT,
BOON_FURY,
BOON_RETURN1,
BOON_DEFENSIVE,
BOON_PROTECTION,
BOON_RESOLUTION,
BOON_RESISTANCE,
BOON_STABILITY,
BOON_AEGIS,
BOON_RETURN2,
BOON_UTILITY,
BOON_ALACRITY,
BOON_QUICKNESS,
BOON_REGENERATION,
BOON_SWIFTNESS,
BOON_VIGOR,
BOON_EXIT,
// === HEALER EXTENSIONS ===
BOON_RETURN3,
BOON_RETURN4,
BOON_GOBACK,
BOON_ADJUSTENVIRONMENT,
BOON_TOGGLEPULSINGARENADAMAGEON,
BOON_ENV_MILD,
BOON_ENV_MODERATE,
BOON_ENV_EXTREME,
// === GOLEM MENU ===
GOLEM_RESPAWNMYPREVIOUSGOLEMINCARNATION,
GOLEM_REMOVEGOLEM,
GOLEM_SPAWNAGOLEM,
GOLEM_HITBOX_SMALL,
GOLEM_HITBOX_MEDIUM,
GOLEM_HITBOX_LARGE,
GOLEM_AVERAGEENEMY,
GOLEM_ADDITIONALOPTIONS,
GOLEM_ADDCONDITIONS,
GOLEM_DAMAGEOVERTIMECONDITIONS,
GOLEM_BLEEDING,
GOLEM_BURNING,
GOLEM_CONFUSION,
GOLEM_POISON,
GOLEM_TORMENT,
GOLEM_GOBACK1,
GOLEM_MOBILITYAFFECTINGCONDITIONS,
GOLEM_CHILL,
GOLEM_CRIPPLE,
GOLEM_IMMOBILIZE,
GOLEM_GOBACK2,
GOLEM_COMBATAFFECTINGCONDITIONS,
GOLEM_BLIND,
GOLEM_SLOW,
GOLEM_VULNERABILITY,
GOLEM_25VULNERABILITY,
GOLEM_GOBACK3,
GOLEM_WEAKNESS,
GOLEM_GOBACK4,
GOLEM_GOBACK5,
GOLEM_PLEASESPAWNMYGOLEM,
GOLEM_EXIT
};
struct GolemTemplate { struct GolemTemplate {
std::string name; std::string name;
bool isQuickDps; bool isQuickDps;
@ -75,6 +145,8 @@ struct GolemHelperState {
bool addStability = false; bool addStability = false;
bool skipAegis = false; bool skipAegis = false;
bool alwaysHideIcon = false; bool alwaysHideIcon = false;
bool autoShowHideUI = false;
bool alwaysLoadLastSettings = false;
int debugCounter = 0; int debugCounter = 0;
int initialDelay = 390; int initialDelay = 390;
@ -83,6 +155,12 @@ struct GolemHelperState {
bool quickAccessVisible = false; bool quickAccessVisible = false;
unsigned int lastMapID = 0; unsigned int lastMapID = 0;
// Calibration
bool calibrationMode = false;
bool hasCalibration = false;
float calibratedScaleX = 1.0f;
float calibratedScaleY = 1.0f;
std::vector<GolemTemplate> templates; std::vector<GolemTemplate> templates;
int selectedTemplateIndex = -1; int selectedTemplateIndex = -1;
int lastUserTemplateIndex = -1; int lastUserTemplateIndex = -1;
@ -90,43 +168,72 @@ struct GolemHelperState {
}; };
struct MenuCoordinates { struct MenuCoordinates {
int golemStepX[24] = { std::map<MenuOption, std::pair<int, int>> coords = {
830, 830, 830, 830, 830, 830, 830, 830, 830, 830, // === BOON MENU ===
830, 830, 830, 830, 830, 830, 830, 830, 830, 830, {BOON_ADJUSTSELF, {830, 262}},
830, 830, 830, 830 {BOON_ADDBOONS, {830, 354}},
}; {BOON_OFFENSIVE, {830, 262}},
{BOON_MIGHT, {830, 262}},
{BOON_25MIGHT, {830, 400}},
{BOON_FURY, {830, 305}},
{BOON_RETURN1, {830, 354}},
{BOON_DEFENSIVE, {830, 305}},
{BOON_PROTECTION, {830, 262}},
{BOON_RESOLUTION, {830, 305}},
{BOON_RESISTANCE, {830, 354}},
{BOON_STABILITY, {830, 400}},
{BOON_AEGIS, {830, 450}},
{BOON_RETURN2, {830, 500}},
{BOON_UTILITY, {830, 354}},
{BOON_ALACRITY, {830, 262}},
{BOON_QUICKNESS, {830, 305}},
{BOON_REGENERATION, {830, 354}},
{BOON_SWIFTNESS, {830, 400}},
{BOON_VIGOR, {830, 450}},
{BOON_EXIT, {830, 550}},
int golemStepY[24] = { // === HEALER EXTENSIONS ===
260, 260, 306, 257, 257, 306, 257, 306, 352, 400, {BOON_RETURN3, {830, 500}},
454, 508, 352, 257, 306, 454, 400, 306, 352, 400, {BOON_RETURN4, {830, 450}},
454, 454, 454, 548 {BOON_GOBACK, {830, 450}},
}; {BOON_ADJUSTENVIRONMENT, {830, 305}},
{BOON_TOGGLEPULSINGARENADAMAGEON, {830, 262}},
{BOON_ENV_MILD, {830, 352}},
{BOON_ENV_MODERATE, {830, 305}},
{BOON_ENV_EXTREME, {830, 262}},
int boonStepX[20] = { // === GOLEM MENU ===
830, 830, 830, 830, 830, 830, 830, 830, 830, 830, {GOLEM_RESPAWNMYPREVIOUSGOLEMINCARNATION, {830, 352}},
830, 830, 830, 830, 830, 830, 830, 830, 830, 830 {GOLEM_REMOVEGOLEM, {830, 306}},
{GOLEM_SPAWNAGOLEM, {830, 260}},
{GOLEM_HITBOX_SMALL, {830, 260}},
{GOLEM_HITBOX_MEDIUM, {830, 305}},
{GOLEM_HITBOX_LARGE, {830, 352}},
{GOLEM_AVERAGEENEMY, {830, 306}},
{GOLEM_ADDITIONALOPTIONS, {830, 257}},
{GOLEM_ADDCONDITIONS, {830, 257}},
{GOLEM_DAMAGEOVERTIMECONDITIONS, {830, 306}},
{GOLEM_BLEEDING, {830, 257}},
{GOLEM_BURNING, {830, 306}},
{GOLEM_CONFUSION, {830, 352}},
{GOLEM_POISON, {830, 400}},
{GOLEM_TORMENT, {830, 454}},
{GOLEM_GOBACK1, {830, 508}},
{GOLEM_MOBILITYAFFECTINGCONDITIONS, {830, 352}},
{GOLEM_CHILL, {830, 257}},
{GOLEM_CRIPPLE, {830, 306}},
{GOLEM_IMMOBILIZE, {830, 400}},
{GOLEM_GOBACK2, {830, 454}},
{GOLEM_COMBATAFFECTINGCONDITIONS, {830, 400}},
{GOLEM_BLIND, {830, 260}},
{GOLEM_SLOW, {830, 306}},
{GOLEM_VULNERABILITY, {830, 352}},
{GOLEM_25VULNERABILITY, {830, 400}},
{GOLEM_GOBACK3, {830, 454}},
{GOLEM_WEAKNESS, {830, 400}},
{GOLEM_GOBACK4, {830, 454}},
{GOLEM_GOBACK5, {830, 454}},
{GOLEM_PLEASESPAWNMYGOLEM, {830, 548}},
{GOLEM_EXIT, {830, 400}},
}; };
int boonStepY[20] = {
262, 354, 262, 262, 400, 305, 354, 305, 262, 305,
450, 500, 354, 262, 305, 354, 400, 450, 262, 550
};
int healerStepX[10] = {
830, 830, 830, 830, 830, 830, 830, 830, 830, 830
};
int healerStepY[10] = {
262, 352, 352, 262, 262, 500, 450, 450, 305, 262
};
int immobilizeX = 830;
int immobilizeY = 400;
int blindX = 830;
int blindY = 260;
int resistanceX = 830;
int resistanceY = 354;
int stabilityX = 830;
int stabilityY = 400;
}; };

View file

@ -22,12 +22,20 @@ void ConfigManager::SaveCustomDelaySettings() {
configFile << "initialDelay=" << g_state.initialDelay << std::endl; configFile << "initialDelay=" << g_state.initialDelay << std::endl;
configFile << "stepDelay=" << g_state.stepDelay << std::endl; configFile << "stepDelay=" << g_state.stepDelay << std::endl;
configFile << "alwaysHideIcon=" << (g_state.alwaysHideIcon ? "1" : "0") << std::endl; 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(); configFile.close();
char logBuffer[300]; char logBuffer[512];
sprintf_s(logBuffer, "Settings saved: initialDelay=%dms, stepDelay=%dms, alwaysHideIcon=%s", sprintf_s(logBuffer, "Settings saved: initialDelay=%dms, stepDelay=%dms, alwaysHideIcon=%s, autoShowHideUI=%s, alwaysLoadLastSettings=%s",
g_state.initialDelay, g_state.stepDelay, g_state.alwaysHideIcon ? "true" : "false"); g_state.initialDelay, g_state.stepDelay,
g_state.alwaysHideIcon ? "true" : "false",
g_state.autoShowHideUI ? "true" : "false",
g_state.alwaysLoadLastSettings ? "true" : "false");
g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer);
} }
@ -73,13 +81,39 @@ void ConfigManager::LoadCustomDelaySettings() {
else if (key == "alwaysHideIcon") { else if (key == "alwaysHideIcon") {
g_state.alwaysHideIcon = (value == "1"); g_state.alwaysHideIcon = (value == "1");
} }
else if (key == "autoShowHideUI") {
g_state.autoShowHideUI = (value == "1");
}
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(); configFile.close();
char logBuffer[300]; char logBuffer[512];
sprintf_s(logBuffer, "Settings loaded: initialDelay=%dms, stepDelay=%dms, alwaysHideIcon=%s", sprintf_s(logBuffer, "Settings loaded: initialDelay=%dms, stepDelay=%dms, alwaysHideIcon=%s, autoShowHideUI=%s, alwaysLoadLastSettings=%s",
g_state.initialDelay, g_state.stepDelay, g_state.alwaysHideIcon ? "true" : "false"); g_state.initialDelay, g_state.stepDelay,
g_state.alwaysHideIcon ? "true" : "false",
g_state.autoShowHideUI ? "true" : "false",
g_state.alwaysLoadLastSettings ? "true" : "false");
g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer); g_api->Log(ELogLevel_INFO, "GolemHelper", logBuffer);
} }
@ -87,3 +121,93 @@ void ConfigManager::LoadCustomDelaySettings() {
g_api->Log(ELogLevel_INFO, "GolemHelper", "Could not load config file, using defaults"); g_api->Log(ELogLevel_INFO, "GolemHelper", "Could not load config file, using defaults");
} }
} }
void ConfigManager::SaveLastUsedSettings() {
if (!g_api) return;
std::string addonPath = g_api->Paths.GetAddonDirectory("GolemHelper");
std::string settingsPath = addonPath + "\\last_settings.ini";
try {
std::ofstream settingsFile(settingsPath);
if (!settingsFile.is_open()) {
g_api->Log(ELogLevel_WARNING, "GolemHelper", "Could not create last settings file");
return;
}
settingsFile << "[LastUsedSettings]" << std::endl;
settingsFile << "isQuickDps=" << (g_state.isQuickDps ? "1" : "0") << std::endl;
settingsFile << "isAlacDps=" << (g_state.isAlacDps ? "1" : "0") << std::endl;
settingsFile << "showBoonAdvanced=" << (g_state.showBoonAdvanced ? "1" : "0") << std::endl;
settingsFile << "environmentDamage=" << (g_state.environmentDamage ? "1" : "0") << std::endl;
settingsFile << "envDamageLevel=" << static_cast<int>(g_state.envDamageLevel) << std::endl;
settingsFile << "skipBurning=" << (g_state.skipBurning ? "1" : "0") << std::endl;
settingsFile << "showAdvanced=" << (g_state.showAdvanced ? "1" : "0") << std::endl;
settingsFile << "skipConfusion=" << (g_state.skipConfusion ? "1" : "0") << std::endl;
settingsFile << "skipSlow=" << (g_state.skipSlow ? "1" : "0") << std::endl;
settingsFile << "addImmobilize=" << (g_state.addImmobilize ? "1" : "0") << std::endl;
settingsFile << "addBlind=" << (g_state.addBlind ? "1" : "0") << std::endl;
settingsFile << "fiveBleedingStacks=" << (g_state.fiveBleedingStacks ? "1" : "0") << std::endl;
settingsFile << "hitboxType=" << static_cast<int>(g_state.hitboxType) << std::endl;
settingsFile << "addResistance=" << (g_state.addResistance ? "1" : "0") << std::endl;
settingsFile << "addStability=" << (g_state.addStability ? "1" : "0") << std::endl;
settingsFile << "skipAegis=" << (g_state.skipAegis ? "1" : "0") << std::endl;
settingsFile.close();
g_api->Log(ELogLevel_INFO, "GolemHelper", "Last used settings saved");
}
catch (...) {
g_api->Log(ELogLevel_WARNING, "GolemHelper", "Failed to save last settings file");
}
}
void ConfigManager::LoadLastUsedSettings() {
if (!g_api) return;
std::string addonPath = g_api->Paths.GetAddonDirectory("GolemHelper");
std::string settingsPath = addonPath + "\\last_settings.ini";
try {
std::ifstream settingsFile(settingsPath);
if (!settingsFile.is_open()) {
g_api->Log(ELogLevel_INFO, "GolemHelper", "No last settings file found");
return;
}
std::string line;
while (std::getline(settingsFile, line)) {
if (line.empty() || line[0] == '[') 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 == "isQuickDps") g_state.isQuickDps = (value == "1");
else if (key == "isAlacDps") g_state.isAlacDps = (value == "1");
else if (key == "showBoonAdvanced") g_state.showBoonAdvanced = (value == "1");
else if (key == "environmentDamage") g_state.environmentDamage = (value == "1");
else if (key == "envDamageLevel") g_state.envDamageLevel = static_cast<EnvironmentDamageLevel>(std::stoi(value));
else if (key == "showAdvanced") g_state.showAdvanced = (value == "1");
else if (key == "skipBurning") g_state.skipBurning = (value == "1");
else if (key == "skipConfusion") g_state.skipConfusion = (value == "1");
else if (key == "skipSlow") g_state.skipSlow = (value == "1");
else if (key == "addImmobilize") g_state.addImmobilize = (value == "1");
else if (key == "addBlind") g_state.addBlind = (value == "1");
else if (key == "fiveBleedingStacks") g_state.fiveBleedingStacks = (value == "1");
else if (key == "hitboxType") g_state.hitboxType = static_cast<HitboxType>(std::stoi(value));
else if (key == "addResistance") g_state.addResistance = (value == "1");
else if (key == "addStability") g_state.addStability = (value == "1");
else if (key == "skipAegis") g_state.skipAegis = (value == "1");
}
settingsFile.close();
g_api->Log(ELogLevel_INFO, "GolemHelper", "Last used settings loaded");
}
catch (...) {
g_api->Log(ELogLevel_INFO, "GolemHelper", "Could not load last settings file");
}
}

View file

@ -4,4 +4,6 @@ class ConfigManager {
public: public:
static void SaveCustomDelaySettings(); static void SaveCustomDelaySettings();
static void LoadCustomDelaySettings(); static void LoadCustomDelaySettings();
static void SaveLastUsedSettings();
static void LoadLastUsedSettings();
}; };

View file

@ -23,6 +23,11 @@ void Load(AddonAPI* aApi) {
ConfigManager::LoadCustomDelaySettings(); ConfigManager::LoadCustomDelaySettings();
TemplateManager::LoadTemplates(); TemplateManager::LoadTemplates();
if (g_state.alwaysLoadLastSettings) {
ConfigManager::LoadLastUsedSettings();
}
FileUtils::CopyResourceIcons(); FileUtils::CopyResourceIcons();
g_api->Renderer.Register(ERenderType_Render, UIManager::RenderUI); g_api->Renderer.Register(ERenderType_Render, UIManager::RenderUI);
@ -35,7 +40,7 @@ void Load(AddonAPI* aApi) {
MapUtils::UpdateQuickAccessVisibility(); MapUtils::UpdateQuickAccessVisibility();
g_api->Log(ELogLevel_INFO, "GolemHelper", "=== GolemHelper v1.5.0.0 Loaded ==="); g_api->Log(ELogLevel_INFO, "GolemHelper", "=== GolemHelper v1.7.1.0 Loaded ===");
g_api->Log(ELogLevel_INFO, "GolemHelper", "<c=#00ff00>GolemHelper addon</c> loaded successfully!"); g_api->Log(ELogLevel_INFO, "GolemHelper", "<c=#00ff00>GolemHelper addon</c> loaded successfully!");
} }
@ -62,13 +67,13 @@ extern "C" __declspec(dllexport) AddonDefinition* GetAddonDef() {
def.Signature = -424248; def.Signature = -424248;
def.APIVersion = NEXUS_API_VERSION; def.APIVersion = NEXUS_API_VERSION;
def.Name = "GolemHelper"; def.Name = "GolemHelper";
def.Version = { 1, 5, 0, 0 }; def.Version = { 1, 7, 1, 0 };
def.Author = "Azrub"; def.Author = "Azrub";
def.Description = "Automates the process of setting optimal boon and golem configurations in the training area"; def.Description = "Automates the process of setting optimal boon and golem configurations in the training area";
def.Load = Load; def.Load = Load;
def.Unload = Unload; def.Unload = Unload;
def.Flags = EAddonFlags_None; def.Flags = EAddonFlags_None;
def.Provider = EUpdateProvider_GitHub; def.Provider = EUpdateProvider_Direct;
def.UpdateLink = "https://github.com/Azrub/GolemHelper"; def.UpdateLink = "https://git.azrub.dev/Azrub/GolemHelper/releases/download/latest/GolemHelper.dll";
return &def; return &def;
} }

View file

@ -154,6 +154,7 @@
<ClInclude Include="Automation\AutomationLogic.h" /> <ClInclude Include="Automation\AutomationLogic.h" />
<ClInclude Include="Automation\CoordinateUtils.h" /> <ClInclude Include="Automation\CoordinateUtils.h" />
<ClInclude Include="Common\Globals.h" /> <ClInclude Include="Common\Globals.h" />
<ClInclude Include="Common\MenuSequences.h" />
<ClInclude Include="Common\Types.h" /> <ClInclude Include="Common\Types.h" />
<ClInclude Include="Config\ConfigManager.h" /> <ClInclude Include="Config\ConfigManager.h" />
<ClInclude Include="Config\TemplateManager.h" /> <ClInclude Include="Config\TemplateManager.h" />

View file

@ -108,6 +108,9 @@
<ClInclude Include="Config\TemplateManager.h"> <ClInclude Include="Config\TemplateManager.h">
<Filter>Config</Filter> <Filter>Config</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Common\MenuSequences.h">
<Filter>Common</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="dllmain.cpp"> <ClCompile Include="dllmain.cpp">

View file

@ -10,7 +10,9 @@ void KeybindManager::RegisterKeybinds() {
Keybind kb_empty = { 0, false, false, false }; Keybind kb_empty = { 0, false, false, false };
g_api->InputBinds.RegisterWithStruct("GolemHelper.ApplyBoons", HandleBoonKeybind, kb_empty); g_api->InputBinds.RegisterWithStruct("GolemHelper.ApplyBoons", HandleBoonKeybind, kb_empty);
g_api->InputBinds.RegisterWithStruct("GolemHelper.ApplyGolem", HandleGolemKeybind, kb_empty); g_api->InputBinds.RegisterWithStruct("GolemHelper.SpawnGolem", HandleGolemKeybind, kb_empty);
g_api->InputBinds.RegisterWithStruct("GolemHelper.RespawnGolem", HandleRespawnGolemKeybind, kb_empty);
g_api->InputBinds.RegisterWithStruct("GolemHelper.RemoveAndRespawnGolem", HandleRemoveAndRespawnGolemKeybind, kb_empty);
g_api->InputBinds.RegisterWithStruct("GolemHelper.QuickDPS", HandleQuickDpsKeybind, kb_empty); g_api->InputBinds.RegisterWithStruct("GolemHelper.QuickDPS", HandleQuickDpsKeybind, kb_empty);
g_api->InputBinds.RegisterWithStruct("GolemHelper.AlacDPS", HandleAlacDpsKeybind, kb_empty); g_api->InputBinds.RegisterWithStruct("GolemHelper.AlacDPS", HandleAlacDpsKeybind, kb_empty);
g_api->InputBinds.RegisterWithStruct("GolemHelper.Toggle", HandleToggleKeybind, kb_empty); g_api->InputBinds.RegisterWithStruct("GolemHelper.Toggle", HandleToggleKeybind, kb_empty);
@ -22,7 +24,9 @@ void KeybindManager::UnregisterKeybinds() {
if (!g_api) return; if (!g_api) return;
g_api->InputBinds.Deregister("GolemHelper.ApplyBoons"); g_api->InputBinds.Deregister("GolemHelper.ApplyBoons");
g_api->InputBinds.Deregister("GolemHelper.ApplyGolem"); g_api->InputBinds.Deregister("GolemHelper.SpawnGolem");
g_api->InputBinds.Deregister("GolemHelper.RespawnGolem");
g_api->InputBinds.Deregister("GolemHelper.RemoveAndRespawnGolem");
g_api->InputBinds.Deregister("GolemHelper.QuickDPS"); g_api->InputBinds.Deregister("GolemHelper.QuickDPS");
g_api->InputBinds.Deregister("GolemHelper.AlacDPS"); g_api->InputBinds.Deregister("GolemHelper.AlacDPS");
g_api->InputBinds.Deregister("GolemHelper.Toggle"); g_api->InputBinds.Deregister("GolemHelper.Toggle");
@ -32,13 +36,25 @@ void KeybindManager::UnregisterKeybinds() {
void KeybindManager::HandleBoonKeybind(const char* id, bool release) { void KeybindManager::HandleBoonKeybind(const char* id, bool release) {
if (!release && g_state.enabled) { if (!release && g_state.enabled) {
AutomationLogic::ApplyAllBoons(); AutomationLogic::ApplyBoons();
} }
} }
void KeybindManager::HandleGolemKeybind(const char* id, bool release) { void KeybindManager::HandleGolemKeybind(const char* id, bool release) {
if (!release && g_state.enabled) { if (!release && g_state.enabled) {
AutomationLogic::ApplyGolemSettings(); AutomationLogic::SpawnGolem();
}
}
void KeybindManager::HandleRespawnGolemKeybind(const char* id, bool release) {
if (!release && g_state.enabled) {
AutomationLogic::RespawnGolem();
}
}
void KeybindManager::HandleRemoveAndRespawnGolemKeybind(const char* id, bool release) {
if (!release && g_state.enabled) {
AutomationLogic::RemoveAndRespawnGolem();
} }
} }

View file

@ -7,6 +7,8 @@ public:
static void HandleBoonKeybind(const char* id, bool release); static void HandleBoonKeybind(const char* id, bool release);
static void HandleGolemKeybind(const char* id, bool release); static void HandleGolemKeybind(const char* id, bool release);
static void HandleRespawnGolemKeybind(const char* id, bool release);
static void HandleRemoveAndRespawnGolemKeybind(const char* id, bool release);
static void HandleQuickDpsKeybind(const char* id, bool release); static void HandleQuickDpsKeybind(const char* id, bool release);
static void HandleAlacDpsKeybind(const char* id, bool release); static void HandleAlacDpsKeybind(const char* id, bool release);
static void HandleToggleKeybind(const char* id, bool release); static void HandleToggleKeybind(const char* id, bool release);

View file

@ -5,11 +5,14 @@
#include "../Config/ConfigManager.h" #include "../Config/ConfigManager.h"
#include "../Utils/MapUtils.h" #include "../Utils/MapUtils.h"
#include "../Config/TemplateManager.h" #include "../Config/TemplateManager.h"
#include "../Automation/CoordinateUtils.h"
#include "../Dependencies/imgui/imgui.h" #include "../Dependencies/imgui/imgui.h"
void UIManager::RenderUI() { void UIManager::RenderUI() {
MapUtils::UpdateQuickAccessVisibility(); MapUtils::UpdateQuickAccessVisibility();
CoordinateUtils::UpdateCalibrationCapture();
if (!g_state.showUI) return; if (!g_state.showUI) return;
ImGui::SetNextWindowSize(ImVec2(450, 600), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(450, 600), ImGuiCond_FirstUseEver);
@ -17,7 +20,7 @@ void UIManager::RenderUI() {
if (ImGui::Begin("GolemHelper", &g_state.showUI, ImGuiWindowFlags_AlwaysAutoResize)) { if (ImGui::Begin("GolemHelper", &g_state.showUI, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextColored(ImVec4(0.2f, 0.8f, 1.0f, 1.0f), "GolemHelper v1.5.0.0"); ImGui::TextColored(ImVec4(0.2f, 0.8f, 1.0f, 1.0f), "GolemHelper v1.7.1.0");
ImGui::Separator(); ImGui::Separator();
if (ImGui::BeginTabBar("GolemHelperTabs", ImGuiTabBarFlags_None)) { if (ImGui::BeginTabBar("GolemHelperTabs", ImGuiTabBarFlags_None)) {
@ -28,46 +31,6 @@ void UIManager::RenderUI() {
} }
if (ImGui::BeginTabItem("Templates")) { 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(); RenderTemplatesTab();
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
@ -82,7 +45,7 @@ void UIManager::RenderUI() {
void UIManager::RenderSettingsTab() { void UIManager::RenderSettingsTab() {
ImGui::Text("Boon Configuration"); ImGui::Text("Boon Configuration");
if (ImGui::Button("Apply Boons", ImVec2(150, 0))) { if (ImGui::Button("Apply Boons", ImVec2(130, 0))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) { if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.ApplyBoons", false); g_api->InputBinds.Invoke("GolemHelper.ApplyBoons", false);
} }
@ -162,9 +125,23 @@ void UIManager::RenderSettingsTab() {
ImGui::Text("Golem Configuration"); ImGui::Text("Golem Configuration");
if (ImGui::Button("Spawn Golem", ImVec2(150, 0))) { if (ImGui::Button("Spawn Golem", ImVec2(110, 0))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) { if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.ApplyGolem", false); g_api->InputBinds.Invoke("GolemHelper.SpawnGolem", false);
}
}
ImGui::SameLine(0, 5);
if (ImGui::Button("Respawn", ImVec2(80, 0))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.RespawnGolem", false);
}
}
ImGui::Spacing();
if (ImGui::Button("Remove and Respawn", ImVec2(150, 0))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.RemoveAndRespawnGolem", false);
} }
} }
@ -227,22 +204,22 @@ void UIManager::RenderSettingsTab() {
int oldInitialDelay = g_state.initialDelay; int oldInitialDelay = g_state.initialDelay;
ImGui::Text("Initial Delay (after F key):"); ImGui::Text("Initial Delay (after F key):");
ImGui::SetNextItemWidth(205); ImGui::SetNextItemWidth(200);
ImGui::SliderInt("##initial", &g_state.initialDelay, 100, 1000, "%d ms"); ImGui::SliderInt("##initial", &g_state.initialDelay, 100, 1000, "%d ms");
ImGui::Text("Step Delay (between clicks):"); ImGui::Text("Step Delay (between clicks):");
ImGui::SetNextItemWidth(205); ImGui::SetNextItemWidth(200);
ImGui::SliderInt("##step", &g_state.stepDelay, 100, 1000, "%d ms"); ImGui::SliderInt("##step", &g_state.stepDelay, 100, 1000, "%d ms");
ImGui::Spacing(); ImGui::Spacing();
if (ImGui::Button("Reset to Default", ImVec2(120, 0))) { if (ImGui::Button("Reset to Default", ImVec2(117, 0))) {
g_state.stepDelay = 290; g_state.stepDelay = 290;
g_state.initialDelay = 390; g_state.initialDelay = 390;
ConfigManager::SaveCustomDelaySettings(); ConfigManager::SaveCustomDelaySettings();
} }
ImGui::SameLine(); ImGui::SameLine(0, 5);
if (ImGui::Button("Slow Mode", ImVec2(80, 0))) { if (ImGui::Button("Slow Mode", ImVec2(78, 0))) {
g_state.stepDelay = 1000; g_state.stepDelay = 1000;
g_state.initialDelay = 600; g_state.initialDelay = 600;
ConfigManager::SaveCustomDelaySettings(); ConfigManager::SaveCustomDelaySettings();
@ -250,30 +227,139 @@ void UIManager::RenderSettingsTab() {
ImGui::Spacing(); 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), "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) { if (oldStepDelay != g_state.stepDelay || oldInitialDelay != g_state.initialDelay) {
ConfigManager::SaveCustomDelaySettings(); ConfigManager::SaveCustomDelaySettings();
} }
} }
ImGui::PopStyleColor(2); ImGui::PopStyleColor(2);
if (g_state.alwaysLoadLastSettings) {
static bool lastIsQuickDps = g_state.isQuickDps;
static bool lastIsAlacDps = g_state.isAlacDps;
static bool lastEnvironmentDamage = g_state.environmentDamage;
static EnvironmentDamageLevel lastEnvDamageLevel = g_state.envDamageLevel;
static bool lastSkipBurning = g_state.skipBurning;
static bool lastSkipConfusion = g_state.skipConfusion;
static bool lastSkipSlow = g_state.skipSlow;
static bool lastAddImmobilize = g_state.addImmobilize;
static bool lastAddBlind = g_state.addBlind;
static bool lastFiveBleedingStacks = g_state.fiveBleedingStacks;
static HitboxType lastHitboxType = g_state.hitboxType;
static bool lastAddResistance = g_state.addResistance;
static bool lastAddStability = g_state.addStability;
static bool lastSkipAegis = g_state.skipAegis;
static bool lastShowBoonAdvanced = g_state.showBoonAdvanced;
static bool lastShowAdvanced = g_state.showAdvanced;
if (lastIsQuickDps != g_state.isQuickDps ||
lastIsAlacDps != g_state.isAlacDps ||
lastEnvironmentDamage != g_state.environmentDamage ||
lastEnvDamageLevel != g_state.envDamageLevel ||
lastSkipBurning != g_state.skipBurning ||
lastSkipConfusion != g_state.skipConfusion ||
lastSkipSlow != g_state.skipSlow ||
lastAddImmobilize != g_state.addImmobilize ||
lastAddBlind != g_state.addBlind ||
lastFiveBleedingStacks != g_state.fiveBleedingStacks ||
lastHitboxType != g_state.hitboxType ||
lastAddResistance != g_state.addResistance ||
lastAddStability != g_state.addStability ||
lastSkipAegis != g_state.skipAegis ||
lastShowBoonAdvanced != g_state.showBoonAdvanced ||
lastShowAdvanced != g_state.showAdvanced) {
ConfigManager::SaveLastUsedSettings();
lastIsQuickDps = g_state.isQuickDps;
lastIsAlacDps = g_state.isAlacDps;
lastEnvironmentDamage = g_state.environmentDamage;
lastEnvDamageLevel = g_state.envDamageLevel;
lastSkipBurning = g_state.skipBurning;
lastSkipConfusion = g_state.skipConfusion;
lastSkipSlow = g_state.skipSlow;
lastAddImmobilize = g_state.addImmobilize;
lastAddBlind = g_state.addBlind;
lastFiveBleedingStacks = g_state.fiveBleedingStacks;
lastHitboxType = g_state.hitboxType;
lastAddResistance = g_state.addResistance;
lastAddStability = g_state.addStability;
lastSkipAegis = g_state.skipAegis;
lastShowBoonAdvanced = g_state.showBoonAdvanced;
lastShowAdvanced = g_state.showAdvanced;
}
}
} }
void UIManager::RenderTemplatesTab() { void UIManager::RenderTemplatesTab() {
if (ImGui::Button("Apply Boons", ImVec2(120, 30))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.ApplyBoons", false);
}
}
ImGui::SameLine();
if (ImGui::Button("Spawn Golem", ImVec2(120, 30))) { std::string currentTemplateName = "None";
if (g_state.enabled && MapUtils::IsInTrainingArea()) { bool foundMatchingTemplate = false;
g_api->InputBinds.Invoke("GolemHelper.ApplyGolem", 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::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::Separator();
ImGui::Spacing();
if (ImGui::Button("Apply Boons", ImVec2(110, 0))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.ApplyBoons", false);
}
}
ImGui::SameLine(0, 5);
if (ImGui::Button("Spawn Golem", ImVec2(110, 0))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.SpawnGolem", false);
}
}
ImGui::Spacing();
if (ImGui::Button("Respawn", ImVec2(110, 0))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.RespawnGolem", false);
}
}
ImGui::SameLine(0, 5);
if (ImGui::Button("Remove and Respawn", ImVec2(150, 0))) {
if (g_state.enabled && MapUtils::IsInTrainingArea()) {
g_api->InputBinds.Invoke("GolemHelper.RemoveAndRespawnGolem", false);
}
}
ImGui::Spacing();
ImGui::Spacing();
ImGui::Separator();
ImGui::Spacing();
ImGui::Text("Template Management"); ImGui::Text("Template Management");
ImGui::Separator(); ImGui::Separator();
@ -281,7 +367,7 @@ void UIManager::RenderTemplatesTab() {
ImGui::Text("Save Current Settings:"); ImGui::Text("Save Current Settings:");
ImGui::SetNextItemWidth(170); ImGui::SetNextItemWidth(170);
ImGui::InputText("##templateName", g_state.newTemplateName, sizeof(g_state.newTemplateName)); ImGui::InputText("##templateName", g_state.newTemplateName, sizeof(g_state.newTemplateName));
ImGui::SameLine(); ImGui::SameLine(0, 5);
if (ImGui::Button("Save", ImVec2(50, 0))) { if (ImGui::Button("Save", ImVec2(50, 0))) {
if (strlen(g_state.newTemplateName) > 0) { if (strlen(g_state.newTemplateName) > 0) {
@ -320,19 +406,19 @@ void UIManager::RenderTemplatesTab() {
} }
ImGui::SetNextItemWidth(170); ImGui::SetNextItemWidth(170);
if (ImGui::Combo("##templateList", &currentUserIndex, userTemplateNames.data(), userTemplateNames.size())) { if (ImGui::Combo("##templateList", &currentUserIndex, userTemplateNames.data(), (int)userTemplateNames.size())) {
g_state.selectedTemplateIndex = userTemplateIndices[currentUserIndex]; g_state.selectedTemplateIndex = userTemplateIndices[currentUserIndex];
g_state.lastUserTemplateIndex = userTemplateIndices[currentUserIndex]; g_state.lastUserTemplateIndex = userTemplateIndices[currentUserIndex];
} }
ImGui::SameLine(); ImGui::SameLine(0, 5);
if (ImGui::Button("Load", ImVec2(50, 0))) { if (ImGui::Button("Load", ImVec2(50, 0))) {
if (currentUserIndex >= 0 && currentUserIndex < userTemplateIndices.size()) { if (currentUserIndex >= 0 && currentUserIndex < userTemplateIndices.size()) {
TemplateManager::LoadTemplate(userTemplateIndices[currentUserIndex]); TemplateManager::LoadTemplate(userTemplateIndices[currentUserIndex]);
} }
} }
ImGui::SameLine(); ImGui::SameLine(0, 5);
if (ImGui::Button("Del", ImVec2(50, 0))) { if (ImGui::Button("Del", ImVec2(50, 0))) {
if (currentUserIndex >= 0 && currentUserIndex < userTemplateIndices.size()) { if (currentUserIndex >= 0 && currentUserIndex < userTemplateIndices.size()) {
TemplateManager::DeleteTemplate(userTemplateIndices[currentUserIndex]); TemplateManager::DeleteTemplate(userTemplateIndices[currentUserIndex]);
@ -448,10 +534,12 @@ void UIManager::RenderTemplatesTab() {
TemplateManager::LoadTemplate(templateIndex); TemplateManager::LoadTemplate(templateIndex);
g_state.selectedTemplateIndex = -1; g_state.selectedTemplateIndex = -1;
} }
if (i < 2) ImGui::SameLine(); if (i < 2) ImGui::SameLine(0, 5);
} }
} }
ImGui::Spacing();
for (int i = 3; i < 5; i++) { for (int i = 3; i < 5; i++) {
const std::string& name = defaultNames[i]; const std::string& name = defaultNames[i];
int templateIndex = -1; int templateIndex = -1;
@ -467,7 +555,7 @@ void UIManager::RenderTemplatesTab() {
TemplateManager::LoadTemplate(templateIndex); TemplateManager::LoadTemplate(templateIndex);
g_state.selectedTemplateIndex = -1; g_state.selectedTemplateIndex = -1;
} }
if (i == 3) ImGui::SameLine(); if (i == 3) ImGui::SameLine(0, 5);
} }
} }
} }
@ -484,79 +572,69 @@ void UIManager::RenderOptions() {
MapUtils::UpdateQuickAccessVisibility(); MapUtils::UpdateQuickAccessVisibility();
} }
bool oldAutoShowHideUI = g_state.autoShowHideUI;
ImGui::Checkbox("Auto Show/Hide UI", &g_state.autoShowHideUI);
if (oldAutoShowHideUI != g_state.autoShowHideUI) {
ConfigManager::SaveCustomDelaySettings();
}
bool oldAlwaysLoadLastSettings = g_state.alwaysLoadLastSettings;
ImGui::Checkbox("Always Load Last Settings", &g_state.alwaysLoadLastSettings);
if (oldAlwaysLoadLastSettings != g_state.alwaysLoadLastSettings) {
ConfigManager::SaveCustomDelaySettings();
}
ImGui::Checkbox("Enable debug mode", &g_state.debugMode); ImGui::Checkbox("Enable debug mode", &g_state.debugMode);
if (ImGui::Button("Reset all settings")) { ImGui::Spacing();
g_state.isQuickDps = false; ImGui::Separator();
g_state.isAlacDps = false;
g_state.environmentDamage = false;
g_state.envDamageLevel = ENV_MILD;
g_state.skipBurning = false;
g_state.skipConfusion = false;
g_state.skipSlow = false;
g_state.addImmobilize = false;
g_state.addBlind = false;
g_state.fiveBleedingStacks = false;
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.skipAegis = false;
g_state.stepDelay = 290;
g_state.initialDelay = 390;
g_state.alwaysHideIcon = false;
ConfigManager::SaveCustomDelaySettings(); ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
MapUtils::UpdateQuickAccessVisibility(); 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(); ImGui::Spacing();
ImGui::Text("Current Modes:");
std::string boonMode = "Normal"; if (ImGui::Button("Calibrate", ImVec2(120, 0))) {
if (g_state.isQuickDps) { CoordinateUtils::StartCalibration();
boonMode = "Quick DPS";
}
else if (g_state.isAlacDps) {
boonMode = "Alac DPS";
} }
if (g_state.environmentDamage) { if (g_state.hasCalibration) {
boonMode += " + Env "; ImGui::SameLine(0, 6);
switch (g_state.envDamageLevel) { if (ImGui::Button("Reset to Default", ImVec2(120, 0))) {
case ENV_MILD: boonMode += "Mild"; break; CoordinateUtils::ResetCalibration();
case ENV_MODERATE: boonMode += "Moderate"; break;
case ENV_EXTREME: boonMode += "Extreme"; break;
} }
} }
ImGui::Text("- Boons: %s", boonMode.c_str()); ImGui::Spacing();
ImGui::TextDisabled("Interact with the Boon Console, then hover over");
std::string golemMods = "Normal"; ImGui::TextDisabled("the middle of \"Adjust Self\" and click.");
if (g_state.showAdvanced && (g_state.skipBurning || g_state.skipConfusion || g_state.skipSlow ||
g_state.addImmobilize || g_state.addBlind || g_state.fiveBleedingStacks)) {
golemMods = "";
if (g_state.skipBurning) golemMods += "Skip Burning ";
if (g_state.skipConfusion) golemMods += "Skip Confusion ";
if (g_state.skipSlow) golemMods += "Skip Slow ";
if (g_state.addImmobilize) golemMods += "Add Immobilize ";
if (g_state.addBlind) golemMods += "Add Blind ";
if (g_state.fiveBleedingStacks) golemMods += "5 Bleeding ";
if (!golemMods.empty()) golemMods.pop_back();
} }
ImGui::Text("- Golem: %s", golemMods.c_str());
const char* hitboxName = g_state.hitboxType == HITBOX_SMALL ? "Small" : ImGui::Spacing();
g_state.hitboxType == HITBOX_MEDIUM ? "Medium" : "Large";
ImGui::Text("- Hitbox: %s", hitboxName);
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());
} }
ImGui::PopStyleColor(2);
} }

View file

@ -51,4 +51,18 @@ void MapUtils::UpdateQuickAccessVisibility() {
} }
} }
} }
if (g_state.autoShowHideUI) {
bool inTrainingArea = IsInTrainingArea();
static bool wasInTrainingArea = false;
if (inTrainingArea && !wasInTrainingArea) {
g_state.showUI = true;
}
else if (!inTrainingArea && wasInTrainingArea) {
g_state.showUI = false;
}
wasInTrainingArea = inTrainingArea;
}
} }