Объявления

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

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

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

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

Сообщение Rolex » 14 ноя 2020, 09:16

AlexSpl, а Вы не могли бы немного "проапгрейдить" ваш код Палатки с массхилом, согласно этому сообщению:

Rolex писал(а):

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

А потому предлагаю сделать для всех живых существ, то есть кроме нежити (включая нейтралов Мумий) и бездушных существ (големы (включая Золотых и Алмазных), горгульи, элементали и боевые машины), следующим образом:

Базовый уровень Первой Помощи: +5% от макс здоровья для всех живых существ, но не ниже 1.
Продвинутый уровень Первой Помощи: +10% от макс здоровья для всех живых существ, но не ниже 2.
Экспертный уровень Первой Помощи: +15% от макс здоровья для всех живых существ, но не ниже 3.

Сможете добавить это в ваш код выше? Можно будет потом как еще один альтернативный плагин выложить в готовых (как с Неудачей).


UPD: Как вариант можно упростить, сделав прибавку всем отрядам героя без исключения (включая неживых и боевые машины).
Последний раз редактировалось Rolex 17 ноя 2020, 12:48, всего редактировалось 2 раз(а).
Вернуться к началу

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

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

Сообщение Rolex » 17 ноя 2020, 10:36

AlexSpl, помогите, пожалуйста, отыскать адрес на доп хук на 39 строку из GENRLTXT.TXT для стреляющих отрядов у которых в запасе остался 1 выстрел.

Код: Выделить всё
_PI->WriteLoHook(0x493053, getLosses); // расчет урона и кол-ва убитых при атаке
_PI->WriteLoHook(0x492619, showLosses); // 38 строка в GENRLTXT.TXT - для обычной атаки
_PI->WriteLoHook(0xADRESS, showLosses); // 39 строка в GENRLTXT.TXT для стрелков у которых в запасе остался 1 выстрел
_PI->WriteLoHook(0x492848, showLosses); // 298 строке - для стрелковой атаки


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

        using namespace std;

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

        int MinDamage, MaxDamage, MinKilled, MaxKilled, FullHealth, shotsLeft, countCurrent;
        string nameSingle, namePlural;
        bool IsMelee;

        int __stdcall getLosses(LoHook* h, HookContext* c)
        {
           int DamageKt = 1;

           _BattleStack_* foeStack = *(_BattleStack_**)(c->ebp + 8);
           _BattleStack_* curStack = o_BattleMgr->GetCurrentStack();
           
           int foeStackID = foeStack->creature_id;
           int curStackID = curStack->creature_id;

           nameSingle = o_pCreatureInfo[foeStackID].name_single;
           namePlural = o_pCreatureInfo[foeStackID].name_plural;
           
           shotsLeft = curStack->creature.shots;
           countCurrent = foeStack->count_current;


           IsMelee = (*(int*)o_BattleMgr->Offset(0x132DC) == 7);

           // Проверка оставшегося кол-ва выстрелов. Удваивание урона для марксменов, грандов и баллисты только при наличии у них в запасе не менее 2-х выстрелов.
           if (shotsLeft > 1) {
              if ((curStackID == CID_MARKSMAN || curStackID == CID_GRAND_ELF) && (!IsMelee))
                 DamageKt = 2;

              _Hero_* CurHero = o_BattleMgr->hero[o_BattleMgr->current_side];
              if (CurHero && curStackID == CID_BALLISTA) {
                 int ARTI_Level = *(char*)((int)CurHero + 201 + 20);
                 // int ARTI_Level = CurHero->second_skill[HSS_ARTILLERY];
                 if (ARTI_Level == 2) DamageKt = 2;
                 else if (ARTI_Level == 3) DamageKt = 4;
              }
           }
             
           MinDamage = DamageKt * c->edi;
           MaxDamage = DamageKt * c->eax;
           
           MinKilled = MinDamage / foeStack->full_hp;
           if (MinDamage % foeStack->full_hp >= foeStack->full_hp - foeStack->lost_hp) ++MinKilled;
           if (MinKilled > foeStack->count_current) MinKilled = foeStack->count_current;

           MaxKilled = MaxDamage / foeStack->full_hp;
           if (MaxDamage % foeStack->full_hp >= foeStack->full_hp - foeStack->lost_hp) ++MaxKilled;
           if (MaxKilled > foeStack->count_current) MaxKilled = foeStack->count_current;

           return EXEC_DEFAULT;
        }

        int __stdcall showLosses(LoHook* h, HookContext* c)
        {
           string Buffer = o_TextBuffer;
           string NewBuffer, Name;

           // получаем имя вряжеского стека (если текущее кол-во юнитов в стеке больше 1, то в множественном числе, иначе в единственном числе).
           if (countCurrent > 1) Name = namePlural; else Name = nameSingle;

           // проверяем родной буфер на вхождение "damage", если оно есть, то формируем строку на англ языке, иначе на рус.
           if (Buffer.find("damage") != -1) {
              // Если у текущего отряда героя есть выстрелы, а также его атака не рукопашная, то есть в соседствующих гексах нет вражеского отряда, то формируем строку для стреляющего отряда, иначе для обычного (англ версия).
              if (shotsLeft > 0 && !IsMelee) NewBuffer = "Shoot " + Name + " (shots left: " + to_string(shotsLeft) + ", damage: "; else
                             NewBuffer = "Attack " + Name + " (damage: ";
           }
           else {
              // Если у текущего отряда героя есть выстрелы, а также его атака не рукопашная, то есть в соседствующих гексах нет вражеского отряда, то формируем строку для стреляющего отряда, иначе для обычного (рус версия).
              if (shotsLeft > 0 && !IsMelee) NewBuffer = "Выстрелить в отряд " + Name + " (осталось выстрелов: " + to_string(shotsLeft) + ", урон: "; else
                             NewBuffer = "Атаковать отряд " + Name + " (урон: ";
           }
           
           // если мин урон равен макс (под Благословением, например), то добавляем к нашей строке только один, иначе оба.
           if (MinDamage == MaxDamage) NewBuffer.append(to_string(MaxDamage)); else
                                NewBuffer.append(to_string(MinDamage) + '-' + to_string(MaxDamage));

           // переганяем стринг в массив чаров для корректного вывода.
           char* NewBufferWrite = new char[NewBuffer.size() + 1];
           strcpy(NewBufferWrite, NewBuffer.c_str());

           if (Buffer.find("damage") != -1) {
              if (MinKilled == MaxKilled) sprintf(o_TextBuffer, "%s, kills: %d)", NewBufferWrite, MaxKilled); else
                                   sprintf(o_TextBuffer, "%s, kills: %d-%d)", NewBufferWrite, MinKilled, MaxKilled);
           }
           else {
              if (MinKilled == MaxKilled) sprintf(o_TextBuffer, "%s, убьет: %d)", NewBufferWrite, MaxKilled); else
                                   sprintf(o_TextBuffer, "%s, убьет: %d-%d)", NewBufferWrite, MinKilled, MaxKilled);
           }

           return EXEC_DEFAULT;
        }



        // запрет на второй выстрел для баллисты и стрелков, если боезапас закончился (после первого выстрела в запасе 0)
        int __stdcall Y_monstreShoot(LoHook* h, HookContext* c)
        {
           _BattleStack_* mon = (_BattleStack_*)c->esi;

           if (mon->creature.shots < 1) {
              c->return_address = 0x43FFFC;
              return NO_EXEC_DEFAULT;
           }

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

                 // второй выстрел марксменами и грандами
                 _PI->WriteLoHook(0x43FF92, Y_monstreShoot);

                 // второй выстрел баллистой
                 _PI->WriteLoHook(0x43FFF4, Y_monstreShoot);

                 _PI->WriteLoHook(0x493053, getLosses);
                 _PI->WriteLoHook(0x492619, showLosses);
                 _PI->WriteLoHook(0x492848, showLosses);
              }
           }

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

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

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

Сообщение AlexSpl » 17 ноя 2020, 13:42

Цитата:
AlexSpl, помогите, пожалуйста, отыскать адрес на доп хук на 39 строку из GENRLTXT.TXT для стреляющих отрядов у которых в запасе остался 1 выстрел.

0x4927B8

Цитата:
AlexSpl, а Вы не могли бы немного "проапгрейдить" ваш код Палатки с массхилом

У Вас есть структура отряда. Попробуйте умножать полное здоровье на Ваши коэффициенты (_int32_ full_hp; // +108 0x6C полное здоровье (исп. как база для лечения)). Может, придётся умножать ещё и creature.hit_points, если это поле используется. Наличие палатки Вы знаете, как проверять. А вот как проверить, идёт ли бой в банке:

Код: Выделить всё
// проверка что бой в банке существ
if ( *(char*)(*(int*)0x699420 + 0x53C5) == 1 ) { ... }

или - проще -

Код: Выделить всё
// проверка что бой в банке существ
if ( o_BattleMgr->Field<char>(0x53C5) == 1 ) { ... }


Осталось только найти место для лоухука. Этим местом может быть старт боя (сразу после инициализации экземпляров структур _BattleStack_ отрядов). Хуки на начало битвы я точно встречал. Посмотрите хотя бы те плагины, которые добавляют +1, +2, +3 к здоровью.

Ещё посмотрите вот этот мод: https://forum.df2.ru/index.php?showtopic=36605&st=0&start=0

* * *
Да, вот это:

Цитата:
А потому предлагаю сделать для всех живых существ, то есть кроме нежити (включая нейтралов Мумий) и бездушных существ (големы (включая Золотых и Алмазных), горгульи, элементали и боевые машины), следующим образом:

проверяется с помощью флагов: creature.flags. Посмотрите примеры плагинов, где работают с флагами, а также HoMM3_ids.h:

Код: Выделить всё
// battle creatures flags
#define BCF_2HEX_WIDE  0x00000001 // - занимает 2 клетки
#define BCF_CAN_FLY   0x00000002 // летает
#define BCF_CAN_SHOOT  0x00000004 // стреляет
#define BCF_2HEX_ATTACK  0x00000008 // расширенный радиус атаки (на две клетки)
#define BCF_ALIVE   0x00000010 // живое существо (можно восстанавливаться вампиру)
#define BCF_CAN_ATTACK_WALL 0x00000020 // - может разрушать стены
#define BCF_CANT_MOVE  0x00000040 // осадное оружие - не двигается (5508CB)
#define BCF_KING_1   0x00000080 // KING_1
#define BCF_KING_2   0x00000100 // KING_2
#define BCF_KING_3   0x00000200 // KING_3
    // 00000400 - 0x0A ??? 00020000 + 40,41,83 - не чуствителен к псих атаке
    // 00000800 - 0x0B нет описания (35,74,75)
    // 00001000 - 0x0C в ближнем бою бьет как в дальнем
    // 00002000 - 0x0D ----
    // 00004000 - 0x0E ??? IMMUNE_TO_FIRE_SPELLS
#define BCF_ATTACK_TWICE  0x00008000 // атакует дважды
    // 00010000 - 0x10 атака без ответа
    // 00020000 - 0x11 ... не подвержен низкой морали (?)
    // 32,33,56-69,112-117,120,121,123,,125,127,129,141,145-149
#define BCF_UNDEAD   0x00040000 // нежить
    // 00080000 - 0x13 бьет всех врагов рядом
    // 00100000 - 0x14 расширенный радиус стреляющих юнитов
    // 00200000 - 0x15 стэк убит? 41E617 чародей,firebird - может еще кастовать?
    // 00400000 - 0x16 421BDC,421FC4 (что-то с вызовом)
#define BCF_CLONE   0x00800000 // копия стэку - умирает сразу
    // 01000000 - 0x18 гарпии-ведьмы
    // 02000000 - 0x19 остался(уже) ждать СБРОСИТЬ - МОЖЕТ ЖДАТЬ СНОВА
    // 04000000 - 0x1A уст. после атаки СБРОСИТЬ - ВНОВЬ МОЖЕТ ОТАКОВАТЬ
    // 08000000 - 0x1B - выбрал защиту
    // 10000000 - 0x1C - не может быть ресуректен ???
    // 20000000 - 0x1D + 43DFAF
    // 40000000 - 0x1E + 43E06F
    // 80000000 - 0x1F дракон

По флагам есть инфа также в гайде от BTB и в ERM help:

 
Цитата:
0x00000001 = 1 - DOUBLE_WIDE - Takes 2 square

0x00000002 = 2 - fly

0x00000004 = 4 - shooter
If you give this ability to a non-shooter, you get several error messages along the lines of "missing
resource." Presumably the graphic showing it shooting.

0x00000008 = 8 - extended attack radius (2 square)
That is, a breath weapon (depth not radius). This doesn't function when using a range ability, but works for a
ranged unit when it hits an adjacent unit.

0x00000010 = 16 - alive

0x00000020 = 32 - CATAPULT
Cyclopes have this ability.

0x00000040 = 64 - SIEGE WEAPON - cannot move

0x00000080 = 128 - KING_1
This is all 7th level creatures and neutral dragons that aren't KING_2 or KING_3.

0x00000100 = 256 - KING_2
Angels, Archangels, Devils, Archdevils.

0x00000200 = 512 - KING_3
Giants, Titans

0x00000400 = 1024 - immune to mind spell

0x00000800 = 2048 - monster: 35,74,75
This means "no obstacle penalty," since Archmages have that ability and Mages don't.
This one seems a bit mystifying. 74 and 75 are Beholders and Evil Eyes and I don't recall them ever having a "no obstacle penalty" ability.

0x00001000 = 4096 - no penalty in close combat

0x00002000 = 8192 - ----

0x00004000 = 16384 - IMMUNE_TO_FIRE_SPELLS

0x00008000 = 32768 - shoot twice
This also makes a non-range unit attack twice - Crusader, Wolf-Raider

0x00010000 = 65536 - no enemy retaliation
The Cerberus has this ability (in addition to Hydra etc.) However if you give a unit this ability, it will attack in all directions, not just forwards like the Cerberus. Also, you can have this ability but still allow retaliation; then the creature actually attacked will retaliate (the others won't).

0x00020000 = 131072 - no moral penalty

0x00040000 = 262144 - undead

0x00080000 = 524288 - attack all enemies around

0x00100000 = 1048576 - extended radius of shooters
This is the Magog/Lich/Power Lich ability. You don't appear to be able to give a creature this ability. I assume since Magogs and Liches work differently, the program must check creature number.

0x80000000 - 2147483648 - Dragon
This one screws you up in ERM because the same bit is used for signs. You can still use it though if you work out what the correct large negative number is. I assume all it affects is the Vial Of Dragon Blood.
And this is used also for "Dragons" Hero's specialty (Mutare).
Вернуться к началу

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

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

Сообщение Rolex » 18 ноя 2020, 15:04

Код: Выделить всё
int __stdcall increaseCreatureHealth(LoHook* h, HookContext* c)
{
   _Hero_* hero = o_BattleMgr->hero[o_BattleMgr->current_side];

   if (hero && hero->second_skill[HSS_FIRST_AID])
   {
      for (int i = 0; i < o_BattleMgr->stacks_count[o_BattleMgr->current_side]; ++i)
      {
         _BattleStack_* stack = &o_BattleMgr->stack[o_BattleMgr->current_side][i];

         switch (hero->second_skill[HSS_FIRST_AID]) {
         case 1: stack->full_hp = (int)(stack->full_hp * 1.05); break;
         case 2: stack->full_hp = (int)(stack->full_hp * 1.10); break;
         case 3: stack->full_hp = (int)(stack->full_hp * 1.15); break;
         }         
      }
   }
      return EXEC_DEFAULT;
}
...
_PI->WriteLoHook(0x478552, increaseCreatureHealth);


Пока делаю упрощенно для всех.

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

Перед return EXEC_DEFAULT; должно видимо быть что-то вроде
c->return_address = АДРЕС
return NO_EXEC_DEFAULT;


Да и за адрес лоухука не уверен, я взял его из setFirstAidShield из ДжебусМода.

И с регистрами процессора пока не все понятно, их нужно ипользовать в самом лоухуке.

Цитата:
Регистры EAX, EBX, ECX, EDX – это регистры общего назначения. Они имеют определённое назначение (так уж сложилось исторически), однако в них можно хранить любую информацию.

Регистры EBP, ESP, ESI, EDI – это также регистры общего назначения. Они имеют уже более конкретное назначение. В них также можно хранить пользовательские данные, но делать это нужно уже более осторожно, чтобы не получить «неожиданный» результат.


А как определить где и какой именнно регистр нужно/можно использовать?

И по сути нам нужно же не только во время боя увеличивать здоровье отрядов, а везде, как с Эликсиром жизни. То есть и в городе при просмотре отряда героя с навыком ПП по ПКМ и в окне героя, оно уже должно быть увеличено в соотв с тем, насколько развит навык ПП. Плюс нужно же сделать так, чтобы это работало не только для героев игрока-человека, а и для героев ИИ.
Последний раз редактировалось Rolex 18 ноя 2020, 21:42, всего редактировалось 2 раз(а).
Вернуться к началу

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

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

Сообщение AlexSpl » 18 ноя 2020, 16:20

Цитата:
И по сути нам нужно же не только во время боя увеличивать здоровье отрядов, а везде, как с Эликсиром жизни. То есть и в городе при просмотре отряда героя с навыком ПП по ПКМ и в окне героя, оно уже должно быть увеличено в соотв с тем, насколько развит навык ПП. Плюс нужно же сделать так, чтобы это работало не только для героев игрока-человека, а и для героев ИИ.

Не хватайтесь за всё сразу. Сделайте что-то одно, но чтобы работало.

Цитата:
Что-то в этом роде должно быть. Но, увы, я, к сожалению, пока еще не понимаю многих вещей.

Вынесите return EXEC_DEFAULT за if { ... } (код по умолчанию мы не трогаем).

Цитата:
Да и за адрес лоухука не уверен, я взял его из setFirstAidShield из ДжебусМода.

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

И общий совет: экспериментируйте :smile2:
Вернуться к началу

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

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

Сообщение Rolex » 18 ноя 2020, 19:11

AlexSpl писал(а):

Не хватайтесь за всё сразу. Сделайте что-то одно, но чтобы работало.

Без вашей помощи, я вообще мало что могу сделать. По большей части так только собрать и потестить.

AlexSpl писал(а):

Вынесите return EXEC_DEFAULT за if { ... } (код по умолчанию мы не трогаем).

За это я в курсе (исправил). Но все равно код не рабочий.

AlexSpl писал(а):

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

Без знаний реверса я сам вряд ли его отыщу. Буду конечно потихоньку разбираться как будет больше времени. Был где-то код (здесь не встречал, вроде от RoseKavalier, во FreshMod есть, вкл по флагу), который добавляет всем живым существам армии +1, +2, +3 к здоровью. Вот бы его отыскать, его бы я может и сумел переделать под то, что нужно мне.
Вернуться к началу

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

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

Сообщение igrik » 27 ноя 2020, 06:19

Rolex писал(а):

Буду конечно потихоньку разбираться как будет больше времени. Был где-то код (здесь не встречал, вроде от RoseKavalier, во FreshMod есть, вкл по флагу), который добавляет всем живым существам армии +1, +2, +3 к здоровью. Вот бы его отыскать, его бы я может и сумел переделать под то, что нужно мне.


Через хайхук вообще всё очень даже просто.
И тут можно реализовать совершенно всё что вздумается из того что есть в структуре _CreatureInfo_ (например двойной удар :smile6: )

Код: Выделить всё
// реализуем HiHook на функцию выдачи бонусов монстрам героя
int __stdcall Y_Hero_SetCreatureBonuses(HiHook* hook, _Hero_ * hero, int monID, _CreatureInfo_* mon)
{
    // выполняем оригинальную функцию игры
    int result = CALL_3(int, __thiscall, hook->GetDefaultFunc(), hero, monID, mon);

    // теперь реализуем свой код: если герой имеет втор.навык Первая помощь
    if ( hero->second_skill[HSS_FIRST_AID] )
    {
        // бонус hp будет = 25 * уровень Первой Помощи
        int bonus = 25 * hero->second_skill[HSS_FIRST_AID];
        mon->hit_points += bonus;
    }

    return result;
}
// ставим HiHook на функцию выдачи бонусов монстрам героя
_PI->WriteHiHook(0x4E6390, SPLICE_, EXTENDED_, THISCALL_, Y_Hero_SetCreatureBonuses);
Вернуться к началу

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

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

Сообщение Rolex » 27 ноя 2020, 08:10

Спасибо. Все работает. Переписал пару строчек, чтобы получить то, что нужно было мне. Правда, чтобы все корректно заработало на VS 2015 структуру _CreatureInfo_ пришлось также обернуть в #pragma pack(push, 1) ... #pragma pack(pop).

Код: Выделить всё
// бонус hp будет = (5% * уровень Первой Помощи) от макс здоровья монстра
int bonus = 5 * hero->second_skill[HSS_FIRST_AID] * mon->hit_points / 100;
// if (monID != CID_FIRST_AID_TENT)
mon->hit_points += max(bonus, hero->second_skill[HSS_FIRST_AID]);
Вернуться к началу

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

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

Сообщение Rolex » 27 ноя 2020, 20:34

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

Суть в том, чтобы добавить в окне повышения уровня героя кнопку отказа от получения вторичного навыка (навык не добавляется), если ни то, ни другое, по каким-то причинам не подходит игроку и он не хочет засорять свободный слот этим навыком.

То есть нужно с другой стороны напротив кнопки подтверждения добавить кнопку отказа от изучения вторичного навыка (как с переигровкой битвы в HD-моде).

 Примерно так:
Изображение Изображение

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

Например, начиная где-то с 24 урвоня, когда у героя уже заняты все слоты под навыки, и все навыки развиты на Эксперте и дальше повышается только первичный навык.
Когда до этого дойдет с кнопкой отмены, то уровень героя вероятно будет повыше, в таком случае эту кнопку можно просто не выводить/скрывать/делать неактивной. Хотя... самый простой и в то же время лучший вараинт, это, наверное, сделать так, чтобы кнопка отмены была активной только в тех случаях, когда герою для изучения предлагаються два абсолютно новых навыка (базового уровня), которых у него еще нет (или когда остался один свободный слот и предлагается один навык базового уровня), во всех остальных случаях делать ее просто неактивной.

PS: Плагины с кнопкой отмены от изучения вторичного навыка у Ученого и в Хижине ведьмы есть даже в теме с готовыми плагинами от RoseKavalier в конце первой страницы, а вот подобного пока не встречал.
Вернуться к началу

offlinearonir  
имя: aronir
 
Сообщения: 3
Зарегистрирован: 07 янв 2021, 19:21
Пол: Мужчина
Поблагодарили: 0 раз.

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

Сообщение aronir » 07 янв 2021, 19:55

Здравствуйте.
Нужен плагин для Sod, чтобы накапливались жители во внешних жилищах, если оно захвачено игроком, а если нейтральное, то не накапливались.
Сразу скажу, что я не программист и далек от этого, но Visual C++ 2008 поставил из начала темы и даже получилось скомпилировать dll, где накопление существ происходит, но они копятся, как в нейтральных жилищах, так и в принадлежащих игроку. Все это делалось по рекомендации от сюда viewtopic.php?f=39&t=391&start=190#p19794.
Собственно код, который писал Ben80 для накопления существ, только в принадлежащих игроку жилищах не компилируется, т.е. этот:
Код: Выделить всё
int __stdcall growthAccumulation(LoHook* h, HookContext* c)
{
   _Dwelling_* dw = (_Dwelling_*)(*(int*)(c->ebp - 8) - 28);

   if(dw->owner_ix >= 0)
   {
      *(_word_*)c->edi = *(_word_*)c->edi + (_word_)c->ecx;
      c->eax = *(int*)c->esi;
      return NO_EXEC_DEFAULT;
   }

   return EXEC_DEFAULT;
}
...
_PI->WriteLoHook(0x4B87A0, growthAccumulation);


Вот, что у меня в файле dllmain.cpp:
Код: Выделить всё
// Раскомментируйте строчку ниже, если у Вас Microsoft Visual Studio 2017 или новее
// #include "pch.h"

// Раскомментируйте строчку ниже, если у Вас более старая версия Microsoft Visual Studio
#include "stdafx.h"

#include "patcher_x86.hpp"

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

int __stdcall growthAccumulation(LoHook* h, HookContext* c)
{
   _Dwelling_* dw = (_Dwelling_*)(*(int*)(c->ebp - 8) - 28);

   if(dw->owner_ix >= 0)
   {
      *(_word_*)c->edi = *(_word_*)c->edi + (_word_)c->ecx;
      c->eax = *(int*)c->esi;
      return NO_EXEC_DEFAULT;
   }

   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((char*)"HD.Plugin.TestPlugin");
            _PI->WriteLoHook(0x4B87A0, growthAccumulation);
        }
    }

    return TRUE;
}


Вот какие ошибки:
 
Compiling...
dllmain.cpp
c:\users\вырезано-цензурой\documents\visual studio 2008\projects\nakoplenie\nakoplenie\patcher_x86.hpp(751) : warning C4010: single-line comment contains line-continuation character
c:\users\вырезано-цензурой\documents\visual studio 2008\projects\nakoplenie\nakoplenie\patcher_x86.hpp(752) : warning C4010: single-line comment contains line-continuation character
.\dllmain.cpp(15) : error C2065: '_Dwelling_' : undeclared identifier
.\dllmain.cpp(15) : error C2065: 'dw' : undeclared identifier
.\dllmain.cpp(15) : error C2065: '_Dwelling_' : undeclared identifier
.\dllmain.cpp(15) : error C2059: syntax error : ')'
.\dllmain.cpp(17) : error C2065: 'dw' : undeclared identifier
.\dllmain.cpp(17) : error C2227: left of '->owner_ix' must point to class/struct/union/generic type
type is ''unknown-type''

Это я так понимаю, не заданы какие то переменные.
Возможно уже есть готовый плагин, то прошу дать ссыль.
Надоело уже по жилищам каждую неделю бегать, в ХОТе с этим проще(
Вернуться к началу

Пред.След.

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

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

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

cron