3D FPS 게임 입니다.
이걸로 메모리 관련 부분을 오토핫키로 제어 하는걸 첫번째로 올릴께요...
아시는 부분들은 다 아시겠지만 모르는 분들은 모르니까요 ;;;
유투브에서 이 게임을 오토핫키로 제어 하도록 만든 예제 동영상도 있습니다.
(외국 어느 사람이 만든겁니다. ^^ 동영상을 보고 배우셔도 됩니다..^^)
예제 설명은 다음편에 진행됩니다.
;//실전 예제 입니다.
startscript:
Gui,+SysMenu +Owner +AlwaysOnTop
Gui, Add, GroupBox, x6 y6 w260 h180 , Assult Cube Viewer
Gui, Add, Text, x16 y22 w200 h12 vNavi, 게임 대기중
;Gui, Add, Text, x140 y27 w120 h12 vNaviA, 프로그램 동작 대기중
Gui, Add, Text, x16 y42 w100 h12 vNaviHP,
Gui, Add, Text, x16 y62 w100 h12 vNaviSP,
Gui, Add, Text, x16 y82 w240 h12 vNaviAP,
Gui, Add, Text, x16 y102 w200 h12 vNaviX,
Gui, Add, Text, x16 y122 w200 h12 vNaviY,
Gui, Add, Text, x16 y142 w200 h12 vNaviZ,
Gui, Add, Text, x16 y162 w200 h12 vNaviV,
;Gui, Add, Text, x56 y40 w80 h12 vNavi,
Gui, Add, Button, x220 y160 w40 h20 gExit, 종료
; Generated using SmartGUI Creator for SciTE
XW := A_ScreenWidth - 300
Gui, Show, x%xw% y0, [실전강좌]-포스몬
gosub, game
;startscript:
;gosub, state_show
settimer,GetPostion,10
return
end::
;종료하시겠습니까 확인창 나오게 하기.
Exit:
GuiClose:
ExitApp
game:
guicontrol,,navi,프로그램 대기중
PROGRAM := "ahk_exe ac_client.exe"
gosub, active
sleep, 100
Base := getProcessBaseAddress("ahk_exe ac_client.exe")
;Base := getProcessBaseAddress(PROGRAM)
guicontrol,,navi,GetProcessHandle
return
Active:
WinWait,ahk_exe ac_client.exe ,
IfWinNotActive, ahk_exe ac_client.exe, , WinActivate, ahk_exe ac_client.exe,
WinWaitActive, ahk_exe ac_client.exe,
;WinMaximize,ahk_exe ac_client.exe
return
GetPostion:
Pointer1 := 0x110
Pointer2 := 0xb0
HPointer := 0xf8
SPointer := 0xfc
APOinter := 0x150
BPOinter := 0x128
GPOinter := 0x158
XPointer := 0x34
YPointer := 0x38
ZPointer := 0x3c
VPointer := 0x40
setformat, integer,HEX
pointerBase := base + 0x000B9990
;msgbox, BASE : %Base%
p1 := ReadMemory(pointerBase, PROGRAM)
;msgbox,P1 : %P1%
p2 := ReadMemory(p1 + Pointer1, PROGRAM)
;msgbox,P2 : %P2%
p3 := ReadMemory(p2 + Pointer2, PROGRAM)
;msgbox,P3 : %P3%
;p3 := ReadMemory(p2 + 0xc, PROGRAM)
;p4 := ReadMemory(p3 + 0x20c, PROGRAM)
setformat, integer,DEC
HP := ReadMemory(P3 + HPointer, PROGRAM)
SP := ReadMemory(P3 + SPointer, PROGRAM)
AP := ReadMemory(P3 + APointer, PROGRAM)
AB := ReadMemory(P3 + BPointer, PROGRAM)
GP := ReadMemory(P3 + GPointer, PROGRAM)
Coordx := HexToFloat(ReadMemory(P3 + XPointer, PROGRAM))
Coordy := HexToFloat(ReadMemory(P3 + YPointer, PROGRAM))
Coordz := HexToFloat(ReadMemory(P3 + ZPointer, PROGRAM))
View := HexToFloat(ReadMemory(P3 + VPointer, PROGRAM))
;msgbox,HP : %HP%
guicontrol,,NaviHP,HP 피값 : %HP%
guicontrol,,NaviSP,SP 실드 : %SP%
guicontrol,,NaviAP,AP 총알 : %AP% / 탄띠 : %AB% / 수류탄 : %GP%
guicontrol,,NaviX,X 좌표 : %Coordx%
guicontrol,,NaviY,Y 좌표 : %Coordy%
guicontrol,,NaviZ,Z 좌표 : %Coordz% - 높이
guicontrol,,NaviV,View 각도 : %View%
return
HexToFloat(x)
{
Return (1-2*(x>>31)) * (2**((x>>23 & 255)-150)) * (0x800000 | x & 0x7FFFFF)
}
getProcessBaseAddress(windowTitle, windowMatchMode := "3")
{
if (windowMatchMode && A_TitleMatchMode != windowMatchMode)
{
mode := A_TitleMatchMode ; This is a string and will not contain the 0x prefix
StringReplace, windowMatchMode, windowMatchMode, 0x ; remove hex prefix as SetTitleMatchMode will throw a run time error. This will occur if integer mode is set to hex and matchmode param is passed as an number not a string.
SetTitleMatchMode, %windowMatchMode% ;mode 3 is an exact match
}
WinGet, hWnd, ID, %WindowTitle%
if mode
SetTitleMatchMode, %mode% ; In case executed in autoexec
if !hWnd
return ; return blank failed to find window
; GetWindowLong returns a Long (Int) and GetWindowLongPtr return a Long_Ptr
return DllCall(A_PtrSize = 4 ; If DLL call fails, returned value will = 0
? "GetWindowLong"
: "GetWindowLongPtr"
, "Ptr", hWnd, "Int", -6, A_Is64bitOS ? "Int64" : "UInt")
; For the returned value when the OS is 64 bit use Int64 to prevent negative overflow when AHK is 32 bit and target process is 64bit
; however if the OS is 32 bit, must use UInt, otherwise the number will be huge (however it will still work as the lower 4 bytes are correct)
; Note - it's the OS bitness which matters here, not the scripts/AHKs
}
ProcessWriteMemory(data, address, processIDorName, type := "Int", numBytes := 4) {
VarSetCapacity(buf, numBytes, 0)
(type = "Str")
? StrPut(data, &buf, numBytes)
: NumPut(data, buf, type)
Process Exist, %processIDorName%
if !processID := ErrorLevel
throw Exception("Invalid process name or process ID:`n`n""" . processIDorName . """")
if !processHandle := DllCall("OpenProcess", "Int", 40, "UInt", 0, "UInt", processID, "Ptr")
throw Exception("Failed to open process.`n`nError code:`t" . A_LastError)
result := DllCall("WriteProcessMemory", "Ptr", processHandle, "Ptr", address, "Ptr", &buf, "Ptr", numBytes, "UInt", 0, "UInt")
if !DllCall("CloseHandle", "Ptr", processHandle, "UInt") && !result
throw Exception("Failed to close process handle.`n`nError code:`t" . A_LastError)
if !result
throw Exception("Failed to write process memory.`n`nError code:`t" . A_LastError)
return result
}
WriteMemory(WriteAddress = "", PROGRAM="", Data="", TypeOrLength = "")
{
Static OLDPROC, hProcess, pid
If (PROGRAM != OLDPROC)
{
if hProcess
closed := DllCall("CloseHandle", "UInt", hProcess), hProcess := 0, OLDPROC := ""
if PROGRAM
{
WinGet, pid, pid, % OLDPROC := PROGRAM
if !pid
return "Process Doesn't Exist", OLDPROC := "" ;blank OLDPROC so subsequent calls will work if process does exist
hProcess := DllCall("OpenProcess", "Int", 0x8 | 0x20, "Int", 0, "UInt", pid)
}
}
If Data is Number ; Either a numeric value or a memory address.
{
If TypeOrLength is Integer ; Address of a buffer was passed.
{
DataAddress := Data
DataSize := TypeOrLength ; Length in bytes of the data in the buffer.
}
Else ; A numeric value was passed.
{
If (TypeOrLength = "Double" or TypeOrLength = "Int64")
DataSize = 8
Else If (TypeOrLength = "Int" or TypeOrLength = "UInt"
or TypeOrLength = "Float")
DataSize = 4
Else If (TypeOrLength = "Short" or TypeOrLength = "UShort")
DataSize = 2
Else If (TypeOrLength = "Char" or TypeOrLength = "UChar")
DataSize = 1
Else {
; MsgBox, Invalid type of number.
Return False
}
VarSetCapacity(Buf, DataSize, 0)
NumPut(Data, Buf, 0, TypeOrLength)
DataAddress := &Buf
}
}
Else ; Data is a string.
{
DataAddress := &Data
If TypeOrLength is Integer ; Length (in characters) was specified.
{
If A_IsUnicode
DataSize := TypeOrLength * 2 ; 1 character = 2 bytes.
Else
DataSize := TypeOrLength
}
Else
{
If A_IsUnicode
DataSize := (StrLen(Data) + 1) * 2 ; Take the whole string
Else ; with the null terminator.
DataSize := StrLen(Data) + 1
}
}
; will return null if write works
if (hProcess && DllCall("WriteProcessMemory", "UInt", hProcess
, "UInt", WriteAddress
, "UInt", DataAddress
, "UInt", DataSize
, "UInt", 0))
return
else return !hProcess ? "Handle Closed:" closed : "Fail"
}
ReadMemory(MADDRESS=0,PROGRAM="",BYTES=4)
{
Static OLDPROC, ProcessHandle
; keep buffer a local variable, rather than static so that it is
; quasi thread safe.
VarSetCapacity(buffer, BYTES)
If (PROGRAM != OLDPROC)
{
if ProcessHandle
closed := DllCall("CloseHandle", "UInt", ProcessHandle), ProcessHandle := 0, OLDPROC := ""
if PROGRAM
{
WinGet, pid, pid, % OLDPROC := PROGRAM
if !pid
return "Process Doesn't Exist", OLDPROC := "" ;blank OLDPROC so subsequent calls will work if process does exist
ProcessHandle := DllCall("OpenProcess", "Int", 16, "Int", 0, "UInt", pid)
}
}
If !(ProcessHandle && DllCall("ReadProcessMemory", "UInt", ProcessHandle, "UInt", MADDRESS, "Ptr", &buffer, "UInt", BYTES, "Ptr", 0))
return !ProcessHandle ? "Handle Closed: " closed : "Fail"
else if (BYTES = 1)
Type := "UChar"
else if (BYTES = 2)
Type := "UShort"
else if (BYTES = 4)
Type := "UInt"
else
Type := "Int64"
return numget(buffer, 0, Type)
}
'프로그래밍 > 오토핫키' 카테고리의 다른 글
| 오토핫키 에디터로 VSCODE 사용하기 [2022-08-11 Update] (1) | 2022.08.11 |
|---|---|
| 오토핫키 에디터로 VSCODE 사용하기 [2019-03-09 Update] (1) | 2019.03.09 |
| IME Check (0) | 2018.08.12 |