Загрузка данных
#SingleInstance Force
#NoEnv
; 1. Открываем скрытую консоль Windows для вывода отладки
DllCall("AllocConsole")
FileAppend, --- Запуск отладки памяти CS2 ---`n, CONOUT$
; Настройки таймера (обновление каждые 200 мс)
SetTimer, ReadCS2Memory, 200
return
ReadCS2Memory:
; Ищем PID процесса игры
WinGet, targetPID, PID, ahk_exe cs2.exe
if (!targetPID) {
UpdateConsole("Ожидание запуска cs2.exe...")
return
}
; Получаем базовый адрес модуля client.dll (необходим для Source 2)
clientBase := GetModuleBaseAddress(targetPID, "client.dll")
if (!clientBase) {
UpdateConsole("Модуль client.dll еще не загружен процессом.")
return
}
; Открываем процесс для чтения памяти (PROCESS_VM_READ = 0x0010)
hProcess := DllCall("OpenProcess", "UInt", 0x0010, "Int", 0, "UInt", targetPID, "Ptr")
if (!hProcess) {
UpdateConsole("Ошибка: Не удалось получить доступ к памяти (OpenProcess).")
return
}
; --- ВНИМАНИЕ: Офсеты устаревают с патчами игры. Их нужно обновлять! ---
dwLocalPlayerPawn := 0x1823A08 ; Пример смещения локального игрока
m_vOldOrigin := 0x1274 ; Пример смещения координат вектора (X, Y, Z)
; 1. Читаем 64-битный указатель на LocalPlayerPawn (8 байт)
localPlayerAddress := ReadMemory64(hProcess, clientBase + dwLocalPlayerPawn)
if (localPlayerAddress > 0) {
; 2. Читаем координаты X, Y, Z (каждая по 4 байта, тип Float)
x := ReadMemoryFloat(hProcess, localPlayerAddress + m_vOldOrigin)
y := ReadMemoryFloat(hProcess, localPlayerAddress + m_vOldOrigin + 4)
z := ReadMemoryFloat(hProcess, localPlayerAddress + m_vOldOrigin + 8)
; Выводим результат в консоль
UpdateConsole("Локальный игрок XYZ: " . Round(x, 2) . " | " . Round(y, 2) . " | " . Round(z, 2))
} else {
UpdateConsole("Игрок не найден в текущей сессии (находится в меню?).")
}
; Закрываем дескриптор, чтобы избежать утечки ресурсов
DllCall("CloseHandle", "Ptr", hProcess)
return
; --- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ РАБОТЫ С ПАМЯТЬЮ И КОНСОЛЬЮ ---
; Функция чтения 64-битных указателей (адресов)
ReadMemory64(hProcess, address) {
VarSetCapacity(buffer, 8, 0)
DllCall("ReadProcessMemory", "Ptr", hProcess, "Ptr", address, "Ptr", &buffer, "Ptr", 8, "Ptr", 0)
return NumGet(buffer, 0, "Int64")
}
; Функция чтения значений с плавающей запятой (координаты)
ReadMemoryFloat(hProcess, address) {
VarSetCapacity(buffer, 4, 0)
DllCall("ReadProcessMemory", "Ptr", hProcess, "Ptr", address, "Ptr", &buffer, "Ptr", 4, "Ptr", 0)
return NumGet(buffer, 0, "Float")
}
; Функция вывода и очистки консоли
UpdateConsole(text) {
DllCall("SetConsoleTitle", "Str", "CS2 Memory Debugger")
; Очистка экрана консоли (простой перенос строки для истории отладки)
FileAppend, % text . "`n", CONOUT$
}
; Функция для динамического поиска client.dll в 64-битном процессе
GetModuleBaseAddress(PID, ModuleName) {
TH32CS_SNAPMODULE := 0x00000008
TH32CS_SNAPMODULE32 := 0x00000010
hSnapshot := DllCall("CreateToolhelp32Snapshot", "UInt", TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, "UInt", PID, "Ptr")
if (hSnapshot = -1)
return 0
if (A_PtrSize = 8) { ; Спецификация для 64-битных систем
VarSetCapacity(me32, 1080, 0)
NumPut(1080, me32, 0, "UInt")
} else {
VarSetCapacity(me32, 548, 0)
NumPut(548, me32, 0, "UInt")
}
if (DllCall("Module32First", "Ptr", hSnapshot, "Ptr", &me32)) {
loop {
modName := StrGet(&me32 + (A_PtrSize = 8 ? 48 : 32), 256, "CP0")
if (modName = ModuleName) {
modBaseAddr := NumGet(&me32 + (A_PtrSize = 8 ? 24 : 20), "Ptr")
DllCall("CloseHandle", "Ptr", hSnapshot)
return modBaseAddr
}
} while (DllCall("Module32Next", "Ptr", hSnapshot, "Ptr", &me32))
}
DllCall("CloseHandle", "Ptr", hSnapshot)
return 0
}
; Кнопка завершения скрипта
F10::
DllCall("FreeConsole") ; Закрываем консоль перед выходом
ExitApp