Объявления

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

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

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

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

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

Ну как бы то, что я знаю и умею - делаю сам. Тут я Вам честно все сказал, что не знаю, как это отследить и проверить. Также не знаю будет ли AI отдавать приоритет грейженным над обычными, если средств хвататет. Точно также не знаю, как будет вести себя AI в ситуации, когда средств на грейженных не хвататет, но хвататет на обычных. Или, когда обычных он может нанять больше, чем грейженных. Особенно это актуально для существ 7-го уровня с подключенным плагином накопления. Как это все проверить я без понятия.
Вернуться к началу

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 » 24 апр 2021, 14:46

Так разве не интересно научиться? Вот что, скажите, Вы не умеете? Мониторить армию героя, ресурсы игрока? :smile2: Да в этой теме куча примеров того, как работать со структурами _Hero_ и _Player_. Окошко-то Вы можете показывать с текущим состоянием армии героя и ресурсами игрока. :smile2: Поработайте хотя бы тестером. Погоняйте описанные выше случаи на реальной карте.
Вернуться к началу

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

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

Сообщение Rolex » 24 апр 2021, 14:53

AlexSpl писал(а):

Так разве не интересно научиться?

Интересно.

AlexSpl писал(а):

Вот что, скажите, Вы не умеете? Мониторить армию героя, ресурсы игрока? :smile2: Да в этой теме куча примеров того, как работать со структурами _Hero_ и _Player_. Окошко-то Вы можете показывать с текущим состоянием армии героя и ресурсами игрока.

Разве что могу вывести обычное сообщение с нужной инфой:
Код: Выделить всё
sprintf(o_TextBuffer, "%s", "Hello world");
b_MsgBox(o_TextBuffer, MBX_OK);

При написании алгоритма для площадных заклов это очень помогло мне. Я передавал туда нужную мне инфу. Если что-то шло не так и мне нужно было понять почему. Это то, что Вы когда-то мне подсказали. Как передать туда игрока 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 » 24 апр 2021, 15:40

Вот код, который выводит информацию об армии героя и остатке золота перед посещением объекта и после:

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

Patcher* _P;
PatcherInstance* _PI;

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 ( *(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];

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

    return 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;
}

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 )
    {
        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;
}

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);

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

    return TRUE;
}

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

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

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

Сообщение Rolex » 24 апр 2021, 15:51

AlexSpl писал(а):

Вот код, который выводит информацию об армии героя и остатке золота перед посещением объекта и после. Для AI будет выводиться информация также и для "расчётного" посещения.

Я уже, вроде, даже придумал как и без вывода ресурсов это проверить. Правда, это будет дольше и сложнее.

AlexSpl писал(а):

Вопрос: какие проблемы с покупкой существ во внешнем двеллинге героями AI в этом плагине?

Вроде покупает. Но мне кажется, что он нанимает тех, которые выбраны по умолчанию. А по умолчанию выбраны грейженные существа. Мне вот интересно, если это будет жилище 7-го уровня и грейженного Древнего Чудища, которое требует 1 Кристалл AI не сможет нанять (из-за отсутствия Кристаллов), в то время как с Золотом у него будет все ок, наймет ли он обычное Чудище, которое не требует Кристаллов?
Последний раз редактировалось Rolex 24 апр 2021, 15:54, всего редактировалось 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 » 24 апр 2021, 15:52

Кстати, полезный плагин. Можно смотреть, как комп пополняет армию и расходует золото. В окошке можно, конечно, показывать и другую полезную информацию.

Цитата:
Вроде покупает. Но мне кажется, что он нанимает тех, которые выбраны по умолчанию. А по умолчанию выбраны грейженные существа.

Он покупает грейженый и негрейженый вариант, причём для жилищ первого уровня бесплатно. Поэтому на покупку для AI нужен будет аналогичный хук.
Вернуться к началу

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

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

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

Проверил!

AI в двеллингах 1-го уровня получает как грейженных, так и обычных существ, причем, без затрат Золота!

UPD: То, о чем Вы и написали.
Вернуться к началу

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

Да, с AI всё сложно. Я нашёл, как сделать так, чтобы двеллинг работал нормально для AI, но это не всё. Теперь двеллинги для AI имеют повышенную ценность из-за второго стека (если, конечно, AI анализирует кол-во существ в двеллинге; по идее, должен: ведь AI не посещает, например, пустые двеллинги). Пока исправлю покупку. А там видно будет.
Вернуться к началу

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

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

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

AlexSpl писал(а):

Теперь двеллинги для AI имеют повышенную ценность из-за второго стека (если, конечно, AI анализирует кол-во существ в двеллинге; по идее, должен: ведь AI не посещает, например, пустые двеллинги). Пока исправлю покупку.

Мне вот интересно, как AI поступит в этой ситуации:
Rolex писал(а):

Мне вот интересно, если это будет жилище 7-го уровня и грейженного Древнего Чудища, которое требует 1 Кристалл 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 » 24 апр 2021, 19:32

Пока такое временное решение, которое работает для AI:

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

Patcher* _P;
PatcherInstance* _PI;

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 skipMessages(LoHook* h, HookContext* c)
{
    if ( _P->VarGetValue("HD.UI.AdvMgr.SkipMapMsgs", 1) )
    {
        c->return_address = 0x4A1917;
        return NO_EXEC_DEFAULT;
    }

    return EXEC_DEFAULT;
}

int __stdcall fixDwellingForAI(LoHook* h, HookContext* c)
{
    _Dwelling_* dwelling = *(_Dwelling_**)(c->ebp + 0xC);

    if ( dwelling && dwelling->type == 0x11 )
    {
        *(int*)(c->ebp - 0x18) = 1;
       
        c->return_address = 0x42CBDC;
        return NO_EXEC_DEFAULT;
    }

    return EXEC_DEFAULT;
}

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 )
    {
        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;
}

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(0x42CBD5, fixDwellingForAI);
            _PI->WriteLoHook(0x42D768, afterHiring);
            _PI->WriteHexPatch(0x42CC06, "90 90 90");

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

    return TRUE;
}

Цена решения - AI видит только грейженые существа в жилище. Это отлично подходит для оценки, стоит ли посещать жилище, т.к. AI потенциально может нанять грейды. Но в ситуации с покупкой есть свои плюсы и минусы. Минус в том, что если AI не хватает ресурсов для покупки хотя бы одного грейженого существа, он ничего не купит. Плюс в том, что он всегда будет покупать улучшенные существа.
Вернуться к началу

Пред.След.

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

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

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

cron