Объявления

Друзья, если не получается зарегистрироваться, напишите на почту vdv_forever@bk.ru.
Я оторву свою задницу от всех дел и обязательно Вас активирую! :smile10:
Добро пожаловать на геройский форум! :smile25:

Как создать плагин для HD мода

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2185 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 04 фев 2019, 14:16

Да, можно использовать любые строки. Главное, чтобы конечная строка была 0-terminated, её адрес (указатель на неё) передаём в качестве аргумента. o_TextBuffer - это char*, поэтому (int)o_TextBuffer - это сразу адрес строки.

* * *
С интервалами примерно так:

Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "HotA\homm3.h"
#include <string>

using namespace std;

Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;

string getInterval(int n) {
    string str = "1-4";
    if ( n > 999 ) str = "1000+"; else
    if ( n > 499 ) str = "500-999"; else
    if ( n > 249 ) str = "250-499"; else
    if ( n > 99 ) str = "100-249"; else
    if ( n > 49 ) str = "50-99"; else
    if ( n > 19 ) str = "20-49"; else
    if ( n > 9 ) str = "10-19"; else
    if ( n > 4 ) str = "5-9";
    return str;
}

int __stdcall showGuards(LoHook* h, HookContext* c)
{
    bool isUtopia = h->GetAddress() == 0x4A1E56;

    // Получаем состояние банка
    _CrBankState_* bankState = (_CrBankState_*)CALL_1(int, __fastcall, 0x405D80, isUtopia ? c->edi : c->ebx);

    int CreaturesCount = bankState->defenders.GetCreaturesCount();
   
    string str = (char*)c->ecx; // Оригинальное сообщение
    str = str + "\n\nAmount: " + getInterval(CreaturesCount);
       
    // Утопия?
    if ( isUtopia ) {
        str = str + " (" + getInterval(bankState->defenders.count[0]) + ", " + getInterval(bankState->defenders.count[1]) + ", " +
            getInterval(bankState->defenders.count[2]) + ", " + getInterval(bankState->defenders.count[3]) + ")";
    } else
    // Если есть грейд
    if ( bankState->defenders.type[2] != bankState->defenders.type[0]) {
        str = str + " (" + getInterval(CreaturesCount - bankState->defenders.count[2]) + ", " + getInterval(bankState->defenders.count[2]) + ")";
    }
           
    // Передаём адрес текстового буфера в качестве аргумента для диалога
    sprintf(o_TextBuffer, "%s", str);
    c->ecx = (int)o_TextBuffer;
   
    return EXEC_DEFAULT;
}

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.ShowGuards");

            _PI->WriteLoHook(0x4A13E6, showGuards);
            _PI->WriteLoHook(0x4A1E56, showGuards);
        }
    }

    return TRUE;
}


UPD: Добавил Утопию.
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 04 фев 2019, 17:39

AlexSpl писал(а):

Да, можно использовать любые строки. Главное, чтобы конечная строка была 0-terminated, её адрес (указатель на неё) передаём в качестве аргумента. o_TextBuffer - это char*, поэтому (int)o_TextBuffer - это сразу адрес строки.

* * *
С интервалами примерно так:

Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "HotA\homm3.h"
#include <string>

using namespace std;

Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;

string getInterval(int n) {
    string str = "1-4";
    if ( n > 999 ) str = "1000+"; else
    if ( n > 499 ) str = "500-999"; else
    if ( n > 249 ) str = "250-499"; else
    if ( n > 99 ) str = "100-249"; else
    if ( n > 49 ) str = "50-99"; else
    if ( n > 19 ) str = "20-49"; else
    if ( n > 9 ) str = "10-19"; else
    if ( n > 4 ) str = "5-9";
    return str;
}

int __stdcall showGuards(LoHook* h, HookContext* c)
{
    // Получаем состояние банка
    _CrBankState_* bankState = (_CrBankState_*)CALL_1(int, __fastcall, 0x405D80, c->ebx);

    int CreaturesCount = bankState->defenders.GetCreaturesCount();
   
    string str = (char*)c->ecx; // Оригинальное сообщение
    str = str + "\n\nAmount: " + getInterval(CreaturesCount);
       
    // Если есть грейд
    if ( bankState->defenders.type[2] != bankState->defenders.type[0]) {
        str = str + " (" + getInterval(CreaturesCount - bankState->defenders.count[2]) + ", " + getInterval(bankState->defenders.count[2]) + ")";
    }
           
    // Передаём адрес текстового буфера в качестве аргумента для диалога
    sprintf(o_TextBuffer, "%s", str);
    c->ecx = (int)o_TextBuffer;
   
    return EXEC_DEFAULT;
}

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.ShowGuards");

            _PI->WriteLoHook(0x4A13E6, showGuards);
        }
    }

    return TRUE;
}


У меня не работает - пишет: (null)
Разбираюсь пока может код неправильно перенес, но ошибок пока не вижу.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2185 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 04 фев 2019, 17:41

Попробуйте версию с Утопой, иначе могу кинуть dll'ку.
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 04 фев 2019, 17:46

AlexSpl писал(а):

Попробуйте версию с Утопой, иначе могу кинуть dll'ку.


Тоже самое, в утопе стандартный текст, а в банках - (null)
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2185 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 04 фев 2019, 17:48

Вот готовый плагин:

ShowGuads.zip
(7.52 КБ) Скачиваний: 270

Если заработает, то, возможно, что-то с настройками компилятора?
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 04 фев 2019, 17:52

AlexSpl писал(а):

Вот готовый плагин:

ShowGuads.zip

Если заработает, то, возможно, что-то с настройками компилятора?


С вашей dll стандартные диалоги выходят.
Странно, прошлая версия ведь работала.

Сделал так:
Код: Выделить всё
  sprintf(o_TextBuffer, "%s%d", (char*)c->ecx, str);

Появился стандартный текст, но вместо описания интервалов, цифры.
Видимо что-то не так с типом строки.
Последний раз редактировалось as239 04 фев 2019, 17:59, всего редактировалось 1 раз.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2185 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 04 фев 2019, 17:57

Действительно странно. Подключён только этот плагин? На какой версии проверяете (игра, версия HD мода)?
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 04 фев 2019, 18:01

AlexSpl писал(а):

Действительно странно. Подключён только этот плагин? На какой версии проверяете (игра, версия HD мода)?


Подключен hw_rules. HD mod 5.0.
И main, у меня такая, содержит еще прочие добавки.
Но хуки нигде не пересекаются.

Код: Выделить всё
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.FreshMod");
         //------------------------------------------------------------------------------------------------
            //AlexSPL
            _PI->WriteLoHook(0x4ABBFA, setCreatureBankReward);
            _PI->WriteLoHook(0x4AC168, restoreOriginalReward);
         //Перестройка ГМ с любого уровня
         _PI->WriteLoHook(0x598510 /* перед загрузкой .vid */, patchDll);
         //------------------------------------------------------------------------------------------------
         //igrik
         // возможность заходить в гильдию магов без наличия книги и денег у героя-гостя
         _PI->WriteHexPatch(0x5CEA83, "EB74");
         _PI->WriteHexPatch(0x5CEACD, "2800");
            // Патч на tiny.fnt малые описания монстров (все в DEC)
            *(int*)6243434 = 6687924; // в бою
            *(int*)6244485 = 6687924; // при покупке
            *(int*)6241855 = 6687924; // не в бою
            // отображение длительности заклинаний в окне монстра (вытащено из HotA.dll)
            _PI->WriteLoHook(0x5F6BE2, Y_SpellShow);
            _PI->WriteLoHook(0x5F4B05, Y_SpellInfo1);  // тут WoG/ERA не дают поставить HiHook 
            _PI->WriteLoHook(0x5F522A, Y_SpellInfo2);
            // отображение длительности заклинаний в расширенной статистике (вытащено из HotA.dll)
            _PI->WriteLoHook(0x46D12B, Y_SpellShow1);   
            _PI->WriteLoHook(0x46D4CB, Y_SpellShow2);   
            _PI->WriteLoHook(0x46D9F0, Y_SpellShow3);
         //Обмен между героями в городе
         _PI->WriteHiHook(0x5D3640, SPLICE_, EXTENDED_, THISCALL_, Y_DlgTown_Proc);

         //Отображение охраны
         _PI->WriteLoHook(0x4A13E6, showGuards);


        }
    }

    return TRUE;
}
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5587
Зарегистрирован: 17 сен 2010, 12:58
Пол: Мужчина
Награды: 14
Высшая медаль (1) Победителю турнира по HMM1_TE (2) Победителю этапа по HMM1 (1) Победителю этапа по HMM2 (1) Лучшему из лучших (1) 2 место 1 этапа по HMM1 (1)
3 место 1 этапа по HMM1 (1) 1 место 2 этапа по HMM2 (1) Победителю турнира по KB (2) Победителю турнира по KB (1) Грандмастер оффлайн-турниров (1) Боевой шлем (1)
Поблагодарили: 2185 раз.

Re: Как создать плагин для HD мода

Сообщение AlexSpl » 04 фев 2019, 18:06

Нужно, чтобы ещё кто-то dll-ку проверил. Очень странно, что собранная не работает. Попробуйте отключить hw_rules.

Уже вижу, что хук для Утопы Вы пропустили. Киньте весь текст плагина.

UPD: Потестил. У меня работает и с hw_rules, и c NewCrBanks.
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

Re: Как создать плагин для HD мода

Сообщение as239 » 04 фев 2019, 18:18

AlexSpl писал(а):

Нужно, чтобы ещё кто-то dll-ку проверил. Очень странно, что собранная не работает. Попробуйте отключить hw_rules.

Уже вижу, что хук для Утопы Вы пропустили. Киньте весь текст плагина.

UPD: Потестил. У меня работает и с hw_rules и c NewCrBanks.


Вот весь код, хук на утопию добавил, теперь там выводится строка во всю ширину экрану с непонятыми символами:

Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#define HK_E 18
#include "homm3.h"
#include <string>

using namespace std;

Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;

#define CREATURE_INFO_OFFSET (*(_ptr_*)0x47ADD1)
#define o_CreatureInfo ((_CreatureInfo_*)CREATURE_INFO_OFFSET)

int sEBX;
int originalCreatureID;
char originalCreatureN;
//
//-------------------------------------------------------------------------------------------------------
//igrik
int __stdcall Y_SpellShow(LoHook* h, HookContext* c)
{
    // цифровое отображение длительности заклинаний (вытащено из HotA.dll)
    int Spell = *(int*)(c->esi);
    int DlgShow = *(int*)(c->ebp-40);
    if (Spell >=0)
    {
        if (Spell == 47 || Spell == 59 || Spell == 72)
            int Spell = 47;
        else
        {
            sprintf(o_TextBuffer, "x%d", *(int*)(c->esi+12));
            int SpellNew = CALL_1 (int, __cdecl, 6386834, 80);
            int SpellShow = CALL_12 (int, __thiscall, 6014624, SpellNew, *(int*)(c->ebp-28), 202, 46, 20, o_TextBuffer, "tiny.fnt", 4, 3003 - *(int*)(c->ebp-32), 10, 0, 8);
            CALL_4 (int, __thiscall, 0x5FE2D0, DlgShow + 48, *(int*)(DlgShow +56), 1, &SpellShow);
        }   
    }
    return EXEC_DEFAULT;
}


int __stdcall Y_SpellInfo1(LoHook* h, HookContext* c)
{
    // в этой функции я не смог поставить HiHook
    // потому что в WoGе после её выполнения вылетает
    if( c->eax >= 3000 && c->eax <= 3007 )
    {   
        switch (c->eax){
            case 3000: c->eax = 11; break;    // спелл_1
            case 3001: c->eax = 11; break;    // спелл_2
            case 3002: c->eax = 11; break;    // спелл_3   
            case 3006: c->eax = 9; break;    // мораль   
            case 3007: c->eax = 10; break;    // удача
            default: c->eax = -1; break;    // на всякий
        }       
        c->return_address = 0x5F4B34;
        return NO_EXEC_DEFAULT;   
    }
    return EXEC_DEFAULT;
}


int __stdcall Y_SpellInfo2(LoHook* h, HookContext* c)
{
    // подсказка для циферных отображений спеллов, морали и удачи
    switch (c->esi){
        case 3000: c->esi = 221; break; // спелл_1
        case 3001: c->esi = 222; break; // спелл_2
        case 3002: c->esi = 223; break; // спелл_3   
        case 3006: c->esi = 219; break; // мораль   
        case 3007: c->esi = 220; break;    // удача
    }
    return EXEC_DEFAULT;
}


int __stdcall Y_SpellShow1(LoHook* h, HookContext* c)
{
    int New = CALL_1 (int, __cdecl, 0x617492, 80);
    int SpellShow = CALL_12 (int, __thiscall, 6014624, New, 15, c->ebx + 16, 46, 20, "", "tiny.fnt", 4, c->edi + 3003, 10, 0, 8);
    CALL_4 (int, __thiscall, 0x4230D0, c->esi, *(int*)(c->esi + 8), 1, &SpellShow);
    return EXEC_DEFAULT;
}

int __stdcall Y_SpellShow2(LoHook* h, HookContext* c)
{
    int New = CALL_1 (int, __cdecl, 0x617492, 80);
    int SpellShow = CALL_12 (int, __thiscall, 6014624, New, 15, *(int*)(c->ebp + 24) + 16, 46, 20, "", "tiny.fnt", 4, c->ebx + 3003, 10, 0, 8);
    CALL_4 (int, __thiscall, 0x4230D0, c->esi, *(int*)(c->esi + 8), 1, &SpellShow);
    return EXEC_DEFAULT;
}


int __stdcall Y_SpellShow3(LoHook* h, HookContext* c)
{
    _Dlg_* dlg = (_Dlg_*)(c->edi + 56);
    int item = 3006 - *(int*)(c->ebp + 8);
    int spell = *(int*)c->esp - 1;

    if (spell >= 0 && spell != 47 && spell != 59 && spell != 72)
        sprintf(o_TextBuffer, "x%d", *(int*)(c->esi + 4 * spell + 408));
    else
        sprintf(o_TextBuffer, "");

    ((_DlgStaticText_*)dlg->GetItem(item))->SetText(o_TextBuffer);

    return EXEC_DEFAULT;
}



int __stdcall Y_DlgTown_Proc(HiHook* hook, _TownMgr_* tm, _EventMsg_* klick)
{
   int res = CALL_2(int, __thiscall, hook->GetDefaultFunc(), tm, klick);

   if (res) {
      if (klick->type == 2 && klick->subtype == HK_E) {
         int heroU_id = tm->town->up_hero_id;
         int heroD_id = tm->town->down_hero_id;

         if ( heroU_id != -1 && heroD_id != -1) {
            _Hero_* heroU = o_GameMgr->GetHero(heroU_id);
            _Hero_* heroD = o_GameMgr->GetHero(heroD_id);

            CALL_2(void, __fastcall, 0x4A25B0, heroU, heroD);
            CALL_3(void, __thiscall, 0x4AAA60, o_AdvMgr, heroU, heroD);

            // делаем автоматический выход из окна города
            o_WndMgr->result_dlg_item_id = 0x7800;
            klick->type = 0x4000;
            klick->subtype = 1;
            klick->item_id = 10;

            return 2;
         }
      }
   }
   return res;
}
//
//-------------------------------------------------------------------------------------------------------
//AlexSPL
int __stdcall setCreatureBankReward(LoHook* h, HookContext* c)
{
    // const char TownType = o_GameMgr->GetTown(o_ActivePlayer->towns_ids[0])->type;
    const int TownType = *(int*)o_GameMgr->Offset(0x1F6A0 + 0x10 + o_ActivePlayerID * 4);

    const int Lvl6CreatureID = TownType == 8 ? CID_PSYCHIC_ELEMENTAL : 10 + TownType * 14;
    const int Lvl7CreatureID = TownType == 8 ? CID_FIREBIRD : 12 + TownType * 14;

    sEBX = c->ebx;
    originalCreatureID = *(int*)(c->ebx + 0x54);
    originalCreatureN = *(char*)(c->ebx + 0x58);

    switch ( originalCreatureID ) {
        // Меняем Ангелов
        case CID_ANGEL:
            *(int*)(c->ebx + 0x54) = Lvl7CreatureID;
            *(char*)(c->ebx + 0x58) = originalCreatureN * 200 / (o_CreatureInfo + Lvl7CreatureID)->hit_points; // N
            if ( *(char*)(c->ebx + 0x58) < 1 ) *(char*)(c->ebx + 0x58) = 1;
            break;

        // Меняем Виверн
        case CID_WYVERN:
            *(int*)(c->ebx + 0x54) = Lvl6CreatureID;
            *(char*)(c->ebx + 0x58) = originalCreatureN * 70 / (o_CreatureInfo + Lvl6CreatureID)->hit_points; // N
            if ( *(char*)(c->ebx + 0x58) < 1 ) *(char*)(c->ebx + 0x58) = 1;
            break;
    }
   
    return EXEC_DEFAULT;
}

int __stdcall restoreOriginalReward(LoHook* h, HookContext* c)
{
    *(int*)(sEBX + 0x54) = originalCreatureID;
    *(char*)(sEBX + 0x58) = originalCreatureN;

    return EXEC_DEFAULT;
}






//int __stdcall newTownShortcut(LoHook* h, HookContext* c)
//{
//    if ( c->edx == 0x12 ) {
//        _Hero_* hero1 = o_GameMgr->GetHero(o_TownMgr->town->up_hero_id);
//        _Hero_* hero2 = o_GameMgr->GetHero(o_TownMgr->town->down_hero_id);
//
//        if ( *(int*)hero1 && *(int*)hero2 ) {
//            CALL_2(int, __fastcall, 0x4A25B0, hero1, hero2); // Показываем диалог Грамотности
//            CALL_1(int, __thiscall, 0x5C75B0, o_TownMgr); // Выходим из города (ExitTownScreen)
//            CALL_3(int, __thiscall, 0x4AAA60, o_AdvMgr, hero1, hero2); // Показываем диалог встречи героев
//            CALL_2(int, __thiscall, 0x5C67C0, o_TownMgr, 0); // Снова заходим в город (EnterTownScreen)
//        }
//    }
//
//    return EXEC_DEFAULT;
//}
int __stdcall patchDll(LoHook* h, HookContext* c)
{
    //Первая версия+
   //HMODULE hHW_SOD = GetModuleHandleA("HW_SOD.dll");
    //char MageGuildPatch = 0xEB;
    //SIZE_T BytesWritten;
    //int DllPatchAddress = (int)hHW_SOD + 0xFE2C;
    //WriteProcessMemory(GetCurrentProcess(), (LPVOID)DllPatchAddress, &MageGuildPatch, 1, &BytesWritten);
   //Первая версия-

    HMODULE hHW_SOD = GetModuleHandleA("HW_SOD.dll");
    _PI->WriteByte((int)hHW_SOD + 0xFE2C, 0xEB);

    //_PI->WriteLoHook((int)GetModuleHandleA("HD_SOD.dll") + 0x10FDC, newTownShortcut);

    return EXEC_DEFAULT;
}


string getInterval(int n) {
    string str = "1-4";
    if ( n > 999 ) str = "1000+"; else
    if ( n > 499 ) str = "500-999"; else
    if ( n > 249 ) str = "250-499"; else
    if ( n > 99 ) str = "100-249"; else
    if ( n > 49 ) str = "50-99"; else
    if ( n > 19 ) str = "20-49"; else
    if ( n > 9 ) str = "10-19"; else
    if ( n > 4 ) str = "5-9";
    return str;
}




int __stdcall showGuards(LoHook* h, HookContext* c)
{
    bool isUtopia = h->GetAddress() == 0x4A1E56;

    // Получаем состояние банка
    _CrBankState_* bankState = (_CrBankState_*)CALL_1(int, __fastcall, 0x405D80, isUtopia ? c->edi : c->ebx);

    int CreaturesCount = bankState->defenders.GetCreaturesCount();
   
    string str = (char*)c->ecx; // Оригинальное сообщение
    str = str + "\n\nAmount: " + getInterval(CreaturesCount);
       
    // Утопия?
    if ( isUtopia ) {
        str = str + " (" + getInterval(bankState->defenders.count[0]) + ", " + getInterval(bankState->defenders.count[1]) + ", " +
            getInterval(bankState->defenders.count[2]) + ", " + getInterval(bankState->defenders.count[3]) + ")";
    } else
    // Если есть грейд
    if ( bankState->defenders.type[2] != bankState->defenders.type[0]) {
        str = str + " (" + getInterval(CreaturesCount - bankState->defenders.count[2]) + ", " + getInterval(bankState->defenders.count[2]) + ")";
    }
           
    // Передаём адрес текстового буфера в качестве аргумента для диалога
    sprintf(o_TextBuffer, "%s", str);
    c->ecx = (int)o_TextBuffer;
   
    return EXEC_DEFAULT;
}

//
//-------------------------------------------------------------------------------------------------------
//MAIN
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.FreshMod");
         //------------------------------------------------------------------------------------------------
            //AlexSPL
            _PI->WriteLoHook(0x4ABBFA, setCreatureBankReward);
            _PI->WriteLoHook(0x4AC168, restoreOriginalReward);
         //Перестройка ГМ с любого уровня
         _PI->WriteLoHook(0x598510 /* перед загрузкой .vid */, patchDll);
         //------------------------------------------------------------------------------------------------
         //igrik
         // возможность заходить в гильдию магов без наличия книги и денег у героя-гостя
         _PI->WriteHexPatch(0x5CEA83, "EB74");
         _PI->WriteHexPatch(0x5CEACD, "2800");
            // Патч на tiny.fnt малые описания монстров (все в DEC)
            *(int*)6243434 = 6687924; // в бою
            *(int*)6244485 = 6687924; // при покупке
            *(int*)6241855 = 6687924; // не в бою
            // отображение длительности заклинаний в окне монстра (вытащено из HotA.dll)
            _PI->WriteLoHook(0x5F6BE2, Y_SpellShow);
            _PI->WriteLoHook(0x5F4B05, Y_SpellInfo1);  // тут WoG/ERA не дают поставить HiHook 
            _PI->WriteLoHook(0x5F522A, Y_SpellInfo2);
            // отображение длительности заклинаний в расширенной статистике (вытащено из HotA.dll)
            _PI->WriteLoHook(0x46D12B, Y_SpellShow1);   
            _PI->WriteLoHook(0x46D4CB, Y_SpellShow2);   
            _PI->WriteLoHook(0x46D9F0, Y_SpellShow3);
         //Обмен между героями в городе
         _PI->WriteHiHook(0x5D3640, SPLICE_, EXTENDED_, THISCALL_, Y_DlgTown_Proc);

         //Отображение охраны
            _PI->WriteLoHook(0x4A13E6, showGuards);
            _PI->WriteLoHook(0x4A1E56, showGuards);

        }
    }

    return TRUE;
}
Вернуться к началу

Пред.След.

Вернуться в Общий раздел

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [bot] и гости: 5