Объявления

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

Сейв делается в бою или на карте приключений?
Вернуться к началу

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

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

Сообщение Rolex » 30 июл 2021, 07:10

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

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 » 30 июл 2021, 08:09

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

Patcher* _P;
PatcherInstance* _PI;

struct PicStruc {
    int type;       // тип картинки (9 - заклинание)
    int id;         // ID картинки
};

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

int captionAddr;
int n = 0;
int spells[70];
_Hero_* heroToLearn = 0;

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 __stdcall learnSpell(LoHook* h, HookContext* c)
{
    _Hero_* hero = o_BattleMgr->hero[1 - o_BattleMgr->current_side];

    if (hero)
    {
        int spell = *(int*)(c->ebp + 8);

        if (spell != ID_NONE && !hero->spell[spell] && hero->doll_art[AS_SPELL_BOOK].id == AID_SPELL_BOOK &&
            o_Spell[spell].level <= hero->second_skill[HSS_WISDOM] + 2 && o_Spell[spell].level <= hero->second_skill[HSS_EAGLE_EYE] + 1)
        {
            unsigned int dice;
            rand_s(&dice);
            dice = (unsigned int)((double)dice / ((double)UINT_MAX + 1) * 100.0) + 1;
            unsigned int eagleEyeProb = (unsigned int)(CALL_1(float, __thiscall, 0x4E4690, hero) * 100.0);
            //if (dice <= eagleEyeProb)
            //{
                spells[n++] = spell;
                hero->spell[spell] = true;
                hero->spell_level[spell] = true;
            //}
        }

        heroToLearn = hero;
    }

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

void showSpells()
{
    _Hero_* hero = o_BattleMgr->hero[o_BattleMgr->current_side];

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

        n = 0;
        heroToLearn = 0;
    }
}

int __stdcall notifyPlayer(LoHook* h, HookContext* c)
{
    showSpells();

    return EXEC_DEFAULT;
}

int __stdcall notifyPlayerAfterBattle(LoHook* h, HookContext* c)
{
    if (heroToLearn && heroToLearn->owner_id == o_GameMgr->GetMeID())
        showSpellDlg(o_BattleMgr->hero[1 - o_BattleMgr->current_side], spells, n);

    return EXEC_DEFAULT;
}

// Заголовок в каждом диалоге
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 __stdcall zeroSpells(LoHook* h, HookContext* c)
{
    n = 0;
    heroToLearn = 0;

    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.NewEagleEye");

            // Меняем коэффициенты
            float eagleEyeCoefs[] = { 0.00f, 0.20f, 0.40f, 0.60f };

            _PI->WriteDword(0x63EA2C, (int&)eagleEyeCoefs[1]);
            _PI->WriteDword(0x63EA30, (int&)eagleEyeCoefs[2]);
            _PI->WriteDword(0x63EA34, (int&)eagleEyeCoefs[3]);

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

            // Пробуем учить заклинания
            _PI->WriteLoHook(0x5A0262, learnSpell);
           
            // Фиксим заголовок диалога
            _PI->WriteLoHook(0x4F7D49, saveCaption);
            _PI->WriteLoHook(0x4F7D54, captionFix);

            // Показываем выученные заклинания
            _PI->WriteLoHook(0x477C00, notifyPlayer);
            _PI->WriteLoHook(0x46FE20, notifyPlayerAfterBattle);

            _PI->WriteLoHook(0x4AD160, zeroSpells);
        }
    }

    return TRUE;
}

Пробуйте этот код. Тестил по TCP/IP, должен работать и в хотсите.
Вернуться к началу

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

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

Сообщение Rolex » 30 июл 2021, 08:24

О, теперь все работает. :smile11:

AlexSpl писал(а):

Осталось только предусмотреть случай, когда герой погибает. Сейчас уведомление показывается победителю, если он выжил (например, после каста Armageddon).

А это, кстати, в последней версии кода еще не предусмотрено?
Последний раз редактировалось Rolex 30 июл 2021, 08:28, всего редактировалось 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 » 30 июл 2021, 08:27

Предусмотрено. Но я нашёл два бага HD. Первый некритичный: Если хост стартанёт до того, как инициализируется гость, будет крэш (я уже писал об этом). Второй очень странный. И повторить его не всегда получается. Суть в том, что если играть по сети, то возможна ситуация, когда первым будет ходить отряд с меньшей скоростью. Так, у меня уже два раза ходили первыми Копейщики, а не Чудища! Пробую повторить. Может, арт на скорость раздало?

Ага, так и есть. Родные земли + 1 скорость + нападающий герой с Копейщиками: 4 + 1 + 1 = 6.
Последний раз редактировалось AlexSpl 30 июл 2021, 08:30, всего редактировалось 1 раз.
Вернуться к началу

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

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

Сообщение Rolex » 30 июл 2021, 08:28

Проверил, сообщение об изучении Армагеддона выводится, хотя оба героя погибли.

AlexSpl писал(а):

Но я нашёл два бага HD. Первый некритичный: Если хост стартанёт до того, как инициализируется гость, будет крэш (я уже писал об этом). Второй очень странный. И повторить его не всегда получается. Суть в том, что если играть по сети, то возможна ситуация, когда первым будет ходить отряд с меньшей скоростью. Так, у меня уже два раза ходили первыми Копейщики, а не Чудища! Пробую повторить. Может, арт на скорость раздало?

Я думаю вам лучше подробно об этом написать разработчику мода на почту, чтобы пофиксил.
Последний раз редактировалось Rolex 30 июл 2021, 08:30, всего редактировалось 1 раз.
Вернуться к началу

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 » 30 июл 2021, 08:30

Цитата:
Проверил, сообщение об изучении Армагеддона выводится, хотя оба героя погибли.

Да, притом тому, кто выучил. Вроде всё предусмотрел :smile2:
Вернуться к началу

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

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

Сообщение Rolex » 30 июл 2021, 08:32

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

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 » 30 июл 2021, 08:33

Каст был? Был. Выучил и погиб. Откопать в таверне же можно потом.
Вернуться к началу

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 » 30 июл 2021, 08:41

По-моему, данная реализация идеальна для возрождения Eagle Eye. Теперь этот навык может быть очень полезным. Я и проценты сделал: 20/40/60%. Вот нет у тебя Slow, противник кастанул, а ты ему уже в свой ход обратно кастануть можешь. Актуальность немножко падает с перестройкой гильдии, но всё равно навык гораздо полезнее, чем в оригинале. Хотя предыдущий вариант был ещё сильнее: герой учит заклинания прямо на старте.
Последний раз редактировалось AlexSpl 30 июл 2021, 08:45, всего редактировалось 1 раз.
Вернуться к началу

Пред.След.

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

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

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

cron