Объявления

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

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineFilin_7  
имя: Филин
 
Сообщения: 2
Зарегистрирован: 26 май 2023, 06:25
Пол: Мужчина
Поблагодарили: 0 раз.

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

Сообщение Filin_7 » 30 май 2023, 10:12

Да действительно. Спасибо за помощь, всё заработало. Если у кого-то вдруг возникнет такая же проблема, то в кодировках нужно выбрать кирилица - виндовс1251 )

А по вампиризму - здесь именно и нужно, что бы добиться полной гармонии, так сказать ) Нужно извлечь оригинальную анимацию и перекрасить её в оттенки синего а лучше сине-зелёного, могильного ) С помощью фотошопа это делается запросто, для меня например нереально извлечь, я в коде ни бум-бум ) Но это всё из разряда предложений - если кто-нибудь, когда-нибудь, вдруг :smile32:

Еще раз спасибо за помощь и всего хорошего :smile17:
Вернуться к началу

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 » 26 июн 2023, 18:45

Прошёл кампанию за Мутаре (если кому интересно - 110 дней без разведки, без генерации навыков: Мутаре без логи ходила, без TP и DD), начал кампанию за Dracon'a (третья в аддоне "Клинок Армагеддона"), которая на время. Понятное дело, что в любом случае она проходится и затупить там сложно при любом раскладе. Однако появился большой соблазн получить Логистику (пусть Advanced хотя бы) и Экспертную Землю, чтоб не страдать. И тут у меня родилась мысль: а почему все навыки равнозначны на левел-апе? Да, у навыков есть веса, но игрок-то эти веса практически не замечает: игра просто ставит игрока перед выбором между двумя навыками. Какой навык полезнее, обычно сразу понятно. Так вот, продолжение мысли, а что если за взятие крутых навыков увеличивать кол-во опыта до следующего уровня? Например, ты взял Логистику, теперь тебе придётся накопить, скажем, в полтора раза больше опыта для перехода на следующий уровень. Иными словами, назначить каждому вторичному навыку множитель: чем круче навык, тем такой множитель больше, и, соответственно, игроку дольше придётся ждать следующего уровня. "Бесполезным" навыкам можно присвоить множители меньше 1 даже, чтобы хоть как-то компенсировать их "бесполезность". Думаю, свежая идея. Только нужно подумать, как быть с прогрессивным кол-вом опыта в Героях (ведь взяв ту же Логистику на втором уровне, игрок при любом множителе не сильно много теряет, так как разница между вторым и третьим уровнями берётся из одного сундука). Кстати, это тоже ерунда, как по мне. Герои просто залпом взлетают вверх по лестнице опыта, а потом такие... ну, когда же, когда же новый уровень? :smile9: Естественно, это идея для плагина и для тех, кто любит экспериментировать. Я бы сделал более плавный набор уровней и привязал бы расстояние между уровнями к ценности выбираемого на левел-апе навыка. При правильной реализации получилось бы нечто интересное и свежее.

Хотя :smile5: Можно и текущие очки опыта оставить. Множитель же можно сделать и 2 и 3 за взятие Логи или Земли? :smile10: А лучше всего привязать этот множитель к расстоянию между уровнями, чтобы не было обидно высокоуровневым героям. Сейчас сколько там топовых навыков? А при данном подходе можно было бы уже задуматься над общей эффективностью (ведь множитель откладывает не только получение следующего вторичного навыка, но и следующего первичного). Если множители выбрать грамотно, то с такими монстрами, как Логистика и Земля уже как-то можно будет бороться навыками, обеспечивающими (гораздо) более быстрое получение уровней. Ну, и ходи со своей Логистикой на 6-м, привет от героя 10-го уровня :smile20:

Почему это здорово? Во-первых, в Героях - пресловутый рандом. Тебе либо везёт, либо нет. И обычно, если тебе не везёт, то везёт твоему сопернику. Так хоть у того, кому не повезло, шансы какие-то будут. Во-вторых, столько жарких споров о том, что навыки в Героях 3 можно отбалансировать. Это же бред. Вы не можете сделать так, чтобы килограмм стал километром. Вторичные навыки в Героях почти всегда несравнимы. А система множителей (штрафов/бонусов за крутость/бесполезность) уже может попытаться это сделать. Это не означает, кстати, что игроки перестанут брать Землю, когда предлагают, это означает, что те, кому её не предлагают, смогут уже конкурировать. Как можно бороться против массслоу? Можно, если у тебя намного круче параметры и армия. Важный момент - найти баланс. Принцип предела: всем же понятно, что если сделать множитель Земли равным бесконечности, то её нельзя будет брать, ибо игрок перестанет вообще развиваться. Но если этот множитель выбрать грамотно, то Землю можно легко занёрфить.

* * *
Сейчас вот думаю демо-плагин написать и пришёл к выводу, что проще всего просто давать штраф к набору опыта после выбора сильного навыка до следующего левел-апа (или бонус - для слабых навыков) :smile11: Что-то вроде динамического обучения (Learning). Естественно, с поправками на излишек опыта.

Есть ещё более простая идея - ввести модификатор (коэффициент) обучаемости. Действует всю игру в зависимости от выбранных вторичных навыков. Этот вариант даже лучше, как мне кажется, и напоминает расширенный механизм вторичного навыка Learning: только здесь процент может быть негативным (-30% к опыту, например; уже можно задуматься).

 Код новой механики натуральным образом встраивается в hero::GetExperienceBonusFactor()
Код: Выделить всё
double __thiscall hero::GetExperienceBonusFactor(hero *this)
{
    char learningLvl; // al
    const THeroSpecificAbility *heroSpecialty; // eax
    float Level; // [esp+0h] [ebp-8h]
    float expMul; // [esp+4h] [ebp-4h]

    learningLvl = this->SSLevel[SS_LEARNING];
    expMul = LearningSkillMultipliers[learningLvl];
    if ( learningLvl > 0 )
    {
        heroSpecialty = &akHeroSpecificAbilities[this->order_ID];
        if ( !heroSpecialty->specialityType && heroSpecialty->specializedID == SS_LEARNING )
        {
            Level = this->Level;
            expMul = (Level * 0.050000001 + 1.0) * expMul;
        }
    }
    return expMul + 1.0;
}

Пример. За каждую ступень Логистики герой получает -7% к опыту, за каждую ступень Магии Земли - минус 10%. Эффект умножается. Так, у героя c Экспертной Логистикой и Землёй будет следующий штраф к получению опыта:

1 - (1 - 0.07)^3 * (1 - 0.10)^3 ~ 41%, а не 51%. Бонусы от слабых навыков суммируются. Например, Eagle Eye можно смело давать в нагрузку +15%. Анекдот: а чего у тебя папка с Орлоглазом? Компенсирую Землю :smile20: Но до ума можно довести при желании.

Разумеется, ни в какие турниры это не пойдёт (разве что экспериментальные). Но интересно было бы обкатать с небольшими штрафами для имбовых навыков, чтобы понять, как такая механика прокачки ощущается. По сути, это работает, как пенальти за имбу. Сейчас получил Логистику - скушал больше всего, опыта больше получил, а такой бы механизм хоть как-то компенсировал "приятные побочки" увеличенной дальности передвижения. То же с Землей: получил массслоу - начал громить всех подряд с минимальными потерями, качаешься куда быстрее. Данная механика вот этот бы приятный "побочный" бонус как раз бы и нивелировала.
Вернуться к началу

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 » 14 июл 2023, 12:06

Цитата:
Хотелось бы того же поведения, что и в Героях 2 для Original/Expansion карт: на картах RoE видеть только объекты и механики RoE, на картах AB - RoE+AB. Пожелание относится к случайной охране, случайным артефактам, сборным артефактам, городу Сопряжение и его героям, существам в лагере беженцев. Всего уже не помню, возможно, ещё проклятая земля и ров.


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

По горячим следам сделал так, чтобы в SoD 3.2 или Complete 4.0 на картах RoE не генерировались монстры из AB (SoD новых существ не добавлял).

 Код
Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0

#pragma warning(disable : 4005)
#pragma warning(disable : 4010)

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

Patcher* _P;
PatcherInstance* _PI;

int __stdcall fixMonsters(LoHook* h, HookContext* c)
{
   if (gpGame->sMapHeader.iVersion == 0x0E)
   {
      for (int i = eCreatureHalfling; i < kNumCreatureTypes; ++i)
      {
         CALL_3(void, __thiscall, 0x4CF730, c->ebp - 0x24, i, 0);
      } 
     
      c->return_address = 0x4C9060;
      return NO_EXEC_DEFAULT;
   }

   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.H3.fixRandomGeneration");
           _PI->WriteLoHook(0x4C9046, fixMonsters);
      }
   }

   return TRUE;
}

Если кто большой фанат порядка и справедливости для RoE под крылом SoD/Complete, прилагаю сам плагин для тестирования:

fixRandomGeneration.zip
(4.35 КБ) Скачиваний: 234

Возможно, позже исправлю и остальные косяки SoD/Complete при игре на картах RoE/AB. Нужно как минимум ещё убрать генерацию артов AB/SoD на картах RoE и артов SoD на картах AB. Такая генерация не только идёт вразрез с механикой, но ещё и забагованная (почитать подробнее можно в FizMiG): например, Эликсир Жизни выглядит на карте, как Плащ Короля Нежити.

* * *
Пока тестировал, нашёл неизвестный мне баг с копией героя. Если Вы поставили на карту героя, то не это ещё не означает, что такой же герой не может появиться в городе/замке (баг). Если двойник поставленного вручную на карту героя всё-таки появился в замке, то герой исчезает с карты, а при рестарте карты в списке героев даже появляется два одинаковых героя, одного из которых нельзя выбрать, но можно кликнуть на портрете. Причём этот баг не исправлен даже в HD моде.
Вернуться к началу

offlineАватара пользователя
void_17  
имя: имя
Ветеран
Ветеран
 
Сообщения: 548
Зарегистрирован: 25 апр 2021, 15:05
Откуда: Оттуда
Пол: Мужчина
Поблагодарили: 132 раз.

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

Сообщение void_17 » 14 июл 2023, 13:26

Цитата:
Причём этот баг не исправлен даже в HD моде.


Пишите бараторчу.
Вернуться к началу

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 » 15 июл 2023, 01:43

Запрет генерации не-RoE монстров на картах RoE + генерации кампанейских и сборных артефактов + запрет Conflux и героев Conflux.

fixRandomGeneration.zip
(4.53 КБ) Скачиваний: 253

 Код
Код: Выделить всё
#define _CRT_SECURE_NO_WARNINGS
#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0

#pragma warning(disable : 4005)
#pragma warning(disable : 4010)

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

Patcher* _P;
PatcherInstance* _PI;

int __stdcall fixMonsters(LoHook* h, HookContext* c)
{
   if (gpGame->sMapHeader.iVersion == 0x0E)
   {
      for (int i = eCreatureHalfling; i < kNumCreatureTypes; ++i)
      {
         CALL_3(void, __thiscall, 0x4CF730, c->ebp - 0x24, i, 0);
      } 
     
      c->return_address = 0x4C9060;
      return NO_EXEC_DEFAULT;
   }

   return EXEC_DEFAULT;
}

int __stdcall excludeConfluxTowns(LoHook* h, HookContext* c)
{
   if (gpGame->sMapHeader.iVersion == 0x0E)
   {
      if (++c->ecx < 8)
      {
         c->return_address = h->GetAddress() == 0x5134F6 ? 0x5134EA : 0x513512;
         return NO_EXEC_DEFAULT;
      }
   }

   return EXEC_DEFAULT;
}

int __stdcall excludeConfluxHeroes(LoHook* h, HookContext* c)
{
   if (gpGame->sMapHeader.iVersion == 0x0E)
   {
      THeroClass heroClass = gpGame->heroPool[c->esi].hero_class;

      if (heroClass == eClassPlaneswalker || heroClass == eClassElementalist)
      {
         c->return_address = 0x4C4B35;
         return NO_EXEC_DEFAULT;
      }
   }

   return EXEC_DEFAULT;
}

TArtifact __stdcall GetRandomArtifactId(HiHook* h, game* thisgame, int ArtifactClass)
{
   return CALL_2(TArtifact, __thiscall, h->GetDefaultFunc(), thisgame, ArtifactClass);
}

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.fixRandomGeneration");
           _PI->WriteLoHook(0x4C9046, fixMonsters);
           _PI->WriteDword(0x4C91C2, 121);
           _PI->WriteDword(0x4C91FF, 121 * sizeof(int));
           _PI->WriteDword(0x4C9248, 121);
           _PI->WriteLoHook(0x5134F6, excludeConfluxTowns);
           _PI->WriteLoHook(0x513520, excludeConfluxTowns);
           _PI->WriteLoHook(0x4C4B2B, excludeConfluxHeroes);
           //_PI->WriteHiHook(0x4C9190, SPLICE_, EXTENDED_, THISCALL_, GetRandomArtifactId);
      }
   }

   return TRUE;
}

Карта с багом (двойник героя, 100% появляется после рестарта карты):

Untitled.zip
(2.19 КБ) Скачиваний: 249
Вернуться к началу

offlineАватара пользователя
void_17  
имя: имя
Ветеран
Ветеран
 
Сообщения: 548
Зарегистрирован: 25 апр 2021, 15:05
Откуда: Оттуда
Пол: Мужчина
Поблагодарили: 132 раз.

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

Сообщение void_17 » 20 июл 2023, 02:32

Только сегодня заметил, что в сохранении/чтении у структуры города есть 61 (!) неиспользованных пустых байтов. (первые 9 используются) Это можно использовать.
Очень щедро!, спасибо NWC за эксплоит мододелам...
Код: Выделить всё
   unsigned char bitset_buffer[kNumSpells];
   std::fill_n(&bitset_buffer[0], kNumSpells, 0);
   for ( int i = 0; i < 70; ++i )
   {
      if ( SpellDisabledMask.test(i) )
         bitset_buffer[i / 8] |= 1 << (i % 8);
   }
   if ( outfile.write(bitset_buffer, 70) < 70 )
           return -1;
Вернуться к началу

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 июл 2023, 03:14

Массив на 70 байтов для хранения запрещённых в городе заклинаний, а используется игрой, как битовый? Или можно использовать, как битовый?
Вернуться к началу

offlineАватара пользователя
void_17  
имя: имя
Ветеран
Ветеран
 
Сообщения: 548
Зарегистрирован: 25 апр 2021, 15:05
Откуда: Оттуда
Пол: Мужчина
Поблагодарили: 132 раз.

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

Сообщение void_17 » 20 июл 2023, 03:25

Это и есть std::bitset. В игре используется как std::bitset. Заполняются только первые 9 байт(это минимальное количество байт для хранения 70 бит) Т.е. у нас есть 61 неиспользуемых байт, куда можно впихнуть много чего.
Вернуться к началу

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 июл 2023, 14:24

В классе playerData есть поле char towns[72]; Т.е. на карте может быть максимум 72 города (официально поддерживается игрой, кажется, 48 из-за битсетов). В Героях 1 все структуры городов, включая пустые, идут в сейв. Если в Героях 3 то же самое, то это не просто 61 байт, а 61 * 72 = 4392 байта. Хотя использовать ненужные байты структуры не под нужды города - это всё равно костыль. А вот для города можно хранить много чего интересного.
Вернуться к началу

offlineigrik  
Подмастерье
Подмастерье
 
Сообщения: 108
Зарегистрирован: 14 сен 2017, 12:35
Пол: Не указан
Поблагодарили: 84 раз.

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

Сообщение igrik » 27 июл 2023, 16:23

AlexSpl писал(а):

Пока тестировал, нашёл неизвестный мне баг с копией героя. Если Вы поставили на карту героя, то не это ещё не означает, что такой же герой не может появиться в городе/замке (баг). Если двойник поставленного вручную на карту героя всё-таки появился в замке, то герой исчезает с карты, а при рестарте карты в списке героев даже появляется два одинаковых героя, одного из которых нельзя выбрать, но можно кликнуть на портрете. Причём этот баг не исправлен даже в HD моде.


В ЭРЕ я это уже давным давно исправил.
Код: Выделить всё
// исправление бага с исчезновением стартового героя при переигрывании
_PI->WriteByte(0x5029C0, 0xEB);


В Хоте тоже уже давно исправлено.
Вернуться к началу

Пред.След.

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

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

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

cron