Объявления

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

Цитата:
Здесь видимо придется еще одно условие добавить:

Лишнее.

Код: Выделить всё
int __stdcall mirthMoraleBonus(LoHook* h, HookContext* c)
{
   int cmAddr = *(int*)0x699420;
   int monSide = *(int*)(c->edi + 244);
   int heroOffset = *(int*)(cmAddr + monSide * 4 + 0x53CC);

   char lvlWaterMagic = heroOffset ? *(char*)(heroOffset + 201 + 16) : 0;
     
   if ( *(int*)(c->edi + 408 + 49 * 4) )
   {
      int k[] = {4, 5, 6, 8};
      unsigned int dice;
      rand_s(&dice);
      dice = (unsigned int)((double)dice / ((double)UINT_MAX + 1) * 96.0) + 1;
      c->flags.ZF = (int)dice <= k[lvlWaterMagic] * *(int*)c->ebx ? 1 : 0;
   }
   
   return EXEC_DEFAULT;
}


dice - положительное число, поэтому заведомо больше любого отрицательного.
Вернуться к началу

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 » 16 авг 2017, 05:43

Если Вы про вероятность выпадения отрицательной Морали, то решение о её выпадении принимается совсем в другом месте кода, а именно здесь: 46479Dh. Заметьте ещё, что вероятность выпадения отрицательной Морали вдвое больше, чем положительной, при равных абсолютных значениях (-M * 1/12). Кроме того, если посмотреть код, можно убедиться в том, что для отрядов ИИ она меньше, чем для отрядов игрока-человека: -M * 1/12 * 3/4.
Вернуться к началу

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

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

Сообщение Ben80 » 16 авг 2017, 17:42

Для Удачи у меня вот что получилось:
(позднее откомпилирую и проверю)

Код: Выделить всё
int __stdcall fortuneSpell(LoHook* h, HookContext* c)
{
   c->edi = 1;
   return EXEC_DEFAULT;
}

int __stdcall fortuneLuckBonusShoot(LoHook* h, HookContext* c)
{
   int cmAddr = *(int*)0x699420; // Получаем адрес Combat Manager
   int monSide = *(int*)(c->edi + 244); // Получаем сторону, на которой сражается монстр
   int heroOffset = *(int*)(cmAddr + monSide * 4 + 0x53CC); // Получаем адрес героя, наложившего Fortune

   if ( !heroOffset ) return EXEC_DEFAULT;
   
   int heroId = *(int*)(heroOffset + 26);
   char lvlAirMagic = *(char*)(heroOffset + 201 + 15);

   if ( *(int*)(c->edi + 408 + 51 * 4) && lvlAirMagic ) // Если "висит" Fortune (#51) и у героя есть Air Magic
   {
      int k[] = {5, 6, 8}; // 5/96 = 1/24 * 1.25 (Basic), 6/96 = 1/24 * 1.50 (Advanced), 8/96 = 1/24 * 2.00 (Expert)
     int km[] = {6, 7, 9}; // для героя Мелодия
     int shanse;
      unsigned int dice;
      rand_s(&dice); // Пользуемся rand_s, чтобы не "сломать" ГПСЧ игры
      dice = (unsigned int)((double)dice / ((double)UINT_MAX + 1) * 96.0) + 1; // Случайное целое из диапазона [1, 96]

     // Проверяем не Мелодия ли наш Герой
     if(heroId == 29)
        shance = km[lvlAirMagic - 1];
     else
        shanse = k[lvlAirMagic - 1];
    
      if ( (int)dice <= shanse * *(int*)c->edi ) // *(int*)c->edi - Удача отряда (-3..3)
         c->return_address = 0x43F67E;
       else
         c->return_address = 0x43F6F6;
        return NO_EXEC_DEFAULT;
   }
   
   return EXEC_DEFAULT;
}


int __stdcall fortuneLuckBonusStrike(LoHook* h, HookContext* c)
{
   int cmAddr = *(int*)0x699420; // Получаем адрес Combat Manager
   int monSide = *(int*)(c->edi + 244); // Получаем сторону, на которой сражается монстр
   int heroOffset = *(int*)(cmAddr + monSide * 4 + 0x53CC); // Получаем адрес героя, наложившего Fortune

   if ( !heroOffset ) return EXEC_DEFAULT;
   
   int heroId = *(int*)(heroOffset + 26);
   char lvlAirMagic = *(char*)(heroOffset + 201 + 15);

   if ( *(int*)(c->edi + 408 + 51 * 4) && lvlAirMagic ) // Если "висит" Fortune (#51) и у героя есть Air Magic
   {
      int k[] = {5, 6, 8}; // 5/96 = 1/24 * 1.25 (Basic), 6/96 = 1/24 * 1.50 (Advanced), 8/96 = 1/24 * 2.00 (Expert)
     int km[] = {6, 7, 9}; // для героя Мелодия
     int shanse;
      unsigned int dice;
      rand_s(&dice); // Пользуемся rand_s, чтобы не "сломать" ГПСЧ игры
      dice = (unsigned int)((double)dice / ((double)UINT_MAX + 1) * 96.0) + 1; // Случайное целое из диапазона [1, 96]

     // Проверяем не Мелодия ли наш Герой
     if(heroId == 29)
        shance = km[lvlAirMagic - 1];
     else
        shanse = k[lvlAirMagic - 1];
    
      if ( (int)dice <= shanse * *(int*)c->edi ) // *(int*)c->edi - Удача отряда (-3..3)
         c->return_address = 0x441560;
       else
         c->return_address = 0x4415D8;
        return NO_EXEC_DEFAULT;
   }
   
   return EXEC_DEFAULT;
}

_PI->WriteLoHook(0x444980, fortuneSpell);
_PI->WriteLoHook(0x43F66B, fortuneLuckBonusShoot);
_PI->WriteLoHook(0x44154D, fortuneLuckBonusStrike);
_PI->WriteHexPatch(0x44497D, "90 90 90");
_PI->WriteHexPatch(0x444986, "90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90");

Последний раз редактировалось Ben80 16 авг 2017, 19:04, всего редактировалось 1 раз.
Вернуться к началу

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

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

Сообщение Ben80 » 16 авг 2017, 17:49

По поводу заклинания Mirth такое еще уточнение - может хук ставить чуть раньше, не на 4645BA, а на 4645A9 ?
А то в 4645B8 флаг устанавливается (или не устанавливается), не скажется ли это в дальнейшем на ходе программы ?

И такой вопрос - как сделать продолжительность для Ослепления в зависимости не от Колдовской силы, а от уровня магии Огня ? Для основного 1, продвинутого 3, эксперта 5 раундов.
Вернуться к началу

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 » 17 авг 2017, 05:11

Можно было и не забивать nop-ами (так Вы убираете эффект специализации героев Мелодия и Даремиф, как я понял). LoHook на 44497Dh:

Код: Выделить всё
int __stdcall fortuneSpell(LoHook* h, HookContext* c)
{
    *(int*)(c->esi + 0x484) = 1;
    c->return_address = 0x444D5C;
    return NO_EXEC_DEFAULT;
}


В хуке fortuneLuckBonusStrike Удача *(int*)c->ebx, а не *(int*)c->edi. Кстати, функции fortuneLuckBonusShoot и fortuneLuckBonusStrike можно объединить в одну.

Цитата:
По поводу заклинания Mirth такое еще уточнение - может хук ставить чуть раньше, не на 4645BA, а на 4645A9 ?
А то в 4645B8 флаг устанавливается (или не устанавливается), не скажется ли это в дальнейшем на ходе программы ?

Флаги устанавливает команда сравнения (cmp) вышe. В общем случае значение флага могут использовать несколько инструкций, но в данном случае значение флага ZF используется только джампом jg ниже. Если хук поставить раньше, до броска кости (call sub_50C7C0), то будет нарушена оригинальная последовательность псевдослучайных чисел (например, некоторые случайные события с плагином и без него будут разными). Это также касается Ваших хуков на Удачу. Вы пропускаете оригинальные броски кости.

* * *

Цитата:
И такой вопрос - как сделать продолжительность для Ослепления в зависимости не от Колдовской силы, а от уровня магии Огня ? Для основного 1, продвинутого 3, эксперта 5 раундов.


Например, так:
Код: Выделить всё
int __stdcall blindSpell(LoHook* h, HookContext* c)
{
   if ( c->ebx == 62 )
   {
      int cmAddr = *(int*)0x699420;
      int monSide = *(int*)(c->esi + 244);
      int heroOffset = *(int*)(cmAddr + (1 - monSide) * 4 + 0x53CC); // Адрес вражеского героя

      int duration[] = {1, 1, 3, 5};

      if ( heroOffset ) c->eax = duration[*(char*)(heroOffset + 201 + 14)];
   }

   return EXEC_DEFAULT;
}

...

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

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

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

Сообщение Ben80 » 17 авг 2017, 08:22

А как Вы вообще ориентируетесь в структуре CombatManager'а ?

"int heroOffset = *(int*)(cmAddr + (1 - monSide) * 4 + 0x53CC)"

53CC особо интересует :smile1:

В заголовочных файлах вроде не находил структуру CombatManager'а...
Вернуться к началу

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 » 17 авг 2017, 08:37

Цитата:
А как Вы вообще ориентируетесь в структуре CombatManager'а ?

В homm3.h она называется _BattleMgr_. 53CCh = 21452 - это смещение указателя на героя нападающей стороны (0 - attacker).
Вернуться к началу

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

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

Сообщение Ben80 » 17 авг 2017, 14:52

А насколько нужно учитывать влияние изменения заклинаний в рамках любого мода (например, моего) на поведение ИИ ? Заклинания изменились, а ИИ об этом не знает... Может быть, известны участки кода, где ИИ производит какие-то оценки эффективности заклинаний (например, выбирает из тех заклинаний, которые у него есть то, которое принесет максимальный эффект) ? Может быть, планирует ряд прыжков Городского портала, заранее рассчитывая напасть на человеческого Героя, находящегося недалеко от его замка ? В этом случае, поскольку я меняю расход MP на применение заклинания, то могу подвести этим ИИ...

Или же все проще - компьютер в целом так далеко не расчитывает (в бою - расчитывает/оценивает в пределах 1 раунда, для Городского портала - заранее не рассчитывает, а скорее пробует - прыгнул в какой-то город - и оценил, на кого, на что он может напасть) ?

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

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

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

Сообщение Ben80 » 17 авг 2017, 15:14

Можно, конечно, для ИИ сделать расходы MP меньше, чем для игрока...
Кстати, интересно, тот факт, что Городской портал он теоретически сможет применять теперь более эффективно чем раньше (если не имеет школы Земли), сможет ли он вообще использовать ? То есть перед применением этого заклинания он вообще смотрит, есть ли у него школа Земли (продвинутая или экспертная) ?
Вернуться к началу

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 » 17 авг 2017, 15:27

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

В Героях 1 и 2 ИИ выбирает, какое заклинание скастовать, исходя из таблицы силы (эффективности) заклинаний. Думаю, в Героях 3 ничего в этом плане не поменялось. Где-то должна быть таблица эффективности заклинаний. Её и нужно менять. Однако этого будет недостаточно, т.к. есть ещё и алгоритм выбора заклинания, в котором реализована зависимость силы заклинания от силы магии (и не только). Если эффект заклинания от силы магии больше не зависит, то нужно также менять и сам алгоритм.

Цитата:
Кстати, интересно, тот факт, что Городской портал он теоретически сможет применять теперь более эффективно чем раньше (если не имеет школы Земли), сможет ли он вообще использовать ?

Иногда код для человека и компа один и тот же, но чаще, я думаю, разный. Сначала лучше всё тестить в игре.
Вернуться к началу

Пред.След.

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

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

Сейчас этот форум просматривают: Yandex [bot] и гости: 3