Итак, обозначим порядок наших действий: 1. Написать нативку и скомпилировать dll 2. Добавить объявление написанной нативки в common.j 3. Написать код, использующий нативку 4. Запустить игру Для начала возьмём классический пример "Hello world": напишем функцию, которая не принимает параметров, а возвращает некоторую строку. Вот наш test.cpp #include <windows.h> #include <stdio.h> #define jNATIVE __stdcall #define jAPI __cdecl #define jString long #define jInt long #define jReal long typedef void(jAPI *jpAddNative)(void *routine, char *name, char *prototype); typedef jString(jAPI *jpStrMap)(const char *str); typedef const char*(jAPI *jpStrGet)(jString strid); jpAddNativejAddNative = NULL; jpStrMapjStrMap = NULL; jpStrGetjStrGet = NULL; jString jNATIVE test() { char *s = "ZOMG TEH FUNC!"; return jStrMap(s); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if (ul_reason_for_call != DLL_PROCESS_ATTACH) return TRUE; DisableThreadLibraryCalls(hModule); HMODULE hjApi = GetModuleHandle("japi.dll"); jAddNative = (jpAddNative)GetProcAddress(hjApi, "jAddNative"); jStrMap= (jpStrMap)GetProcAddress(hjApi, "jStrMap"); jStrGet= (jpStrGet)GetProcAddress(hjApi, "jStrGet"); jAddNative((void *)test, "test", "()S"); return TRUE; } Два важных места здесь - это: jString jNATIVE test() { char *s = "ZOMG TEH FUNC!"; return jStrMap(s); } и jAddNative((void *)test, "test", "()S"); Третий аргумент функции jAddNative определяет типы, передаваемые функции и возвращаемые ей. Теперь скомпилируем DLL. Для этого в командной строке напишем bcc32 -WD -e"test.dll" test.cpp -WD значит компилировать dll, -e определяет выходной файл и test.cpp - соответственно наш файл с исходным текстом. Следующим шагом нам необходимо добавить эту функцию в common.j (если у вас его нет, всегда можно достать последнюю версию из war3patch.mpq): native test takes nothing returns string Теперь создадим карту, в которой будет вызвана наша функция. Назовем её test.w3m и сохраним в папку Maps директории Warcraft. В карте создадим триггер Test, выполняющийся при инициализации и в действия добавим: call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,test()) Не забудьте импортировать в карту измененный common.j с путем "scripts\common.j", иначе при сохранении будет выдана ошибка. Пришло время запускать игру. Распакуйте Grimoire в какую-то директорию неподалёку и приготовьтесь печатать. Открываем startwar3.bat, пишем и сохраняем: bin\exehack.exe -s war3.lua -loadfile "Maps\test.w3m" Теперь редактируем ongameload.lua, вот всё, что должно в нем остаться: loaddll("bin\\japi.dll") loaddll("bin\\test.dll")
|