Help creating AHK script for AutoSelect Topic is solved

Ask gaming related questions (AHK v1.1 and older)
wtvr
Posts: 6
Joined: 27 May 2017, 12:25

Help creating AHK script for AutoSelect

27 May 2017, 12:57

I did NOT mean to click Solved.... that was a misclick I meant to click edit, but now I cannot undo?? can someone please fix
Now that I have run a few tests, I dont think this will work for me at all. It works with static images but not moving or animated objects :(
Hi, my name is Sean.

I would like to create a script that can detect actions or events, and auto-select units within a game. I have tested the ImageSearch feature, which can detect images on screen and move the mouse over them. I was able to get this to work, but it is very very slow and it also takes over control of the mouse so I cannot move it once I begin the imagesearch. I was hoping it could be instant?

Here is the current ImageSearch script I am using
f1::

ImageSearch, FoundX, FoundY, 0,0, 1300, 1300, C:\My Images\test.bmp

if ErrorLevel = 2
tooltip Could not conduct the search.
else if ErrorLevel = 1
tooltip Image could not be found on the screen.
else
loop
{
mousemove, %FoundX%, %FoundY%, 50
tooltip The image was found at %FoundX%x%FoundY%.
}
return

esc::
msgbox script closed by user
exitapp

I was talking to ZeenMarley on Discord and he suggested qdip_Imagesearch which might be faster, but he suggested I talk to nnnik about it.
I found a guide but it seems very advanced https://autohotkey.com/board/topic/7110 ... agesearch/

Is it possible for AHK to detect multiple images and select all of them at once? Is there another way to do it besides using images? like can AHK detect in-game units that are not on screen?

I know that if it is possible, if I can just get it working for one unit, then I will have to create an entire list of scripts for each unit I want it to detect, and there could be between 5-10 that I might want within a given game. I realize this is going to take me weeks, maybe even months to make a complete working script that does everything I am hoping it can do, but if somebody could just help get me started I think I can take things from there :) I am a novice with this stuff, but I have made a few basic scripts so I know some beginner stuff, just not anything this advanced
Last edited by wtvr on 27 May 2017, 14:12, edited 2 times in total.
neomulemi6
Posts: 216
Joined: 30 Jun 2016, 06:01

Re: Help creating AHK script for AutoSelect

27 May 2017, 12:59

You can use ControlClick instead of MouseMove, to click things without losing control of your mouse.
wtvr
Posts: 6
Joined: 27 May 2017, 12:25

Re: Help creating AHK script for AutoSelect

27 May 2017, 13:03

does ControlClick require the Coordinates to be exact and predefined? I need the ability to locate units in various locations, sometimes while they are moving
neomulemi6
Posts: 216
Joined: 30 Jun 2016, 06:01

Re: Help creating AHK script for AutoSelect

27 May 2017, 13:33

You can still use ImageSearch. Just use ControlClick instead of MouseMove. As far as making ImageSearch faster, you can specify a smaller search region.. not much else you can do.
wtvr
Posts: 6
Joined: 27 May 2017, 12:25

Re: Help creating AHK script for AutoSelect

27 May 2017, 13:59

I tried ControlClick, and it said "image located" but it did not click the unit

I also tried MouseClick and it sort of worked, except it clicked in the wrong location (oh wait I think i fixed that)

Im kind of newbie with this but does this look right?
f1::

ImageSearch, FoundX, FoundY, 0,0, 1300, 1300, C:\My Images\test.bmp

if ErrorLevel = 2
tooltip Could not conduct the search.
else if ErrorLevel = 1
tooltip Image could not be found on the screen.
else
loop
{
MouseClick, %FoundX%, %FoundY%, 50
tooltip The image was found at %FoundX%x%FoundY%.
}
return

esc::
msgbox script closed by user
exitapp
ugh i keep getting this problem where it wont stop looping and I cant move my mouse so I have to ctrl alt del + sign out lol guess Ill erase that line

maybe now I can start making some progress, its going to be a lot of work and Im not even exactly sure if it will work that well, but thanks for the help :)
wtvr
Posts: 6
Joined: 27 May 2017, 12:25

Re: Help creating AHK script for AutoSelect

27 May 2017, 14:01

Sorry I did NOT mean to click Solved.... that was a misclick I meant to click edit, but now I cannot undo??


Now that I have run a few tests, I dont think this will work for me at all. It works with static images but not moving or animated objects :(
neomulemi6
Posts: 216
Joined: 30 Jun 2016, 06:01

Re: Help creating AHK script for AutoSelect

27 May 2017, 15:08

It should work with moving or animated objects just fine. Maybe try specifying a variation in your ImageSearch, like so: ImageSearch, FoundX, FoundY, 0,0, 1300, 1300, *10 C:\My Images\test.bmp

Also, that loop will run forever, and since the ImageSearch isn't enclosed inside the loop, why do you need to execute the click multiple times?

Here's how to use ControlClick properly, in the currently active window.

Code: Select all

WinGetActiveTitle, CurrentWindow
ControlClick, x%FoundX% y%FoundY%, %CurrentWindow%
If you want the script to keep searching until it finds the image:

Code: Select all

WinGetActiveTitle, CurrentWindow
Loop
{
	ImageSearch, FoundX, FoundY, 0,0, 1300, 1300, C:\My Images\test.bmp
	If (!ErrorLevel) ; Only click if the ImageSearch was successful.
	{
		ControlClick, x%FoundX% y%FoundY%, %CurrentWindow%
		Break ; Stops the loop when the image has been found & clicked.
	}
}
I could help you more if I knew exactly what you were trying to do.
wtvr
Posts: 6
Joined: 27 May 2017, 12:25

Re: Help creating AHK script for AutoSelect

27 May 2017, 15:38

Thank you :) I was trying to talk to the discord chat but they all seem to think what I am trying to do is too advanced.

I am playing an RTS game that allows players to customize our hotkeys, but since it is an older game the way they allow us to customize them is very limited. So many players use AHK to swap the hotkeys around and that works fine (so I have some experience with AHK). But I would like to take things one step further, and improve the Unit Grouping feature in the game. RTS games are where you control an army of many units, and players can group units together for different tactics. But in most RTS you have to manually set your groups using Ctrl + # each time you create or add new units.

I have always wanted to make a mod/tool that presets the group # keys. So when I am making my army, I usually set Ctrl 1 to melee units, 2 to range, 3 other and so on. But I was hoping maybe with AHK i could have it auto-select them without the need for pressing Ctrl and adding new units each time they are created, this way a new unit would automatically be grouped with your army already.

After talking to the AHK discord, nnnik suggested I try using CheatEngine which can be combined with AHK. Though he did not go into any further details beyond "its very advanced". Anyway, I am reading guides that I can find, and posting on various forums to get any help that I can. I do have some very minor knowledge of Hex Editing, and I have been toying with CheatEngine tutorials. I was able to modify unit HP and Food supply in the game using CheatEngine, but I do not know how to find the unit type, attack type, armor, etc

The game I am playing is WarCraft III
neomulemi6
Posts: 216
Joined: 30 Jun 2016, 06:01

Re: Help creating AHK script for AutoSelect

27 May 2017, 17:12

Well, Cheat Engine comes with a great tutorial. And you can find a library of AutoHotkey memory functions with a quick Google search.

Here's the one I use:

Code: Select all

Global PROCESS_ALL_ACCESS        := 0x001F0FFF
Global PROCESS_VM_READ           := 0x10
Global PROCESS_QUERY_INFORMATION := 0x400

Global TOKEN_ALL_ACCESS        := 0xF01FF
Global TOKEN_QUERY             := 0x8
Global TOKEN_ADJUST_PRIVILEGES := 0x20

Global SE_PRIVILEGE_ENABLED := 2

Global PAGE_READWRITE         := 0x04
Global PAGE_EXECUTE_READWRITE := 0x40

Global TH32CS_SNAPMODULE := 0x00000008

Global INVALID_HANDLE_VALUE := -1

Global MODULEENTRY32_SIZE := 548

Global MODULEENTRY32_modBaseAddr := 20

Global MODULEENTRY32_hModule := 29

Global MODULEENTRY32_szModule := 32

Memory_GetProcessID(process_name)
{
    Process, Exist, %process_name%
    process_id = %ErrorLevel%

    Return, process_id
}

Memory_GetProcessHandle(process_id)
{
    process_handle := DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", false, "UInt", process_id, "Ptr") ; PROCESS_ALL_ACCESS

    Return, process_handle
}

Memory_GetModuleBase(process_id, module_name)
{
    snapshot_handle := DllCall("CreateToolhelp32Snapshot", "UInt", 0x00000008, "UInt", process_id) ; TH32CS_SNAPMODULE

    If (snapshot_handle = INVALID_HANDLE_VALUE)
    {
        Return, False
    }

    VarSetCapacity(me32, 548, 0) ; MODULEENTRY32_SIZE

    NumPut(548, me32) ; MODULEENTRY32_SIZE

    If (DllCall("Module32First", "UInt", snapshot_handle, "UInt", &me32))
    {
        While (DllCall("Module32Next", "UInt", snapshot_handle, "UInt", &me32))
        {
            If (module_name == StrGet(&me32 + 32, 256, "CP0")) ; MODULEENTRY32_szModule
            ;If (DllCall("lstrcmpi", "Str", module_name, "UInt", &me32 + 32) = -1)
            {
                DllCall("CloseHandle", "UInt", snapshot_handle)

                Return, NumGet(&me32, 20) ; MODULEENTRY32_modBaseAddr
            }
        }
    }

    DllCall("CloseHandle", "UInt", snapshot_handle)

    Return, False
}

Memory_CloseHandle(process_handle)
{
    DllCall("CloseHandle", "Ptr", process_handle)
}

Memory_Read(process_handle, address)
{
    VarSetCapacity(value, 4, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", 4, "UInt *", 0)

    Return, NumGet(value, 0, "UInt")

    ;Return, *(&value + 3) << 24 | *(&value + 2) << 16 | *(&value + 1) << 8 | *(&value)
}

Memory_ReadEx(process_handle, address, size)
{
    VarSetCapacity(value, size, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", size, "UInt *", 0)

    Return, NumGet(value, 0, "UInt")
}

Memory_ReadFloat(process_handle, address)
{
    VarSetCapacity(value, 4, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", 4, "UInt *", 0)

    Return, NumGet(value, 0, "Float")
}

Memory_ReadReverse(process_handle, address)
{
    VarSetCapacity(value, 4, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", 4, "UInt *", 0)

    Return, *(&value + 3) | *(&value + 2) << 8 | *(&value + 1) << 16 | *(&value) << 24
}

Memory_ReadString(process_handle, address, size)
{
    VarSetCapacity(value, size, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", size, "UInt *", 0)

    Loop, %size%
    {
        current_value := NumGet(value, A_Index - 1, "UChar")

        ;MsgBox, current_value = %current_value%

        If (current_value = 0)
        {
            Break
        }

        result .= Chr(current_value)
    }

    ;MsgBox, result = %result%

    Return, result
}

Memory_ReadStringEx(process_handle, address, size)
{
    result = 

    Loop, %size%
    {
        output := "x"

        read := DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", output, "UInt", 1, "UInt *", 0)
        If (ErrorLevel or !read)
        {
            Return, result
        }

        If output = 
        {
            Break
        }

        output_character := *(&output)

        IfEqual, output_character, 32 ; Space
        {
            result .= " "
        }
        Else
        {
            result = %result%%output%
        }

        address++
    }

    Return, result
}

Memory_Write(process_handle, address, value)
{
    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", 4, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt *", value, "UInt", 4, "UInt *", 0)
}

Memory_WriteEx(process_handle, address, value, size)
{
    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", size, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt *", value, "UInt", size, "UInt *", 0)
}

Memory_WriteFloat(process_handle, address, value)
{
    value := FloatToHex(value)

    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", 4, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt *", value, "UInt", 4, "UInt *", 0)
}

Memory_WriteNops(process_handle, address, size)
{
    If (size <= 0)
    {
        Return
    }

    VarSetCapacity(value, size)

    Loop, %size%
    {
        NumPut(0x90, value, A_Index - 1, "UChar")
    }

    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", size, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt", &value, "UInt", size, "UInt *", 0)
}

Memory_WriteBytes(process_handle, address, bytes)
{
    bytes_size := 0
    Loop, Parse, bytes, `,
    {
        bytes_size += 1
    }

    ;Sort, bytes, D`, N R ; bytes in reverse order

    VarSetCapacity(value, bytes_size)

    Loop, Parse, bytes, `,
    {
        byte = 0x%A_LoopField% ; pre-append 0x

        NumPut(byte, value, A_Index - 1, "UChar")
    }

    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", bytes_size, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt", &value, "UInt", bytes_size, "UInt *", 0)
}
wtvr
Posts: 6
Joined: 27 May 2017, 12:25

Re: Help creating AHK script for AutoSelect

27 May 2017, 17:15

neomulemi6 wrote:Here's the one I use:

Code: Select all

Global PROCESS_ALL_ACCESS        := 0x001F0FFF
Global PROCESS_VM_READ           := 0x10
Global PROCESS_QUERY_INFORMATION := 0x400

Global TOKEN_ALL_ACCESS        := 0xF01FF
Global TOKEN_QUERY             := 0x8
Global TOKEN_ADJUST_PRIVILEGES := 0x20

Global SE_PRIVILEGE_ENABLED := 2

Global PAGE_READWRITE         := 0x04
Global PAGE_EXECUTE_READWRITE := 0x40

Global TH32CS_SNAPMODULE := 0x00000008

Global INVALID_HANDLE_VALUE := -1

Global MODULEENTRY32_SIZE := 548

Global MODULEENTRY32_modBaseAddr := 20

Global MODULEENTRY32_hModule := 29

Global MODULEENTRY32_szModule := 32

Memory_GetProcessID(process_name)
{
    Process, Exist, %process_name%
    process_id = %ErrorLevel%

    Return, process_id
}

Memory_GetProcessHandle(process_id)
{
    process_handle := DllCall("OpenProcess", "UInt", 0x001F0FFF, "Int", false, "UInt", process_id, "Ptr") ; PROCESS_ALL_ACCESS

    Return, process_handle
}

Memory_GetModuleBase(process_id, module_name)
{
    snapshot_handle := DllCall("CreateToolhelp32Snapshot", "UInt", 0x00000008, "UInt", process_id) ; TH32CS_SNAPMODULE

    If (snapshot_handle = INVALID_HANDLE_VALUE)
    {
        Return, False
    }

    VarSetCapacity(me32, 548, 0) ; MODULEENTRY32_SIZE

    NumPut(548, me32) ; MODULEENTRY32_SIZE

    If (DllCall("Module32First", "UInt", snapshot_handle, "UInt", &me32))
    {
        While (DllCall("Module32Next", "UInt", snapshot_handle, "UInt", &me32))
        {
            If (module_name == StrGet(&me32 + 32, 256, "CP0")) ; MODULEENTRY32_szModule
            ;If (DllCall("lstrcmpi", "Str", module_name, "UInt", &me32 + 32) = -1)
            {
                DllCall("CloseHandle", "UInt", snapshot_handle)

                Return, NumGet(&me32, 20) ; MODULEENTRY32_modBaseAddr
            }
        }
    }

    DllCall("CloseHandle", "UInt", snapshot_handle)

    Return, False
}

Memory_CloseHandle(process_handle)
{
    DllCall("CloseHandle", "Ptr", process_handle)
}

Memory_Read(process_handle, address)
{
    VarSetCapacity(value, 4, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", 4, "UInt *", 0)

    Return, NumGet(value, 0, "UInt")

    ;Return, *(&value + 3) << 24 | *(&value + 2) << 16 | *(&value + 1) << 8 | *(&value)
}

Memory_ReadEx(process_handle, address, size)
{
    VarSetCapacity(value, size, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", size, "UInt *", 0)

    Return, NumGet(value, 0, "UInt")
}

Memory_ReadFloat(process_handle, address)
{
    VarSetCapacity(value, 4, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", 4, "UInt *", 0)

    Return, NumGet(value, 0, "Float")
}

Memory_ReadReverse(process_handle, address)
{
    VarSetCapacity(value, 4, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", 4, "UInt *", 0)

    Return, *(&value + 3) | *(&value + 2) << 8 | *(&value + 1) << 16 | *(&value) << 24
}

Memory_ReadString(process_handle, address, size)
{
    VarSetCapacity(value, size, 0)
    DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", value, "UInt", size, "UInt *", 0)

    Loop, %size%
    {
        current_value := NumGet(value, A_Index - 1, "UChar")

        ;MsgBox, current_value = %current_value%

        If (current_value = 0)
        {
            Break
        }

        result .= Chr(current_value)
    }

    ;MsgBox, result = %result%

    Return, result
}

Memory_ReadStringEx(process_handle, address, size)
{
    result = 

    Loop, %size%
    {
        output := "x"

        read := DllCall("ReadProcessMemory", "UInt", process_handle, "UInt", address, "Str", output, "UInt", 1, "UInt *", 0)
        If (ErrorLevel or !read)
        {
            Return, result
        }

        If output = 
        {
            Break
        }

        output_character := *(&output)

        IfEqual, output_character, 32 ; Space
        {
            result .= " "
        }
        Else
        {
            result = %result%%output%
        }

        address++
    }

    Return, result
}

Memory_Write(process_handle, address, value)
{
    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", 4, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt *", value, "UInt", 4, "UInt *", 0)
}

Memory_WriteEx(process_handle, address, value, size)
{
    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", size, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt *", value, "UInt", size, "UInt *", 0)
}

Memory_WriteFloat(process_handle, address, value)
{
    value := FloatToHex(value)

    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", 4, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt *", value, "UInt", 4, "UInt *", 0)
}

Memory_WriteNops(process_handle, address, size)
{
    If (size <= 0)
    {
        Return
    }

    VarSetCapacity(value, size)

    Loop, %size%
    {
        NumPut(0x90, value, A_Index - 1, "UChar")
    }

    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", size, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt", &value, "UInt", size, "UInt *", 0)
}

Memory_WriteBytes(process_handle, address, bytes)
{
    bytes_size := 0
    Loop, Parse, bytes, `,
    {
        bytes_size += 1
    }

    ;Sort, bytes, D`, N R ; bytes in reverse order

    VarSetCapacity(value, bytes_size)

    Loop, Parse, bytes, `,
    {
        byte = 0x%A_LoopField% ; pre-append 0x

        NumPut(byte, value, A_Index - 1, "UChar")
    }

    DllCall("VirtualProtectEx", "UInt", process_handle, "UInt", address, "UInt", bytes_size, "UInt", 0x04, "UInt *", 0) ; PAGE_READWRITE

    DllCall("WriteProcessMemory", "UInt", process_handle, "UInt", address, "UInt", &value, "UInt", bytes_size, "UInt *", 0)
}
hey what is this for exactly?

are you on discord?
neomulemi6
Posts: 216
Joined: 30 Jun 2016, 06:01

Re: Help creating AHK script for AutoSelect

28 May 2017, 00:30

Those are functions for reading and writing memory addresses. If you do the Cheat Engine tutorial, you'll understand.

Return to “Gaming Help (v1)”

Who is online

Users browsing this forum: No registered users and 60 guests