Объявления
Поздравляем
Roman2211


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

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 07 июн 2019, 16:13

feanor писал(а):

Для новонарисованных и RMG можно отредактировать шаблон в текстовиках объектов, для старых - только если изменять все вот это вот при загрузке карты.


Редактировать ресурсные файлы - это уже, пожалуй, прошлый век. То есть не прошлый век, конечно, но так делали лет 15-20 назад, во времена ВОГа.

Сейчас самый технологичный способ - поставить хук чуть позже места, где загружается Objects.txt и инфа оттуда преобразуется в игровые структуры (возможно даже, непосредственно в _Template_ - по терминологии SDK Бараторча). По аналогии - не редактировать, скажем, SPTRAITS.txt, а изменять в памяти o_Spell[i] - сразу после парсинга SPTRAITS.txt в оригинальном коде.

Однако стоит заметить, что шаблоны для объектов в игре существуют в 2 видах - для менеджера игры и для генератора случайных карт. Формат масок для "желтых" и "красных" клеток в них, впрочем, одинаков.
Вернуться к началу

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

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

Сообщение as239 » 07 июн 2019, 16:46

Решил делать через запоминание последнего заклинания т.к. игровую структуру я не найду.
Запоминание сделал:

Код: Выделить всё
int __stdcall RememberLastBattleCast(LoHook* h, HookContext* c)
{
    _Hero_* hero[] = {o_BattleMgr->hero[ATTACKER], o_BattleMgr->hero[DEFENDER]};
   if ( hero[ATTACKER] && hero[DEFENDER] )
   {
      LastBattleCast[o_BattleMgr->current_side] = c->eax;
   }
   return EXEC_DEFAULT;
}
...
_PI->WriteLoHook(0x5A019E, RememberLastBattleCast );


Но не могу найти адрес где игрок получает ход в каждом раунде.
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Посвященный
Посвященный
 
Сообщения: 88
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 22 раз.

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

Сообщение Catastrophe » 07 июн 2019, 17:32

Ben80 писал(а):

Редактировать ресурсные файлы - это уже, пожалуй, прошлый век. То есть не прошлый век, конечно, но так делали лет 15-20 назад, во времена ВОГа.

Редактировать ресурсные файлы в разы удобнее при работе с таблицами и в глобальных модах без этого никак не обойтись (либо придется их делать с одной локализацией как минимум)
Быстрее всего смогу ответить вам в Telegram: @PleaseAndThankYou
Вернуться к началу

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

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

Сообщение Ben80 » 07 июн 2019, 17:36

Делал модуль, он работал одновременно с несколькими локализациями. Это было сделать несложно.И все очень просто для пользователя - просто подключи Dll и все - модуль сам определит твою локализацию и все, что нужно сделает. И все чистенько в папке с игрой.
Так что по моему опыту - так удобнее. Хоть и не в разы ))). Ты бы еще сказал "на порядки".
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Посвященный
Посвященный
 
Сообщения: 88
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 22 раз.

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

Сообщение Catastrophe » 07 июн 2019, 17:58

Ben80 писал(а):

И все чистенько в папке с игрой.

Так через ммархив все же прекрасно в h3bitmap.lod запихивается мелкими щелчками, а в MoP вообще используются свои отдельные архивы
Быстрее всего смогу ответить вам в Telegram: @PleaseAndThankYou
Вернуться к началу

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

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

Сообщение Ben80 » 07 июн 2019, 18:00

Ну вообще то ты прав насчет того, что если данных очень много, то лучше таблички редактировать.

И MM работает согласен. Да, не делал я глобальных модов. И для тех Dll ок которые я делаю, как-то мне уже некамильфо ресурсы редактировать.

Ну Бараторч ведь тоже вроде предпочитает, чтобы Dll делала работы по максимуму. И чтобы всегда можно было легко откатиться к более старой версии игры, просто удалив некие папки/файлы.
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Посвященный
Посвященный
 
Сообщения: 88
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 22 раз.

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

Сообщение Catastrophe » 07 июн 2019, 18:47

Ben80 писал(а):

Да, не делал я глобальных модов. И для тех Dll ок которые я делаю, как-то мне уже некамильфо ресурсы редактировать.

Ну так мы о разном говорим, у мелких плагинов, когда отредачен 1 спелл к примеру, такое приемлимо, у меня же все отредаченное в плагин запихивать это можно с ума сойти (в одном sptraits.txt изменено под половину ячеек)
Быстрее всего смогу ответить вам в Telegram: @PleaseAndThankYou
Вернуться к началу

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

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

Сообщение Ben80 » 08 июн 2019, 08:51

В Objects.txt каждому подобъекту соответствует своя отдельная строка. Например, для Обелисков их 7.
И есть определенное удобство делать изменения с помощью кода, а не редактированием ресурсов.
Циклы программирования позволяют написать всего 1 строку с изменениями вместо редактирования нескольких строк. Условия и ветвления позволяют определять версию игры/локализацию и иметь одну версию Dll и одну версию ресурсов вместо нескольких.
Вернуться к началу

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

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

Сообщение as239 » 08 июн 2019, 10:10

Получилось сделать с существующим адресом, при активации каждого боевого стека:

Код: Выделить всё
struct PicStruc {
    int type;       // тип картинки (9 - заклинание)
    int id;         // ID картинки
};

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

int captionAddr;
int LastBattleCast[] = {-1, -1};

// Заголовок в каждом диалоге
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 showSpellDlg(_Hero_* hero, int spells[], int nPics)
{
    if ( !nPics ) return 0;

    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 = spells[i];
    }

    picList.Creation = (_ptr_)pic + 4;
    picList.Data = pic + 1; // Адрес первого элемента в списке
    picList.EndData = picList.Data + nPics; // Адрес следующего за последним элементом в списке байта
    picList.EndMem = (_ptr_)picList.EndData;

    sprintf(o_TextBuffer, "Благодаря навыку {Орлиный глаз}, {%s} выучил%s следующ%s заклинан%s:",
        hero->name, hero->sex ? "а" : "", nPics > 1 ? "ие" : "ее", nPics > 1 ? "ия" : "ие");
    CALL_5(unsigned int, __fastcall, 0x4F7D20, o_TextBuffer, &picList, -1, -1, 0);

    delete [] pic;

    return 0;
}

int getEagleEyeSpells(_Hero_* hero, _Hero_* heroDonor, int i)
{
   int n = 0;
   unsigned int eagleEyeProb = (unsigned int)(CALL_1(float, __thiscall, 0x4E4690, hero) * 100.0);

   if ( heroDonor->spell_level[i] && !hero->spell[i] )
   {
      unsigned int dice;
      rand_s(&dice);
      dice = (unsigned int)((double)dice / ((double)UINT_MAX + 1) * 100.0) + 1;
      if ( dice <= eagleEyeProb )
      {
         n = 1;
         hero->spell[i] = 1;
         hero->spell_level[i] = 1;
      }
   }
   return n;
}

int __stdcall eagleEyeMain(LoHook* h, HookContext* c)
{
    _Hero_* hero[] = {o_BattleMgr->hero[ATTACKER], o_BattleMgr->hero[DEFENDER]};

    if ( hero[ATTACKER] && hero[DEFENDER] )
    {
      if ( LastBattleCast[o_BattleMgr->current_side] == -1 ) return EXEC_DEFAULT;

        int spells[1];

        for (int i = ATTACKER; i <= DEFENDER; ++i)
        {
            if ( o_BattleMgr->current_side == i && hero[i]->second_skill[HSS_EAGLE_EYE] &&
                hero[i]->doll_art[AS_SPELL_BOOK].id == AID_SPELL_BOOK )
            {
                // Учим заклинания всегда.
            spells[0] = LastBattleCast[o_BattleMgr->current_side];
                int n = getEagleEyeSpells(hero[i], hero[1 - i], LastBattleCast[o_BattleMgr->current_side]);
            LastBattleCast[o_BattleMgr->current_side] = -1;

                // Но диалог показываем только для игрока-человека:
                // в хотсите - диалог для обоих героев, в сетевой игре - только для своего героя.
                if ( o_GameMgr->GetPlayer(hero[i]->owner_id)->IsHuman() ) {
                    int id = o_GameMgr->GetMeID();
                    if ( !o_NetworkGame || hero[i]->owner_id == id ) {
                        o_ActivePlayerID = hero[i]->owner_id;
                        showSpellDlg(hero[i], spells, n);
                        o_ActivePlayerID = id;
                    }
                }
            }
        }
    }

    return EXEC_DEFAULT;
}


int __stdcall RememberLastBattleCast(LoHook* h, HookContext* c)
{
    _Hero_* hero[] = {o_BattleMgr->hero[ATTACKER], o_BattleMgr->hero[DEFENDER]};
   if ( hero[ATTACKER] && hero[DEFENDER] )
   {
      LastBattleCast[1-o_BattleMgr->current_side] = c->eax;
   }
   return EXEC_DEFAULT;
}

......
        _PI->WriteLoHook(0x5A019E, RememberLastBattleCast );
            // Убираем оригинальный эффект
            _PI->WriteHexPatch(0x469C23, "EB");
            _PI->WriteHexPatch(0x476996, "E9 DD 01 00 00");

            // Фиксим заголовок диалога
            _PI->WriteLoHook(0x4F7D49, saveCaption);
            _PI->WriteLoHook(0x4F7D54, captionFix);
            _PI->WriteLoHook(0x477C00, eagleEyeMain);
Последний раз редактировалось as239 09 июн 2019, 05:00, всего редактировалось 1 раз.
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Посвященный
Посвященный
 
Сообщения: 88
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 22 раз.

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

Сообщение Catastrophe » 09 июн 2019, 01:13

Как получить id героя, который на данный момент ходит в бою / колдует заклинание?
 Либо, как перенести вот это?
Изображение

Через ассемблерную вставку вроде получилось сделать, но все застопорилось на вызове функции:
Код: Выделить всё
int __stdcall c_spec_spell_mirth(LoHook *h, HookContext *c)
{
   __asm
   {
      mov ecx, [ebp+0x14]
      mov [esi+0x468], edi
      test ecx, ecx
      jz 00444d5ch
      mov eax, [esi+0x78]
      mov edx, [ebp+0x8]
      push edi
      push eax
      push edx
      call 004e6260h // error C2415: improper operand type
      add [esi+0x468], eax
   }
   return EXEC_DEFAULT;
}

// dllmain

         _PI->WriteLoHook(0x44496D, c_spec_spell_mirth);
Быстрее всего смогу ответить вам в Telegram: @PleaseAndThankYou
Вернуться к началу

Пред.След.

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

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

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

cron