Объявления

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

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

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

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

Сообщение AlexSpl » 26 фев 2021, 19:18

Я же выше писал :smile1: if ( o_GameMgr->GetHero(o_ActivePlayer->selected_hero_id)->second_skill[HSS_WISDOM] ) { ... } или, если так понятнее, if ( o_GameMgr->GetHero(o_ActivePlayer->selected_hero_id)->second_skill[HSS_WISDOM] > 0 ) { ... }

А лучше сразу сравнивать с уровнем заклинания. Только учтите, что уровень начинается с 0 (0 - 1-й уровень, 1 - 2-й и т.д.).
Вернуться к началу

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

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

Сообщение Rolex » 28 фев 2021, 16:22

Готовый код Ученого - отображение бонуса, который получит активный герой при посещении Ученого. Отображает верно даже если нет Книги заклинаний или недостаточно Мудрости. Если герой не может получить основной бонус, отображается дефолтный: первичный навык. Если никакой из героев не выбран (выбран, например, город), тогда при наведении курсора на Ученого отображается основной бонус.

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


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


char o_TxtBuffer[50];


int __stdcall showScholarInfo(LoHook* h, HookContext* c)
{
   // Учёный?
   if (c->eax == 0x51) {
      int ScholarType = (*(int*)c->ebx << 29) >> 29;
      int ScholarPrimarySkill = *(int*)c->ebx << 26 >> 29;
      int ScholarSecondarySkill = *(int*)c->ebx << 19 >> 25;
      int ScholarSpell = *(int*)c->ebx << 9 >> 22;

      _Hero_* hero = o_GameMgr->GetHero(o_ActivePlayer->selected_hero_id);

      if (ScholarType == 0) {
            sprintf(o_TxtBuffer, "%s (%s)", (char*)c->edi, *(char**)(0x6A5330 + (0x32 + ScholarPrimarySkill) * 4));
      } else
      if (ScholarType == 1) {
         if (o_ActivePlayer->selected_hero_id != ID_NONE && ((hero->second_skill_count > 7 && !hero->second_skill[ScholarSecondarySkill]) || hero->second_skill[ScholarSecondarySkill] > 2))
            sprintf(o_TxtBuffer, "%s (%s)", (char*)c->edi, *(char**)(0x6A5330 + (0x32 + ScholarPrimarySkill) * 4)); else
            sprintf(o_TxtBuffer, "%s (%s)", (char*)c->edi, *(char**)(*(int*)0x67DCF0 + ScholarSecondarySkill * 16));
      } else
      if (ScholarType == 2) {
         if (o_ActivePlayer->selected_hero_id != ID_NONE && (!hero->DoesWearArtifact(AID_SPELL_BOOK) || o_Spell[ScholarSpell].level > hero->second_skill[HSS_WISDOM] + 2 || hero->spell[ScholarSpell]))
            sprintf(o_TxtBuffer, "%s (%s)", (char*)c->edi, *(char**)(0x6A5330 + (0x32 + ScholarPrimarySkill) * 4)); else
            sprintf(o_TxtBuffer, "%s (%s)", (char*)c->edi, o_Spell[ScholarSpell].name);
      }

      c->edi = (int)o_TxtBuffer;
   }

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

         _PI->WriteLoHook(0x40D059, showScholarInfo);
      }
   }

   return TRUE;
}


AlexSpl, хотел бы сюда еще добавить Witch Hut. Чтобы при наведении курсора отображался вторичный навык, который там можно получить. Нужна помощь в поиске адреса хука. С хранением тут уже должно быть попроще, чем с Ученым. Нет ни типов, ни первичных навыков, ни заклинаний. Для вторичных навыков нам потребуется 5 бит на хранение всех навыков и 1 бит на хранение знака. Итого 6 бит.
Последний раз редактировалось Rolex 10 мар 2021, 13:20, всего редактировалось 2 раз(а).
Вернуться к началу

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

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

Сообщение AlexSpl » 28 фев 2021, 20:26

Цитата:
хотел бы сюда еще добавить Witch Hut

Witch Hut ID = 0x71. Все регистры останутся теми же, только номер навыка не через ebx получается, а через *(int*)(c->ebp + 8): int WitchHutSecondarySkill = *(int*)*(int*)(c->ebp + 8) << 12 >> 25; (это из-за того, что для Witch Hut подсказку печатает отдельная функция, а *(int*)(c->ebp + 8) - это аргумент (ebx в стеке)).

Можете сказать, с какого бита начинается битовое поле, хранящее номер вторичного навыка для Witch Hut, и какова его длина (x << 12 >> 25)? :smile1:

Самое главное забыл. Хук сюда: 0x40DC31.
Вернуться к началу

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

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

Сообщение Rolex » 01 мар 2021, 08:38

Спасибо. Хижина работает. Но заметил один момент. В случае с Хижиной наш извлекаемый бонус дописывается не только в инфо-строке, а еще и в диалоге по ПКМ. А вот с Ученым бонус отображается только в инфо-строке. Думаю, надо бы как-то привести все к общему знаменателю. То есть либо, чтобы Ученый также как и Хижина в диалоге по ПКМ отображал в скобках бонус - Ученый (бонус), либо же сделать так, чтобы Хижина в диалоге по ПКМ не отображала бонус, а отображала его только в инфо-строке. Подозреваю, что проблема кроется именно в адресах хуков.

AlexSpl писал(а):

Можете сказать, с какого бита начинается битовое поле, хранящее номер вторичного навыка для Witch Hut, и какова его длина (x << 12 >> 25)?

Код: Выделить всё
X  X  X  X  X  X  X  X  X  X  X  X  S  S  S  S  S  S  S  X  X  X  X  X  X  X  X  X  X  X  X  X

Битовое поле начинается с бита с номером N = 13, а его длина L = 7. Верно? :smile1:
Вернуться к началу

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

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

Сообщение AlexSpl » 01 мар 2021, 11:19

Цитата:
Битовое поле начинается с бита с номером N = 13, а его длина L = 7. Верно?

x << l >> r; l = 12, r = 25.

Нужно решить систему уравнений:
{ 32 - (N + L) = l;
{ 32 - L = r.

Длина: L = 32 - r. Начальный бит: N = r - l. Для примера выше L = 32 - 25 = 7, N = 25 - 12 = 13. Всё верно :smile1:

Цитата:
В случае с Хижиной наш извлекаемый бонус дописывается не только в инфо-строке, а еще и в диалоге по ПКМ

Вот, значит, зачем вывод этой строки засунули в отдельную функцию. Будем тогда отличать подсказку в статусной строке от подсказки по ПКМ по адресу возврата из этой функции. Добавьте в условие, где проверяете ID Хижины, следующее: *(int*)(c->ebp + 4) == 0x40D045.
Вернуться к началу

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

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

Сообщение AlexSpl » 01 мар 2021, 12:44

Как лучше реализовать ограничение на прокачку вторичных героев?

Сейчас думаю, что так: герой получает достаточно опыта, чтобы перейти на последний разрешённый в соответствующей секции файла ini уровень. Если герой не является стартовым, весь избыток опыта усекается до минимального количества, необходимого для достижения этого уровня. После диалога выбора вторичных навыков появляется сообщение о том, что достигнут максимальный уровень, но только один раз за всю игру, чтобы не мешал. Опыт продолжает накапливаться, ибо писать хук для каждого случая получения опыта замучаешься, но (!) игрок этого не видит, в статистике всё красиво: висит последний разрешённый уровень и минимальное кол-во опыта для его достижения.

Чтобы отличать стартовых героев от второстепенных, придётся воспользоваться неиспользуемым полем структуры _Hero_, т.к. для игры нет понятия "стартовый игрок": она сгенерировала и забыла. Придётся запоминать, причём не только на время текущего сеанса игры, а так, чтобы флажок "стартовый игрок" сохранялся и после загрузки сейва. Для этого отлично подходит поле id_wtf :smile1: Это поле всегда ноль для героев, которых сгенерировала игра, а не поставил на карту картостроитель. Даже на картах с редактированными героями это поле не используется (что-то вроде уникального идентификатора героя, который ему назначает редактор карт).

* * *
Поправочка. Вспомнил, что стартовый замок запоминается. Посмотрел шпаргалку и нашёл стартового героя недалеко от стартового замка:

Код: Выделить всё
int playerID;
const int startHeroID = o_GameMgr->Field<int>(0x1F6A0 + 0x1A4 + playerID * 4);
Последний раз редактировалось AlexSpl 02 мар 2021, 08:50, всего редактировалось 2 раз(а).
Вернуться к началу

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

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

Сообщение Rolex » 01 мар 2021, 16:36

Не привык бросать уже начатое. Надо бы довести его до ума.

AlexSpl писал(а):

Для Пирамиды используется тот же алгоритм определения кол-ва стеков, что и для нейтралов, а также Заброшенной шахты (т.е. Deviation нельзя взять и убрать). Просто от результирующего кол-ва Золотых големов отнимается 2 (ну, и идёт проверка, чтобы их не стало меньше одного). Для HD+ нужны другие коэффициенты devCoef[] и их нужно вычислять.

Ну вы же понимаете, что сам я их уж точно не вычислю. А кроме вас, помочь здесь могут ну еще от силы пару человек, которых вы прекрасно знаете. Но они, к сожалению, посещают данный форум уж явно реже вас. Так что помочь, кроме вас, то особо и некому...


Код: Выделить всё
int getStacksCount(double k, char x, char y, char z)
{
   __int64 devCoef[] = { 0xA, 0xB, 0xC, 0xD }; // for HD+

   int n = 2;
   if (k < 0.50) n = 7; else
      if (k < 0.67) n = 6; else
         if (k < 1.00) n = 5; else
            if (k < 1.50) n = 4; else
               if (k < 2.00) n = 3;


   // Deviation
   __int64 splitValue = (((devCoef[0] * x + devCoef[1] * y + devCoef[2] * z + devCoef[3]) >> 0x10) & 0x7FFF) % 100 + 1;
   if (splitValue <= 20) --n;
   if (splitValue >= 80 && n < 7) ++n;

   return n;
}


В общем нужна ваша помощь в вычислении devCoef для HD+.

Ну и, наверное, надо бы проверку в getStacksCount добавить на то, вкл ли HD+. Если HD+ выкл, то брать эти коеф:
{ 0x5C6F80EB, 0xC8374AB9, 0x73D409E3, 0xBD38DECE }, а если вкл, то другие (для HD+).

Rolex писал(а):

Как я понимаю теперь нам нужно переприсвоить оригинальному сообщению в функции showGuardsRMB по Пирамиде первую строку с названием объекта, чтобы убрать два перевода строк и строку (Посещено). Как вообще более правильно поправить код, чтобы вывод после посещения был общей охраны (Толпа 20-49 и тп) из ARRAYTXT, как на скрине со Склепом без разбивки на отряды по ПКМ (разбивка только в диалоге при посещении)?

AlexSpl писал(а):

Поставить хук туда, где добавляется "\n\n(Visited)" и переписать сообщение на своё. Завтра гляну.

Эх, уже месяц прошел, а мы так с вами это и не сделали...
Вернуться к началу

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

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

Сообщение RoseKavalier » 01 мар 2021, 19:02

Splitting
All adventure map objects , including Scholar.

This will fail if someone places a HiHook there, just keep that in mind for long-term.
Код: Выделить всё
* (int *) (c-> ebp + 4) == 0x40D045
Вернуться к началу

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

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

Сообщение AlexSpl » 02 мар 2021, 04:38

You can break one plugin with another in more vague ways, so let's just call it incompatibility :smile2:

Цитата:
All adventure map objects , including Scholar.

Why do you use unsigned type for bit fields when they are actually signed (shl, sar)?
Вернуться к началу

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

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

Сообщение AlexSpl » 02 мар 2021, 09:47

Аккуратное ограничение уровня второстепенных героев.

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

#include "..\..\HotA\homm3.h"

Patcher* _P;
PatcherInstance* _PI;

char iniPath[MAX_PATH];

void __stdcall LevelCap(HiHook* h, _Hero_* hero)
{
    char maxLevel = GetPrivateProfileIntA("Limits", "MaxLevel", 74, iniPath);
   
    // Если герой второстепенный, не позволяем ему получить уровень выше, чем заданный в файле ini
    if ( hero->id == o_GameMgr->Field<int>(0x1F6A0 + 0x1A4 + o_ActivePlayerID * 4) || hero->level < maxLevel )
        CALL_1(void, __thiscall, h->GetDefaultFunc(), hero);
}

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

            GetCurrentDirectoryA(sizeof(iniPath), iniPath);
            strcat(iniPath, "\\LevelCap.ini");

            _PI->WriteHiHook(0x4DA990, SPLICE_, EXTENDED_, THISCALL_, LevelCap);
        }
    }

    return TRUE;
}

Примечание. Стартовым может быть только один герой. Если вдруг захочется использовать этот плагин, например, в кампаниях, разрешите свободную прокачку настроенным в редакторе карт героям: добавьте в условие ... || hero->id_wtf.

* * *
Для кампаний нужно ещё разрешать прокачку переходящим героям. Если реально кому-то будет интересно играть кампании с ограничением уровня второстепенных героев, то следует разрешить прокачку героев из этого списка: o_GameMgr->saved_hero_list.
Вернуться к началу

Пред.След.

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

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

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