Объявления

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

Научил AI покупать неулучшенных существ в новых двеллингах:

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

Patcher* _P;
PatcherInstance* _PI;

// For debugging purposes
void showDebugInfo(const char* format, ...)
{
    va_list args;
    va_start(args, format);

    vsprintf(o_TextBuffer, format, args);
    b_MsgBox(o_TextBuffer, MBX_OK);

    va_end(args);
}

int __stdcall showInfo(LoHook* h, HookContext* c)
{
    char TxtBuffer[1024] = "";
    char infoStr[1024] = "";
   
    _Hero_* hero = &o_GameMgr->hero[o_ActivePlayer->selected_hero_id];
   
    if ( hero )
    {
        sprintf(infoStr, "{%s}\n\n", hero->name);

        for (int i = 0; i < 7; ++i)
        {
            if ( hero->army.type[i] != ID_NONE )
                sprintf(TxtBuffer, "%s: %d\n", o_pCreatureInfo[hero->army.type[i]].name_plural, hero->army.count[i]);
            else
                sprintf(TxtBuffer, "%s\n", "[Empty]");
            strcat(infoStr, TxtBuffer);
        }

        showDebugInfo("%s\nGold: %d", infoStr, o_ActivePlayer->resourses.gold);
    }

    return EXEC_DEFAULT;
}

int __stdcall setCreatures(LoHook* h, HookContext* c)
{
    _Dwelling_* dwelling = (_Dwelling_*)c->esi;
    int upgMonId = CALL_1(int, __fastcall, 0x47AAD0, dwelling->creature_types[0]);
   
    if ( upgMonId != ID_NONE && dwelling->creature_types[1] == ID_NONE ) {
        dwelling->creature_types[1] = dwelling->creature_types[0];
        dwelling->creature_counts[1] = dwelling->creature_counts[0];
        dwelling->creature_types[0] = upgMonId;
        if ( dwelling->defenders.type[0] != ID_NONE )
            dwelling->defenders.type[0] = upgMonId;
    }

    return EXEC_DEFAULT;
}

_Dwelling_* GetDwelling(_int_ dwellingId) {
    return (_Dwelling_ *)(o_GameMgr->Field<int>(0x4E39C) + 92 * dwellingId);
}

int __stdcall afterHiring(LoHook* h, HookContext* c)
{
    // Если нанимаем не в городе
    if ( h->GetAddress() == 0x42D768 || *(int*)(c->esi + 0x48) != 0x62 )
    {
        _Hero_* hero = &o_GameMgr->hero[o_ActivePlayer->selected_hero_id];
        if ( hero )
        {
            _MapItem_* item = o_GameMgr->Map.GetItem(hero->x, hero->y, hero->z);
            if ( item->object_type == 0x11 )
            {
                _Dwelling_* dwelling = GetDwelling(item->setup);
                if ( dwelling && dwelling->creature_types[1] != ID_NONE )
                {
                    dwelling->creature_counts[0] = min(dwelling->creature_counts[0], dwelling->creature_counts[1]);
                    dwelling->creature_counts[1] = dwelling->creature_counts[0];

                    if ( h->GetAddress() == 0x5510B1 )
                    {
                        c->return_address = 0x55121B;
                        return NO_EXEC_DEFAULT;
                    }
                }
            }
        }
    }

    return EXEC_DEFAULT;
}

int __stdcall AIHiring(LoHook* h, HookContext* c)
{
    while ( CALL_2(int, __thiscall, 0x42D420, c->edi, c->esi) > 0 )
    {
        _Hero_* hero = &o_GameMgr->hero[o_ActivePlayer->selected_hero_id];
        if ( hero && o_GameMgr->Map.GetItem(hero->x, hero->y, hero->z)->object_type == 0x11 ) break;
    }
   
    c->return_address = 0x42D728;
    return NO_EXEC_DEFAULT;
}

int __stdcall skipMessages(LoHook* h, HookContext* c)
{
    if ( _P->VarGetValue("HD.UI.AdvMgr.SkipMapMsgs", 1) )
    {
        c->return_address = 0x4A1917;
        return NO_EXEC_DEFAULT;
    }

    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.NewDwellings");
            _PI->WriteLoHook(0x4B85EE, setCreatures);
            _PI->WriteLoHook(0x5510B1, afterHiring);
            _PI->WriteHexPatch(0x4A197B, "90 90");
            _PI->WriteHexPatch(0x4AB812, "90 90");
            _PI->WriteLoHook(0x4A17BD, skipMessages);

            // AI
            _PI->WriteLoHook(0x42D71C, AIHiring);
            _PI->WriteLoHook(0x42D768, afterHiring);
            _PI->WriteHexPatch(0x42CC06, "90 90 90");
            _PI->WriteHexPatch(0x42D557, "90 90");

            // Debug
            _PI->WriteLoHook(0x4AA766, showInfo);
            _PI->WriteLoHook(0x4AA76B, showInfo);
            _PI->WriteLoHook(0x4ACA04, showInfo);
            _PI->WriteLoHook(0x4ACA09, showInfo);
        }
    }

    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 » 25 апр 2021, 16:26

void_17 писал(а):

AlexSpl писал(а):

Код: Выделить всё
    int BonusDamage = *(int*)(c->ebp - 0x10);
    int BasicDamage = *(int*)(c->ebp + 8);
    int LuckFlag = *(int*)(c->ebx + 0x70);


Поясните новичку, для чего делаются такие трюки? Почему нельзя было просто написать
Код: Выделить всё
    int BonusDamage = *(int*)(c->ebp);
    int BasicDamage = *(int*)(c->ebp);
    int LuckFlag = *(int*)(c->ebx);

Можете привести пример, чтобы было понятно, как это работает и для чего это делается? Спасибо.

Если на пальцах. с->xxx - это регистры процессора. *(int*)xxx - это чтение из оперативной памяти целого числа int по адресу xxx. Поэтому, например, *(int*)(c->ebx + 0x70) - это чтение целого числа int по адресу c->ebx + 0x70. Т.е. читаем значение, которое хранится в регистре c->ebx, прибавляем к нему шестнадцатеричное число 0x70 и читаем из оперативной памяти число по получившемуся в результате сложения адресу.
Вернуться к началу

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

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

Сообщение Rolex » 25 апр 2021, 16:30

AlexSpl писал(а):

Научил AI покупать неулучшенных существ в новых двеллингах:

Кстати, я так подумал, все же правильней было бы сделать следующим образом:
Если при захвате героем внешнего жилища, существо, которое в нем обитает принадлежит хотя бы к одному из имеющихся в распоряжении героя городов (родные + захваченны). И в этом городе отстроено улучшенное жилище для этого существа, то в захваченном жилище выводим 2 типа существ: грейженный и негрейженный стеки.

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

Пример, у героя есть три города типа Замок и еще один какой-то другой город (не Замок, а, допустим, Башня). В одном Замке остроен Ул. Портал славы с Архангелами, в другом отстроен только обычный Портал славы с Ангелами, а в третьем Замке вообще не отстроен Портал славы.

У нас одно захваченное жилище Портал славы, в котором мы можем купить либо Архангелов, либо Англелов. Если же враг у нас отвоевывает Замок в котором отстроен Ул. Портал славы с Архангелами, то жилище возвращается к своему первоначальному виду, то есть мы можем нанимать только Ангелов. Ибо в одном из оставшихся Замков у нас есть только обычный Портал славы с Ангелами, в другом Замке вообще не отстроен Портал славы, а третий город Башня вообще не соответствует нашему существу из жилища.

Как только мы завоюем Замок с остроенными Ул. Порталом славы в Замке свой или какой-то другой вражеский, котороый станет нашим, то и в соответствующем жилище снова должна появится возможность нанимать как обычных, так и грейженных.

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

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

По-моему, именно так все будет логично и найболее правильно. Я бы лично подобное хотел бы увидеть в HotA. Очень полезный плагин на самом деле.
Последний раз редактировалось Rolex 25 апр 2021, 16:50, всего редактировалось 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 » 25 апр 2021, 16:39

Я об этом тоже думал. Хотел предложить (ещё я опередил ваш предложение по охране двеллингов: сейчас их охраняют улучшенные существа). Это довольно легко реализовать. Думаю, стоит добавить.
Вернуться к началу

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

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

Сообщение Rolex » 25 апр 2021, 16:43

AlexSpl писал(а):

ещё я опередил ваш предложение по охране двеллингов: сейчас их охраняют улучшенные существа

В том виде, в котором плагин сейчас, то есть грейженный стек есть всегда, то логично, что и охрана должна быть грейдом. Вы все верно сделали. А вот в том случае, о котором я написал, какую охрану выводить для жилищ 5-7 уровня (грейд или нет) нужно будет определять точно также, как я описал выше.
Последний раз редактировалось Rolex 25 апр 2021, 16:44, всего редактировалось 2 раз(а).
Вернуться к началу

offlineАватара пользователя
void_17  
имя: имя
Ветеран
Ветеран
 
Сообщения: 548
Зарегистрирован: 25 апр 2021, 15:05
Откуда: Оттуда
Пол: Мужчина
Поблагодарили: 132 раз.

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

Сообщение void_17 » 25 апр 2021, 16:43

Кто-нибудь делал плагин на разнообразие условий победы в случайных картах?
Вернуться к началу

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 » 25 апр 2021, 16:47

Версия плагина с просмотром ресурсов для контроля. Оптимально тестировать при нехватке ценных ресурсов у AI для покупки грейда.

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

Patcher* _P;
PatcherInstance* _PI;

// For debugging purposes
void showDebugInfo(const char* format, ...)
{
    va_list args;
    va_start(args, format);

    vsprintf(o_TextBuffer, format, args);
    b_MsgBox(o_TextBuffer, MBX_OK);

    va_end(args);
}

int __stdcall showInfo(LoHook* h, HookContext* c)
{
    char TxtBuffer[1024] = "";
    char infoStr[1024] = "";
   
    _Hero_* hero = &o_GameMgr->hero[o_ActivePlayer->selected_hero_id];
   
    if ( hero )
    {
        sprintf(infoStr, "{%s}\n\n", hero->name);

        for (int i = 0; i < 7; ++i)
        {
            if ( hero->army.type[i] != ID_NONE )
                sprintf(TxtBuffer, "%s: %d\n", o_pCreatureInfo[hero->army.type[i]].name_plural, hero->army.count[i]);
            else
                sprintf(TxtBuffer, "%s\n", "[Empty]");
            strcat(infoStr, TxtBuffer);
        }

        showDebugInfo("%s\nWood: %d | Ore: %d | Mercury: %d | Sulfur: %d | Crystal: %d | Gems: %d | Gold: %d", infoStr,
            o_ActivePlayer->resourses.wood, o_ActivePlayer->resourses.ore, o_ActivePlayer->resourses.mercury,
            o_ActivePlayer->resourses.sulfur, o_ActivePlayer->resourses.crystal, o_ActivePlayer->resourses.jems, o_ActivePlayer->resourses.gold);
    }

    return EXEC_DEFAULT;
}

int __stdcall setCreatures(LoHook* h, HookContext* c)
{
    _Dwelling_* dwelling = (_Dwelling_*)c->esi;
    int upgMonId = CALL_1(int, __fastcall, 0x47AAD0, dwelling->creature_types[0]);
   
    if ( upgMonId != ID_NONE && dwelling->creature_types[1] == ID_NONE ) {
        dwelling->creature_types[1] = dwelling->creature_types[0];
        dwelling->creature_counts[1] = dwelling->creature_counts[0];
        dwelling->creature_types[0] = upgMonId;
        if ( dwelling->defenders.type[0] != ID_NONE )
            dwelling->defenders.type[0] = upgMonId;
    }

    return EXEC_DEFAULT;
}

_Dwelling_* GetDwelling(_int_ dwellingId) {
    return (_Dwelling_ *)(o_GameMgr->Field<int>(0x4E39C) + 92 * dwellingId);
}

int __stdcall afterHiring(LoHook* h, HookContext* c)
{
    // Если нанимаем не в городе
    if ( h->GetAddress() == 0x42D768 || *(int*)(c->esi + 0x48) != 0x62 )
    {
        _Hero_* hero = &o_GameMgr->hero[o_ActivePlayer->selected_hero_id];
        if ( hero )
        {
            _MapItem_* item = o_GameMgr->Map.GetItem(hero->x, hero->y, hero->z);
            if ( item->object_type == 0x11 )
            {
                _Dwelling_* dwelling = GetDwelling(item->setup);
                if ( dwelling && dwelling->creature_types[1] != ID_NONE )
                {
                    dwelling->creature_counts[0] = min(dwelling->creature_counts[0], dwelling->creature_counts[1]);
                    dwelling->creature_counts[1] = dwelling->creature_counts[0];

                    if ( h->GetAddress() == 0x5510B1 )
                    {
                        c->return_address = 0x55121B;
                        return NO_EXEC_DEFAULT;
                    }
                }
            }
        }
    }

    return EXEC_DEFAULT;
}

int __stdcall AIHiring(LoHook* h, HookContext* c)
{
    while ( CALL_2(int, __thiscall, 0x42D420, c->edi, c->esi) > 0 )
    {
        _Hero_* hero = &o_GameMgr->hero[o_ActivePlayer->selected_hero_id];
        if ( hero && o_GameMgr->Map.GetItem(hero->x, hero->y, hero->z)->object_type == 0x11 ) break;
    }
   
    c->return_address = 0x42D728;
    return NO_EXEC_DEFAULT;
}

int __stdcall skipMessages(LoHook* h, HookContext* c)
{
    if ( _P->VarGetValue("HD.UI.AdvMgr.SkipMapMsgs", 1) )
    {
        c->return_address = 0x4A1917;
        return NO_EXEC_DEFAULT;
    }

    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.NewDwellings");
            _PI->WriteLoHook(0x4B85EE, setCreatures);
            _PI->WriteLoHook(0x5510B1, afterHiring);
            _PI->WriteHexPatch(0x4A197B, "90 90");
            _PI->WriteHexPatch(0x4AB812, "90 90");
            _PI->WriteLoHook(0x4A17BD, skipMessages);

            // AI
            _PI->WriteLoHook(0x42D71C, AIHiring);
            _PI->WriteLoHook(0x42D768, afterHiring);
            _PI->WriteHexPatch(0x42CC06, "90 90 90");
            _PI->WriteHexPatch(0x42D557, "90 90");

            // Debug
            _PI->WriteLoHook(0x4AA766, showInfo);
            _PI->WriteLoHook(0x4AA76B, showInfo);
            _PI->WriteLoHook(0x4ACA04, showInfo);
            _PI->WriteLoHook(0x4ACA09, showInfo);
        }
    }

    return TRUE;
}

Цитата:
Кто-нибудь делал плагин на разнообразие условий победы в случайных картах?

Не слышал о таком.
Вернуться к началу

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

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

Сообщение Rolex » 25 апр 2021, 16:58

AlexSpl писал(а):

Версия плагина с просмотром ресурсов для контроля. Оптимально тестировать при нехватке ценных ресурсов у AI для покупки грейда.

А можно ли в это окошко еще и выводить, какие постройки AI покупает в каждом своем городе каждый свой ход?
Вернуться к началу

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 » 25 апр 2021, 17:04

Цитата:
А можно ли в это окошко еще и выводить, какие постройки AI покупает в городе каждый свой ход?

Можно добавить. Но позже. Сейчас я хочу научить AI покупать неулучшенные существа в городе.
Вернуться к началу

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

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

Сообщение Rolex » 25 апр 2021, 17:12

Так в RoE 1.3, AB и SoD AI, вроде, это умеет:
Цитата:
Non-upgraded creatures can be recruited from an upgraded creature dwelling inside the town.

Если я что-то не так понял, поясните, пожалуйста.
Вернуться к началу

Пред.След.

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

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

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

cron