era.h, которую точно принимает MSVC++ 9.0 прилагается к
тому, что я делал выше.
totkotoriy, если ты не осилил плагин, которыя я для тебя переписал, вот упрощённый и чуть более плотно прокомментированный вариант. Тут создаётся триггер, в него передаются и из него принимаются параметры !!SN:X. Разумеется, тут ничего особенного не происходит, но триггер вызывается.
Это код на MSVC++ 9.0, по идее должен компилироваться, если положить рядом era.h, расширение плагина для работоспособности нужно изменять на "era" после компиляции.
#include "era.h"
//Переменная битов целей атакующей стороны (1-й - 21-й биты).
unsigned int LeftSideBits = 0;
//Переменная битов целей защищающейся стороны (1-й - 21-й биты).
unsigned int RightSideBits = 0;
//Номер стека - основной цели.
int MainTarget = -1;
//Номер атакующего стека.
int Atacker = -1;
//Триггер до удара.
void __declspec(naked) Damage_trigger()
{
__asm
{
// Сохраняем все регистры.
pushad
//Обнуляем переменные-параметры.
mov LeftSideBits, 0
mov RightSideBits, 0
mov MainTarget, 0
mov Atacker, 0
/*
...Тут идёт код, вычисляющий переменные-параметры...
*/
//Записываем цели в параметры !!SN:X.
mov edi, EventParams // Это специальный масив Эры для передачи параметров. При помощи erm-команды !!SN:X можно будет их считать в скрипте.
mov eax, LeftSideBits
mov [edi], eax // EventParams[0] = LeftSideBits;
mov eax, RightSideBits
mov [edi + 4], eax // EventParams[1] = RightSideBits;
//Записываем номер основной цели в параметры !!SN:X.
mov eax, MainTarget
mov [edi + 8], eax // EventParams[2] = MainTarget;
//Записываем номер атакующего стека в параметры !!SN:X.
mov eax, Atacker
mov [edi + 12], eax // EventParams[3] = Atacker;
//Вызываем ERM-функцию 78001 (перед ударом), из неё получаем параметры для записи в переменные целей.
push 78001
mov eax, 0x74CE30
call eax
add esp, 4
//Считываем новые цели из параметров !!SN:X.
mov edi, EventParams // В erm-коде с помощью команды !!SN:X в этот массив был записаны новые значения. Мы можем их считать и что-нибудь изменить в зависимости от них.
mov eax, [edi]
mov ebx, [edi + 4]
//Записываем новые цели в переменные целей.
mov LeftSideBits, eax // LeftSideBits = EventParams[0];
mov RightSideBits, ebx // RightSideBits = EventParams[1];
/*
...Тут могли бы обрабатываться параметры и что-нибудь изменяться...
*/
// Восстанавливаем все регистры.
popad
//Вызываем затёртую функцию (вместо вызова этой функции в игре теперь стоит вызов кода этого хука, поэтому вызываем её вручную).
mov eax, 0x465BC0
call eax
// push + ret = jmp (то есть это просто прыжок на адрес 0x44134B, возвращение из хука в код игры).
push 0x44134B
ret
}
}
//После кода WoG.
void __stdcall OnAfterWoG(PEvent Event)
{
//Создание триггера до удара.
Hook(Damage_trigger, HOOKTYPE_JUMP, 5, (void*)0x441346);
}
//Начало.
extern "C" __declspec(dllexport) BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID lpReserved)
{
if (reason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hInst);
// Инициализация, создание связи с Эрой.
ConnectEra();
// Регистрируем обработчик, который запустится после выполнения кода WoG в начале запуска программы и вызовет указанную функцию.
RegisterHandler(OnAfterWoG, "OnAfterWoG");
}
return TRUE;
};