Объявления

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

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineigrik  
Подмастерье
Подмастерье
 
Сообщения: 108
Зарегистрирован: 14 сен 2017, 12:35
Пол: Не указан
Поблагодарили: 84 раз.

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

Сообщение igrik » 16 авг 2019, 11:11

AlexSpl писал(а):

Т.е. глобальный массив запрещает даже Некромантию!

Конечно! Там во всей функции выдачи нового втон.навыка при повышении уровня идет сначала проверка на глобальный массив, а потом проверяются поклассово

Например 0x4DB15E
Код: Выделить всё
   v20 = 0;
    SSkill = 0;
    while ( 1 )
    {
      ss_lvl = Hero->SSkill[SSkill];
      if ( ss_lvl >= maxSkillLev || ss_lvl < v29 || SSkill == SkipSkill )
        goto LABEL_59;
      if ( o_GameMgr_isBannedSkills[SSkill] )
        break;
      v22 = HeroClass->ProbSSkill[SSkill];
      if ( !HeroClass->ProbSSkill[SSkill] )
        goto LABEL_56;
LABEL_58:
      v20 += v22;
LABEL_59:
      if ( ++SSkill >= 28 )
      {
        if ( v20 )
        {
          v23 = Random(1, v20);
          result = 0;
          while ( 1 )
          {
            v24 = Hero->SSkill[result];
            if ( v24 < maxSkillLev && v24 >= v29 && result != SkipSkill )
              break;
LABEL_73:
            if ( ++result >= 28 )
              return -1;
          }
          if ( !o_GameMgr_isBannedSkills[result] )
          {
            v25 = HeroClass->ProbSSkill[result];
            if ( !HeroClass->ProbSSkill[result] )
            {
LABEL_70:
Вернуться к началу

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

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

Сообщение AlexSpl » 16 авг 2019, 11:40

Всё, посмотрел свой старый код и наконец разобрался :smile1: Нет никакого отдельного массива запрещённых навыков для классов героев! Если только глобальный :smile1:

Цитата:
SkillTableOffset := $4E658;

Запутала моя структура TWeights, которая есть часть структуры _HeroType_ (с добавлением глобального массива запрещённых навыков) :smile4:
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

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

Сообщение RoseKavalier » 16 авг 2019, 12:53

as239 писал(а):

Ок значит буду сам сохранять.

Нужна помощь с запретом навыка "Навигация".
Правильно ли я нашел адрес для хука: "0x54AE6A"?
И что здесь будет являться аналогом: "c->ebp - 0x34"?


0x54AE6A is too early, the loop begins at 0x54AF2F so anything that hook would do is overwritten.

Try 0x54AF69 instead and use c->ecx.

as239 писал(а):

Жалко только что rmg->waterAmount не работает, приходится доставать его из _RMGStruct_.

It could be the RMG_Main offset just needs to be corrected, the water amount is copied to RMG_Main at 0x538147. I will try to check and make corrections if needed.

ED. yep, incorrect.
Изображение
Вернуться к началу

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

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

Сообщение AlexSpl » 16 авг 2019, 13:07

Код: Выделить всё
.text:0054AF1E                 xor     esi, esi
.text:0054AF20                 cmp     esi, 1Ch
.text:0054AF23                 mov     [ebp-10h], esi
.text:0054AF26                 mov     [ebp+8], esi
.text:0054AF29                 jnb     loc_54AFB8
.text:0054AF2F
.text:0054AF2F loc_54AF2F:                             ; CODE XREF: sub_54A1A0+DC2↓j
.text:0054AF2F                 mov     ecx, esi
.text:0054AF31                 mov     edx, 1
.text:0054AF36                 and     ecx, 1Fh
.text:0054AF39                 mov     eax, esi
.text:0054AF3B                 shl     edx, cl
.text:0054AF3D                 shr     eax, 5
.text:0054AF40                 test    [ebp+eax*4-10h], edx

Обратите внимание на первую строчку (54AF1Eh: c->esi = 0) и третью (54AF23h: *(int*)(c->ebp - 0x10) = c->esi, т.е. 0!). Здесь (54AF40h) мы всегда с нулём сравниваем? Баг?
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

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

Сообщение RoseKavalier » 16 авг 2019, 13:15

It's two steps into one action.
First it initiates esi as the iterator (++i) for the loop
Second it nulls out the bitfield, [ebp - 10h] = 0

RMG_Main is corrected.
Вернуться к началу

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

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

Сообщение AlexSpl » 16 авг 2019, 13:19

Поэтому и не работало. Хук был выше, а ниже маска обнулялась.
Вернуться к началу

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

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

Сообщение AlexSpl » 16 авг 2019, 14:10

Вот так работает:

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

Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;

int DisabledSpellsList[] = {SPL_MAGIC_ARROW, SPL_SLOW, SPL_STONE_SKIN, SPL_SHIELD};
int DisabledSkillsList[] = {HSS_NAVIGATION, HSS_LEARNING};

void disable(int* bf, int* list, int n)
{
    for (int i = 0; i < n; ++i)
    {
        *(int*)(&bf)[list[i] >> 5] |= 1 << (list[i] & 31);
    }
       
    return;
}

int __stdcall RMGDisableSpells(LoHook* h, HookContext* c)
{
    disable((int*)(c->ebp - 0x34), DisabledSpellsList, sizeof(DisabledSpellsList) / sizeof(int));
   
    return EXEC_DEFAULT;
}

int __stdcall RMGDisableSkills(LoHook* h, HookContext* c)
{
    disable((int*)(c->ebp - 0x10), DisabledSkillsList, sizeof(DisabledSkillsList) / sizeof(int));

    return EXEC_DEFAULT;
}

bool isSpellAllowed(int ID)
{
    bool isAllowed = true;
   
    for (int i = 0; i < sizeof(DisabledSpellsList) / sizeof(int); ++i)
    {
        if (ID == DisabledSpellsList[i])
        {
            isAllowed = false;
            break;
        }
    }

    return isAllowed;
}

// Считаем кол-во разрешённых заклинаний
int __stdcall RMGDisableSpellsInScrollsA(LoHook* h, HookContext* c)
{
    // Получаем ID текущего заклинания
    int ID = (c->eax - (int)&o_Spell->school_flags) / sizeof(_Spell_);

    if (!isSpellAllowed(ID))
    {
        c->return_address = 0x5353EE;
        return NO_EXEC_DEFAULT;
    }
       
    return EXEC_DEFAULT;
}

// Выбираем разрешённое заклинание
int __stdcall RMGDisableSpellsInScrollsB(LoHook* h, HookContext* c)
{
    // Получаем ID текущего заклинания
    int ID = (c->eax - (int)&o_Spell->school_flags) / sizeof(_Spell_);

    if (!isSpellAllowed(ID))
    {
        c->return_address = 0x535423;
        return NO_EXEC_DEFAULT;
    }
       
    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((char*)"HD.Plugin.RMGDisableSpellsAndSkills");
            _PI->WriteLoHook(0x54AE23, RMGDisableSpells);
                       
            // Запрещаем заклинания в свитках
            _PI->WriteLoHook(0x5353E8, RMGDisableSpellsInScrollsA);
            _PI->WriteLoHook(0x535417, RMGDisableSpellsInScrollsB);

            // Запрещаем вторичные навыки
            _PI->WriteLoHook(0x54AF26, RMGDisableSkills);
        }
    }

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

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

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

Сообщение as239 » 16 авг 2019, 16:01

Цитата:
RMG_Main is corrected.

Thanks!
Is it possible to fix "templateName"?
It is always "null".
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Посвященный
Посвященный
 
Сообщения: 88
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 22 раз.

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

Сообщение Catastrophe » 18 авг 2019, 16:26

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

Код: Выделить всё
         // neutrals always split
         _PI->WriteJmp(0x4AC380, 0x4AC398);
         _PI->WriteDword(0x4AC39E, 99);

         // neutrals always have upgraded stack
         _PI->WriteDword(0x4AC463, 2);

Помогите, пожалуйста, сделать фичу. Она существовала еще в WoG, как элемент системы опыта существ.
Например, все гаргульи начинают бой уже под баффом "каменная кожа". Как в четвертых героях.
Быстрее всего смогу ответить вам в Telegram: @PleaseAndThankYou
Вернуться к началу

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

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

Сообщение AlexSpl » 19 авг 2019, 00:41

Цитата:
Помогите, пожалуйста, сделать фичу. Она существовала еще в WoG, как элемент системы опыта существ.
Например, все гаргульи начинают бой уже под баффом "каменная кожа". Как в четвертых героях.


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

Patcher* _P;
PatcherInstance* _PI;
static _bool_ plugin_On = 0;

int __stdcall CastStoneSkinOnGargoyles(LoHook* h, HookContext* c)
{
    for (int side = ATTACKER; side <= DEFENDER; ++side)
    {
        for (int i = 0; i < o_BattleMgr->stacks_count[side]; ++i)
        {
            if (o_BattleMgr->stack[side][i].creature_id == CID_STONE_GARGOYLE ||
                o_BattleMgr->stack[side][i].creature_id == CID_OBSIDIAN_GARGOYLE)
            {
                // int __thiscall combatMonster_ApplySpell(_CombatMonster_ *this, int spell, int SpellPower, int SchoolLevel, _Hero_ *hero)
                CALL_5(int, __thiscall, 0x444610, &o_BattleMgr->stack[side][i], SPL_STONE_SKIN, 3, 0, 0);
                // 3 - продолжительность заклинания, 0 - уровень (0 = None, 1 = Basic, 2 = Advanced, 3 = Expert), 0 - нет (бонусов) героя
                // последним аргументом может быть герой (o_BattleMgr->hero[side]), если нужны его бонусы (Кси, Дарксторн, Мерист, Лабета)
            }
        }
    }
                           
    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((char*)"HD.Plugin.CastStoneSkinOnGargoyles");
           
            _PI->WriteLoHook(0x462E26, CastStoneSkinOnGargoyles);
        }
    }

    return TRUE;
}

Вот, кстати, интересная идея для плагина: дать Астралу (спецу по Гипнозу) абилку гипнотизировать рандомный вражеский стек, если выполнены требования по здоровью: (50 + SpellPower * 25) * (1 + [HeroLevel / CreatureLevel] * 0.03) :smile1:

Да и вообще, интересная тема. Можно "прикрутить" заклинания, накладываемые в начале боя, спецам по существам, героям с определёнными вторичными навыками и т.п.
Можно даже привязать накладываемые заклы ко дню недели (тоже бы интересно было), либо ослабить временные бонусы от посещения различных объектов: например, вместо бонуса к Удаче накладывать на все отряды заклинание Fortune на определённое кол-во раундов (скажем, на три) и т.д. :smile1:

А вот идея для нового артефакта: вешать в начале боя на каждый союзный отряд случайное усиливающее заклинание; либо ослабляющее на отряды противника.

Всё это бы разнообразило игру, не разрушая её духа.
Вернуться к началу

Пред.След.

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

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

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