Объявления

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

Это не для AI, а для человека. Раньше выбора не было.
Вернуться к началу

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

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

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

Понял. Я почему-то изначально подумал, что это для AI. Вот интересно, а разрабы HotA научили 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, 21:57

Научил, вроде :smile1:

Код: Выделить всё
#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);
}

void showInfo(_Army_* army)
{
    char TxtBuffer[1024] = "";
    char infoStr[1024] = "";

    for (int i = 0; i < 7; ++i)
    {
        if ( army->type[i] != ID_NONE )
            sprintf(TxtBuffer, "%s: %d\n", o_pCreatureInfo[army->type[i]].name_plural, 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);
}

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 ( o_ActivePlayer->selected_hero_id != ID_NONE && (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 AI_TryingToHire(LoHook* h, HookContext* c)
{
    int creatureTypeAddr = 0;
    int creatureType = ID_NONE;
    creatureTypeAddr = *(int*)(c->edi + 0x30);
    if ( creatureTypeAddr ) {
        creatureType = *(int*)creatureTypeAddr;
        showDebugInfo("Trying to hire {%s}", o_pCreatureInfo[creatureType].name_plural);
    }
   
    bool hired = false;
    int value;
    do {
        value = CALL_2(int, __thiscall, 0x42D420, c->edi, c->esi);
        if ( value > 0 )
        {
            hired = true;
            _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;
        }
    } while ( value > 0 );

    if ( creatureTypeAddr )
    {
        _Army_* army = *(_Army_**)(c->ebp + 8);
        if ( hired )
            showInfo(army);
        else
        {
            showDebugInfo("Failed :(");
           
            int basicType = creatureType - 1;

            showDebugInfo("Trying to hire {%s}", o_pCreatureInfo[basicType].name_plural);
               
            *(int*)creatureTypeAddr = basicType;
            while ( CALL_2(int, __thiscall, 0x42D420, c->edi, c->esi) > 0 );

            showInfo(army);
        }
    }
       
    c->return_address = 0x42D728;
    return NO_EXEC_DEFAULT;
}

int __stdcall AI_ThinkingOfHiring(LoHook* h, HookContext* c)
{
    int creatureTypeAddr = *(int*)(c->esi + 0x30);
    int creatureType = ID_NONE;
    if ( creatureTypeAddr ) {
        creatureType = *(int*)creatureTypeAddr;
        showDebugInfo("Thinking of hiring {%s}", o_pCreatureInfo[creatureType].name_plural);
    }
       
    int value;
    do {
        value = CALL_2(int, __thiscall, 0x42D420, c->esi, 0);
        c->edx = *(int*)(c->ebp + 8);
        c->edx += value;
        *(int*)(c->ebp + 8) = c->edx;
    } while ( value > 0 );
       
    c->return_address = 0x42D864;
    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, AI_TryingToHire);
            _PI->WriteLoHook(0x42D84F, AI_ThinkingOfHiring);
            _PI->WriteLoHook(0x42D768, afterHiring);
            _PI->WriteHexPatch(0x42CC06, "90 90 90");
            _PI->WriteHexPatch(0x42D557, "90 90");
        }
    }

    return TRUE;
}

Пробуйте тестировать в ситуациях, когда у AI нет ресурсов для покупки грейда. Да, пока даунгрейд считаю, просто отнимая единицу :smile1: Не тестируйте с Conflux на карте.
Вернуться к началу

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

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

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

Цитата:
Не тестируйте с Conflux на карте.

Почему?

AlexSpl писал(а):

Минус в том, что если 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, 22:21

Цитата:
Почему?

Цитата:
Да, пока даунгрейд считаю, просто отнимая единицу

Ни на картах с Conflux, ни с их двеллингами.

Цитата:
Кстати, а это уже исправлено, ибо еще не успел проверить?

Да.

Кстати, очень критично написать функцию нахождения даунгрейда. Обычно AI не фейлит покупку негрейженых существ, но если зафейлит, то он попробует купить существа с ID на единицу меньше, в результате чего получим вылет. Пока думаю, как её лучше написать (родной для даунгрейдов нет).
Вернуться к началу

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, 23:15

Код: Выделить всё
#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);
}

void showInfo(const _Army_* army, const int action)
{
    char txtBuffer[1024];
    char infoStr[1024];

    sprintf(infoStr, "Player: {%d}  |  Hero: {%s}  |  Action: {%d}\n\n", o_ActivePlayer->id,
        o_ActivePlayer->selected_hero_id != ID_NONE ? o_GameMgr->hero[o_ActivePlayer->selected_hero_id].name : "N/A", action);
   
    for (int i = 0; i < 7; ++i)
    {
        if ( army->type[i] != ID_NONE )
            sprintf(txtBuffer, "{%s}: %d\n", o_pCreatureInfo[army->type[i]].name_plural, army->count[i]);
        else
            sprintf(txtBuffer, "%s\n", "[Empty]");
        strcat(infoStr, txtBuffer);
    }
   
    showDebugInfo("%s\nWood: {%d} | Ore: {%d}\nMercury: {%d} | Sulfur: {%d} | Crystal: {%d} | Gems: {%d}\nGold: {%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);
}

int getCreatureBasicType(const int id)
{
    int basicType = id;
   
    if ( id % 2 && (id < CID_AIR_ELEMENTAL || id == CID_SPRITE || id == CID_MAGIC_ELEMENTAL || id == CID_PHOENIX) )
        basicType = id - 1;
    else
    switch ( id )
    {
    case CID_STORM_ELEMENTAL:
        basicType = CID_AIR_ELEMENTAL;
        break;
    case CID_MAGMA_ELEMENTAL:
        basicType = CID_EARTH_ELEMENTAL;
        break;
    case CID_ENERGY_ELEMENTAL:
        basicType = CID_FIRE_ELEMENTAL;
        break;
    case CID_ICE_ELEMENTAL:
        basicType = CID_WATER_ELEMENTAL;
        break;
    }

    return basicType;
}

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

int __stdcall initDwelling(LoHook* h, HookContext* c)
{
    _Dwelling_* dwelling = (_Dwelling_*)c->esi;
    int upgMonId = CALL_1(int, __fastcall, 0x47AAD0, dwelling->creature_types[0]);
   
    if ( dwelling->type == 0x11 && upgMonId != 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;
}

void __stdcall fixDwellingDefenders(HiHook* h, _Dwelling_* dwelling, bool unused)
{
    CALL_2(void, __thiscall, h->GetDefaultFunc(), dwelling, unused);

    dwelling->defenders.type[1] = ID_NONE;
    dwelling->defenders.count[1] = 0;
}

int __stdcall afterHiring(LoHook* h, HookContext* c)
{
    // Если нанимаем не в городе
    if ( o_ActivePlayer->selected_hero_id != ID_NONE && (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 AI_TryingToHire(LoHook* h, HookContext* c)
{
    int stacksBegin = *(int*)(c->edi + 0x30);
    int stacksEnd = *(int*)(c->edi + 0x34);
    int stacksNumber = stacksBegin ? (stacksEnd - stacksBegin) / 12 : 0;

    if ( stacksBegin )
    {
        char txtBuffer[1024] = "";
        char infoStr[1024];

        sprintf(infoStr, "Trying to hire {%d} stack%s:\n\n", stacksNumber, stacksNumber > 1 ? "s" : "");

        for (int i = stacksEnd - 12; i >= stacksBegin; i -= 12)
        {
            int stackType = *(int*)i;
            sprintf(txtBuffer, "{%s}\n", o_pCreatureInfo[stackType].name_plural);
            strcat(infoStr, txtBuffer);
        }

        showDebugInfo(infoStr);
    }

    int action = 0;

    // Показываем армию и ресурсы до найма
    _Army_* army = *(_Army_**)(c->ebp + 8);
    showInfo(army, action++);
   
    int value;
    do
    {
        // Пытаемся нанять отряды
        value = CALL_2(int, __thiscall, 0x42D420, c->edi, c->esi);

        army = *(_Army_**)(c->ebp + 8);
        showInfo(army, action++);
    }
    while (value > 0);
                       
    c->return_address = 0x42D728;
    return NO_EXEC_DEFAULT;
}

int __stdcall AI_ThinkingOfHiring(LoHook* h, HookContext* c)
{
    // Раскомментируйте, чтобы проследить мысль AI
    /*
    int stacksBegin = *(int*)(c->esi + 0x30);
    int stacksEnd = *(int*)(c->esi + 0x34);
    int stacksNumber = stacksBegin ? (stacksEnd - stacksBegin) / 12 : 0;
       
    if ( stacksBegin )
    {
        char txtBuffer[1024] = "";
        char infoStr[1024];
       
        sprintf(infoStr, "Thinking of hiring {%d} stack%s:\n\n", stacksNumber, stacksNumber > 1 ? "s" : "");

        for (int i = stacksEnd - 12; i >= stacksBegin; i -= 12)
        {
            int stackType = *(int*)i;
            sprintf(txtBuffer, "{%s}\n", o_pCreatureInfo[stackType].name_plural);
            strcat(infoStr, txtBuffer);
        }

        showDebugInfo(infoStr);
    }
    */

    c->edx = *(int*)(c->ebp + 8);
    int value;
    do
    {
        value = CALL_2(int, __thiscall, 0x42D420, c->esi, 0);
        c->edx += value;
    }
    while (value > 0);
       
    c->return_address = 0x42D864;
    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(0x4A17BD, skipMessages);
            _PI->WriteLoHook(0x4B85EE, initDwelling);
            _PI->WriteLoHook(0x5510B1, afterHiring);
            _PI->WriteHexPatch(0x4A197B, "90 90");
            _PI->WriteHexPatch(0x4AB812, "90 90");
            _PI->WriteHiHook(0x4B8760, SPLICE_, EXTENDED_, THISCALL_, fixDwellingDefenders);
           
            // AI
            _PI->WriteLoHook(0x42D71C, AI_TryingToHire);
            _PI->WriteLoHook(0x42D84F, AI_ThinkingOfHiring);
            _PI->WriteLoHook(0x42D768, afterHiring);
            _PI->WriteHexPatch(0x42CC06, "90 90 90");
        }
    }

    return TRUE;
}

* * *
Потестил. Теперь в случае отсутствия ресурсов AI покупает неулучшенные существа (точнее, пока ещё нет). Но на практике сложно встретить такую ситуацию, т.к. обычно есть Рынок, и AI будет менять ресурсы на нужные для покупки грейда. В HotA данный баг ещё не исправлен.

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

* * *
UPD: AI нанимает сразу вектор отрядов, а не по одному. Обновил код. Исправил обновление охраны двеллинга в начале новой недели. Ещё заметил странное поведение AI (в том числе и в оригинальной игре), когда AI игрок тратит всё золото к концу игрового дня. Пока скажу, что это в некоторых ситуациях ведёт к длительному простою его героев.

С покупкой негрейженых существ не всё так просто :smile2: Если у AI не получается купить грейженый отряд сильных существ, AI покупает покупает существ послабее, а не неулучшенные существа. Нужно форсировать покупку неулучшенных существ до вызова 0x42D420 (функция, которая выбирает лучший стек; AI пытается нанять самый сильный отряд существ, но если не может его нанять, покупает более слабый). Пока можно просто понаблюдать за изменением армии и ресурсов AI игроков.

* * *
Кажется, не придётся редактировать 0x42D420. При достаточном количестве ресурсов AI покупает отряды согласно вектору. Остаётся только самому прикидывать, как там у него по ресурсам и редактировать этот вектор соответствующим образом. Очень надеюсь, что я мыслю в правильном направлении :smile1:
Последний раз редактировалось AlexSpl 27 апр 2021, 10:43, всего редактировалось 1 раз.
Вернуться к началу

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

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

Сообщение Rolex » 27 апр 2021, 10:38

AlexSpl писал(а):

Если у AI не получается купить грейженый отряд сильных существ, AI покупает покупает существ послабее, а не неулучшенные существа. Нужно форсировать покупку неулучшенных существ до вызова 0x42D420 (функция, которая выбирает лучший стек; 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 » 27 апр 2021, 10:45

Вот только что на этот счёт отписался. Кажется, я разобрался наконец :smile1: Думаю, скоро закончу и можно будет зависимость от построек в городе пилить.

Вот тестирую я на рандомных картах, а тут такая красота сгенерилась:

Изображение
Изображение
Последний раз редактировалось AlexSpl 27 апр 2021, 11:39, всего редактировалось 3 раз(а).
Вернуться к началу

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

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

Сообщение Rolex » 27 апр 2021, 10:50

AlexSpl писал(а):

и можно будет зависимость от построек в городе пилить.

А это еще что такое? Вы хотите вообще кардинально прокачать алгоритмы AI и по оптимальной расстройке в городе?
***
UPD: Я понял, о чем Вы. Это то, о чем я писал ранее.
-----------------------------------------------------------------------------
Вообще предлагаю тогда, после того, как Вы закончите, разделить этот плагин на три.

1. Улучшенный плагин скупки существ AI в городе. Который будут юзать все.

2. Плагин для анализа и отслеживания размера армии, золота, кол-ва ценных и обычных ресурсов. В это окошко конечно хотелось выводить максимум полезной инфы. Было бы неплохо туда добавить, как я писал ранее, название построек, которые AI покупает в каждом своем городе каждый свой ход. Плюс другую полезную инфу, которая может быть полезной для анализа того, как мыслит AI.

3. Это наш плагин с грейженным стеком в жилищах на постоянной основе (без дебага и БЕЗ ФИКСА СКУПКИ СУЩЕСТВ В ГОРОДЕ). Фикс скупки существ в городе должен идти отдельным плагином.

4. Вывод грейженного стека в жилищах в зависимости от построек в городе (опять же без фикса скупки существ в городе). То, о чем я подробно писал вот здесь:
viewtopic.php?f=56&t=518&start=2650#p22157

Фикс скупки существ в городе должен идти отдельно для тех игроков, которые возможно не захотят использовать плагины с грейженными стеками в жилищах, но будут заинтересованы в более гибком и умном AI в плане скупки существ в городе. А какой плагин с грейженным стеком игроку (или группе игроков) больше по душе, каждый сможет также решить сам для себя.
Последний раз редактировалось Rolex 27 апр 2021, 14:58, всего редактировалось 8 раз(а).
Вернуться к началу

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 » 27 апр 2021, 11:12

Разобрался с алгоритмом :smile11:

Изображение ИзображениеИзображение

Итак, вектор отрядов - это рекомендация AI, какие отряды ему покупать. При наличии достаточного кол-ва ресурсов и места в армии/гарнизоне AI купит их все (хорошо, постарается купить; есть нюансы с Моралью, например; неплохо было бы разобрать всю функцию). Когда ресурсов на всех не хватает, в игру вступают хитрые алгоритмы выбора (AI даже заморочится с обменом ресурсов, если нужно будет). Но я не буду их трогать. Моя идея заключается в том, что если я вижу в векторе грейженый отряд, и вижу, что у компа не хватает ресурсов, чтобы его купить, то я заменяю его на отряд негрейженых существ (разумеется, после того, как AI купил максимально возможное на его ресурсы кол-во грейженых). Вот так просто. Больше никаких правок.
Вернуться к началу

Пред.След.

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

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

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

cron