Объявления

Друзья, если не получается зарегистрироваться, напишите на почту 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 » 08 окт 2020, 18:32

Так как Вы, я заметил, всё равно подключаете библиотеку homm3.h, то задача изменения прироста сильно упрощается:

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

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

int __stdcall changeGrowth(LoHook* h, HookContext* c)
{
    o_pCreatureInfo[CID_FIREBIRD].growth = 1;
    o_pCreatureInfo[CID_PHOENIX].growth = 1;

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

            _PI->WriteLoHook(0x47ADA0, changeGrowth);
        }
    }

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

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

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

Сообщение Rolex » 08 окт 2020, 20:23

Изменение границ Боевого духа от -12 (100%) до +24 (100%).

Решение через WriteHexPatch:
Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "patcher_x86.hpp"

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

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

         _PI->WriteHexPatch(0x464580 + 6, "18 00 00 00");
         _PI->WriteHexPatch(0x464580 + 12, "E8");
         _PI->WriteHexPatch(0x464590 + 3, "E8 FF FF FF");
         _PI->WriteHexPatch(0x4645A0, "18");

         _PI->WriteHexPatch(0x464740 + 11, "0C 00 00 00");
         _PI->WriteHexPatch(0x464750 + 4, "F4 FF FF FF");
         _PI->WriteHexPatch(0x464770 + 12, "F4");
         _PI->WriteHexPatch(0x464780 + 12, "0C");
      }
   }

   return TRUE;
}


Изменение границ Боевого духа от -12 (100%) до +24 (100%).

Решение через WriteDword:
Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "patcher_x86.hpp"

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

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

         _PI->WriteDword(0x464580 + 6, 0x00000018);
         _PI->WriteDword(0x464580 + 12, 0xE8);
         _PI->WriteDword(0x464590 + 3, 0xFFFFFFE8);
         _PI->WriteDword(0x4645A0, 0x18);

         _PI->WriteDword(0x464740 + 11, 0x0000000C);
         _PI->WriteDword(0x464750 + 4, 0xFFFFFFF4);
         _PI->WriteDword(0x464770 + 12, 0xF4);
         _PI->WriteDword(0x464780 + 12, 0x0C);
      }
   }

   return TRUE;
}


Все верно? Положительная вроде как работает. Отрицательную мораль нужно еще протестить.

AlexSpl писал(а):

03 00 00 00 = 0x00000003, ведущие нули можно убрать, получится 0х3

Исходя из этого 0x00000003 эквивалентно 0х3? Тогда возникает вопрос, а зачем нам вообще патчить нулевые байты?

То есть, может сразу писать в WriteDword без ведущих нулей:
Код: Выделить всё
_PI->WriteDword(0x464580 + 6, 0x00000018) = _PI->WriteDword(0x464580 + 6, 0x18)
_PI->WriteDword(0x464740 + 11, 0x0000000C) = _PI->WriteDword(0x464740 + 11, 0xC);
Вернуться к началу

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 » 08 окт 2020, 22:44

Цитата:
Тогда возникает вопрос, а зачем нам вообще патчить нулевые байты?

3 - это число, вы можете его как угодно писать: 2 + 1, 0x003, 6 / 2, от этого оно не перестанет быть 3. И Вам совсем необязательно в случае WriteByte/WriteWord/WriteDword пользоваться шестнадцатеричной системой счисления. Вы можете использовать десятичные числа.

Потом. Вот это:

Код: Выделить всё
_PI->WriteDword(0x464580 + 6, 0x00000018);
_PI->WriteDword(0x464580 + 12, 0xE8);
_PI->WriteDword(0x464590 + 3, 0xFFFFFFE8);
_PI->WriteDword(0x4645A0, 0x18);

некорректно.

Если вы патчите байт, используйте WriteByte. Например, _PI->WriteDword(0x4645A0, 0x18); - эквивалентно _PI->WriteHexPatch(0x4645A0, "18 00 00 00"); Вы не только пишете 0x18, но ещё и затираете следующие три байта нулями. Правильно - _PI->WriteByte(0x4645A0, 0x18); или _PI->WriteByte(0x4645A0, 24); (как Вам удобнее).
Вернуться к началу

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

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

Сообщение Rolex » 09 окт 2020, 06:20

AlexSpl писал(а):

_PI->WriteLoHook(0x47ADA0, changeGrowth);

Этого адреса нет в btb2. Я так понимаю, что для того, чтобы узнать нужный адрес самому необходимы уже знания Ассемблера. Есть ли где-то инструкция, с помощью какого ПО и вообще по какому приниципу проводится анализ и нахождение нужного адреса?

AlexSpl писал(а):

И Вам совсем необязательно в случае WriteByte/WriteWord/WriteDword пользоваться шестнадцатеричной системой счисления. Вы можете использовать десятичные числа.

Буду знать. Благодарю.

AlexSpl писал(а):

Если вы патчите байт, используйте WriteByte. Например, _PI->WriteDword(0x4645A0, 0x18); - эквивалентно _PI->WriteHexPatch(0x4645A0, "18 00 00 00"); Вы не только пишете 0x18, но ещё и затираете следующие три байта нулями. Правильно - _PI->WriteByte(0x4645A0, 0x18); или _PI->WriteByte(0x4645A0, 24); (как Вам удобнее).

Ага, понял. Спасибо. Исходя из этого:
Цитата:
WriteByte(0xАдрес, один байт - 0xAB для примера); - эквивалент WriteHexPatch(0xАдрес, "AB");
WriteWord(0xАдрес, два байта - 0xABСD для примера); - эквивалент WriteHexPatch(0xАдрес, "СD AB");
WriteDword(0xАдрес, четыре байта - 0xABСDEF01 для примера); - эквивалент WriteHexPatch(0xАдрес, "01 EF CD AB");
Если нужно пропатчить три или более 4-х байт, всегда используйте WriteHexPatch: WriteHexPatch(0xАдрес, "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");

Dword - 4 байта, значит патча всего 1 байт, мы оставшиеся 3 затираем нулями. По-моему, в данном случае, чтобы не мешать WriteByte/WriteWord/WriteDword, лучше использовать один WriteHexPatch - он более универсален, ним можно пропатчить любое количество байтов.

И мы плавно переходим к последнему (если не считать 5-6 и 10-12), самому интересному и, пожалуй, самому важному пункту:
Цитата:
7) Очень нужен отдельный плагин для SoD/Complete, который восстановит код Отрицательной Удачи (Неудачи) (анимацию можно использовать из заклинания "Неудача"). При отрицательной Удаче отряд имеет шанс нанести половинный урон. Чем выше степень отрицательной удачи - тем выше шанс (-1: 8.3%, -2: 16.7%, -3: 25%). (этого нет в SoD_SP).

Отрицательная Удача есть в Ad Fontes, WoG/ERA, HotA, но я нигде еще не встречал отдельльный плагин Отрицательной Удачи к HD-моду для SoD/Complete. В SoD_SP - ее тоже нет.
Одни говорят, что отсутвие Отрицательной Удачи - это баг, другие же, напротив, говорят, что она якобы была, но в последний момент разработчики NWC, по непонятным причинам ее вырезали.
Короче, какая-то тайна, покрытая мраком. А ведь все говорит о том, что она должна была быть и должна была работать. Ведь Мораль то, отрицательная есть и работает, и Удача должна тоже работать, описание для нее же есть, даже заклинание "Неудача" есть. Но из-за не работы самой Отрицательной Удачи и заклинание "Неудача" становится бесполезным...

А вы никогда не писали может для себя подобного плагина, который восстанавливает код Отрицательной Удачи? Сложно ли будет его написать?
Вернуться к началу

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 » 09 окт 2020, 13:33

Неудача была в Героях 1, но там герои не могли получить значение Удачи меньше нуля, поэтому её никто никогда не видел. В Героях 2 также была неудача и её даже видели те "счастливчики", которым довелось посетить разграбленную пирамиду. По идее, в Героях 3 она тоже должна быть, но нет... От неудачи не осталось и следа. Если и был код для неудачи, то его тщательно выпилили.

Однако это не значит, что её нельзя вернуть. Причём возвращается она очень просто, если не заморачиваться с иконками. А всё потому, что неудача может использовать код удачи с небольшими правками. Кстати, откуда брать текст для выпавшей неудачи в бою? HotA его откуда брала?
Вернуться к началу

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

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

Сообщение Ben80 » 09 окт 2020, 15:27

Так отсюда вроде:
Код: Выделить всё
(const char *)*(int*)(*(int*)((*(int*)0x6A5DC4) + 32) + 180)


Итого:
Код: Выделить всё
_cstr_ v18 = GetCreatureName(stack->creature_id, stack->count_current);
sprintf(o_TextBuffer, (const char *)*(int*)(*(int*)((*(int*)0x6A5DC4) + 32) + 180), v18);
Вернуться к началу

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 » 09 окт 2020, 18:28

Ben80, всё-таки в игре есть какие-то упоминания о Неудаче? Я реально уже не помню, встречал ли я упоминания о Неудаче в данных игры. Но если посмотреть код, то она оттуда чистенько выпилена, как будто её и не было. Думаю, это осознанное решение разработчиков, иначе хотя бы намёк остался.

Например, в Героях 1 фраза "вернуть Неудачу обратно" звучит уместно, потому что в Героях 1 есть код, полностью поддерживающий Неудачу. Для Героев 3 уже совсем по-другому. Нельзя говорить "вернуть Неудачу". Её там попросту нет.

* * *
Но если предположить, что в Героях 3 Неудача была такой же, как и в первых двух частях (я подозреваю, что в ресурсах есть упоминание о половинном уроне), то не факт что она имела те же свойства. Это всего лишь наши догадки, основанные на том, что мы о ней знаем из предыдущих частей. Технически нет никаких препятствий написать код для Неудачи, но хотелось бы понять, откуда ноги растут. Откуда вероятности выпадения Неудачи? Где-то в ресурсах они прописаны или это просто аналогия с Героями 1 и 2?

* * *
Если так подумать, то от Неудачи осознанно избавились. В Героях 1 чисто теоретически её давал Fizbin of Misforture (но, опять же, это всего лишь предположение). В Героях 2 её можно было получить только одним способом. Логично предположить, что разработчики её решили выпилить совсем, так как получить её сродни чуду :smile2:

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

Плюсом к моим аргументам будет то, что в Героях 3 не было неудачи даже в самых ранних версиях, хотя в Героях 2 она была.
Вернуться к началу

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

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

Сообщение Rolex » 09 окт 2020, 19:19

AlexSpl писал(а):

Причём возвращается она очень просто, если не заморачиваться с иконками.

Ссылка на архив BadLuckAnim.rar с def-ками (ILCK22, ILCK30, ILCK42, ilck82, ilckb, ILCKS), которые взяты из HotA.lod, они отрисованы с учетом уже отрицательной удачи и подменяют дефолтные, которые находятся в H3sprite.lod. Анимация отрицательной удачи из заклинания "Неудача" тоже находится в H3sprite.lod под именем "C10SPF0.def".
https://drive.google.com/file/d/19GZYyE ... sp=sharing

AlexSpl писал(а):

Но если посмотреть код, то она оттуда чистенько выпилена, как будто её и не было. Думаю, это осознанное решение разработчиков, иначе хотя бы намёк остался.

Даже все def-ки отрисованы с учетом ее отсутствия. Можно глянуть ILCK22, ILCK30, ILCK42, ilck82, ilckb, ILCKS в H3sprite.lod.

AlexSpl писал(а):

Но если предположить, что в Героях 3 Неудача была такой же, как и в первых двух частях (я подозреваю, что в ресурсах есть упоминание о половинном уроне), то не факт что она имела те же свойства.

62 строка - ARRAYTXT.TXT - Bad luck sometimes falls on your armies in combat, causing their attacks to only do half damage.

AlexSpl писал(а):

Откуда вероятности выпадения Неудачи?

Аналогия Морали. Положительные вероятности выпадения Морали и Удачи совпадают. Можно предположить, что и отрицательные должны совпадать.

AlexSpl писал(а):

Логично предположить, что разработчики её решили выпилить совсем, так как получить её сродни чуду

Скорей всего так и есть.
Последний раз редактировалось Rolex 16 окт 2020, 15:42, всего редактировалось 5 раз(а).
Вернуться к началу

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

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

Сообщение RoseKavalier » 09 окт 2020, 19:29

Ben80 писал(а):

Так отсюда вроде:
Код: Выделить всё
(const char *)*(int*)(*(int*)((*(int*)0x6A5DC4) + 32) + 180)

EDIT Ugh, forum ate my post. ENDEDIT

This hurts to see, because I have to load up a bunch of things to figure out what it means :smile7:

Код: Выделить всё
P_GeneralText[45]

or non-macro style

P_GeneralText()[45]


Maybe it's just me but I always prefer spending a bit more time defining relevant structures and using it to write code I can quickly read and understand at a later time :smile24:


@Rolex
SoD_SP's extra archives support is added through H3.LodTable, you just need to add it to an active plugin folder and it takes care of the rest.

Otherwise I think HDmod provides that kind of feature if you provide a Files.ini document in your root folder, e.g. <...>/_HD3_Data/Common/
Вернуться к началу

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

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

Сообщение Ben80 » 09 окт 2020, 21:49

AlexSpl писал(а):

Ben80, всё-таки в игре есть какие-то упоминания о Неудаче? Я реально уже не помню, встречал ли я упоминания о Неудаче в данных игры. Но если посмотреть код, то она оттуда чистенько выпилена, как будто её и не было. Думаю, это осознанное решение разработчиков, иначе хотя бы намёк остался.


Да, есть. Правой кнопкой в окне героя с отрицательной удачей - надпись, что при срабатывании отриц. удачи будет половинный урон. Или правой кнопкой по юниту - точно не помню, но надпись есть.

AlexSpl писал(а):

Логично предположить, что разработчики её решили выпилить совсем, так как получить её сродни чуду :smile2:


Кстати, отриц. удачу в Тройке можно получить не только в Пирамиде, а при посещении фонтана какого-то (точно не помню, что за объект), причем необязательно "разграбленного" :smile12:

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

Скажем, ИИ, пытаясь прикинуть, не наложить ли ему Misfortune, считает что противник с отрицат. удачей и вправду будет иногда наносить половинный урон.

Мое мнение насчет отрицат. удачи - это та вещь, которая достаточно канонична, плюс скорее улучшает игру, чем ухудшает (приводит "в порядок" случаи с Misfortune и Дьяволами). Но строго говоря - да, это волюнтаристское решение, которое нельзя отнести к багфиксам.

RoseKavalier писал(а):

This hurts to see, because I have to load up a bunch of things to figure out what it means :smile7:


Я просто скопировал этот код из плагина Феанора и Сава, не особо задумываясь о том, как это следовало написать наиболее правильно.
Вернуться к началу

Пред.След.

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

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

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