Объявления
Поздравляем
Roman2211


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

Оказывается, у Берсерка отдельный кейс, т.е. площадный Берсерк уникален :smile2: Хотя код не пришлось сильно переделывать. Даже есть намёк на универсальность.

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

Patcher* _P;
PatcherInstance* _PI;

bool showMagicMirrorAnim, showMagicResistAnim, showSpellAnim;
bool needMagicMirrorAnim[2][20], needMagicResistAnim[2][20], needSpellAnim[2][20];
int stackIndex;

bool magicMirrorLucky(_BattleStack_* stack, int spell)
{
    int effSchoolLevel = CALL_3(int, __thiscall, 0x4E52F0, o_BattleMgr->hero[stack->side], SPL_MAGIC_MIRROR, o_BattleMgr->spec_terr_type);
   
    return !(o_Spell[spell].flags & SPF_FRIENDLY_HAS_MASS) && (stack->side != o_BattleMgr->current_side || spell == SPL_BERSERK ) &&
        stack->active_spell_duration[SPL_MAGIC_MIRROR] > 0 && Randint(1, 100) <= o_Spell[SPL_MAGIC_MIRROR].effect[effSchoolLevel];
}

_BattleStack_* getEnemyStackToRedirectTo(_BattleStack_* stack, int spell)
{
    // В целях демонстрации работы просто перенаправим заклинание на первый доступный вражеский отряд
    int sideFoe = 1 - stack->side;
    _BattleStack_* stackFoe = stackIndex < o_BattleMgr->stacks_count[sideFoe] &&
        !o_BattleMgr->stack[sideFoe][stackIndex].is_killed ? &o_BattleMgr->stack[sideFoe][stackIndex] : 0;

    ++stackIndex;
    return stackFoe;
}

int __stdcall dataInit(LoHook* h, HookContext* c)
{
    showMagicMirrorAnim = false;
    showMagicResistAnim = false;
    showSpellAnim = false;
    memset(needMagicMirrorAnim, false, 40);
    memset(needMagicResistAnim, false, 40);
    memset(needSpellAnim, false, 40);
    stackIndex = 0;
   
    return EXEC_DEFAULT;
}

int __stdcall skipOrigSound(LoHook* h, HookContext* c)
{
    char switchCase = ((char*)0x5A2B48)[*(int*)(c->ebp + 8) - 0xA];

    if ( !c->edi && (switchCase == 0x11 || switchCase == 0x18) || o_BattleMgr->ShouldNotRenderBattle() )
    {
        c->return_address = 0x5A0646;
        return NO_EXEC_DEFAULT;
    }
   
    return EXEC_DEFAULT;
}

int __stdcall reflectSpell(LoHook* h, HookContext* c)
{
    _Hero_* hero;
    _BattleStack_* stack;
    int spell, spellPower, schoolLevel;
    int casterSide = o_BattleMgr->current_side;

    if ( h->GetAddress() == 0x5A6A50 ) {
        stack = (_BattleStack_*)c->esi;
        spell = *(int*)(c->ebp + 0xC);
        spellPower = *(int*)(c->ebp + 0x14);
        schoolLevel = *(int*)(c->ebp + 0x10);
        hero = *(_Hero_**)(c->ebp + 8);
        c->return_address = 0x5A6A83;
    } else {
        stack = *(_BattleStack_**)(c->ebp + 0x14);
        spell = *(int*)(c->ebp + 8);
        spellPower = *(int*)(c->ebp + 0x1C);
        schoolLevel = c->esi;
        hero = *(_Hero_**)(c->ebp - 0x14);
        c->return_address = 0x5A210E;
    }
   
    // Если сработало Magic Mirror, перенаправляем заклинание на вражеский отряд
    if ( magicMirrorLucky(stack, spell) )
    {
        showMagicMirrorAnim = true;
        needMagicMirrorAnim[stack->side][stack->index_on_side] = true;
        _BattleStack_* stackFoe = getEnemyStackToRedirectTo(stack, spell);
        if ( stackFoe )
        {
            // Определяем, сработает ли резист против отражённого заклинания
            int resistPercentage = 100 * CALL_7(float, __thiscall, 0x5A83A0, o_BattleMgr, spell,
                casterSide, stackFoe, 1, 1, *(int*)(c->ebp + 0x1C));

            if ( Randint(1, 100) <= resistPercentage )
            {
                CALL_5(void, __thiscall, 0x444610, stackFoe, spell, spellPower, schoolLevel, hero);
                showSpellAnim = true;
                needSpellAnim[stackFoe->side][stackFoe->index_on_side] = true;
            }
            else if ( resistPercentage )
            {
                showMagicResistAnim = true;
                needMagicResistAnim[stackFoe->side][stackFoe->index_on_side] = true;
            }
        }
    }
    else {
        if ( Randint(1, 100) <= c->eax )
        {
            // Если не сработал резист, применяем эффект заклинания
            CALL_5(void, __thiscall, 0x444610, stack, spell, spellPower, schoolLevel, hero);
            showSpellAnim = true;
            needSpellAnim[stack->side][stack->index_on_side] = true;
        }
        // Если сработал резист, отмечаем отряд как требующий анимации резиста
        else if ( c->eax )
        {
            showMagicResistAnim = true;
            needMagicResistAnim[stack->side][stack->index_on_side] = true;
        }
    }
   
    return NO_EXEC_DEFAULT;
}

int __stdcall massReflection(LoHook* h, HookContext* c)
{
    // Проигрываем массовую анимацию и звук Magic Mirror
    if ( showMagicMirrorAnim )
    {
        CALL_3(void, __fastcall, 0x59A890, o_Spell[SPL_MAGIC_MIRROR].wav_name, -1, 3);
        CALL_4(void, __thiscall, 0x5A6AD0, o_BattleMgr, &needMagicMirrorAnim, o_Spell[SPL_MAGIC_MIRROR].animation_ix, 0);
    }

    // Проигрываем массовую анимацию и звук резиста
    if ( showMagicResistAnim )
    {
        CALL_3(void, __fastcall, 0x59A890, "MagicRes.wav", -1, 3);
        CALL_4(void, __thiscall, 0x5A6AD0, o_BattleMgr, &needMagicResistAnim, 78, 0);
    }

    // Проигрываем массовую анимацию и звук кастуемого заклинания
    if ( showSpellAnim )
    {
        _Spell_* spell = (_Spell_*)*(int*)(c->ebp - 0x10);
        CALL_3(void, __fastcall, 0x59A890, spell->wav_name, -1, 3);
        CALL_4(void, __thiscall, 0x5A6AD0, o_BattleMgr, &needSpellAnim, spell->animation_ix, 0);
    }
   
    c->return_address = h->GetAddress() == 0x5A2156 ? 0x5A2168 : 0x5A13FC;
    return NO_EXEC_DEFAULT;
}

int __stdcall playMagicMirrorSound(LoHook* h, HookContext* c)
{
    CALL_3(void, __fastcall, 0x59A890, o_Spell[SPL_MAGIC_MIRROR].wav_name, -1, 3);
   
    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.NewMagicMirrorTest");
           
            _PI->WriteLoHook(0x5A13D2, dataInit);
            _PI->WriteLoHook(0x5A20BB, dataInit);
            _PI->WriteLoHook(0x5A6A50, reflectSpell);
            _PI->WriteLoHook(0x5A20F4, reflectSpell);
            _PI->WriteLoHook(0x5A13E5, massReflection);
            _PI->WriteLoHook(0x5A2156, massReflection);

            // Проигрываем звук Magic Mirror при отражении одиночного заклинания
            _PI->WriteLoHook(0x5A059A, playMagicMirrorSound);

            // Пропускаем оригинальный звук заклинания, чтобы воспроизвезти его позже
            _PI->WriteLoHook(0x5A0634, skipOrigSound);
        }
    }

    return TRUE;
}

Дамажащие заклы позже посмотрю. Одиночный Берсерк тоже не смотрел пока. В FizMiG'е только про Гипноз написано.

* * *
Странно. У меня одиночный Берсерк отражается. Это в оригинале так или я случаем захватил и одиночный каст, являющийся подмножеством площадного? :smile5:
Последний раз редактировалось AlexSpl 19 мар 2021, 14:28, всего редактировалось 2 раз(а).
Вернуться к началу

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

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

Сообщение Rolex » 19 мар 2021, 14:20

Берсерк идет как площадное, то есть теоретически можно поставить на свои отряды. А если свои отряды под Зеркалом, должен ли Берсерк отражатся от своих отрядов на вражеские если был наложен своим героем на свои отряды?
Вернуться к началу

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 » 19 мар 2021, 14:21

Должен. Реализовал.

Походу, всё-таки захватил я случай одиночного каста.
Вернуться к началу

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

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

Сообщение Rolex » 19 мар 2021, 14:54

AlexSpl писал(а):

Дамажащие заклы позже посмотрю.

Я вот глянул, у Инферно полная площадь атаки 19 гексов, в то время как у Метеоритного дождя всего 7 гексов. Но при касте в углу мы можем срезать площадь атаки Инферно вплоть до 7 гексов, а площадь атаки Метеритного дождя вплоть до 3 гексов. А что, если упростить алгоритм отражения? Например, если мы можем отразить площадное на вражеские отряды в том кол-ве которое его отразило так, чтобы не задеть ни одного своего, то делаем это, иначе разворачиваем его так, чтобы задеть максимальное кол-во вражеских отрядов не задев при этом своих, которое будет максимально близко к тому числу отрядов, которые его отразили, но не обязательно равное ему.
Вернуться к началу

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

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

Сообщение Rolex » 20 мар 2021, 07:48

На время тестов выставил на Эксперте Magic Mirror вероятность отражения 100% (потом верну на 50%). Так вот, столкнулся с такой проблемой. Если тестирую в Хотсите, то Зеркало отражает. Когда тестирую против AI, в случае если у AI на всех отрядах стоит Magic Mirror со 100% отражением, то при касте мною на отряды AI закл также отражается на мои отряды. А вот если наоборот, у всех моих отрядов стоит Magic Mirror со 100% отражением, то когда кастует AI (Цепная молния) у него этот закл всегда накладывается, хотя должен всегда отражаться. Получается в бою с AI отражение на отряды AI не работает.

Исходя из сообщения RoseKavalier AI кастует тогда, когда вероятность отражения 50% или ниже, а когда она выше 50%, то 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 » 20 мар 2021, 12:55

В FizMiG'е написано, что заклинания AI не отражаются (видимо, другая функция вызывается или есть специальное условие где-то). Добавить отражение?
Вернуться к началу

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

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

Сообщение Rolex » 20 мар 2021, 13:40

AlexSpl писал(а):

В FizMiG'е написано, что заклинания 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 » 20 мар 2021, 20:06

Цитата:
Добавьте, пожалуйста, если не сложно. Иначе смысла от этого плагина будет мало, только для мультиплеера разве что.


При масскасте отражает, проверил. Функция та же. Получается, не работает для синглкаста.
Вернуться к началу

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

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

Сообщение Rolex » 20 мар 2021, 20:28

AlexSpl писал(а):

Получается, не работает для синглкаста.

Получается, что так. Я проверял на сингкасте (Цепная молния). Надо бы тогда синглкаст поправить.
Вернуться к началу

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 » 20 мар 2021, 21:57

Немножко сложнее, чем я предполагал. Неотражение для AI, похоже, осознанный выбор разработчиков. Пока так:

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

Patcher* _P;
PatcherInstance* _PI;

bool showMagicMirrorAnim, showMagicResistAnim, showSpellAnim;
bool needMagicMirrorAnim[2][20], needMagicResistAnim[2][20], needSpellAnim[2][20];
int stackIndex;

bool magicMirrorLucky(_BattleStack_* stack, int spell)
{
    int effSchoolLevel = CALL_3(int, __thiscall, 0x4E52F0, o_BattleMgr->hero[stack->side], SPL_MAGIC_MIRROR, o_BattleMgr->spec_terr_type);
   
    return !(o_Spell[spell].flags & SPF_FRIENDLY_HAS_MASS) && (stack->side != o_BattleMgr->current_side || spell == SPL_BERSERK ) &&
        stack->active_spell_duration[SPL_MAGIC_MIRROR] > 0 && Randint(1, 100) <= o_Spell[SPL_MAGIC_MIRROR].effect[effSchoolLevel];
}

_BattleStack_* getEnemyStackToRedirectTo(_BattleStack_* stack, int spell)
{
    // В целях демонстрации работы просто перенаправим заклинание на первый доступный вражеский отряд
    int sideFoe = 1 - stack->side;
    _BattleStack_* stackFoe = stackIndex < o_BattleMgr->stacks_count[sideFoe] &&
        !o_BattleMgr->stack[sideFoe][stackIndex].is_killed ? &o_BattleMgr->stack[sideFoe][stackIndex] : 0;

    ++stackIndex;
    return stackFoe;
}

int __stdcall newTarget(LoHook* h, HookContext* c)
{
    // Если нужно изменить оригинальный выбор цели, пропишите указатель на отряд в eaх
    // (!) Обязательно, чтобы работало отражение синглкаста AI (!)
    // В этом примере заклинание перенаправляется на вражеский отряд с индексом 0, даже если он погиб,
    // так что здесь нужно написать свой алгоритм выбора цели
    c->eax = (int)&o_BattleMgr->stack[o_BattleMgr->current_side][0];
    return EXEC_DEFAULT;
}

int __stdcall magicMirrorAI(LoHook* h, HookContext* c)
{
    int spell = *(int*)(c->ebp + 8);
    int effSchoolLevel = CALL_3(int, __thiscall, 0x4E52F0, c->edi, SPL_MAGIC_MIRROR, o_BattleMgr->spec_terr_type);
   
    // Если не масскаст, игрок - AI и улыбнулась удача (в оригинале для AI не делается бросок), а также оригинальные проверки, то разрешаем отразить магию
    if ( c->edi && !CALL_2(bool, __thiscall, 0x4CE600, o_GameMgr, o_BattleMgr->owner_id[o_BattleMgr->current_side]) &&
        Randint(1, 100) <= o_Spell[SPL_MAGIC_MIRROR].effect[effSchoolLevel] && spell != SPL_TELEPORT && spell != SPL_SACRIFICE )
    {
        // Проигрываем одиночную анимацию
        CALL_5(void, __thiscall, 0x4963C0, o_BattleMgr, o_Spell[SPL_MAGIC_MIRROR].animation_ix, c->edi, 100, 0);

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

    return EXEC_DEFAULT;
}

int __stdcall dataInit(LoHook* h, HookContext* c)
{
    showMagicMirrorAnim = false;
    showMagicResistAnim = false;
    showSpellAnim = false;
    memset(needMagicMirrorAnim, false, 40);
    memset(needMagicResistAnim, false, 40);
    memset(needSpellAnim, false, 40);
    stackIndex = 0;
   
    return EXEC_DEFAULT;
}

int __stdcall skipOrigSound(LoHook* h, HookContext* c)
{
    char switchCase = ((char*)0x5A2B48)[*(int*)(c->ebp + 8) - 0xA];

    if ( !c->edi && (switchCase == 0x11 || switchCase == 0x18) || o_BattleMgr->ShouldNotRenderBattle() )
    {
        c->return_address = 0x5A0646;
        return NO_EXEC_DEFAULT;
    }
   
    return EXEC_DEFAULT;
}

int __stdcall reflectSpell(LoHook* h, HookContext* c)
{
    _Hero_* hero;
    _BattleStack_* stack;
    int spell, spellPower, schoolLevel;
    int casterSide = o_BattleMgr->current_side;

    if ( h->GetAddress() == 0x5A6A50 ) {
        stack = (_BattleStack_*)c->esi;
        spell = *(int*)(c->ebp + 0xC);
        spellPower = *(int*)(c->ebp + 0x14);
        schoolLevel = *(int*)(c->ebp + 0x10);
        hero = *(_Hero_**)(c->ebp + 8);
        c->return_address = 0x5A6A83;
    } else {
        stack = *(_BattleStack_**)(c->ebp + 0x14);
        spell = *(int*)(c->ebp + 8);
        spellPower = *(int*)(c->ebp + 0x1C);
        schoolLevel = c->esi;
        hero = *(_Hero_**)(c->ebp - 0x14);
        c->return_address = 0x5A210E;
    }
   
    // Если сработало Magic Mirror, перенаправляем заклинание на вражеский отряд
    if ( magicMirrorLucky(stack, spell) )
    {
        showMagicMirrorAnim = true;
        needMagicMirrorAnim[stack->side][stack->index_on_side] = true;
        _BattleStack_* stackFoe = getEnemyStackToRedirectTo(stack, spell);
        if ( stackFoe )
        {
            // Определяем, сработает ли резист против отражённого заклинания
            int resistPercentage = 100 * CALL_7(float, __thiscall, 0x5A83A0, o_BattleMgr, spell,
                casterSide, stackFoe, 1, 1, *(int*)(c->ebp + 0x1C));

            if ( Randint(1, 100) <= resistPercentage )
            {
                CALL_5(void, __thiscall, 0x444610, stackFoe, spell, spellPower, schoolLevel, hero);
                showSpellAnim = true;
                needSpellAnim[stackFoe->side][stackFoe->index_on_side] = true;
            }
            else if ( resistPercentage )
            {
                showMagicResistAnim = true;
                needMagicResistAnim[stackFoe->side][stackFoe->index_on_side] = true;
            }
        }
    }
    else {
        if ( Randint(1, 100) <= c->eax )
        {
            // Если не сработал резист, применяем эффект заклинания
            CALL_5(void, __thiscall, 0x444610, stack, spell, spellPower, schoolLevel, hero);
            showSpellAnim = true;
            needSpellAnim[stack->side][stack->index_on_side] = true;
        }
        // Если сработал резист, отмечаем отряд как требующий анимации резиста
        else if ( c->eax )
        {
            showMagicResistAnim = true;
            needMagicResistAnim[stack->side][stack->index_on_side] = true;
        }
    }
   
    return NO_EXEC_DEFAULT;
}

int __stdcall massReflection(LoHook* h, HookContext* c)
{
    // Проигрываем массовую анимацию и звук Magic Mirror
    if ( showMagicMirrorAnim )
    {
        CALL_3(void, __fastcall, 0x59A890, o_Spell[SPL_MAGIC_MIRROR].wav_name, -1, 3);
        CALL_4(void, __thiscall, 0x5A6AD0, o_BattleMgr, &needMagicMirrorAnim, o_Spell[SPL_MAGIC_MIRROR].animation_ix, 0);
    }

    // Проигрываем массовую анимацию и звук резиста
    if ( showMagicResistAnim )
    {
        CALL_3(void, __fastcall, 0x59A890, "MagicRes.wav", -1, 3);
        CALL_4(void, __thiscall, 0x5A6AD0, o_BattleMgr, &needMagicResistAnim, 78, 0);
    }

    // Проигрываем массовую анимацию и звук кастуемого заклинания
    if ( showSpellAnim )
    {
        _Spell_* spell = (_Spell_*)*(int*)(c->ebp - 0x10);
        CALL_3(void, __fastcall, 0x59A890, spell->wav_name, -1, 3);
        CALL_4(void, __thiscall, 0x5A6AD0, o_BattleMgr, &needSpellAnim, spell->animation_ix, 0);
    }
   
    c->return_address = h->GetAddress() == 0x5A2156 ? 0x5A2168 : 0x5A13FC;
    return NO_EXEC_DEFAULT;
}

int __stdcall playMagicMirrorSound(LoHook* h, HookContext* c)
{
    CALL_3(void, __fastcall, 0x59A890, o_Spell[SPL_MAGIC_MIRROR].wav_name, -1, 3);
   
    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.NewMagicMirrorTest");

            // Одиночный каст
            _PI->WriteLoHook(0x5A05CC, newTarget);
            _PI->WriteLoHook(0x5A058B, magicMirrorAI);
           
            _PI->WriteLoHook(0x5A13D2, dataInit);
            _PI->WriteLoHook(0x5A20BB, dataInit);
            _PI->WriteLoHook(0x5A6A50, reflectSpell);
            _PI->WriteLoHook(0x5A20F4, reflectSpell);
            _PI->WriteLoHook(0x5A13E5, massReflection);
            _PI->WriteLoHook(0x5A2156, massReflection);

            // Проигрываем звук Magic Mirror при отражении одиночного заклинания
            _PI->WriteLoHook(0x5A059A, playMagicMirrorSound);

            // Пропускаем оригинальный звук заклинания, чтобы воспроизвезти его позже
            _PI->WriteLoHook(0x5A0634, skipOrigSound);
        }
    }

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

Пред.След.

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

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

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