Hey @sokalbr remember I'm using AutoHotKey, maybe on AutoIt there is better or fancier ways of doing what you tell. Anyways, using AutoHotKey I've tried pretty much every approach, from searching all over the screen for certain pixel colors (resources), search by areas, search by color pallets, manual search with pixel comparison and finally manual search with mouse cursor comparison. As I said on other posts, I think the manual approach is the most boring to code, but at the same time, the most efficient one considering execution time and computational cost. I would recommend you the mouse cursor approach, since it is the fastest and most accurate of any other,
But, since you really want to investigate, I will give you some hints about the issues you will face when trying the 2 approaches you want.
- Coding a script recorder to copy your idea (Get pixel color manually, on each map, press a key for recording). The problem is if the ressource is not collectable when you record
This is not bad. I had some problems when I used this method:
1- Each ressource is not only one color, on darker or lighter areas, it can vary. You will need a color pallet and make a regex. Also as you mentioned if the resource is not collectable you will have to wait to record its position! that sucks... I solved that by using my own private 2.53 server, there every resource is always up lmao :cool:
2. What are you going to do with fish? it's an absolute pain to record the colors of the fish on rivers and seas. Literally every area has different water color...
3. What if there is a mob of monsters in front of your resource? you wont be able to detect it. What if you force the click? you will get in combat and probably be killed if its a strong mob (abyss of sufokia for example xd). Tip: press Shift always, that way you wont start a combat when clicking on a mob.
- Coding a search algo. Did you have some idea for the best path to me ? Maybe Is it possible to search multiples pixel in a specific zone to validate the ressource ?
1- Ok I first tried to store an image of a resource, and the compare it against all the screen and try to find similar images. The problem is that is not accurate enough, it will only detect it like 50% of the times if you are lucky. As soon as the map is slightly different, it will not find it.
2-I also tried to search for a bunch of pixels, like the chestnut on chestnut trees. Same issues, sometimes it finds it, sometimes not. And it is slow.
3-You can try an algo that moves the mouse cursor all over the screen until it changes to the "collectable" cursor. But its slow.
4. You can leave autoit and try your luck with python or other languages that offer a big integration with advanced image search libraries, but yeah, it is time consuming and I doubt it will be more efficient than the manual search approach.
I will give you an example of one script that farms using the manual mouse cursor approach on frigost to farm this thing.

Some functions are in spanish but you can use a translator. Good luck little padawan :3
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
#SingleInstance Force ; Allow only one running instance of script.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
; Disclaimer: Este script ha sido creado por Keka Bron con un objetivo de mero aprendizaje y con interés educativo para los demás.
; En ningún caso autorizo el uso fraudulento de este script o cualquier otro script derivado para objetivos ligados a realizar trampas
; en el juego Dofus o cualquier otro. Keka Bron apoya el fair play y anima a todos a jugar de manera ética, así como a seguir las reglas de Dofus.
; 07/10/2021
SetTitleMatchMode RegEx
IfWinExist, .*Dofus.*
{
WinActivate
Sleep, 1500
WinMaximize
Sleep, 1000
CoordMode, Pixel, Screen
CoordMode, Mouse, Screen
global times
CloseScript("alamotemblon2.ahk")
Loop{
Pods()
Sleep, 2000
AlamoTemblon()
}
AlamoTemblon(){
Frigost()
Move("arriba", 5)
Move("derecha", 5)
;--------------------------------------
; [-73, -46]
Farm(1288, 578, 5000)
Move("arriba", 3)
;--------------------------------------
; [-73, -49]
Farm(1376, 190, 5000)
Move("izquierda", 2)
;--------------------------------------
; [-75, -49]
Farm(1244, 385, 5000)
Move("derecha", 1)
Move("arriba", 3)
;--------------------------------------
; [-74, -52]
Farm(1464, 450, 5000)
Move("arriba", 2)
;--------------------------------------
; [-74, -54]
Farm(1030, 707, 5000)
Move("derecha", 1)
Move("abajo", 1)
;--------------------------------------
; [-73, -53]
Farm(1291, 623, 5000)
Move("derecha", 1)
Move("arriba", 1)
;--------------------------------------
; [-72, -54]
Farm(760, 280, 5000)
Farm(1289, 277, 5000)
Move("derecha", 6)
Move("abajo", 6)
;--------------------------------------
; [-66, -48]
Farm(499, 755, 5000)
Move("abajo", 1)
;--------------------------------------
; [-66, -47]
Farm(822, 484, 5000)
Move("derecha", 1)
;--------------------------------------
; [-65, -47]
Farm(987, 298, 5000)
Move("arriba", 2)
Move("derecha", 1)
;--------------------------------------
; [-64, -49]
Farm(1290, 234, 5000)
Move("arriba", 2)
Move("derecha", 1)
Move("arriba", 2)
Move("derecha", 3)
;--------------------------------------
; [-60, -53]
Farm(1035, 587, 5000)
Move("arriba", 1)
Move("derecha", 2)
;--------------------------------------
; [-58, -54]
Farm(804, 475, 5000)
Move("izquierda", 1)
Move("arriba", 2)
Move("derecha", 2)
;--------------------------------------
; [-57, -56]
Farm(468, 687, 5000)
Move("arriba", 1)
Move("derecha", 2)
;--------------------------------------
; [-55, -57]
Farm(844, 232, 5000)
Move("arriba", 2)
Move("izquierda", 2)
;--------------------------------------
; [-57, -59]
Farm(670, 623, 5000)
Move("arriba", 2)
Move("izquierda", 2)
;--------------------------------------
; [-57, -59]
Farm(976, 559, 5000)
Move("izquierda", 5)
Move("abajo", 1)
;--------------------------------------
; [-64, -60]
Farm(1246, 558, 5000)
Move("izquierda", 1)
;--------------------------------------
; [-65, -60]
Farm(553, 515, 5000)
Move("izquierda", 3)
;--------------------------------------
; [-68, -60]
Farm(539, 648, 5000)
Move("arriba", 1)
Move("derecha", 3)
Move("arriba", 2)
;--------------------------------------
; [-65, -63]
Farm(596, 279, 5000)
Move("derecha", 1)
;--------------------------------------
; [-64, -63]
Farm(890, 340, 5000)
Move("derecha", 3)
Move("arriba", 1)
;--------------------------------------
; [-61, -64]
Farm(1236, 302, 5000)
Move("derecha", 3)
;--------------------------------------
; [-58, -64]
Farm(1030, 538, 5000)
Move("arriba", 4)
;--------------------------------------
; [-58, -68]
Farm(1463, 278, 5000)
Move("derecha", 2)
;--------------------------------------
; [-56, -68]
Farm(1463, 362, 5000)
Send {Shift up}
Sleep, 10000
;--------------------------------------
;--------------------------------------
;--------------------------------------
Sepultado()
Move("izquierda", 1)
Move("abajo", 3)
Move("izquierda", 3)
Move("abajo", 1)
;--------------------------------------
; [-81, -69]
Farm(890, 472, 5000)
Move("abajo", 1)
;--------------------------------------
; [-81, -68]
Farm(1188, 286, 5000)
Farm(1020, 537, 5000)
Move("derecha", 1)
Move("abajo", 1)
;--------------------------------------
; [-80, -67]
Farm(585, 407, 5000)
Move("derecha", 1)
Move("abajo", 1)
;--------------------------------------
; [-79, -66]
Farm(899, 213, 5000)
Farm(1333, 428, 5000)
Move("derecha", 1)
;--------------------------------------
; [-78, -66]
Farm(1203, 494, 5000)
Farm(1149, 602, 5000)
Send {Shift up}
Sleep, 10000
Pods()
}
Move(direction, repeat)
{
times=0
counter=0
Send {Shift down}
while(times<repeat)
{
Switch direction
{
case "derecha":
MouseMove, 1650, 450
case "izquierda":
MouseMove, 324, 540
case "arriba":
MouseMove, 1000, 45
case "abajo":
MouseMove, 891, 902
}
Click
times+=1
Loop
{
PixelGetColor, color, 200, 200
PixelGetColor, color2, 700, 350
PixelGetColor, color3, 1650, 450
counter+=1
if(counter>500)
{
RunWait, alamotemblon2.ahk, %A_ScriptDir%
}
} Until (color = 0x000000 and color2 = 0x000000 and color3 = 0x000000)
Sleep, 2000
}
return
}
check(){
sleep, 500
if (checkFight() = 1)
{
Send {Shift up}
Sleep, 1000
RunWait, pelea.ahk, %A_ScriptDir%
Sleep, 2000
Send {Enter}
Sleep, 5000
CloseScript("pelea.ahk")
RunWait, alamotemblon2.ahk, %A_ScriptDir%
Sleep, 5000
}
return
}
checkFight(){
PixelGetColor, color, 160, 488, RGB
PixelGetColor, color2, 1732, 476, RGB
PixelGetColor, color3, 1343, 960, RGB
if (color = 0x000000 and color2 = 0x000000 and color3 = 0xCEF000)
return 1
else
return 0
}
Pods()
{
PixelGetColor, colorPods, 1300, 1018, RGB
if (colorPods = 0x60BE35)
{
irABanco()
Sleep, 1500
RunWait, alamotemblon2.ahk, %A_ScriptDir%
}
else
{
return
}
}
irABanco()
{
Frigost()
Move("derecha", 1)
Interact(1095, 517, 7000) ;bank door
Interact(975, 532, 2000) ;talk to the owl
Interact(920, 749, 3000) ;open my bank account
Interact(1477, 146, 3000) ;resources
Interact(1262, 149, 1500) ;advanced transfer arrow
Interact(1311, 180, 5000) ;transfer visible items
Interact(1551, 108, 3000) ;close bank
return
}
Farm(posX, posY, timer)
{
Send {Shift down}
MouseMove, %posX%, %posY%
Sleep, 250
id := IsMatchCursor("testCursor.bmp")
Switch id
{
case 0:
return
case 1:
Click
Sleep, %timer%
check()
return
}
return
}
Interact(posX, posY, timer)
{
MouseMove, %posX%, %posY%
Click
Sleep, %timer%
return
}
Frigost()
{
Send {h} ;Ir al merkasako
Sleep, 3000
Interact(562, 361, 2000)
Interact(1107, 229, 500)
Send burgo
Sleep, 1000
Send {Enter}
Sleep, 5000
Send {Shift up}
}
Sepultado()
{
Send {h} ;Ir al merkasako
Sleep, 3000
Interact(562, 361, 2000)
Interact(1107, 229, 500)
Send sepultado
Sleep, 1000
Send {Enter}
Sleep, 5000
Send {Shift up}
}
CloseScript(Name)
{
DetectHiddenWindows On
SetTitleMatchMode RegEx
IfWinExist, i)%Name%.* ahk_class AutoHotkey
{
WinClose
WinWaitClose, i)%Name%.* ahk_class AutoHotkey, , 2
If ErrorLevel
return
else
return
}
else
return
}
Esc:: ExitApp
+Esc:: ExitApp
;---------------------------------------------------------------
; CaptureCursor and IsMatchCursor
;---------------------------------------------------------------
;captureTo: "clipboard"=save to clipboard , "bitmap_handle"=return current cursor bitmap handle.
;return: 0=fail , 1=success
CaptureCursor(captureTo="clipboard", cursorSize=32)
{
VarSetCapacity(CURSORINFO, A_PtrSize=8? 24:20, 0)
VarSetCapacity(ICONINFO, A_PtrSize=8? 32:20, 0)
NumPut(A_PtrSize=8? 24:20, CURSORINFO, 0,"UInt")
DllCall("GetCursorInfo", "UPTR", &CURSORINFO)
hCursor := NumGet(CURSORINFO, 8, "UPtr")
flags := NumGet(CURSORINFO, 4, "UInt")
if !hCursor or !flags
return 0
hCursor := DllCall("CopyIcon", "UPTR", hCursor)
DllCall("GetIconInfo", "UPTR", hCursor, "UPTR", &ICONINFO)
mDC := DllCall("CreateCompatibleDC", "UPTR", 0, "UPTR")
hBM := CreateDIBSection(mDC, cursorSize, cursorSize)
oBM := DllCall("SelectObject", "UPTR", mDC, "UPTR", hBM, "UPTR")
DllCall("DrawIcon", "UPTR", mDC, "int",0, "int",0, "UPTR", hCursor)
DllCall("SelectObject", "UPTR", mDC, "UPTR", oBM)
DllCall("DeleteDC", "UPTR", mDC)
DllCall("DestroyIcon", "UPTR", hCursor)
If hbmMask := NumGet(ICONINFO, A_PtrSize=8? 16:12, "UPtr")
DllCall("DeleteObject", "UPTR", hbmMask)
If hbmColor := NumGet(ICONINFO, A_PtrSize=8? 24:16, "UPtr")
DllCall("DeleteObject", "UPTR", hbmColor)
if captureTo=bitmap_handle
return hBM
If captureTo=clipboard
SetClipboardData(hBM)
else
SaveHBITMAPToFile(hBM, captureTo)
DllCall("DeleteObject", "UPTR", hBM)
return 1
}
;compare cursor bmp file to current mouse cursor.
; 1 : cursor image match
; 0 : cursor image unmatch
; ""; hide mouse cursor or can't get cursor handle.
IsMatchCursor(bmpCursorFile)
{
if !hCursorBmp := CaptureCursor("bitmap_handle", bmpSize:=32)
return ""
hSourceBmp := LoadBMP(bmpCursorFile)
return !CompareBitmap(hSourceBmp, hCursorBmp, bmpSize)
}
;---------------------------------------------------------------
; Sub function
;---------------------------------------------------------------
;this function takes two bitmaps and compares the first 32x32 pixel square on them
;hBM1 and hBM2: bitmap handle
;return: 0=match, 1=unmatch
CompareBitmap(hBM1, hBM2, size=32)
{
x=0
mDC1 := DllCall("CreateCompatibleDC", "Uint", 0) ;create DC compatible with screen
mDC2 := DllCall("CreateCompatibleDC", "Uint", 0)
oBM1 := DllCall("SelectObject", "UPTR", mDC1, "UPTR", hBM1) ;put the object in the device context
oBM2 := DllCall("SelectObject", "UPTR", mDC2, "UPTR", hBM2)
while x < size
{
y=0
while y < size
{
color1 := DllCall("GetPixel", "UPTR", mDC1, "int", x, "int",y) ;get the RGB of pixel (x, y)
color2 := DllCall("GetPixel", "UPTR", mDC2, "int", x, "int",y)
if color1 <> %color2% ;if colors are different, didn't match
return 1
y+=1
}
x+=1
}
DllCall("SelectObject", "UPTR", mDC1, "UPTR", oBM1) ;put the original contents back in DC
DllCall("SelectObject", "UPTR", mDC2, "UPTR", oBM2)
DllCall("DeleteDC", "UPTR", mDC1) ;delete DC (prevent memory leak)
DllCall("DeleteDC", "UPTR", mDC2)
DllCall("DeleteObject", "UPTR", hBM1) ;delete the images in memory
DllCall("DeleteObject", "UPTR", hBM2)
return 0 ;0 return if match
}
CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
{
VarSetCapacity(BITMAPINFO, 44, 0)
NumPut(44, BITMAPINFO, 0,"UInt")
NumPut(nW, BITMAPINFO, 4,"Int")
NumPut(nH, BITMAPINFO, 8,"Int")
NumPut(1, BITMAPINFO, 12,"UShort")
NumPut(bpp, BITMAPINFO, 14,"UShort")
Return DllCall("gdi32\CreateDIBSection", "UPTR", hDC, "UPTR", &BITMAPINFO, "Uint", 0, "UPTR", pBits, "Uint", 0, "Uint", 0)
}
SetClipboardData(hBitmap)
{
VarSetCapacity(DIBSECTION, A_PtrSize=8? 104:84, 0)
NumPut(40, DIBSECTION, A_PtrSize=8? 32:24,"UInt") ;dsBmih.biSize
DllCall("GetObject", "UPTR", hBitmap, "int", A_PtrSize=8? 104:84, "UPTR", &DIBSECTION)
biSizeImage := NumGet(DIBSECTION, A_PtrSize=8? 52:44, "UInt")
hDIB := DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+biSizeImage)
pDIB := DllCall("GlobalLock", "UPTR", hDIB)
DllCall("RtlMoveMemory", "UPTR", pDIB, "UPTR", &DIBSECTION + (A_PtrSize=8? 32:24), "Uint", 40)
DllCall("RtlMoveMemory", "UPTR", pDIB+40, "Uint", NumGet(DIBSECTION, A_PtrSize=8? 24:20, "UPtr"), "Uint", biSizeImage)
DllCall("GlobalUnlock", "UPTR", hDIB)
DllCall("DeleteObject", "UPTR", hBitmap)
DllCall("OpenClipboard", "Uint", 0)
DllCall("EmptyClipboard")
DllCall("SetClipboardData", "Uint", 8, "UPTR", hDIB)
DllCall("CloseClipboard")
}
LoadBMP(bmpFile)
{
bmpFile := GetValidFilePath(bmpFile)
hBmp := DllCall("LoadImage","Uint", 0, "str", bmpFile, "Uint", 0, "int", 32, "int",32, "Uint", 0x00000010) ;load the image from file
return hBmp
}
SaveHBITMAPToFile(hBitmap, sFile)
{
sFile := GetValidFilePath(sFile)
VarSetCapacity(DIBSECTION, A_PtrSize=8? 104:84, 0)
NumPut(40, DIBSECTION, A_PtrSize=8? 32:24,"UInt") ;dsBmih.biSize
DllCall("GetObject", "UPTR", hBitmap, "int", A_PtrSize=8? 104:84, "UPTR", &DIBSECTION)
hFile:= DllCall("CreateFile", "UPTR", &sFile, "Uint", 0x40000000, "Uint", 0, "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
DllCall("WriteFile", "UPTR", hFile, "int64P", 0x4D42|14+40+(biSizeImage:=NumGet(DIBSECTION, A_PtrSize=8? 52:44, "UInt"))<<16, "Uint", 6, "UintP", 0, "Uint", 0)
DllCall("WriteFile", "UPTR", hFile, "int64P", 54<<32, "Uint", 8, "UintP", 0, "Uint", 0)
DllCall("WriteFile", "UPTR", hFile, "UPTR", &DIBSECTION + (A_PtrSize=8? 32:24), "Uint", 40, "UintP", 0, "Uint", 0)
DllCall("WriteFile", "UPTR", hFile, "Uint", NumGet(DIBSECTION, A_PtrSize=8? 24:20, "UPtr"), "Uint", biSizeImage, "UintP", 0, "Uint", 0)
DllCall("CloseHandle", "UPTR", hFile)
}
GetValidFilePath(filename)
{
SplitPath, filename, , sDir, sExt, sName
IfNotInString, sDir, :
sDir = %A_ScriptDir%\%sDir%
filename = %sDir%\%sName%.%sExt%
StringReplace, filename, filename, \\, \, All
return filename
}
;---------------------------------------------------------------
; Struct List
;---------------------------------------------------------------
/*
typedef struct {
DWORD cbSize;
DWORD flags;
HCURSOR hCursor;
POINT ptScreenPos;
} CURSORINFO, *PCURSORINFO, *LPCURSORINFO;
typedef struct _ICONINFO {
BOOL fIcon;
DWORD xHotspot;
DWORD yHotspot;
HBITMAP hbmMask;
HBITMAP hbmColor;
} ICONINFO, *PICONINFO;
typedef struct tagDIBSECTION {
BITMAP dsBm;
BITMAPINFOHEADER dsBmih;
DWORD dsBitfields[3];
HANDLE dshSection;
DWORD dsOffset;
} DIBSECTION, *PDIBSECTION;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
typedef struct tagBITMAP {
LONG bmType;
LONG bmWidth;
LONG bmHeight;
LONG bmWidthBytes;
WORD bmPlanes;
WORD bmBitsPixel;
LPVOID bmBits;
} BITMAP, *PBITMAP;
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
*/
}