Объявления

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

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineRolex  
имя: Alex
Ветеран
Ветеран
 
Сообщения: 898
Зарегистрирован: 22 сен 2020, 18:58
Откуда: УКРАИНА
Пол: Мужчина
Поблагодарили: 53 раз.

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

Сообщение Rolex » 05 авг 2021, 11:02

Результат тот же. Не работает, хоть с активной, хоть с неактивной. Можно попробовать через два хука. Правда много дублирующегося кода будет.
Вернуться к началу

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 » 05 авг 2021, 11:02

Так-с. Пробуйте через один. Там два прохода по коду. Первый должен выводить.
Вернуться к началу

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 » 05 авг 2021, 11:03

Скиньте текущий код.
Вернуться к началу

offlineRolex  
имя: Alex
Ветеран
Ветеран
 
Сообщения: 898
Зарегистрирован: 22 сен 2020, 18:58
Откуда: УКРАИНА
Пол: Мужчина
Поблагодарили: 53 раз.

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

Сообщение Rolex » 05 авг 2021, 11:15

Код почти готов, только с неактивной кнопкой осталось разобраться. Пробовал ставить отдельный хук по адресу 0x5F5329 для неактивной кнопки. Но все равно для неактивной не работает...

Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "HotA\homm3.h"
#define o_GENRLTXT_TXT (*(_TXT_**)0x6A5DC4)

using namespace std;

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

struct _TXTEX_ : public _TXT_ {
   inline void SetString(int index, char* str)
   {
      *(char**)(*(int*)((int)this + 32) + index * 4) = str;
   }
};

string getString(int id, int number, string str, string separator)
{
   str = str + separator + "(" + o_GENRLTXT_TXT->GetString(626) + ": " + to_string((o_CreatureInfo[CALL_1(int, __fastcall, 0x47AAD0, id)].cost.gold - o_CreatureInfo[id].cost.gold) * number);

   int crystal = o_CreatureInfo[CALL_1(int, __fastcall, 0x47AAD0, id)].cost.crystal - o_CreatureInfo[id].cost.crystal;
   int jems = o_CreatureInfo[CALL_1(int, __fastcall, 0x47AAD0, id)].cost.jems - o_CreatureInfo[id].cost.jems;
   int mercury = o_CreatureInfo[CALL_1(int, __fastcall, 0x47AAD0, id)].cost.mercury - o_CreatureInfo[id].cost.mercury;
   int sulfur = o_CreatureInfo[CALL_1(int, __fastcall, 0x47AAD0, id)].cost.sulfur - o_CreatureInfo[id].cost.sulfur;

   if (mercury != 0) str = str + ", " + o_GENRLTXT_TXT->GetString(621) + ": " + to_string(mercury * number) + ")"; else
      if (sulfur != 0) str = str + ", " + o_GENRLTXT_TXT->GetString(623) + ": " + to_string(sulfur * number) + ")"; else
         if (crystal != 0) str = str + ", " + o_GENRLTXT_TXT->GetString(624) + ": " + to_string(crystal * number) + ")"; else
            if (jems != 0) str = str + ", " + o_GENRLTXT_TXT->GetString(625) + ": " + to_string(jems * number) + ")"; else
               str = str + ")";
   return str;
}

int __stdcall showGuardsRMB(LoHook* h, HookContext* c)
{
   if (c->esi == 0xD)
   {
      string str = *(char**)(c->esi * 8 + 0x6A74C4); // Оригинальное сообщение

      int id = *(int*)(c->ebx + 0x60);
      int number = *(int*)(c->ebx + 0x64);

      string separator = "\n";

      str = getString(id, number, str, separator);

      // Передаём адрес текстового буфера в качестве аргумента для диалога
      sprintf(o_TextBuffer, "%s", str.c_str());
      c->esi = (int)o_TextBuffer;

      c->return_address = 0x5F4CA0;
      return NO_EXEC_DEFAULT;      
   }
   
   return EXEC_DEFAULT;
}

int __stdcall showInfoButton(LoHook* h, HookContext* c)
{
   if (c->eax == 0xD)   
   {
      string str = *(char**)(c->eax * 8 + 0x6A74C0); // Оригинальное сообщение

      int id = *(int*)(c->ebx + 0x60);
      int number = *(int*)(c->ebx + 0x64);

      string separator = " ";

      str = getString(id, number, str, separator);

      // Передаём адрес текстового буфера в качестве аргумента для диалога
      sprintf(o_TextBuffer, "%s", str.c_str());
      c->edi = (int)o_TextBuffer;

      c->return_address = 0x5F5336;
      return NO_EXEC_DEFAULT;
   }

   return EXEC_DEFAULT;
}

int __stdcall showInfoButtonTwo(LoHook* h, HookContext* c)
{
   if (c->eax >= 0xEC && c->eax <= 0x10D)
   {
      string str = *(char**)(0xD * 8 + 0x6A74C0); // Оригинальное сообщение

      int id = *(int*)(c->ebx + 0x60);
      int number = *(int*)(c->ebx + 0x64);

      string separator = " ";

      str = getString(id, number, str, separator);

      // Передаём адрес текстового буфера в качестве аргумента для диалога
      sprintf(o_TextBuffer, "%s", str.c_str());
      c->edi = (int)o_TextBuffer;

      c->return_address = 0x5F5336;
      return NO_EXEC_DEFAULT;
   }

   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((char*)"HD.Plugin.UpgradeCost");

         // Сообщения по правому клику
         _PI->WriteLoHook(0x5F4C99, showGuardsRMB);

         _PI->WriteLoHook(0x5F5320, showInfoButton);      
         _PI->WriteLoHook(0x5F5329, showInfoButtonTwo);
         
      }
   }

   return TRUE;
}
Последний раз редактировалось Rolex 05 авг 2021, 11:25, всего редактировалось 2 раз(а).
Вернуться к началу

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 » 05 авг 2021, 11:24

Всё-таки в данной реализации нужно два хука. Вот недостающий код для неактивной кнопки. Там два прохода. При активной, если делать через один хук, сообщение переписывается во втором проходе для активной кнопки.

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

Patcher* _P;
PatcherInstance* _PI;

int __stdcall showUpgradeCost(LoHook* h, HookContext* c)
{
    if (c->edx >= 0xEC && c->edx <= 0x10D)
    {
      string str = *(char**)(0xD * 8 + 0x6A74C0); // Оригинальное сообщение

      str = str + " test";

      // Передаём адрес текстового буфера в качестве аргумента для диалога
      sprintf(o_TextBuffer, "%s", str.c_str());
      c->edi = (int)o_TextBuffer;
    }
   
    return EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    static bool plugin_On = false;

    if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
    {
        if ( !plugin_On )
        {
            plugin_On = true;
            _P = GetPatcher();
            _PI = _P->CreateInstance((char*)"HD.Plugin.UpgradeInfo");

            _PI->WriteLoHook(0x5F5329, showUpgradeCost);
        }
    }

    return TRUE;
}

Да, и есть проблема на границах кнопок. Нужны более жёсткие условия. Например, плавно ведите мышку вправо с кнопки "Dismiss unit". При достижении границы будет показана подсказка для кнопки "Upgrade unit", если провести мышкой ещё чуть дальше вправо, то этот хинт исчезнет. Нужно исправлять. Я уже знаю что. Странно что мы сравниваем только вертикальные координаты :smile2:
Последний раз редактировалось AlexSpl 05 авг 2021, 11:35, всего редактировалось 1 раз.
Вернуться к началу

offlineRolex  
имя: Alex
Ветеран
Ветеран
 
Сообщения: 898
Зарегистрирован: 22 сен 2020, 18:58
Откуда: УКРАИНА
Пол: Мужчина
Поблагодарили: 53 раз.

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

Сообщение Rolex » 05 авг 2021, 11:35

Сделал у себя. Теперь работает с неактивной.

AlexSpl писал(а):

Да, и есть проблема на границах кнопок. Нужны более жёсткие условия. Например, плавно ведите мышку вправо с кнопки "Dismiss unit". При достижении границы будет показана подсказка для кнопки "Upgrade unit", если провести мышкой ещё чуть дальше вправо, то этот хинт исчезнет. Нужно исправлять.

А как исправить?
Вернуться к началу

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 » 05 авг 2021, 11:36

Нужно сравнивать ещё и горизонтальные координаты, думаю. А вообще, я подумаю, как объединить код в один хук. Просто нужно больше времени.
Вернуться к началу

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 » 05 авг 2021, 12:21

Пока есть решение через абсолютные координаты (MouseMgr):

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

Patcher* _P;
PatcherInstance* _PI;

int __stdcall showUpgradeCost(LoHook* h, HookContext* c)
{
    int x = *(int*)(*(int*)(c->ebp + 8) + 0x10);
    int y = *(int*)(*(int*)(c->ebp + 8) + 0x14);

    char* str = *(char**)(c->eax * 8 + 0x6A74C0); // Оригинальное сообщение

    // Передаём адрес текстового буфера в качестве аргумента для диалога
    sprintf(o_TextBuffer, "[%d : %d]", x, y);
    c->edi = (int)o_TextBuffer;
   
    return EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    static bool plugin_On = false;

    if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
    {
        if ( !plugin_On )
        {
            plugin_On = true;
            _P = GetPatcher();
            _PI = _P->CreateInstance((char*)"HD.Plugin.UpgradeInfo");

            _PI->WriteLoHook(0x5F5336, showUpgradeCost);
        }
    }

    return TRUE;
}

При наведении мышкой на границу, Вы увидите её координаты. Их потом нужно использовать в качестве условия. Т.е. если курсор попадает в выбранную область, выводим подсказку. Правда, в общем случае необходимо получить также координаты левого верхнего угла диалога. Я ещё x и y перепутал, но не суть. А нет, всё в порядке :smile14:

Наверное, проще получить родительский диалог, а из него координаты левого верхнего угла. Потом получить кнопку и её координаты. Т.е. через диалоги решение. Так, наверное, правильнее.
Вернуться к началу

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 » 05 авг 2021, 12:43

Короче, вот так всё работает. Добавьте координаты в условие просто:

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

Patcher* _P;
PatcherInstance* _PI;

int __stdcall showUpgradeCost(LoHook* h, HookContext* c)
{
    int x = *(int*)(*(int*)(c->ebp + 8) + 0x10);
    int y = *(int*)(*(int*)(c->ebp + 8) + 0x14);

    _Dlg_* dlg = (_Dlg_*)c->ebx;
   
    sprintf(o_TextBuffer, "[%d : %d]", x - dlg->x, y - dlg->y);
    c->edi = (int)o_TextBuffer;
   
    return EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    static bool plugin_On = false;

    if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
    {
        if ( !plugin_On )
        {
            plugin_On = true;
            _P = GetPatcher();
            _PI = _P->CreateInstance((char*)"HD.Plugin.UpgradeInfo");

            _PI->WriteLoHook(0x5F5336, showUpgradeCost);
        }
    }

    return TRUE;
}

Если можно проще, то я уже не знаю как.
Вернуться к началу

offlineRolex  
имя: Alex
Ветеран
Ветеран
 
Сообщения: 898
Зарегистрирован: 22 сен 2020, 18:58
Откуда: УКРАИНА
Пол: Мужчина
Поблагодарили: 53 раз.

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

Сообщение Rolex » 05 авг 2021, 12:53

Типа вместо этого:
Код: Выделить всё
if (c->edx >= 0xEC && c->edx <= 0x10D)

Так?
Код: Выделить всё
int x = *(int*)(*(int*)(c->ebp + 8) + 0x10);
int y = *(int*)(*(int*)(c->ebp + 8) + 0x14)

if (c->edx >= x && c->edx <= y)


Или к нему как доп условие?

А это тогда зачем?
Код: Выделить всё
_Dlg_* dlg = (_Dlg_*)c->ebx;


Вот текущее решение в моем коде:
Код: Выделить всё
int __stdcall showUpgradeCost(LoHook* h, HookContext* c)
{
   if (c->edx >= 0xEC && c->edx <= 0x10D)
   {
      string str = *(char**)(0xD * 8 + 0x6A74C0); // Оригинальное сообщение

      int id = *(int*)(c->ebx + 0x60);
      int number = *(int*)(c->ebx + 0x64);

      string separator = " ";

      str = getString(id, number, str, separator);

      // Передаём адрес текстового буфера в качестве аргумента для диалога
      sprintf(o_TextBuffer, "%s", str.c_str());
      c->edi = (int)o_TextBuffer;
   }

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

Пред.След.

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

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

cron