После того как мы разобрались в предыдущей статье, как вызывать функцию по адресу, теперь можно переходить к вызову методов класса. Принцип вызова метода почти такой же, но разница лишь в том, что надо еще передавать адрес самого объекта, к которому принадлежит метод. Для примера сделаем вызов нескольких методов CCamera (камеры) игры. Для начала как обычно откроем базу и затем перейдем по адресу 0046B863 используя как обычно кнопку “G” :
Здесь я выделил адреса, которые нам нужны будут для объявлений прототипов, это для Camera__WidescreenOff 0046B863 и для CCamera__WidescreenOn 0046B875. Обратите внимания я также выделил еще ecx регистр внутри метода CCamera__WidescreenOff, это и есть то, что внутри идет обращение к полям самого объекта CCamera. Значит вывод какой?
ECX – содержит указатель на сам объект и нам обязательно надо его знать адрес, иначе мы не сможем вызывать правильно метод и игра может завершиться ошибкой. Хорошо, не беда, для этого последуем по порядку действий и узнаем наконец адрес объекта, который содержится непосредственно в ecx. Сперва нам надо узнать откуда вызывается сам метод, для этого наведем курсор на его название “Camera__WidescreenOff” и затем нажмем кнопку X. Перед нами появится такое окошко со списком где вызывается наш метод:
Кликнем левой кнопкой мыши из списка самый первый вызов и затем, попадем вот сюда:
Теперь обратите внимание я выделил красным маркером наконец сам объект _camera. Почему это он? Да потому-что перед вызовом метода “Camera__WidescreenOff”, в ecx как раз и передается его адрес. Вот таким образом вы всегда можете отличить методы от функций и также заглянув во внутрь самого метода, удостоверяясь что действительно он обращаться сразу же к ecx как чтением или записью. Далее просто кликнем левой кнопкой мышью по _camera и мы попадем теперь вот сюда:
Ну вот наконец-то! Мы нашли адрес самого объекта я его выделил красным маркером, вот он 007E4688. Ну что дорогие любители моддинга, данные мы все собрали которые были нам нужны, ну а теперь переходим к написанию кода C++ для нашего плагина:
#include "stdafx.h"
//Объявляем прототип класса
class CCamera;
//Объявляем прототипы методы камеры
auto CCamera__WidescreenOff = (void (__thiscall*)(CCamera * camera))0x046B863;
auto CCamera__WidescreenOn = (void (__thiscall*)(CCamera * camera))0x046B875;
//Подхватываем переменную это наш объект CCamerа
auto _camera = (CCamera*)0x07E4688;
//Для клавиши
bool isPress = false;
//Код обработки нажатия M
void Update() {
if (!GetKeyState(0x4D) > 0 ){
CCamera__WidescreenOff(_camera);
isPress = false;
}
if ( (GetKeyState(0x4D) > 0 ) && (isPress == false) ) {
isPress = true;
CCamera__WidescreenOn(_camera);
}
};
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
//Тут установим таймер
SetTimer(0,0, 16, (TIMERPROC)Update);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Обратите внимание что сразу бросается новое в глаза, это какой-то пустой класс прототип и другие странные объявления прототипов функций. Сейчас начнем по порядку и рассмотрим наконец как это все работает.
class CCamera;
Это обыкновенный прототип класса, так как у нас пока, нет не каких его исходных кодов, при больших разработках лучше объявлять все это с именами, так что не чего не обычного в нем нет. Теперь рассмотрим наши прототипы методы:
auto CCamera__WidescreenOff = (void (__thiscall*)(CCamera * camera))0x046B863;
auto CCamera__WidescreenOn = (void (__thiscall*)(CCamera * camera))0x046B875;
Это тоже самое как и в том примере, работает, но есть не большие разницы. Заместо метода передачи параметров (__cdecl) как в предыдущей статье, мы уже используем (__thiscall*). Второе адрес самого объекта, входит как первый параметр, как указатель CCamera * camera, так что тут всегда первый параметр, должен быть наш адрес самого объекта, будьте внимательными! Только лишь потом можно уже передавать параметры, если метод принимает конечно же.
auto _camera = (CCamera*)0x07E4688;
Тут все просто, мы уже этот материал проходили, это подхват переменной это тот самый наш адрес объекта. Таким образом мы можем подхватывать не только обычные типы, но и объекты классов, структуры и даже массивы. Ну в результате если мы сделали все правильно, то по нажатию в игре кнопке “M” у нас будет выглядеть в игре так:
Стоит опять нажать кнопку M, как мы запрограммировали в коде, то вызовется другой метод, который спрячет эти полосы. Приятного вам моддинга дорогие друзья!
call_mt_plugin.rar [22,04 Kb] (cкачиваний: 43)