Во первых разберёмся в вопросе зачем это нужно. Ну например для того, кто пишет свои mix'ы или dll файлы. Или просто для обучения программированию. В примере процесс будет сразу запускаться с загрузкой варкрафта, но можно внедрить этот процесс и в карту с помощью мем хака. Или просто зарегистрировать свои нативные функции в mix файле.
У тех у кого не установлена Visual Studio, устанавливаем. Далее создаём пустой проект C++. Чтобы это сделать нажимаем в меню Файл->Создать->Проект...
Появиться следующее окно.
У тех у кого не установлена Visual Studio, устанавливаем. Далее создаём пустой проект C++. Чтобы это сделать нажимаем в меню Файл->Создать->Проект...
Появиться следующее окно.
В свойствах проекта должно быть выставлено Без поддержки CLR-среды в поле Поддержка общеязыковой среды выполнения (CLR). А то варкрафт с другим свойством не загрузит dll или mix файл.
Также в свойствах проекта в закладке Свойства конфигурации->Общее нужно выставить в поле Тип конфигурации свойство Динамическая библиотека (.dll). Чтобы создать библиотеку, а не exe файл. =)
Также в свойствах проекта в закладке Свойства конфигурации->Общее нужно выставить в поле Тип конфигурации свойство Динамическая библиотека (.dll). Чтобы создать библиотеку, а не exe файл. =)
Далее создаём файл С++, его ещё называют модулем. Назовём его "Test_Debug,cpp".
Что нам потребуется для подключения к процессу. Да вообщем то ничего. Только нажать на нужные кнопки. Но чтобы войти в отладку своей библиотеки или mix файла для примера, нам потребуется сначала зарегистрировать свою нативную функцию в варкрафте. После загрузить карту и попасть в отладку при вызове этой нативной функции. Например зарегистрировав триггер в карте на ввод сообщения. Но чтобы зарегистрировать свою нативную функцию в варкрате нам потребуются дополнительные библиотеки такие как: JassApi.dll, RedirectCalls.dll, которые содержат в себе определённые функции которые помогают в работе, например, со своими функциями. Эти две библиотеки я заархивирую в файле, который будет на скачивание в этой статье.
Закидываем эти две библиотеки в папку с варкрафтом в корень. Устанавливаем Warcraft 3 TFT, ести его нету. Версия 1.26a.
Далее нам нужно создать свою библиотеку в которой будет находится наша функция для тестирования. Функция для исполнения библиотеки которая стандартно называется DllMain. Она то и будет запускаться прямо с загрузкой варкрафта.
Далее нам потребуются нативные функции для тестирования, возьмём например создание юнита на карте CreateUnit. Это уже будет функция из библиотек варкрафта. То есть самой игры. Другие функции прикреплю с тестовым выходным проектом. И тестовой картой. Где будет JASS-код с триггером на событие точное совпадение написания в чат сообщения "-test" красным игроком, при котором будет запускаться наша нативная функция, например, "fTest_Debug". Код выкладывать не буду потому что очень много его. Посмотрите сами для этого я использую программу JassCraft с помощью которой можно посмотреть JASS код. И программу WinMPQ с помощь которой можно открыть MPQ архив. А карта в варкрафте является MPQ архивом.
Для начала закинем в архив карты файл "common.j" по пути "scripts\common.j", который находится в папке Отредактированная карта. Находим в карте файл "common.j" и открываем его. Смотрим, что в нём присутствует объявление нашей нативной функции в самом конце файла
Закидываем эти две библиотеки в папку с варкрафтом в корень. Устанавливаем Warcraft 3 TFT, ести его нету. Версия 1.26a.
Далее нам нужно создать свою библиотеку в которой будет находится наша функция для тестирования. Функция для исполнения библиотеки которая стандартно называется DllMain. Она то и будет запускаться прямо с загрузкой варкрафта.
Далее нам потребуются нативные функции для тестирования, возьмём например создание юнита на карте CreateUnit. Это уже будет функция из библиотек варкрафта. То есть самой игры. Другие функции прикреплю с тестовым выходным проектом. И тестовой картой. Где будет JASS-код с триггером на событие точное совпадение написания в чат сообщения "-test" красным игроком, при котором будет запускаться наша нативная функция, например, "fTest_Debug". Код выкладывать не буду потому что очень много его. Посмотрите сами для этого я использую программу JassCraft с помощью которой можно посмотреть JASS код. И программу WinMPQ с помощь которой можно открыть MPQ архив. А карта в варкрафте является MPQ архивом.
Для начала закинем в архив карты файл "common.j" по пути "scripts\common.j", который находится в папке Отредактированная карта. Находим в карте файл "common.j" и открываем его. Смотрим, что в нём присутствует объявление нашей нативной функции в самом конце файла
native fTest_Debug takes nothing returns nothing
Функция которая не принимает и не отдаёт параметров.
В файле карты "war3map.j" мы вызываем нашу функцию "fTest_Debug" в триггере gg_trg_Chat. После каждого изменения в файле кода нужно подтверждать изменения в программе WinMPQ, нажимая "да" по английски в вылетающем сообщении.
Приступим к написанию кода в нашем проекте.
В файле карты "war3map.j" мы вызываем нашу функцию "fTest_Debug" в триггере gg_trg_Chat. После каждого изменения в файле кода нужно подтверждать изменения в программе WinMPQ, нажимая "да" по английски в вылетающем сообщении.
Приступим к написанию кода в нашем проекте.
Открыть
#include <windows.h>
typedef int LongBool;
typedef void *Pointer;
typedef char *PChar;
typedef bool Boolean;
typedef int Integer;
typedef char* String;
typedef float Single;
typedef void procedure;
typedef long longword;
typedef float *PSingle;
const wchar_t JASS_API_DLL_NAME[] = L"JassApi.dll";
typedef void *PJassString;
typedef longword TJassStringHandle;
typedef longword TJassObjectHandle;
typedef longword TJassFunctionHandle;
typedef longword TJassHandle;
typedef Pointer TCode;
typedef TJassHandle HAGENT;
typedef HAGENT HEVENT;
typedef HAGENT HPLAYER;
typedef HAGENT HWIDGET;
typedef HWIDGET HUNIT;
typedef Pointer (__stdcall *pGetJassNative)(PChar Name);
typedef LongBool (__stdcall *pRegisterJassNative) (PChar Name, PChar Signature, Pointer Address);
HUNIT CreateUnit(HPLAYER id, Integer unitid, Single x, Single y, Single face);
HPLAYER Player(Integer number);
pGetJassNative GetJassNative = NULL;
pRegisterJassNative RegisterJassNative = NULL;
bool fRegistrJassApi();
bool fRegistrNatives();
void fTest_Debug();
// Наша функция
void fTest_Debug()
{
int vvi;
HPLAYER vRedPlayer = Player(0);// Берём id игрока
Integer vId_Unit;
vId_Unit = 'hpea';//1096173142; // Пристваеваем id юнита(рабочего)
CreateUnit(vRedPlayer,vId_Unit,0,0,0);
CreateUnit(Player(1),vId_Unit,1400,1400,0);
// Делаем квадрат из юнитов по координатам x и y
for (vvi = 0; vvi < 12; vvi++)
{
CreateUnit(vRedPlayer,vId_Unit,-200+vvi*32,200,0);//слева на право
}
for (vvi = 0; vvi < 12; vvi++)
{
CreateUnit(vRedPlayer,vId_Unit,200,200-vvi*32,0);//сверху вниз
}
for (vvi = 12; vvi > 0; vvi--)
{
CreateUnit(vRedPlayer,vId_Unit,200-vvi*32,-200,0);//справо на лево
}
for (vvi = 12; vvi > 0; vvi--)
{
CreateUnit(vRedPlayer,vId_Unit,-200,-200+vvi*32,0);//снизу вверх
}
}
// Функция кторая будет запускаться при запуске варкрафта
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call != DLL_PROCESS_ATTACH) return TRUE;
DisableThreadLibraryCalls(hModule);
if (fRegistrJassApi() == FALSE) return TRUE;
if (fRegistrNatives() == FALSE) return TRUE;
RegisterJassNative("fTest_Debug", "()V",(void *)fTest_Debug);// Регистрация нативки в варкрафте
return TRUE;
}
bool fRegistrJassApi()
{
HMODULE hJassApi = GetModuleHandle(JASS_API_DLL_NAME);
if(!hJassApi) return FALSE;
GetJassNative = (pGetJassNative)GetProcAddress(hJassApi, "GetJassNative");
if(!GetJassNative) return FALSE;
RegisterJassNative = (pRegisterJassNative)GetProcAddress(hJassApi, "RegisterJassNative");
if(!RegisterJassNative) return FALSE;
return TRUE;
}
HUNIT (__cdecl *_CreateUnit) (HPLAYER id, Integer unitid, PSingle x, PSingle y, PSingle face);
HPLAYER (__cdecl *_Player) (Integer number);
bool fRegistrNatives()
{
*((int*)&_CreateUnit) = (int)GetJassNative("CreateUnit");
*((int*)&_Player) = (int)GetJassNative("Player");
return TRUE;
}
HUNIT CreateUnit(HPLAYER id, Integer unitid, Single x, Single y, Single face)
{
return _CreateUnit(id, unitid, &x, &y, &face);
}
HPLAYER Player(Integer number)
{
return _Player(number);
}
Также в свойствах проекта нужно сделать Свойства конфигурации->Общее->Набор символов - "Использовать набор символов Юникода".
Ещё в Свойства конфигурации->С/С++->Препроцессор->Определение процессора - "WIN32;_DEBUG;%(PreprocessorDefinitions)".
И Свойства конфигурации->Компоновщик->Включить инкрементную компоновку - "Да (/INCREMENTAL)".
Компилируем проект. Вытаскиваем dll файл(Test_Debug.dll) вставляем его в папку с варкрафтом. Переименовываем в "Test_Debug.mix". Файл "RedirectCalls.dll" переименовываем в "RedirectCalls.mix". Не на всех компьютерах запускаются mix файлы так что имейте это ввиду.
Запускаем варкрафт в оконном режиме для этого нужно сделать ярлык на ехе файл варкрафта и в свойствах ярлыка указать Объект "Полный путь к exe файлу" -window.
Если запустите в не оконном режиме, то не сможете отлаживать программу через Visual Studio,
Запустили варкрафт. В Visual Studio нажимаем в меню Сервис->Присоединиться к процессу...->Выбираем процесс "War3". Ставим точку останова в нашей функции. И запускаем карту, которую нужно скопировать в папку с картами, которую мы отредактировали.
Выбираем красного игрока. Начинаем игру. После загрузки карты. Пишем в чате "-test" и отлаживаем программу в VS. Если продолжим то получим квадрат из рабочих в центре карты.
Ещё в Свойства конфигурации->С/С++->Препроцессор->Определение процессора - "WIN32;_DEBUG;%(PreprocessorDefinitions)".
И Свойства конфигурации->Компоновщик->Включить инкрементную компоновку - "Да (/INCREMENTAL)".
Компилируем проект. Вытаскиваем dll файл(Test_Debug.dll) вставляем его в папку с варкрафтом. Переименовываем в "Test_Debug.mix". Файл "RedirectCalls.dll" переименовываем в "RedirectCalls.mix". Не на всех компьютерах запускаются mix файлы так что имейте это ввиду.
Запускаем варкрафт в оконном режиме для этого нужно сделать ярлык на ехе файл варкрафта и в свойствах ярлыка указать Объект "Полный путь к exe файлу" -window.
Если запустите в не оконном режиме, то не сможете отлаживать программу через Visual Studio,
Запустили варкрафт. В Visual Studio нажимаем в меню Сервис->Присоединиться к процессу...->Выбираем процесс "War3". Ставим точку останова в нашей функции. И запускаем карту, которую нужно скопировать в папку с картами, которую мы отредактировали.
Выбираем красного игрока. Начинаем игру. После загрузки карты. Пишем в чате "-test" и отлаживаем программу в VS. Если продолжим то получим квадрат из рабочих в центре карты.