Объявления

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

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 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)
Поблагодарили: 2184 раз.

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

Сообщение AlexSpl » 12 сен 2017, 10:07

Цитата:
Мудрость, кстати, оказалась не нужна для получения заклинаний Орлиным глазом.

Этого я не знал. Интересно.

Цитата:
Код: Выделить всё
double EagleEyePower = CALL_1(long double, __thiscall, 0x4E4690, Hero);

Технически декомпилятор прав: значение возвращается в регистре сопроцессора ST(0), а он long double. Но если вы посмотрите код, то увидите там:

Код: Выделить всё
004E47E3                 fld     dword ptr [ebp-4]

Так что возвращаемый тип всё-таки float:

Код: Выделить всё
float EagleEyePower = CALL_1(float, __thiscall, 0x4E4690, Hero);


Цитата:
Код: Выделить всё
if(*(int*)(Hero_1 + 201 + 11)>1)
   makeEagleEye(Hero_1, Hero_2);

if(*(int*)(Hero_2 + 201 + 11)>1)
   makeEagleEye(Hero_2, Hero_1);

Здесь нужно условие больше 0 (> 0), т.к. уже на базовом уровне Eagle Eye герой может подглядеть заклинания.

Цитата:
Код: Выделить всё
_PI->WriteHexPatch(0x63EA2C, "9A 99 99 3E"); // 0.30
_PI->WriteHexPatch(0x63EA30, "33 33 B3 3E"); // 0.35
_PI->WriteHexPatch(0x63EA34, "CD CC CC 3E"); // 0.40

Тут проще писать _PI->WriteDword(0x63EA2C, 0x3E99999A); и т.д. - и тогда не нужно инвертировать байты.

Ещё проверку на уже изученные заклинания забыли:

Код: Выделить всё
if ( *(char*)(HeroDonor + 1072 + i) && !*(char*)(Hero + 1002 + i) )


* * *
Вот такая красота получилась:

Изображение

Надо ещё проверить, нужна ли книга для того, чтобы выучить заклинание с помощью Eagle Eye.

* * *
Проверил. Сообщение о выученном заклинании после боя появляется, как обычно. Но заклинание в книгу не попадает после её покупки. Так что нужно ещё проверку на наличие книги вставить.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 12 сен 2017, 13:54

AlexSpl писал(а):


Цитата:
Код: Выделить всё
_PI->WriteHexPatch(0x63EA2C, "9A 99 99 3E"); // 0.30
_PI->WriteHexPatch(0x63EA30, "33 33 B3 3E"); // 0.35
_PI->WriteHexPatch(0x63EA34, "CD CC CC 3E"); // 0.40

Тут проще писать _PI->WriteDword(0x63EA2C, 0x3E99999A); и т.д. - и тогда не нужно инвертировать байты.


Я эти значения все равно получаю компиляцией тестовой программы на ассемблере, которую смотрю в OllyDbg.
Там уже все в инвертированном виде. Другого способа не придумал.


Еще вот такой код в начало добавил:
Код: Выделить всё
int attackerHeroOwner = *(int*)(c->ebx + 0x54A8);
int defenderHeroOwner = *(int*)(c->ebx + 0x54AC);
if(attackerHeroOwner == -1 || defenderHeroOwner == -1)
   return EXEC_DEFAULT;


Напишите, пожалуйста, полный код для плагина, который у Вас получился.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 12 сен 2017, 13:59

Кстати, склоняюсь к мысли сделать значения 0.25/0.3/0.35 и оставить еще и дефолтное действие навыка (после битвы) - с теми же 0.25/0.3/0.35, причем сделать это даже в случае проигрыша битвы.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 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)
Поблагодарили: 2184 раз.

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

Сообщение AlexSpl » 12 сен 2017, 14:20

Цитата:
Напишите, пожалуйста, полный код для плагина, который у Вас получился.

Вот код плагина для Eagle Eye (на основе Вашего кода):

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

Patcher* _P;
PatcherInstance* _PI;

static _bool_ plugin_On = 0;

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

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

int captionAddr;

// Заголовок в каждом диалоге
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 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 = (_ptr_)pic + (nPics + 1) * 8; // Адрес следующего за последним элементом в списке байта
    picList.EndMem = 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 getEagleEyeSpells(_Hero_* hero, _Hero_* heroDonor, int spells[])
{
    int n = 0;
    unsigned int eagleEyeProb = (unsigned int)(CALL_1(float, __thiscall, 0x4E4690, hero) * 100.0f);

    for (_Spell_* iSpell = o_Spell + SPL_QUICKSAND; iSpell <= o_Spell + SPL_AIR_ELEMENTAL; ++iSpell)
    {
        int i = iSpell - o_Spell;
        if ( heroDonor->spell_level[i] && !hero->spell[i] )
        {
            if ( iSpell->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;
                if ( dice <= eagleEyeProb )
                {
                    spells[n++] = i;
                    hero->spell[i] = 1;
                    hero->spell_level[i] = 1;
                }
            }
        }
    }

    return n;
}

int __stdcall eagleEyeMain(LoHook* h, HookContext* c)
{
    _Hero_* attHero = o_BattleMgr->hero[ATTACKER];
    _Hero_* defHero = o_BattleMgr->hero[DEFENDER];
   
    if ( attHero && defHero )
    {
        int spells[70];

        if ( attHero->second_skill[HSS_EAGLE_EYE] && attHero->DoesWearArtifact(AID_SPELL_BOOK) )
            showSpellDlg(attHero, spells, getEagleEyeSpells(attHero, defHero, spells));
     
        if ( defHero->second_skill[HSS_EAGLE_EYE] && defHero->DoesWearArtifact(AID_SPELL_BOOK) )
            showSpellDlg(defHero, spells, getEagleEyeSpells(defHero, attHero, spells));
    }
   
    return EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
    {
        if ( !plugin_On )
        {
            plugin_On = 1;
            _P = GetPatcher();
            _PI = _P->CreateInstance("HD.Plugin.NewEagleEye");

            // Меняем коэффициенты
            float eagleEyeCoefs[] = {0.00f, 0.30f, 0.35f, 0.40f};
                       
            _PI->WriteDword(0x63EA2C, *(int*)&eagleEyeCoefs[1]);
            _PI->WriteDword(0x63EA30, *(int*)&eagleEyeCoefs[2]);
            _PI->WriteDword(0x63EA34, *(int*)&eagleEyeCoefs[3]);

            // Убираем оригинальный эффект
            _PI->WriteHexPatch(0x469C23, "EB");
            _PI->WriteHexPatch(0x476996, "E9 DD 01 00 00");
           
            // Фиксим заголовок диалога
            _PI->WriteLoHook(0x4F7D49, saveCaption);
            _PI->WriteLoHook(0x4F7D54, captionFix);
           
            _PI->WriteLoHook(0x462C7D, eagleEyeMain);
        }
    }
   
    return TRUE;
}


Плагин для тестов:

Test.zip
(6.03 КБ) Скачиваний: 276

Осталось только написать код для сетевой игры.

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

См. код выше. Так удобнее:

Код: Выделить всё
// Меняем коэффициенты
float eagleEyeCoefs[] = {0.00f, 0.30f, 0.35f, 0.40f};
                       
_PI->WriteDword(0x63EA2C, *(int*)&eagleEyeCoefs[1]);
_PI->WriteDword(0x63EA30, *(int*)&eagleEyeCoefs[2]);
_PI->WriteDword(0x63EA34, *(int*)&eagleEyeCoefs[3]);


* * *
UPD Заменил неблагозвучное DoesHasArtifact(AID_SPELL_BOOK) на DoesWearArtifact(AID_SPELL_BOOK), тем более так правильнее.
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 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)
Поблагодарили: 2184 раз.

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

Сообщение AlexSpl » 12 сен 2017, 19:27

Вот ещё одна проблема субъективного характера. Функция rand_s() очень хороша для онлайна. Я бы все вызовы стандартного броска поменял на rand_s(). Для офлайна же важна повторяемость. Поэтому смотрите сами, какую функцию использовать - оригинальную (гарантирует повторяемость) или rand_s() (гарантирует fair play и защиту от всевозможных программ, которые предсказывают псевдослучайную последовательность генерируемых чисел).

Код: Выделить всё
// Меняем коэффициенты
float eagleEyeCoefs[] = {0.00f, 0.30f, 0.35f, 0.40f};
                       
_PI->WriteDword(0x63EA2C, (int&)eagleEyeCoefs[1]);
_PI->WriteDword(0x63EA30, (int&)eagleEyeCoefs[2]);
_PI->WriteDword(0x63EA34, (int&)eagleEyeCoefs[3]);


Всё время забываю, но так лучше конвертить float в dword.

* * *
Лирическое отступление. Многие считают Eagle Eye бесполезным навыком, но в данной реализации он становится намного привлекательнее. Прикиньте такой вариант: лошок c Орлоглазом и Грамотностью нападает на папку, сбегает, а потом делится выученными заклинаниями с нашим папкой :) Очень ничего тактика. Да даже мейну в финальной битве такой навык бы пригодился: кто знает, что в книге у соперника? :smile2:
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 13 сен 2017, 04:02

AlexSpl писал(а):

Вот ещё одна проблема субъективного характера. Функция rand_s() очень хороша для онлайна. Я бы все вызовы стандартного броска поменял на rand_s(). Для офлайна же важна повторяемость. Поэтому смотрите сами, какую функцию использовать - оригинальную (гарантирует повторяемость) или rand_s() (гарантирует fair play и защиту от всевозможных программ, которые предсказывают псевдослучайную последовательность генерируемых чисел).


Спасибо за информацию. Тогда действительно надо будет подумать как-нибудь о такой замене.
Когда Вы говорили о том, чтобы не "сломать" стандартный ГСК, то имели в виду нарушение последовательности псевдослучайных чисел ? Если так, то "сломать" - это даже хорошо :smile1: Поскольку это делает псевдослучайную последовательность более "случайной".

AlexSpl писал(а):

Лирическое отступление. Многие считают Eagle Eye бесполезным навыком, но в данной реализации он становится намного привлекательнее. Прикиньте такой вариант: лошок c Орлоглазом и Грамотностью нападает на папку, сбегает, а потом делится выученными заклинаниями с нашим папкой :) Очень ничего тактика. Да даже мейну в финальной битве такой навык бы пригодился: кто знает, что в книге у соперника? :smile2:


Рад, что Вам нравится то, что мы делаем.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 13 сен 2017, 04:08

Ben80 писал(а):

Кстати, склоняюсь к мысли сделать значения 0.25/0.3/0.35 и оставить еще и дефолтное действие навыка (после битвы) - с теми же 0.25/0.3/0.35, причем сделать это даже в случае проигрыша битвы.


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

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 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)
Поблагодарили: 2184 раз.

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

Сообщение AlexSpl » 13 сен 2017, 10:07

Цитата:
Немного "воговщина" - навешиваем сразу несколько фишек. Но поскольку эти фишки в одном направлении, то в принципе ничего страшного. Просто немного нелогично будет, если противник применит в бою несколько раз какое-то заклинание, а наш герой его так и не выучит.

Я считаю, что новая механика Eagle Eye будет плохо сочетаться с оригинальной. Во-первых, из-за кардинально разных способов получения заклинаний. Во-вторых, два диалога - в начале и в конце боя - многовато для одного вторичного навыка.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 13 сен 2017, 10:39

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

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5584
Зарегистрирован: 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)
Поблагодарили: 2184 раз.

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

Сообщение AlexSpl » 13 сен 2017, 11:20

Переписал eagleEyeMain() для работы в том числе и в сетевой игре:

Код: Выделить всё
int __stdcall eagleEyeMain(LoHook* h, HookContext* c)
{
    _Hero_* hero[] = {o_BattleMgr->hero[ATTACKER], o_BattleMgr->hero[DEFENDER]};
       
    if ( hero[ATTACKER] && hero[DEFENDER] )
    {
        int spells[70];         
           
        for (int i = ATTACKER; i <= DEFENDER; ++i)
        {
            if ( hero[i]->second_skill[HSS_EAGLE_EYE] && hero[i]->doll_art[AS_SPELL_BOOK].id == AID_SPELL_BOOK )
            {
                // Учим заклинания всегда.
                int n = getEagleEyeSpells(hero[i], hero[1 - i], spells);

                // Но диалог показываем только для игрока-человека:
                // в хотсите - диалог для обоих героев, в сетевой игре - только для своего героя.
                if ( o_GameMgr->GetPlayer(hero[i]->owner_id)->IsHuman() )
                    if ( !o_NetworkGame || hero[i]->owner_id == o_GameMgr->GetMeID() )
                        showSpellDlg(hero[i], spells, n);
            }
        }
    }
   
    return EXEC_DEFAULT;
}

Потестил бой против компа и хотсит PvP. Cетевую игру пока не проверял.

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

Patcher* _P;
PatcherInstance* _PI;

static _bool_ plugin_On = 0;

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

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

int captionAddr;

// Заголовок в каждом диалоге
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 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 getEagleEyeSpells(_Hero_* hero, _Hero_* heroDonor, int spells[])
{
   int n = 0;
   unsigned int eagleEyeProb = (unsigned int)(CALL_1(float, __thiscall, 0x4E4690, hero) * 100.0);

   for (_Spell_* iSpell = o_Spell + SPL_QUICKSAND; iSpell <= o_Spell + SPL_AIR_ELEMENTAL; ++iSpell)
   {
      int i = iSpell - o_Spell;
      if ( heroDonor->spell_level[i] && !hero->spell[i] )
      {
         if ( iSpell->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;
            if ( dice <= eagleEyeProb )
            {
               spells[n++] = i;
               hero->spell[i] = 1;
               hero->spell_level[i] = 1;
            }
         }
      }
   }

   return n;
}

int __stdcall eagleEyeMain(LoHook* h, HookContext* c)
{
   _Hero_* hero[] = {o_BattleMgr->hero[ATTACKER], o_BattleMgr->hero[DEFENDER]};
      
   if ( hero[ATTACKER] && hero[DEFENDER] )
   {
      int spells[70];         
         
      for (int i = ATTACKER; i <= DEFENDER; ++i)
      {
         if ( hero[i]->second_skill[HSS_EAGLE_EYE] && hero[i]->doll_art[AS_SPELL_BOOK].id == AID_SPELL_BOOK )
         {
            // Учим заклинания всегда.
            int n = getEagleEyeSpells(hero[i], hero[1 - i], spells);

            // Но диалог показываем только для игрока-человека:
            // в хотсите - диалог для обоих героев, в сетевой игре - только для своего героя.
            if ( o_GameMgr->GetPlayer(hero[i]->owner_id)->IsHuman() )
               if ( !o_NetworkGame || hero[i]->owner_id == o_GameMgr->GetMeID() )
                  showSpellDlg(hero[i], spells, n);
         }
      }
   }
   
   return EXEC_DEFAULT;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
   if ( DLL_PROCESS_ATTACH == ul_reason_for_call )
   {
      if ( !plugin_On )
      {
         plugin_On = 1;
         _P = GetPatcher();
         _PI = _P->CreateInstance("HD.Plugin.NewEagleEye");

         // Меняем коэффициенты
         float eagleEyeCoefs[] = {0.00f, 0.30f, 0.35f, 0.40f};
                  
         _PI->WriteDword(0x63EA2C, (int&)eagleEyeCoefs[1]);
         _PI->WriteDword(0x63EA30, (int&)eagleEyeCoefs[2]);
         _PI->WriteDword(0x63EA34, (int&)eagleEyeCoefs[3]);

         // Убираем оригинальный эффект
         _PI->WriteHexPatch(0x469C23, "EB");
         _PI->WriteHexPatch(0x476996, "E9 DD 01 00 00");
         
         // Фиксим заголовок диалога
         _PI->WriteLoHook(0x4F7D49, saveCaption);
         _PI->WriteLoHook(0x4F7D54, captionFix);
         
         _PI->WriteLoHook(0x462C7D, eagleEyeMain);
      }
   }
   
   return TRUE;
}

* * *
Странно, что у Вас owner_id не работает. У меня возвращает корректный номер игрока. Может, у Вас в свойствах проекта (Configuration Properties > C/C++ > Code Generation) Struct Member Alignment (выравнивание членов структур) в 1 байт не выставлено?
Последний раз редактировалось AlexSpl 13 сен 2017, 16:08, всего редактировалось 2 раз(а).
Вернуться к началу

Пред.След.

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

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

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