Объявления

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

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5547
Зарегистрирован: 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)
Поблагодарили: 2162 раз.

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

Сообщение AlexSpl » 19 авг 2017, 09:38

Вот новый код для Blind. Длительность заклинания 1/1/3/5 раундов (None/Basic/Advanced/Expert Fire Magic). Длительность Ослепления Единорогов - 3 раунда (по умолчанию). Заклинание "Волшебное зеркало" (Magic Mirror) учтено.

LoHook @ 44467Eh:
Код: Выделить всё
int __stdcall blindSpell(LoHook* h, HookContext* c)
{
   if ( c->ebx == 62 )
   {
      int cmAddr = *(int*)0x699420;
      int currentSide = *(int*)(cmAddr + 0x132C0); // Текущая сторона
      int hero = *(int*)(cmAddr + currentSide * 4 + 0x53CC); // Адрес героя, который кастует заклинание, или 0, если героя нет
      int actionId = *(int*)(cmAddr + 0x3C); // ID текущего действия (1 - каст заклинания героем, 2 - передвижение отряда по полю боя и т.п.)
         
      int duration[] = {1, 1, 3, 5};
      if ( actionId == 1 ) c->eax = duration[*(char*)(hero + 201 + 14)];
   }

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

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

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

Сообщение Ben80 » 19 авг 2017, 10:42

У меня пока дальнейшее освоение кодинга и вообще работа над Ботвинник модом продвигается очень медленно, по ряду причин. Поэтому озадачивать Вас еще чем-нибудь мне пока неловко.
Но при удобном случае напишу Вам здесь.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5547
Зарегистрирован: 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)
Поблагодарили: 2162 раз.

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

Сообщение AlexSpl » 19 авг 2017, 12:42

Код для Disguise можно и без диалогов пока написать (для какого-нибудь тестового значения) или даже серию стандартных диалогов "Да/Нет" вставить для выбора коэффициента. Когда будет нормальный диалог, внести изменения труда не составит.

P.S. Я где-то видел на DF2 пример работы с диалогами, но найти не могу.
Вернуться к началу

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

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

Сообщение Ben80 » 19 авг 2017, 13:19

AlexSpl писал(а):

Код для Disguise можно и без диалогов пока написать (для какого-нибудь тестового значения) или даже серию стандартных диалогов "Да/Нет" вставить для выбора коэффициента. Когда будет нормальный диалог, внести изменения труда не составит.

P.S. Я где-то видел на DF2 пример работы с диалогами, но найти не могу.


Согласен. Я не пытаюсь увильнуть от сложностей, хотя они есть :smile1:

Для начала попробую понять, как нужно изменить код, чтобы игра брала нужное значение из поля disguise. То есть найти код, который срабатывает при просмотре игроком героя противника правой кнопкой. И код, который делает это для ИИ, если таковой вообще есть (известно же, что ИИ читер, всю инфу знает точно).

Приложил, кстати, файл, где начал заполнять список изменений. Надеюсь, это Вас хоть чуть-чуть интересует :smile1:
Может быть, есть какие-то критические замечания ? :smile1:
Вложения
Ботвинник_мод.xls
(12.5 КБ) Скачиваний: 250
Вернуться к началу

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

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

Сообщение Ben80 » 19 авг 2017, 13:33

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

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5547
Зарегистрирован: 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)
Поблагодарили: 2162 раз.

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

Сообщение AlexSpl » 28 авг 2017, 18:38

Участник форума DF2 igrik поделился примером создания кастомных диалогов для HD мода. Я немного переделал код и написал плагин, демонстрирующий работу с диалогами:

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

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

// Количество раундов
int n;

// Создаём стандартный задник с рамкой цвета игрока
void setStdBackground(_Dlg_* dlg)
{
    CALL_5 (int, __thiscall, 0x48FA80, dlg, dlg->x, dlg->y, dlg->width, dlg->height);

    for (int i = dlg->field_4C; i <= dlg->field_50; ++i)
    {
        CALL_5 (int, __thiscall, 0x5FF400, dlg, 512, 13, i, o_GameMgr->GetMeID());   
    }
}

void __fastcall scrollDlgCallback(int click_id, _Dlg_* dlg)
{
    // Выводим в текстовое поле текущее значение, выбранное с помощью ползунка
    n = click_id + 1;
    sprintf(o_TextBuffer, "%d", n);
    ((_DlgStaticText_*)dlg->GetItem(14))->SetText(o_TextBuffer);
    dlg->Redraw(TRUE);
}

void yDlgShow(int width, int height, int count, char* captionText, char* messageText, bool middle = true, int x = 0, int y = 0)
{
    // Создаём по центру экрана пустой диалог с тенью
    _Dlg_* dlg = _CustomDlg_::Create(DLG_X_CENTER, DLG_Y_CENTER, width, height, DF_SCREENSHOT | DF_SHADOW, NULL);
   
    // Добавляем задник (фон) и рамку по цвету игрока
    setStdBackground(dlg);
       
    // Добавляем заголовок диалога
    dlg->AddItem(_DlgStaticText_::Create(0, 20, dlg->width, 30,
        captionText, "bigfont.fnt", 7, 1, ALIGN_H_CENTER | ALIGN_V_TOP, 0));

    // Добавляем текст
    dlg->AddItem(_DlgStaticText_::Create(0, 50, dlg->width, 50,
        messageText, "medfont.fnt", 1, 0, ALIGN_H_CENTER | ALIGN_V_TOP, 0));

    // Добавляем полосу горизонтальной прокрутки
    dlg->AddItem(_DlgScroll_::Create(30, dlg->height - 90, dlg->width - 30 * 2 + 1, 16, 40, count,
        (_ptr_)scrollDlgCallback, 0, 18, 0));
   
    // Добавляем текстовое поле для отображения значений, выбираемых с помощью ползунка
    dlg->AddItem(_DlgStaticText_::Create((dlg->width - 30) / 2 + 1, dlg->height - 61, 30, 30,
        "1", "medfont.fnt", 1, 14, ALIGN_H_CENTER | ALIGN_V_CENTER, 0));

    // Добавляем кнопку OK
    dlg->AddItem(_DlgStaticPcx8_::Create(30, dlg->height - 61, 0, "Box64x30.pcx"));
    dlg->AddItem(_DlgButton_::Create(31, dlg->height - 60, 64, 30, 30722, "iOkay.def", 0, 1, 1, 28, 2));

    // Добавляем кнопку Cancel
    dlg->AddItem(_DlgStaticPcx8_::Create(dlg->width - 31 - 64, dlg->height - 61, 0, "Box64x30.pcx"));
    dlg->AddItem(_DlgButton_::Create(dlg->width - 30 - 64, dlg->height - 60, 64, 30, 30721, "iCancel.def", 0, 1, 1, 1, 2));

    if ( !middle ) dlg->SetPos(x, y);
    dlg->Run();
    dlg->Destroy(TRUE);
}

int __stdcall blindSpell(LoHook* h, HookContext* c)
{
    if ( c->ebx == SPL_BLIND )
    {
        n = 1;
       
        // Если герой скастовал Blind, показываем диалог
        yDlgShow(240, 140, 10, "Blind", "Please set spell duration\nfrom 1 to 10 rounds:");

        // Если нажата кнопка OK (30722), то устанавливаем длительность заклинания Blind = n,
        // иначе - длительность остаётся по умолчанию
        if ( o_WndMgr->result_dlg_item_id == 30722 ) c->eax = n;
    }

    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.TestCustomDialog");
                _PI->WriteLoHook(0x44467E, blindSpell);
            }
            break;

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


Сам плагин в архиве:
Test.zip
(5.95 КБ) Скачиваний: 227


Изображение

* * *
Чуть позже выяснил, что предпоследний аргумент здесь:

Код: Выделить всё
// Добавляем полосу горизонтальной прокрутки
dlg->AddItem(_DlgScroll_::Create(30, dlg->height - 90, dlg->width - 30 * 2 + 1, 16, 40, count, (_ptr_)scrollDlgCallback, 0, 18, 0));

это шаг при клике на полосе прокрутки, его нужно установить в 1 (пока что). Последний аргумент, судя по всему, флаг (bool) - разрешёно ли управление ползунком с клавиатуры.

* * *
2Ben80: Так что, если у Вас есть время и желание, можете продолжить работу над Disguise :smile1:
Вернуться к началу

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

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

Сообщение Ben80 » 29 авг 2017, 19:51

Работа непременно будет завершена, зря что ли начинали :smile1:
Вернуться к началу

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

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

Сообщение Ben80 » 02 сен 2017, 06:21

Потестировал свой плагин для Городского портала. Комп не использует эту возможность при основном уровне Магии Земли.

Значит, при действиях на карте, он проверяет, есть ли у него Городской портал и какой у него уровень Магии Земли.

Можно ли как-то определить участок кода, где это делается ? То есть можно ли, например, отследить обращения к данному поле в объекте Герой (Магия Земли) ?

Идея в том, чтобы просто отключить эту проверку. Мне бы этого было достаточно, чтобы считать, что все работает ОК.
По адресу 0x41D6D1 отключал проверку собственно при кастовании заклинания, но, видимо, этого недостаточно.

В df2 форуме написал на эту тему.
Вернуться к началу

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

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

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

Вот здесь еще фигурирует уровень Магии Земли:

0041D7F8

Не подскажите, что там вообще происходит, по этому адресу и пониже ?

В самой процедуре Cast_TownPortal Игрок (AI) может принимать решение о том, кастовать или нет
и если что-то его не устраивает, то выходить из процедуры, не прокастовав реально ?
Вернуться к началу

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

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

Сообщение Ben80 » 02 сен 2017, 14:34

Написал код для модификации Зыбучих песков и Мин. Теперь их количество 6/8/10 в зависимости от уровня магии.
Через SPTRAITS.txt такая модификация невозможна.

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

Patcher* _P;
PatcherInstance* _PI;


int __stdcall quicksandSpell(LoHook* h, HookContext* c)
{
   
   int peski[] = {6, 6, 8, 10};
   c->edi = peski[c->esi];
   
   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.Quicksand");

_PI->WriteLoHook(0x5A066B, quicksandSpell);

}
break;

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

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

Пред.След.

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

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

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