[Free Plugin] DivineGiftAutoClicker
Here we go, a quick port of the ahk script i wrote yesterday, in plugin form and attached to the archeage client it runs in.
edit: New version available with automatic position handling.
edit2: fixed an issue with minimized window interfering with the window size detection
edit3: new version that include a few checks to make sure it did obtain a gift (and try again if it fail) as well as a few checks to avoid spamming it non stop once you did get all 10 (only work if you dont restart the plugin for a very long time).
edit4 Jan 27: new version will attempt to find a working click location when it fails (it seem depending on settings, the viewport undergo scaling so the click position doesnt match the position on the render), this address it, at least to a point (updated both code and dll)
compiled dll is attached for people who dont know / dont want to compile it themself
If people want to donate i wont stop them, but keep in mind, ill keep making free plugins on my freetime with or without donations.
Here we go, a quick port of the ahk script i wrote yesterday, in plugin form and attached to the archeage client it runs in.
edit: New version available with automatic position handling.
edit2: fixed an issue with minimized window interfering with the window size detection
edit3: new version that include a few checks to make sure it did obtain a gift (and try again if it fail) as well as a few checks to avoid spamming it non stop once you did get all 10 (only work if you dont restart the plugin for a very long time).
edit4 Jan 27: new version will attempt to find a working click location when it fails (it seem depending on settings, the viewport undergo scaling so the click position doesnt match the position on the render), this address it, at least to a point (updated both code and dll)
Code:
using System;
using System.Collections.Generic;
using System.Threading;
using ArcheBuddy.Bot.Classes;
using System.Runtime.InteropServices;
using System.Windows;
namespace DivineGiftClicker
{
public class DivineGiftClicker : Core
{
private int secondsBetweenClick = 2700; //45mins is more than enough if your bot run more than 7.5hours per day but whatever number works for you
public static string GetPluginAuthor()
{
return "mm2211";
}
public static string GetPluginVersion()
{
return "1.2";
}
public static string GetPluginDescription()
{
return "DivineGiftClick";
}
int windowDimensionsW = 1920;
int windowDimensionsH = 1080;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
public void PluginRun()
{
Log(DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff") + " > Starting divinegiftclicker");
Thread.Sleep(5000);
handle = GetGameClientHandle();
try
{
int style = GetWindowLong(handle, GWL_STYLE);
bool wasminimized = false;
if ((style & WS_MINIMIZE) == WS_MINIMIZE)
{ //this workaround an issue where the minimized game return a very small size (160x90 in my tests)
Log(" Window was minimized, restoring temporarily");
wasminimized = true;
ShowWindowAsync(handle, 1);//activate it
//because im too lazy to implement a proper way with call backs or locks, ill just spam it ! :P
Thread.Sleep(5000);
ShowWindowAsync(handle, 1);//activate it
Thread.Sleep(5000);
ShowWindowAsync(handle, 1);//activate it
Thread.Sleep(1000);
ShowWindowAsync(handle, 1);//activate it
Thread.Sleep(100);
ShowWindowAsync(handle, 1);//activate it
}
object o = new object();
RECT data = new RECT();
HandleRef hwnd = new HandleRef(o, handle);
GetWindowRect(hwnd, out data);
windowDimensionsH = Math.Abs(data.Bottom - data.Top);
windowDimensionsW = Math.Abs(data.Left - data.Right);
Log(" Window dimensions are : " + windowDimensionsW + " x " + windowDimensionsH);
if (wasminimized)
{
Log(" Window was minimized, minimizing back");
ShowWindowAsync(handle, 6);//minize it back
Thread.Sleep(5000);
//because im too lazy to implement a proper way with call backs or locks, ill just spam it ! :P
ShowWindowAsync(handle, 6);//minize it back
Thread.Sleep(1000);
}
}
catch (Exception e)
{
if (e.GetType() != typeof(System.Threading.ThreadAbortException))
{
Log("windowsgetdimension ERROR " + e.GetType().ToString() + " " + e.StackTrace);
Log(e.Message);
}
}
double lastupdate = 0;
while (true)
{ //to quit this plugin, you must click the stop button in the plugin manager, if the game crash the plugin will remain stuck in memory
Thread.Sleep(10000);
if (gameState != GameState.Ingame)
continue;
double now = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
if (now - lastupdate > secondsBetweenClick)
{
lastupdate = now + (120 - r.Next(240)); //give or take 2 minutes
getDivineGift();
Log(DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff") + " > Clicked the gift icon");
}
}
}
private long LastPauseRequest = 0;
private int GiftAttemptCount = 0;
private bool GaveErrorMessage = false;
private int[] offsety = {0,-10, -20, 10,20};
private void getDivineGift()
{
int retrycount = 0;
if (gameState != GameState.Ingame)
return; //not ingame
if ((long)((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds) - LastPauseRequest < 1400)
{
return; //wait for 4 hours after a pause is requested
}
if (GiftAttemptCount > 12)
{
Log(DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff") + " > Did it 11 times in this session, stop bothering for 4hours");
LastPauseRequest = (long)((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds); //well try again in 4 hours
GiftAttemptCount = 0;
}
int giftcount = 0;
{
List<Item> gifts = getInvItems(8000136);
foreach (Item gift in gifts)
{
giftcount += gift.count;
}
}
int newgiftcount = giftcount;
while (giftcount == newgiftcount && retrycount < 6)
{
Click(25, Convert.ToInt32(windowDimensionsH - 80 + offsety[retrycount]));
Thread.Sleep(2000);
newgiftcount = 0;
{
List<Item> gifts = getInvItems(8000136);
foreach (Item gift in gifts)
{
newgiftcount += gift.count;
}
}
if (giftcount == newgiftcount)
{
retrycount++;
Log(DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff") + " > Click error, trying again in 5 secs... attempt:" + retrycount);
Thread.Sleep(5000);
}
else
{
if (retrycount != 0)
{
offsety[0] = offsety[retrycount];
}
Log(DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff") + " > Got Divine gift.");
return;
}
}
if (!GaveErrorMessage && giftcount == newgiftcount)
{
Log(DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff") + " > Unable to get the divine gift or it was sent to mail. Make sure you have an inventory slot, this can also happen if no gift are remaining. You will only see that message once");
GaveErrorMessage = true;
}
}
private static Random r = new Random(Convert.ToInt32(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds));
private IntPtr handle;
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
const UInt32 WS_MINIMIZE = 0x20000000;
const int GWL_STYLE = (-16);
private void Click(int x, int y)
{
object o = new object();
HandleRef hwnd = new HandleRef(o, handle);
IntPtr secondparam = new IntPtr((y << 16) | x);
IntPtr secondparamoffset = new IntPtr(((y+5) << 16) | (x+5));
IntPtr zero = new IntPtr(0);
int basesleep = 100;
PostMessage(hwnd, 0x200, zero, secondparam); //first move the mouse virtually inside the window
Thread.Sleep(r.Next(basesleep, basesleep * 2));
PostMessage(hwnd, 0x202, zero, secondparam); //release the click
Thread.Sleep(10);
PostMessage(hwnd, 0x200, zero, secondparam); //move it again just in case the user is also moving the mouse
PostMessage(hwnd, 0x201, zero, secondparam); //click the position
Thread.Sleep(r.Next(basesleep / 4, basesleep/2));
PostMessage(hwnd, 0x200, zero, secondparamoffset); //move it again just in case the user is also moving the mouse
PostMessage(hwnd, 0x202, zero, secondparamoffset); //release the click
}
public void PluginStop()
{
Log(DateTime.Now.ToString("M/d/yyyy H:mm:ss.fff") + " > ----- " + GetPluginDescription() + " stopped -----");
}
}
}
compiled dll is attached for people who dont know / dont want to compile it themself
If people want to donate i wont stop them, but keep in mind, ill keep making free plugins on my freetime with or without donations.

Attachments
Last edited: