Объявления

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

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

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

Хотфикс. Дело реально оказалось в этом.

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

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

#include "stdafx.h"
#include "..\..\headers\HoMM3API.h"

Patcher* _P;
PatcherInstance* _PI;

void __stdcall forgetSecSkill(HiHook* h, char const* cText, int iMBType, int x, int y,
                              int iResType1, int iResExtra1, int iResType2, int iResExtra2,
                              int iSpecial, int iTimeout, int iResType3, int iResExtra3)
{
   if (iResExtra1 && iMBType == 1)
      iMBType = 2;

   CALL_12(void, __fastcall, h->GetDefaultFunc(), cText, iMBType, x, y,
      iResType1, iResExtra1, iResType2, iResExtra2, iSpecial, iTimeout, iResType3, iResExtra3);

   if (iResExtra1 && pWindowManager->dialogReturn == 0x7806)
   {
      pWindowManager->dialogReturn = 0;

      hero* gpHero = *(hero**)0x698B70;

      if (gpHero)
      {
         int skill = (iResExtra1 - 3) / 3;
         TSkillMastery mastery = (TSkillMastery)((iResExtra1 - 3) % 3 + 1);
         
         --gpHero->SSLevel[skill];

         if (mastery == eMasteryBasic)
         {
            --gpHero->numSSs;
           
            for (int i = 0; i < 28; ++i)
               if (gpHero->SSOrder[i] > gpHero->SSOrder[skill])
                  --gpHero->SSOrder[i];

            gpHero->SSOrder[skill] = 0;
         }

         heroWindow* heroWnd = *(heroWindow**)0x698AC8;

         CALL_1(void, __thiscall, 0x4E1CC0, heroWnd);
         CALL_4(void, __thiscall, *(int*)(*(int*)heroWnd + 0x14), heroWnd, true, -65535, 65535);
      }
   }
}

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

         _PI->WriteHiHook(0x4DE843, CALL_, EXTENDED_, FASTCALL_, forgetSecSkill);
      }
   }
   
   return TRUE;
}

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

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

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5539
Зарегистрирован: 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 ноя 2022, 12:11

Возникла идея перенести механику Морали Героев 6 в Герои 3, но так, чтобы не потерялась оригинальность троечной механики. Напомню, что в Героях 6 бросок Морали выполняется непосредственно перед ходом отряда, т.е. игрок заранее знает, получит ли его отряд повторный ход или нет. Мне в своё время такой подход к проблеме Морали очень понравился, т.к. является золотой серединой между рандомом и планированием. Однако в Героях 6 Мораль сильно обрезали: дальность хода и урон отряда во время повторного хода снижены вдвое. При желании можно тупо скопировать механику Морали из Героев 6, но в Героях 3 все давно привыкли получать полноценный повторный ход, поэтому я написал плагин, который просто ставит игрока в известность анимацией "птички" о том, получит ли отряд повторный ход или нет. Нет "птички" - ничего не жди, была "птичка" - можешь с уверенностью планировать основной и дополнительный ход :smile20:

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

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

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

Patcher* _P;
PatcherInstance* _PI;

#define gpCombatManager (*(combatManager**)0x699420)

class SAMPLE2 {
public:
   //sample *resSample;
   int* resSample;
   //HS AMPLE playSample;
   int* playSample;
};

void debugStrWin(const char* format, ...)
{
   va_list args;
   va_start(args, format);

   vsprintf(o_TextBuffer, format, args);
   ShowMessage(o_TextBuffer);
   
   va_end(args);
}

struct MoraleInfo
{
   bool rolled;
   bool predictionShown;
}
moraleInfo[2][21];

inline SAMPLE2 LoadPlaySample(char const* cSampleName)
{
   return CALL_1(SAMPLE2, __fastcall, 0x59A770, cSampleName);
}

inline void WaitEndSample(SAMPLE2 sample2, int iMilliWait)
{
   CALL_2(void, __fastcall, 0x59A7C0, &sample2, iMilliWait);
}

class army : public _BattleStack_ {
public:

};

class combatManager : public _BattleMgr_ {
public:
   inline void SpellEffect(int effect, ::army* target_army, int iDelay, bool bDoWince)
   {
      CALL_5(void, __thiscall, 0x4963C0, this, effect, target_army, iDelay, bDoWince);
   }
};

void __stdcall resetRound(HiHook* h, army* Army)
{
   CALL_1(void, __thiscall, h->GetDefaultFunc(), Army);
   moraleInfo[Army->side][Army->index_on_side].rolled = false;
   moraleInfo[Army->side][Army->index_on_side].predictionShown = false;
}

void __stdcall onLoadArmies(HiHook* h, combatManager* combatMgr, bool is_surrounded)
{
   CALL_2(void, __thiscall, h->GetDefaultFunc(), combatMgr, is_surrounded);

   for (int side = ATTACKER; side <= DEFENDER; ++side)
      for (int i = 0; i < 21; ++i)
      {
         moraleInfo[side][i].rolled = false;
         moraleInfo[side][i].predictionShown = false;
      }
}

int __stdcall rollMorale(LoHook* h, HookContext* c)
{
   army* Army = (army*)c->edi;
   int Morale = max(-3, min(3, Army->Field<int>(0x4E8)));

   if (!moraleInfo[Army->side][Army->index_on_side].predictionShown && Randint(1, 24) <= Morale)
   {
      SAMPLE2 playSample = LoadPlaySample("GoodMrle.wav");
      gpCombatManager->SpellEffect(20, Army, 100, 0);
      WaitEndSample(playSample, -1);
      moraleInfo[Army->side][Army->index_on_side].rolled = true;
      moraleInfo[Army->side][Army->index_on_side].predictionShown = true;
   }
   
   return EXEC_DEFAULT;
}

int __stdcall processMorale(LoHook* h, HookContext* c)
{
   army* Army = (army*)c->edi;
   
   c->return_address = moraleInfo[Army->side][Army->index_on_side].rolled ? 0x4645C0 : 0x464708;
   moraleInfo[Army->side][Army->index_on_side].rolled = false;

   return NO_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.InstantMorale");

         _PI->WriteHiHook(0x446E40, SPLICE_, EXTENDED_, THISCALL_, resetRound);
         _PI->WriteHiHook(0x4631E0, SPLICE_, EXTENDED_, THISCALL_, onLoadArmies);
         _PI->WriteLoHook(0x464EF2, rollMorale);
         _PI->WriteLoHook(0x4645B3, processMorale);
      }
   }
   
   return TRUE;
}

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

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5539
Зарегистрирован: 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 » 20 дек 2022, 22:55

Решил добавить подтверждение удаления вторичного навыка, чтобы случайно тем же эскейпом не удалить, и заодно проверил удаление навыков из окна героя, когда игрок в него попадает из: а) обзора королевства; б) диалога встречи героев. Если в случае а) навыки в окне обзора королевства обновляются корректно после выхода из окна героя, то в случае б) картинки навыков не обновляются, обновляются только кликабельные области. Интересно, отчего такая разница в поведении и связано ли это как-то с тем, что диалог встречи героев сильно переделан в HD моде?
Вернуться к началу

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

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

Сообщение void_17 » 25 дек 2022, 14:29

@AlexSpl, @RoseKavalier
Скоро сделаю репозиторий API на gitHub, где будет и база и хедеры и все остальное. Вы поможете с заполнением?
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5539
Зарегистрирован: 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 » 25 дек 2022, 14:45

В каком плане? Дальнейший разбор классов? Документация?
Вернуться к началу

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

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

Сообщение void_17 » 25 дек 2022, 15:22

Документация в основном.
Вернуться к началу

offlinegeorg22  
имя: georg
 
Сообщения: 3
Зарегистрирован: 11 сен 2022, 23:28
Пол: Мужчина
Поблагодарили: 0 раз.

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

Сообщение georg22 » 01 янв 2023, 16:24

AlexSpl писал(а):

...
You need to call this function (0x41DAB0) to teleport hero to packedXYZ:

Код: Выделить всё
advManager::TeleportTo(this, hero, packedXYZ, akSpellTraits[SPL_DIMENSION_DOOR].wav_name, 0, 1, 0);

So, basically you hook the function which intercepts keystrokes, write simple interface for XYZ input, and, finally, call the above function. To make things even simpler, hook cheat-codes function and parse new cheat, e.g. nwcteleportmeto0320451. You can shorten "teleportmeto" part though :smile1:


Я работаю над этим уже месяц и не могу добиться никакого прогресса ...

Код: Выделить всё
advManager::TeleportTo(this, hero, packedXYZ, akSpellTraits[SPL_DIMENSION_DOOR].wav_name, 0, 1, 0);

Где вы нашли эту функцию? Я просмотрел весь "HotA/homm3.h" и "H3API.hpp", но нигде не смог найти эту функцию.

AlexSpl писал(а):

So, basically you hook the function which intercepts keystrokes, write simple interface for XYZ input, and, finally, call the above function

Как мне это сделать? Я начал с того, что было дано в этом руководстве viewtopic.php?f=56&t=518, но я не знаю, как проверить нажатие клавиш. Я хотел бы получить координаты от текущей позиции курсора. Можете ли вы дать мне начальный код, который я могу использовать для плагина? Извините, я стараюсь изо всех сил, но я не программист.

Другие функции, которые я хотел бы иметь, и мои вопросы о том, что мне нужно для них (очень долго терять, я извиняюсь)
1a) Удалить объект, на который указывает курсор - как получить позицию курсора, как удалить объект?
1b) Освободить героя из тюрьмы, в которой находится курсор
2a) Добавить / снять 1 очко заклинаний с текущего героя - где хранится количество очков заклинаний?
2b) Добавить 100 очков движения текущему герою - где хранятся очки движения?
3a) мгновенно выиграть битву, открыть всю карту - где найти оригинальные функции чит-кода?
4) позволить текущему городу построить второе здание за день - где хранится информация о том, что здание уже построено?
5) Покрыть всю карту туманом войны - это вообще возможно? Я хочу использовать это для сброса зрения после того, как город с дирижаблем уже был завоеван.
6) Наложить эффект Fly / Waterwalk на текущего героя, или создать городской портал - как вызываются эти функции?
7a) Изменить тип местности / дороги на плитке, на которой находится курсор - здесь лучше всего подойдет то, что вы предложили для "teleportmeto" - например, "changeterrain 20 20 0 dirt cobble".
7b) Наложить магическую местность на данную плитку, например, "terrain 20 20 0 cursedground".
7c) Можно ли изменить владение героем? Например, "changeheroownership 20 20 0 1(red)".
7d) Установить ресурсы игроков на заданную сумму - например, "resources gold 1(red) 10000".

С наилучшими пожеланиями

Переведено с помощью www.DeepL.com/Translator (бесплатная версия) :smile14:
-----------------------

AlexSpl писал(а):

...
You need to call this function (0x41DAB0) to teleport hero to packedXYZ:

Код: Выделить всё
advManager::TeleportTo(this, hero, packedXYZ, akSpellTraits[SPL_DIMENSION_DOOR].wav_name, 0, 1, 0);

So, basically you hook the function which intercepts keystrokes, write simple interface for XYZ input, and, finally, call the above function. To make things even simpler, hook cheat-codes function and parse new cheat, e.g. nwcteleportmeto0320451. You can shorten "teleportmeto" part though :smile1:


I have worked on this on and off for a month and I cannot make any progress ...

Код: Выделить всё
advManager::TeleportTo(this, hero, packedXYZ, akSpellTraits[SPL_DIMENSION_DOOR].wav_name, 0, 1, 0);

Where did you find this function? I looked through all of "HotA/homm3.h" and "H3API.hpp" but I could not find this function anywhere.

AlexSpl писал(а):

So, basically you hook the function which intercepts keystrokes, write simple interface for XYZ input, and, finally, call the above function

How do I do this? I started with what was given in this guide viewtopic.php?f=56&t=518 but I do not know how to check for keyboard presses. I would like to get coordinates from current cursor position. Can you maybe give me a starting code framework that I can use for the plugin? Sorry, I am trying my best, but I am not a programmer.

Other functions I would like to have and my questions on what I need for them (extremely long lost, I apologize)
1a) Delete Object cursor is pointed to - how do I get cursor position, how do I delete an object?
1b) Free hero from prison where cursor is located
2a) Add / remove 1 spell point from current hero - where is the spell point amount stored?
2b) Add 100 movement points to current hero - where is movement points stored?
3a) instantly win battle, uncover whole map - where do I find the original cheat code functions?
4) allow current city to build a second building in a day - where is the information stored if a building has already been built?
5) Cover entire map in fog of war - is this even possible? I want to use this to reset vision after a city with Airship has already been conquered
6) Put Fly / Waterwalk effect on current hero, or cast town portal - how are these functions called?
7a) Change terrain / road type of tile where cursor is on - this one would be best as you suggested for "teleportmeto" -e.g. "changeterrain 20 20 0 dirt cobble"
7b) Put magical terrain on a given tile, e.g. "terrain 20 20 0 cursedground"
7c) Is it possible to change hero ownership? e.g. "changeheroownership 20 20 0 1(red)"
7d) Set players resources to given amount - e.g. "resources gold 1(red) 10000"

Best wishes
Вернуться к началу

offlineАватара пользователя
AlexSpl  
имя: Александр
Эксперт
Эксперт
 
Сообщения: 5539
Зарегистрирован: 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 янв 2023, 17:22

Всё возможно :smile2: Но это очень длинный список пожеланий для реализации. К сожалению, я сейчас работаю над одним проектом по King's Bounty, поэтому смогу ответить после того, как закончу.
Вернуться к началу

offlinegeorg22  
имя: georg
 
Сообщения: 3
Зарегистрирован: 11 сен 2022, 23:28
Пол: Мужчина
Поблагодарили: 0 раз.

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

Сообщение georg22 » 02 янв 2023, 20:29

Спасибо! Я буду продолжать попытки. :)
Вернуться к началу

offlinevovacyxov  
имя: Влaдимир
 
Сообщения: 9
Зарегистрирован: 08 ноя 2022, 12:30
Пол: Мужчина
Поблагодарили: 3 раз.

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

Сообщение vovacyxov » 09 янв 2023, 12:32

Всех с прошедшими праздниками, я тут опять со своими наркоманскими идеями..... есть у меня карта любимая, (Прекрасный новый мир) вот и как бы так сделать или может кто сможет сделать чтоб одна и та же карта была на двух уровнях, а я уже сам ее чуток подредактирую.. я нигде не нашел нужного инструмента, на всякий случай отправлю сюда файл карты. Извените что не по теме...
И еще вопрос к знатокам, в редакторе карт когда нажимаю к примеру на любой ресурс( при выборе с права в программе) вылетает ошибка Failed to Launch Help , я даже героев решил переустановить, не помогло.... может кто сталкивался с этим)
Вложения
Brave New World.rar
(41.28 КБ) Скачиваний: 45
Вернуться к началу

Пред.След.

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

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

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