Объявления
Поздравляем
Roman2211


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

Вот это тоже в тот лоухук:

Код: Выделить всё
int LMEffects[] = { 1, 1, 2, 3 };

for (int i = 0; i < 4; ++i)
{
  o_Spell[SPL_MIRTH].effect[i] = LMEffects[i];
  o_Spell[SPL_SORROW].effect[i] = -LMEffects[i];
  o_Spell[SPL_FORTUNE].effect[i] = LMEffects[i];
  o_Spell[SPL_MISFORTUNE].effect[i] = -LMEffects[i];
}

o_Spell[SPL_HASTE].effect[3] = 7;

float SlowValueOne = 0.20f;
float SlowValueTwo = 0.40f;
float SlowValueThree = 0.60f;

o_Spell[SPL_SLOW].effect[0] = (int)&SlowValueOne;
o_Spell[SPL_SLOW].effect[1] = (int)&SlowValueOne;
o_Spell[SPL_SLOW].effect[2] = (int)&SlowValueTwo;
o_Spell[SPL_SLOW].effect[3] = (int)&SlowValueThree;

А хайхук удалите.

И почему _PI->WriteLoHook(0x59E437, afterInit); ? В примере с массхилом другой адрес (его менять не нужно).
Вернуться к началу

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 » 31 окт 2020, 19:32

Да, и насчёт Slow. Используйте целые числа, если в текстовиках они целые.
Вернуться к началу

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

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

Сообщение Rolex » 31 окт 2020, 20:36

AlexSpl писал(а):

А хайхук удалите.
И почему _PI->WriteLoHook(0x59E437, afterInit); ? В примере с массхилом другой адрес (его менять не нужно).

Вот теперь работает.

Код: Выделить всё
// dllmain.cpp: определяет точку входа для приложения DLL.
#define _CRT_SECURE_NO_WARNINGS

#include "stdafx.h"
#include "HotA\patcher_x86.hpp"
#include "HotA\homm3.h"

Patcher* _P;
PatcherInstance* _PI;

static _bool_ plugin_On = 0;

struct SpellDesc
{
   char* DefaultDesc;
   char* BasicDesc;
   char* AdvancedDesc;
   char* ExpertDesc;
};

SpellDesc MirthDesc =
{
   "{Радость}\n\n+1 к боевому духу всех дружественных отрядов.",
   "{Базовая Радость}\n\n+1 к боевому духу всех дружественных отрядов.",
   "{Продвинутая Радость}\n\n+2 к боевому духу всех дружественных отрядов.",
   "{Экспертная Радость}\n\n+3 к боевому духу всех дружественных отрядов."
};

SpellDesc SorrowDesc =
{
   "{Печаль}\n\n-1 к боевому духу всех вражеских отрядов.",
   "{Базовая Печаль}\n\n-1 к боевому духу всех вражеских отрядов.",
   "{Продвинутая Печаль}\n\n-2 к боевому духу всех вражеских отрядов.",
   "{Экспертная Печаль}\n\n-3 к боевому духу всех вражеских отрядов."
};

SpellDesc FortuneDesc =
{
   "{Удача}\n\n+1 к удаче всех дружественных отрядов.",
   "{Базовая Удача}\n\n+1 к удаче всех дружественных отрядов.",
   "{Продвинутая Удача}\n\n+2 к удаче всех дружественных отрядов.",
   "{Экспертная Удача}\n\n+3 к удаче всех дружественных отрядов."
};

SpellDesc MisfortuneDesc =
{
   "{Неудача}\n\n-1 к удаче всех вражеских отрядов.",
   "{Базовая Неудача}\n\n-1 к удаче всех вражеских отрядов.",
   "{Продвинутая Неудача}\n\n-2 к удаче всех вражеских отрядов.",
   "{Экспертная Неудача}\n\n-3 к удаче всех вражеских отрядов."
};

SpellDesc HasteDesc =
{
   "{Ускорение}\n\n+3 к скорости всех дружественных отрядов.",
   "{Базовое Ускорение}\n\n+3 к скорости всех дружественных отрядов.",
   "{Продвинутое Ускорение}\n\n+5 к скорости всех дружественных отрядов.",
   "{Экспертное Ускорение}\n\n+7 к скорости всех дружественных отрядов."
};

SpellDesc SlowDesc =
{
   "{Медлительность}\n\n-20% к скорости всех вражеских отрядов.",
   "{Базовая Медлительность}\n\n-20% к скорости всех вражеских отрядов.",
   "{Продвинутая Медлительность}\n\n-40% к скорости всех вражеских отрядов.",
   "{Экспертная Медлительность}\n\n-60% к скорости всех вражеских отрядов."
};

int __stdcall afterInit(LoHook* h, HookContext* c)
{
   int LMEffects[] = { 1, 1, 2, 3 };

   for (int i = 0; i < 4; ++i)
   {
      o_Spell[SPL_MIRTH].effect[i] = LMEffects[i];
      o_Spell[SPL_SORROW].effect[i] = -LMEffects[i];
      o_Spell[SPL_FORTUNE].effect[i] = LMEffects[i];
      o_Spell[SPL_MISFORTUNE].effect[i] = -LMEffects[i];
   }

   o_Spell[SPL_HASTE].effect[3] = 7;
   
   o_Spell[SPL_SLOW].effect[0] = 80;
   o_Spell[SPL_SLOW].effect[1] = 80;
   o_Spell[SPL_SLOW].effect[2] = 60;
   o_Spell[SPL_SLOW].effect[3] = 40;

   *(SpellDesc*)(o_Spell + SPL_MIRTH)->description = MirthDesc;
   *(SpellDesc*)(o_Spell + SPL_SORROW)->description = SorrowDesc;
   *(SpellDesc*)(o_Spell + SPL_FORTUNE)->description = FortuneDesc;
   *(SpellDesc*)(o_Spell + SPL_MISFORTUNE)->description = MisfortuneDesc;
   *(SpellDesc*)(o_Spell + SPL_HASTE)->description = HasteDesc;
   *(SpellDesc*)(o_Spell + SPL_SLOW)->description = SlowDesc;
   
   return EXEC_DEFAULT;
}


char __stdcall IsSpellSingleTarget(HiHook *h, int spell, int ssLevel)
{
   switch (spell)
   {
   case 49: case 50: case 51: case 52: case 53: case 54:
      return FALSE;
      break;
   default:
      return CALL_2(char, __fastcall, h->GetDefaultFunc(), spell, ssLevel);
   }
}

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

         _PI->WriteHiHook(0x59E360, SPLICE_, EXTENDED_, FASTCALL_, IsSpellSingleTarget);
         _PI->WriteLoHook(0x4EE1C1, afterInit);
      }
   }

   return TRUE;
}


AlexSpl писал(а):

Да, и насчёт Slow. Используйте целые числа, если в текстовиках они целые.

В том то и проблема, что ускорение меняется на фиксированные целые значения, а вот медлительность понижает скорость на фиксированный процент от базовой скорости существа. В оригинале это 25%/25%/50%/50%, я же делаю 20%/20%/40%/60%. И почему-то решил что здесь не целые. Как бы итоговое значение то в любом случае будет целое после округления. Но после взятия процента оно не целое. Через
Код: Выделить всё
o_Spell[SPL_SLOW].effect[0] = 0x3E4CCCCD;
o_Spell[SPL_SLOW].effect[1] = 0x3E4CCCCD;
o_Spell[SPL_SLOW].effect[2] = 0x3ECCCCCD;
o_Spell[SPL_SLOW].effect[3] = 0x3F19999A;

Получил космические скорости.

Потом задал целые:
Код: Выделить всё
o_Spell[SPL_SLOW].effect[0] = 20;
o_Spell[SPL_SLOW].effect[1] = 20;
o_Spell[SPL_SLOW].effect[2] = 40;
o_Spell[SPL_SLOW].effect[3] = 60;


И то же мимо. Как оказалось нужно задавать не тот процент на который идет снижение от базовой скорости, а тот, который остается после снижения, то есть так:
Код: Выделить всё
o_Spell[SPL_SLOW].effect[0] = 80;
o_Spell[SPL_SLOW].effect[1] = 80;
o_Spell[SPL_SLOW].effect[2] = 60;
o_Spell[SPL_SLOW].effect[3] = 40;


Правда округляет оно как-то непонятно. В Героях вообще округление всегда идет вниз. Так вот есть два существа со скоростью 7. Ставлю Медлительность на Эксперте, у одного скорость становится 3, а у второго 2. Хотя 7 - 60% = 7 - 4,2 = 2,8. То есть получается для одного округлило вверх, а для другого вниз. Как так?
Вернуться к началу

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 » 31 окт 2020, 20:45

Цитата:
Так вот есть два существа со скоростью 7. Ставлю массовою Медлительность на Эксперте, у одного скорость становится 3, а второго 2.

Нужно смотреть, как оно работает. У меня мысли о том, что Slow снижает базовую скорость существа. А у одного из существ со скоростью 7 единичка могла быть за родные земли.
Вернуться к началу

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

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

Сообщение Rolex » 31 окт 2020, 20:52

AlexSpl писал(а):

Нужно смотреть, как оно работает. У меня мысли о том, что Slow снижает базовую скорость существа. А у одного из существ со скоростью 7 единичка могла быть за родные земли.

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

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

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

Сообщение Rolex » 01 ноя 2020, 14:38

1) А как можно из плагина изменить текст диалога, который показывается при входе в Хижину ведьмы?

2) У Палатки Первой помощи есть описания, как артефакта и как сущеста в бою (#define CID_FIRST_AID_TENT 147) + описания вторичного навыка Первая помощь. Вот как изменить описание вторичного навыка и артефакта я уже в курсе, а вот описание абилки существа - нет.
Нужен адрес на таблицу с описаниями существ из файла CRTRAITS.TXT.

Должно как-то так менятся, если брать по аналогии с заклинаниями, хотя не уверен, может там есть еще какие-то нюансы.

*(Общее_название_структуры_описания_существ*)(адрес_на_таблицу_с_описанием_абилок_существ + id_палатки_как_существа * размер структуры?)->specification_description = название_структуры_с_описанием_абилки_конкретного_существа;

Вот id_палатки_как_существа у меня есть, а вот адрес_на_таблицу_с_описанием_абилок_существ (файл CRTRAITS.TXT) - нету. Нужна помощь, лучше с примером.

3) В моде есть такая особенность, что он не отображает вступительный видеоролик. Экзешник, который создается из лаунчера самого мода основан на англоязычном экзешнике. Точно не скажу, то ли на англ Complete 4.0, то ли на переименованном SoD 3.2.
Так вот, он изначально крутит заставку 3DO, после NWC и дальше - главное меню. То есть вступительный ролик в отличии от оригинального экзешника мод не отображает (который должен идти после NWC).

Можно ли как-то пропатчить эксзешник созданый модом так, чтобы он отображал после NWC вступительный видеоролик (H3INTRO.SMK/H3INTRO.BIK), либо же через плагин, который будучи подключеным крутил бы этот ролик. Также если возможно после основного ролика было бы неплохо еще показывать вступительный ролик из AB (H3X1intr.smk/H3X1intr.bik).

К слову, в RoE были как вступительный видеоролик (H3INTRO.SMK/H3INTRO.BIK), так и заключительный (ENDGAME.smk/ENDGAME.bik), в AB - только вступительный (H3X1intr.smk/H3X1intr.bik), в SoD не было вообще никаких видеороликов (заставки кампаний не считаем). А в Complete были оба ролика из RoE с озвучкой, но не было немого ролика из AB.

Так вот задача состоит в том, чтобы восстановить проигрывание вступительного ролика (H3INTRO) и за ним ролика из AB (H3X1intr), которые будут включены в VIDEO.VID при запуске игры с экзешника созданного лаунчером мода, с помощью патча этого экзешника или же плагина, который будет подключаться к моду. Насколько сложно это будет сделать?
Вернуться к началу

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 » 02 ноя 2020, 02:16

Цитата:
Нужен адрес на таблицу с описаниями существ из файла CRTRAITS.TXT.

Код: Выделить всё
struct MonBattleDesc
{
   char* nameSingle;
   char* namePlural;
   char* desc;
} monBattleDesc[150];

...

// В afterInit():
monBattleDesc[CID_FIRST_AID_TENT].desc = "I'm a First Aid Tent (your description here)";
*(MonBattleDesc*)(0x6703CC + 116 * CID_FIRST_AID_TENT) = monBattleDesc[CID_FIRST_AID_TENT];


Цитата:
А как можно из плагина изменить текст диалога, который показывается при входе в Хижину ведьмы?

С advevent.txt должно быть аналогично. Завтра поищу адреса текстов.

А вот с роликами неохота разбираться (того не стоит) :smile3: Ролики хорошо смотреть, когда начинаешь прохождение кампаний, и совсем не весело их каждый раз скипать после. Вот в RoE, кажется, грамотно было сделано: показали ролик один раз и хватит.

Вы там свой мод делаете? :smile1:
Вернуться к началу

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

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

Сообщение Rolex » 02 ноя 2020, 07:42

AlexSpl писал(а):

С advevent.txt должно быть аналогично. Завтра поищу адреса текстов.

Да я в курсе. Но нужно именно через плагин.

AlexSpl писал(а):

А вот с роликами неохота разбираться (того не стоит) :smile3: Ролики хорошо смотреть, когда начинаешь прохождение кампаний, и совсем не весело их каждый раз скипать после.

Самое интересное, что в оригинале при первом запуске этот ролик даже скипнуть не дает. То есть нужно хотя бы разок его полностью просмотреть, чтобы в реестр прописался параметр Bink Video, после чего уже можно будет скипать. Как вариант можно паковать ресурсы в инсталятор (Inno Setup, например) и во время установки/распаковки файлов игры прописывать все настройки в реестр, как будто игра уже запускалась на этом компьютере. Ну это относится к оригиналу, ибо мод тянет все настройки с ini-файла. Касательно роликов это так, если будет время и желание. :smile2:

AlexSpl писал(а):

Вы там свой мод делаете? :smile1:

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

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 » 02 ноя 2020, 11:23

advevent.txt:

Код: Выделить всё
#define o_ADVEVENT (*(_TXTEX_**)0x696A68)

struct _TXTEX_ : public _TXT_ {
   inline void SetString(int index, char* str) { *(char**)(*(int*)((int)this + 32) + index * 4) = str; }
};

int __stdcall afterInit(LoHook* h, HookContext* c)
{
    o_ADVEVENT->SetString(171, "{Witch's Hut}\n\nYour text #1 here.");
    o_ADVEVENT->SetString(172, "{Witch's Hut}\n\nYour text #2 here.");
    o_ADVEVENT->SetString(173, "{Witch's Hut}\n\nYour text #3 here.");
    o_ADVEVENT->SetString(190, "{Witch's Hut}\n\nYour text #4 here.");
   
    return EXEC_DEFAULT;
}

...

_PI->WriteLoHook(0x4EE1C1, afterInit);
Вернуться к началу

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

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

Сообщение Rolex » 02 ноя 2020, 11:54

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

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

struct SpecDesc
{
   char* shortName;
   char* fullName;
   char* desc;
} mySpecDesc;

char __stdcall ChangeSpecDesc(HiHook* hook)
{
   char res = CALL_0(char, __cdecl, hook->GetDefaultFunc());

   int heroID[] = { 15, 18, 47, 52, 70, 79, 84, 142, 143 };

   for (int i = 0; i < 9; ++i)
   *(SpecDesc*)(*(int*)0x679C80 + heroID[i] * 40 + 0x1C) = mySpecDesc;

   return res;
}

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

         mySpecDesc.shortName = "+500 зол./день.";
         mySpecDesc.fullName = "Специализация - Золото";
         mySpecDesc.desc = "Увеличивает ежедневный доход королевства на 500 золотых.";
         _PI->WriteHiHook(0x4D7410, SPLICE_, EXTENDED_, CDECL_, ChangeSpecDesc);
         _PI->WriteDword(0x4E4680 + 1, 500);
      }
   }

   return TRUE;
}

Доделал плагин, который меняет доход специалиста по Золоту для всех героев с этой специализацией (таких 9). Но что-то mySpecDesc.fullName не отображается.
Вернуться к началу

Пред.След.

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

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

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