- Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "HotA\homm3.h"
Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;
int __stdcall shiftBlocks(HiHook* h, _AdvMgr_* advManager, int a2)
{
_GameMap_* Map = &o_GameMgr->Map;
_MapItem_* MapItem;
int Count = 0;
for (int z = 0; z <= Map->has_underground; ++z)
{
for (int y = 0; y < o_MapHeight; ++y)
{
for (int x = 0; x < o_MapWidth; ++x)
{
MapItem = Map->GetItem(x, y, z);
if ( MapItem->GetReal__object_type() == 54 ) ++Count;
}
}
}
sprintf(o_TextBuffer, "Monsters: %d", Count);
b_MsgBox(o_TextBuffer, 1);
return CALL_2(int, __thiscall, h->GetDefaultFunc(), advManager, a2);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
{
if ( !plugin_On )
{
plugin_On = 1;
_P = GetPatcher();
_PI = _P->CreateInstance("HD.Plugin.ShiftBlocks");
_PI->WriteHiHook(0x406F60, SPLICE_, EXTENDED_, THISCALL_, shiftBlocks);
}
}
return TRUE;
}
Плагин просто показывает кол-во нейтральных отрядов на карте во время её загрузки. На этом этапе можно проверять, блокирует ли монстр дорогу, и если да, сдвигать его. В структуре _MapItem_ есть поле road, с помощью которого можно определить, есть ли на тайле дорога, а также object_type, u3, os_type, но нужно разбираться, какие из этих полей следует скопировать, чтобы переместить монстра. Нужно сравнивать структуру "пустой" клетки и клетки, на которой стоит монстр.
UPD: Ещё и с отрисовкой монстра придётся повозиться. Просто скопировать os_type недостаточно. Да, объект ведёт себя, как монстр, но не выглядит, как монстр Похоже, тут дело в полях draw. Я пытался скопировать и их, но, по всей видимости, нужно менять значения draw и для соседних клеток, иначе, например, если скопировать поля draw копейщика в тайл, на котором стоит крестьянин, у последнего только тело копейщика получается, а голова остаётся крестьянская Короче, главная проблема будет в корректной отрисовке перемещённого монстра.
Хочется надеяться, что где-то в коде игра сама заполняет эти поля. Тогда было бы намного проще. Т.е., например, стоит на тайле карты монстр (координаты и ID), а уже сама игра при загрузке карты корректно заполняет соседние _MapItem_'ы. Скорее всего, так и есть, иначе бы как игра отрисовывала рандомные шарики монстров (шарики в анимированных монстров на карте)? Нужно искать место, где инициализируется 3-х мерный массив тайлов и уже там пытаться сдвигать монстров. Какая-то функция должна отвечать за конверсию _EditorMapItem_ (?) в _MapItem_. Даже если взять RMG. Я думаю, он не заморачивается с отрисовкой: просто ставит монстра на конкретную клетку, а корретно заполнить _MapItem_'ы - задача, которую выполняет другой алгоритм.
Нужно ставить брейкпоинты на запись в поля draw _MapItem_. Я чувствую, что изобретаю велосипед. Но кто же поделится инфой?
* * *
Ещё одна идея пришла: есть же функция, которая корректно убирает монстра с карты, а если та, которая корректно рисует?