Объявления

Друзья, если не получается зарегистрироваться, напишите на почту 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 » 10 сен 2017, 08:08

Пример использования динамического массива картинок + фикс заголовка диалога (для того случая, когда картинок больше 8).
После каста заклинания в бою, имеющего продолжительность раунд/сила магии (например, Bless), показывает серию диалогов со всеми заклинаниями в игре.

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

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

struct PicStruc {
    int type;       // тип картинки (9 - заклинание)
    int id;         // ID заклинания
};

// кастомный _List_
struct List {
    _ptr_ Creation;
    PicStruc* Data;
    _ptr_ EndData;
    _ptr_ EndMem;
};

int captionAddr;

// Заголовок в каждом диалоге
int __stdcall saveCaption(LoHook* h, HookContext* c)
{
    captionAddr = c->ecx; 
    return EXEC_DEFAULT;
}

int __stdcall captionFix(LoHook* h, HookContext* c)
{
    *(int*)(c->ebp - 0x14) = captionAddr;
    return EXEC_DEFAULT;
}

int __stdcall showSpellDlg(LoHook* h, HookContext* c)
{
    int nPics = 70; // Кол-во картинок
    List picList;
   
    // Динамический массив картинок
    // Первый и последний элемент резервируем для полей Creation и EndData/EndMem соответственно
    PicStruc* pic = new PicStruc[nPics + 2];

    for (int i = 0; i < nPics; ++i) {
        pic[i + 1].type = 9;
        pic[i + 1].id = i;
    }
   
    picList.Creation = (_ptr_)pic + 4;
    picList.Data = &pic[1]; // Адрес первого элемента в списке
    picList.EndData = (_ptr_)pic + (nPics + 1) * 8; // Адрес следующего за последним элементом в списке байта
    picList.EndMem = picList.EndData;
   
    char Text[200] = "{Spell List}";
    CALL_5 (unsigned int, __fastcall, 0x4F7D20, Text, &picList, -1, -1, 0);

    delete [] pic;
   
    return EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch ( ul_reason_for_call )
    {
        case DLL_PROCESS_ATTACH:
            if ( !plugin_On )
            {
                plugin_On = 1;
                _P = GetPatcher();
                _PI = _P->CreateInstance("HD.Plugin.TestComplexDialog");
                _PI->WriteLoHook(0x4F7D49, saveCaption);
                _PI->WriteLoHook(0x4F7D54, captionFix);
                _PI->WriteLoHook(0x44467E, showSpellDlg);
            }
            break;

        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}


Плагин для проверки:
Test.zip
(5.63 КБ) Скачиваний: 255


2Ben80: А как список определён в воговской базе? Скопируйте сюда, если не сложно, ту структуру с полями First, Last, Ref, All.

* * *
 Типы картинок (из справки ERM-Help)
Типы картинок (для !!IF:Q)

Название | Тип | Подтип

Ресурс | Тип (0...7) | Количество
Артефакт | 8 | Номер артефакта
Заклинание | 9 | Номер заклинания
Флаг | 10 | Номер флага (8 - светло-оранжевый флаг с подписью "Человек или компьютер")
Удача (позитивная) | 11 | + удачи
Удача (нейтральная) | 12 | Не имеет значения
Удача (отрицательная) | 13 | - удачи
Мораль (позитивная) | 14 | + морали
Мораль (нейтральная) | 15 | Не имеет значения
Мораль (отрицательная) | 16 | - морали
Опыт | 17 | Количество
Вторичный навык | 20 | Навык + уровень
Монстр | 21 | Тип монстра
Здание в городе | 22...30 (в зависимости от типа города) | Номер строения
Первичный навык | 31...34 (прибавьте к 31 номер нужного) | Количество
Баллы заклинаний | 35 | Количество
Золото | 36 | Количество


* * *
Если не заморачиваться на раздельных диалогах для игроков (я предлагаю сначала написать работающий код для хотсита, а потом уже думать о сетевой игре), то новый Eagle Eye практически готов: патч, отменяющий действие стандартного Eagle Eye в конце боя, написан, диалог с картинками есть, а minWisdom() и getSpellLevel() легко получить из o_Spell. Только вероятности изучения заклинаний нужно уменьшить, т.к. стандартные (40/50/60%) такие большие, потому что набор ограничен лишь теми заклинаниями, которые герой использовал в бою. Теперь же этот набор - вся книга заклинаний.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 10 сен 2017, 15:00

AlexSpl писал(а):

А как список определён в воговской базе? Скопируйте сюда, если не сложно, ту структуру с полями First, Last, Ref, All.



Код: Выделить всё
00000000 _Memory_            struc ; (sizeof=0x10)
00000000 Ref                 dd ?
00000004 First               dd ?
00000008 Last                dd ?
0000000C All                 dd ?
00000010 _Memory_            ends


Не уверен что это то, что Вам нужно, в общем там так.
Это для Mon2Way

Вы, кстати, можете поставить себе IDA 5.5 на какую-нибудь виртуалку, разве нет ?
Последний раз редактировалось Ben80 10 сен 2017, 15:04, всего редактировалось 1 раз.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 10 сен 2017, 15:03

AlexSpl писал(а):

* * *
 Типы картинок (из справки ERM-Help)
Типы картинок (для !!IF:Q)

Название | Тип | Подтип

Ресурс | Тип (0...7) | Количество
Артефакт | 8 | Номер артефакта
Заклинание | 9 | Номер заклинания
Флаг | 10 | Номер флага (8 - светло-оранжевый флаг с подписью "Человек или компьютер")
Удача (позитивная) | 11 | + удачи
Удача (нейтральная) | 12 | Не имеет значения
Удача (отрицательная) | 13 | - удачи
Мораль (позитивная) | 14 | + морали
Мораль (нейтральная) | 15 | Не имеет значения
Мораль (отрицательная) | 16 | - морали
Опыт | 17 | Количество
Вторичный навык | 20 | Навык + уровень
Монстр | 21 | Тип монстра
Здание в городе | 22...30 (в зависимости от типа города) | Номер строения
Первичный навык | 31...34 (прибавьте к 31 номер нужного) | Количество
Баллы заклинаний | 35 | Количество
Золото | 36 | Количество




Ну вот, уже не первый раз встречаюсь с тем, что в ERM много полезной информации.
Но заставить себя изучать ERM не могу :smile1:
Мне проще писать плагины на C++, чем вникнуть в ERM.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 10 сен 2017, 15:08

AlexSpl писал(а):

Только вероятности изучения заклинаний нужно уменьшить, т.к. стандартные (40/50/60%) такие большие, потому что набор ограничен лишь теми заклинаниями, которые герой использовал в бою. Теперь же этот набор - вся книга заклинаний.


Будет 30/35/40%, если не возражаете. Проценты несколько завышены, но штука в том, что наиболее популярный формат игры сейчас - PvP, 1 на 1, и первый же большой бой часто бывает последним.

Даже стандартный EagleEye от NWC был бы неплохим навыком, если бы 1) играли 4 и более игроков 2) был бы хороший AI, который целенаправленно добывает хорошие заклинания и применяет их в бою.
И, кстати, когда-то оригинальный AI и был для меня весьма хорош. Это были мои первые игры в Героев 3, и тогда все навыки мне казались полезными и в одном бою, помню, я получил от компа целую кучу хороших заклинаний. После этого, не помню уж когда применял я Орлиный глаз, не упомню.
Собственно, этим модом я бы хотел как бы заново открыть для себя игру, как бы вернуться в те времена, когда все элементы игры казались осмысленными и полезными. Только чтобы на этот раз они действительно были полезными.
Последний раз редактировалось Ben80 10 сен 2017, 15:54, всего редактировалось 3 раз(а).
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 10 сен 2017, 15:12

Артефакты, связанные с Орлиным глазом, как я понял, не умножают вероятности (на 1.05, 1.1, 1.15) а прибавляют, что имеет более сильный эффект.
Оценив стоимость данных артефактов в оригинальной игре, считаю, что в данном случае как раз справедливость будет восстановлена, если эту стоимость оставить (и также оставить то, как они влияют на вероятность, то есть просто прибавляют). А в условиях оригинальной игры эта стоимость, хоть и небольшая, но была завышена.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 10 сен 2017, 15:21

AlexSpl писал(а):

Если не заморачиваться на раздельных диалогах для игроков (я предлагаю сначала написать работающий код для хотсита, а потом уже думать о сетевой игре), то новый Eagle Eye практически готов: патч, отменяющий действие стандартного Eagle Eye в конце боя, написан, диалог с картинками есть, а minWisdom() и getSpellLevel() легко получить из o_Spell.


Кстати, кроме создания массивов fireSpells, earthSpells, airSpells, waterSpells (для обработки артефактов-книг) еще пришлось создавать 2 массива для специализаций по спеллам (1 массив для ID героев, 2 - для номеров спеллов).
Так что рутины вышло немало (из-за того, что не узнал вовремя про o_Spell).

Если нужны упомянутые 2 массива, могу скопировать их Вам.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 10 сен 2017, 19:02

AlexSpl писал(а):

Если не заморачиваться на раздельных диалогах для игроков (я предлагаю сначала написать работающий код для хотсита, а потом уже думать о сетевой игре)


Да, с налета сетевая игра не задалась - думал, что оба игрока получат диалог (причем разный, показывающий ID данного игрока), а получил только один игрок.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 11 сен 2017, 15:19

Мудрость, кстати, оказалась не нужна для получения заклинаний Орлиным глазом.
Так что не будем менять это.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 11 сен 2017, 20:20

Написал версию для хотсита (без диалогов).
Какие изменения нужно внести, чтобы в сетевой игре работало ? (отправить каждому игроку свой диалог, если есть навык, конечно)

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

Patcher* _P;
PatcherInstance* _PI;


void makeEagleEye(int Hero, int HeroDonor)
{
   int spellTable = *(int*)(0x687FA8);
   double EagleEyePower = CALL_1(long double, __thiscall, 0x4E4690, Hero);
   
   for(int i=10; i<70; i++)
   {
      if(*(char*)(HeroDonor + 1072 + i) == 1)
      {
         int spellLevel = *(int*)(spellTable + 136*i + 0x18);
         if(spellLevel<=(*(char*)(Hero + 201 + 11)+1))
         {
            unsigned int dice;
            rand_s(&dice);
            if(((double) dice/((double) UINT_MAX + 1)*1.0)<EagleEyePower)
            {
               *(char*)(Hero + 1002 + i) = 1;
               *(char*)(Hero + 1072 + i) = 1;
            }
         }
         
      }
   }
}

int __stdcall eagleEyeMain(LoHook* h, HookContext* c)
{
   int Hero_1 = *(int*)(c->ebx + 0x53CC);
   int Hero_2 = *(int*)(c->ebx + 0x53CC + 4);

   if(*(int*)(Hero_1 + 201 + 11)>1)
      makeEagleEye(Hero_1, Hero_2);

   if(*(int*)(Hero_2 + 201 + 11)>1)
      makeEagleEye(Hero_2, Hero_1);
   
   return EXEC_DEFAULT;
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                )
{
   static _bool_ plugin_On = 0;
   switch (ul_reason_for_call)
   {
   case DLL_PROCESS_ATTACH:
      if (!plugin_On)
      {
         plugin_On = 1;
         _P = GetPatcher();
         _PI = _P->CreateInstance("HD.Plugin.EagleEyeTest2");
         _PI->WriteLoHook(0x462C7D, eagleEyeMain);
         _PI->WriteHexPatch(0x63EA2C, "9A 99 99 3E"); // 0.30
         _PI->WriteHexPatch(0x63EA30, "33 33 B3 3E"); // 0.35
         _PI->WriteHexPatch(0x63EA34, "CD CC CC 3E"); // 0.40
      }
      break;
   case DLL_THREAD_ATTACH:
   case DLL_THREAD_DETACH:
   case DLL_PROCESS_DETACH:
      break;
   }
   return TRUE;
}

Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 11 сен 2017, 20:22

Забыл только написать проверку - не с монстрами ли бой.
Вернуться к началу

Пред.След.

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

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

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