Объявления

Форум о Героях Меча и Магии и King's Bounty. Если Вы любите эти игры, мы будем рады видеть Вас в наших рядах. :smile2:

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

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineBen80  
Ветеран
Ветеран
 
Сообщения: 618
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 110 раз.

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

Сообщение Ben80 » 21 май 2019, 03:26

LoHook исполняется не вместо оригинального кода, а перед оригинальным кодом. И только если он возвращает NO_EXEC_DEFAULT, оригинальная инструкция не выполняется.

Соответственно, если ставить LoHook на 5B, то сначала в EAX запишется то, что вы хотите (посредством LoHook). А потом EAX еще увеличится на 0x28. И это уже лишнее.
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Новичок
Новичок
 
Сообщения: 40
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 7 раз.

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

Сообщение Catastrophe » 21 май 2019, 18:32

Ben80 писал(а):

LoHook исполняется не вместо оригинального кода, а перед оригинальным кодом. И только если он возвращает NO_EXEC_DEFAULT, оригинальная инструкция не выполняется.

Да, я так и понял, сформулировал неправильно только
Ben80 писал(а):

Соответственно, если ставить LoHook на 5B, то сначала в EAX запишется то, что вы хотите (посредством LoHook). А потом EAX еще увеличится на 0x28. И это уже лишнее.

А вот про это я совсем забыл! но чтобы этого не было, достаточно оставить эту строку:
Код: Выделить всё
_PI->WriteByte(0x4BFB5D, 0); // additional exp offset

 И еее, все работает
Изображение
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Новичок
Новичок
 
Сообщения: 40
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 7 раз.

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

Сообщение Catastrophe » 21 май 2019, 20:11

Пытаюсь сделать создание чего-нибудь, кроме дыры при копании (или вообще ничего):
 PutAHoleObject в IDA
Изображение

Команда push 124 подписана как Hole, при этом в ERM Help дыра имеет как раз ID 124:
http://www.wakeofgods.com/erm_help/format/format_ob.htm

Само значение 124 лежит по адресу 0xEE98 (0x40EE98), но при попытке заменить его на 0 (ничего), 22 (труп), 101 (сундук с сокровищами)
 происходит одно и то же
Изображение
Изображение

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

offlineАватара пользователя
Catastrophe  
имя: Alex
Новичок
Новичок
 
Сообщения: 40
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 7 раз.

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

Сообщение Catastrophe » 22 май 2019, 00:35

Изменение типов существ, производимых некромантией и плащом короля нежити:
Код: Выделить всё
         // creatures produced by necromancy
         _PI->WriteDword(0x4E3F3A, 56); // skeletons
         // creatures procuced by cloak of the undead king
         _PI->WriteDword(0x4E3F33, 58); // skeleton warriors ; with basic necromancy
         _PI->WriteDword(0x4E3F2A, 60); // walking dead ; with advanced necromancy
         _PI->WriteDword(0x4E3F1F, 62); // zombies ; with expert necromancy

Но это все и так, наверное, знали, поэтому разобрал нетронутое из базы, а именно специализации по спеллам.

Например, увидел там неподписанный блок, обращающийся к этой строке:
Изображение
Проверил - как я и думал, она отвечает за специализацию по заклинанию "Палач".
Эта специализация уникальна тем, что работает только на первые 4 уровня существ. Но ее можно разделить на все 7 уровней:
Код: Выделить всё
         // slayer specialty bonus
         _PI->WriteDword(0x63EAC4, 7); // lvl 1 creatures
         _PI->WriteDword(0x63EAC8, 6); // lvl 2 creatures
         _PI->WriteDword(0x63EACC, 5); // lvl 3 creatures
         _PI->WriteDword(0x63EAD0, 4); // lvl 4 creatures
         _PI->WriteDword(0x63EAD4, 3); // lvl 5 creatures
         _PI->WriteDword(0x63EAD8, 2); // lvl 6 creatures
         _PI->WriteDword(0x63EADC, 1); // lvl 7 creatures


Со строчкой сверху все оказалось еще проще - это классическая специализация по бафам/дебафам, с ней все абсолютно так же:
Код: Выделить всё
         // buff/debuff specialty bonus
         _PI->WriteDword(0x63EAA8, 7); // lvl 1 creatures
         _PI->WriteDword(0x63EAAC, 6); // lvl 2 creatures
         _PI->WriteDword(0x63EAB0, 5); // lvl 3 creatures
         _PI->WriteDword(0x63EAB4, 4); // lvl 4 creatures
         _PI->WriteDword(0x63EAB8, 3); // lvl 5 creatures
         _PI->WriteDword(0x63EABC, 2); // lvl 6 creatures
         _PI->WriteDword(0x63EAC0, 1); // lvl 7 creatures


Дальше у нас идет специализация по заклинанию "Удача":
Изображение
К сожалению, она не добавляет, а заменяет ее эффект.
Код: Выделить всё
         _PI->WriteDword(0x4E62CE, 50); // luck spell effect specialty effect


Специализация по заклинанию "Разрушающий луч":
Изображение
В отличии от удачи, не заменяет, а добавляет.
Код: Выделить всё
         _PI->WriteDword(0x4E62E6, 50); // disrupting ray spell specialty bonus


Здесь судя по sar 1 (арифметический сдвиг вправо на один бит), выполняется деление на 2.
Изображение
Делаю вывод, что это специализация по заклинанию "Волшебная стрела" - полученное число идет в бонус.
Без использования хуков, я так понимаю, в положительную сторону ее не изменить (разве что заменой 1 на 0, можно ли так?)
Код: Выделить всё
int __stdcall c_ma_spec(LoHook* h, HookContext* c)
{
   здесь должен быть эквивалент "sal eax, 2", подскажете, как он должен выглядеть?
   return EXEC_DEFAULT;
}
...
_PI->WriteLoHook(0x4E62F7, c_ma_spec);


Осталась последняя неподписанная специализация, методом исключения делаем вывод, что она по ударным заклинаниям (+3% урона за каждые (1 * уровень существа-жертвы) уровней героя)
 в ней побольше кода, чем в других
Изображение

Самый простой способ на нее повлиять - изменить ее множитель
 он записан в немного необычной форме
Изображение
Вернуться к началу

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

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

Сообщение AlexSpl » 22 май 2019, 10:21

Цитата:
Пытаюсь сделать создание чего-нибудь, кроме дыры при копании (или вообще ничего)

Если Вы посмотрите код функции PlaceObjectOnMap, то увидите, что она предназначена только для того, чтобы оставлять яму при раскопках и расставлять монстров в месяц существ. Больше она ничего не умеет. Чтобы вместо ямы рисовался другой объект, кроме Вашего изменения, необходимо также исправить cmp eax, 124 и push 124 по адресам 4C959Ah и 4C95D4h соответственно.

Цитата:
Здесь судя по sar 1 (арифметический сдвиг вправо на один бит), выполняется деление на 2.

Код: Выделить всё
int __stdcall c_ma_spec(LoHook* h, HookContext* c)
{
   // c->eax = Ваша_формула; например, c->eax *= 2; c->eax /= 2 и т.п.
   
   c->return_address = 0x4E62F7;
   return SKIP_DEFAULT;
}
...
_PI->WriteLoHook(0x4E62F5, c_ma_spec);

Цитата:
Самый простой способ на нее повлиять - изменить ее множитель

Это тип double (8 байтов). Менять константы не советую, т.к. их могут использовать разные инструкции. Если всё-таки нужно изменить константу double (и без калькулятора), то можно поступить так:

Код: Выделить всё
double k = 0.05; // Константа
                       
_PI->WriteDword(0xADDRESS, *(int*)&k);
_PI->WriteDword(0xADDRESS + 4, *(int*)((int)&k + 4));

С float (4 байта) проще:

Код: Выделить всё
float k = 0.05f; // Константа
                       
_PI->WriteDword(0xADDRESS, *(int*)&k);
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Новичок
Новичок
 
Сообщения: 40
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 7 раз.

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

Сообщение Catastrophe » 23 май 2019, 01:43

AlexSpl писал(а):

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

Не спорю, но это может сильно сэкономить время (не в этом, но в другом случае). Например я хочу переделать все классические специализации по вторичным навыкам. В оригинальной игре все они используют такую формулу:
  • Берется число из массива ExampleSkillMultipliers[x], где x - уровень этого скилла у героя
  • Это число умножается на (HeroLevel * Mult + Add), где Mult в оригинальной игре - 0.05f, а Add - 1.0f, я же хочу их выставить на 0 и 2.0f (или хотя бы 1.67f, с 1.5f специалисты по лидерству и удаче будут иметь +1 бонус вместо +2)
Результат пусть у нас будет Result. А дальше у каждого скилла происходит свой выкрутас:
Код: Выделить всё
return Add + Result; // обучение, интеллект, первая помощь (видимо, без этого шага, герои без этих скиллов не смогут получать опыт, ману и лечить палаткой?)
return Add - Result; // дипломатия, сопротивление, орлиный глаз, защита
return Result; // разведка, некромантия, нападение, стрельба, логистика, навигация, поместья, лидерство, удача, мистицизм

Что вы порекомендуете сделать в этой ситуации? Не трогать константу Add? Но что тогда делать?
 пример команды return Add (IntellSecScSpecAdd) + Result (LearPow) у навыка обучение
Изображение


И еще, как происходит сложение/вычитание десятичного числа и float? 2.0f + 2 = 4.0f?
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Новичок
Новичок
 
Сообщения: 40
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 7 раз.

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

Сообщение Catastrophe » 23 май 2019, 04:01

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

Изображение

Изображение

Изображение

Изображение

Код: Выделить всё
            _PI->WriteDword(0x63B850, 66); // fire elem
            _PI->WriteDword(0x63B854, 5); // chance
           
            _PI->WriteDword(0x63B858, 67); // earth elem
            _PI->WriteDword(0x63B85C, 5); // chance
           
            _PI->WriteDword(0x63B860, 68); // water elem
            _PI->WriteDword(0x63B864, 5); // chance
           
            _PI->WriteDword(0x63B868, 69); // air elem
            _PI->WriteDword(0x63B86C, 5); // chance
           
            _PI->WriteDword(0x63B870, 22); // inferno
            _PI->WriteDword(0x63B874, 15); // chance
           
            _PI->WriteDword(0x63B878, 23); // meteor shower
            _PI->WriteDword(0x63B87C, 15); // chance
           
            _PI->WriteDword(0x63B880, 19); // chain lightning
            _PI->WriteDword(0x63B884, 15); // chance
           
            _PI->WriteDword(0x63B888, 11); // land mine
            _PI->WriteDword(0x63B88C, 15); // chance
Вернуться к началу

offlineBen80  
Ветеран
Ветеран
 
Сообщения: 618
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 110 раз.

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

Сообщение Ben80 » 23 май 2019, 08:35

Catastrophe писал(а):

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


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

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

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

Сообщение AlexSpl » 23 май 2019, 09:41

Цитата:
Что вы порекомендуете сделать в этой ситуации?

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

Цитата:
И еще, как происходит сложение/вычитание десятичного числа и float? 2.0f + 2 = 4.0f?

Как и в других случаях, происходит неявное преобразование операндов: 2.0f + 2 = 2.0f + 2.0f = 4.0f.
Вернуться к началу

offlineАватара пользователя
Catastrophe  
имя: Alex
Новичок
Новичок
 
Сообщения: 40
Зарегистрирован: 07 мар 2019, 11:50
Пол: Мужчина
Поблагодарили: 7 раз.

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

Сообщение Catastrophe » 25 май 2019, 09:57

AlexSpl писал(а):

Цитата:
Если Вы посмотрите код функции PlaceObjectOnMap, то увидите, что она предназначена только для того, чтобы оставлять яму при раскопках и расставлять монстров в месяц существ. Больше она ничего не умеет. Чтобы вместо ямы рисовался другой объект, кроме Вашего изменения, необходимо также исправить cmp eax, 124 и push 124 по адресам 4C959Ah и 4C95D4h соответственно.

Все работает, а насколько сложно задать этому объекту параметры? Например для id 79 (ресурс) указать его тип - id 6 (золото)
 такое без моддинга вообще возможно?
Изображение


Смена существа, владеющего способностью "Страх":
 в журнале по прежнему пишутся лазурные драконы
Изображение

Код: Выделить всё
         // creature with fear ability
         _PI->WriteDword(0x46492E, 0);
         _PI->WriteDword(0x464947, 0);
         _PI->WriteDword(0x4649AB, 0);
         _PI->WriteDword(0x4649EF, 0);
         _PI->WriteDword(0x4649FB, 0);


Изменение способности энчантеров:
 описание уже неактуально
Изображение

Код: Выделить всё
         // enchanter behaviour
         _PI->WriteByte(0x447F66, 1); // spell power (duration)
         _PI->WriteByte(0x447F68, 1); // skill level (0/1/2/3)

Массив их спеллов:
Код: Выделить всё
         _PI->WriteDword(0x6608B8, 27); // shield
         _PI->WriteDword(0x6608BC, 10); // chance

         _PI->WriteDword(0x6608C0, 28); // air shield
         _PI->WriteDword(0x6608C4, 10); // chance

         _PI->WriteDword(0x6608C8, 45); // weakness
         _PI->WriteDword(0x6608CC, 20); // chance

         _PI->WriteDword(0x6608D0, 46); // stoneskin
         _PI->WriteDword(0x6608D4, 20); // chance

         _PI->WriteDword(0x6608D8, 49); // mirth
         _PI->WriteDword(0x6608DC, 15); // chance

         _PI->WriteDword(0x6608E0, 51); // fortune
         _PI->WriteDword(0x6608E4, 15); // chance

         _PI->WriteDword(0x6608E8, 53); // haste
         _PI->WriteDword(0x6608EC, 5); // chance

         _PI->WriteDword(0x6608F0, 54); // slow
         _PI->WriteDword(0x6608F4, 5); // chance

По неизвестным причинам, сумма шансов в оригинале составляет не 100%
 а 84%
ускорение 15%
воздушный щит 10%
замедление 10%
каменная кожа 15%
жажда крови 5%
благословление 15%
лечение 10%
слабость 4%


Изменение типов существ, которые могут удвоить свою популяцию в начале месяца:
 то бишь стать существом месяца
Изображение

Код: Выделить всё
         _PI->WriteHexPatch(0x63E678, "00 01 02 03 04 05 06 07 08 09 0A 0B");


Изменение существ / очков в таблице рекордов, по 2 байта на id существа и столько же на границу очков:
 пустая таблица в комплект не входит
Изображение

Код: Выделить всё
// creatures sorted in ai value order, gold and diamond golems replaced with peasant and azure dragon
_PI->WriteHexPatch(0x67F1FE, "8B 00 08 00 1C 00 0C 00 2A 00 10 00 62 00 14 00 46 00 18 00 54 00 1C 00 38 00 20 00 2B 00 24 00 1D 00 28 00 55 00 2C 00 00 00 30 00 47 00 34 00 39 00 38 00 63 00 3C 00 3A 00 40 00 0E 00 44 00 01 00 48 00 64 00 4C 00 02 00 50 00 3B 00 54 00 56 00 58 00 10 00 5C 00 0F 00 60 00 48 00 64 00 65 00 68 00 2C 00 6C 00 1E 00 70 00 03 00 74 00 58 00 78 00 1F 00 7C 00 57 00 80 00 11 00 84 00 12 00 88 00 49 00 8C 00 59 00 90 00 2D 00 94 00 20 00 98 00 3C 00 9C 00 68 00 A0 00 69 00 A4 00 73 00 A8 00 3D 00 AC 00 71 00 B0 00 13 00 B4 00 4A 00 B8 00 72 00 BB 00 04 00 BE 00 70 00 C1 00 2E 00 C4 00 4B 00 C7 00 2F 00 CA 00 21 00 CD 00 5A 00 D0 00 30 00 D3 00 06 00 D6 00 05 00 D9 00 31 00 DC 00 08 00 DF 00 4C 00 E2 00 16 00 E5 00 14 00 E8 00 15 00 EB 00 6A 00 EE 00 3E 00 F1 00 07 00 F4 00 22 00 F7 00 4D 00 FA 00 5B 00 FD 00 23 00 00 01 6B 00 03 01 09 00 06 01 32 00 09 01 3F 00 0C 01 17 00 0F 01 4E 00 12 01 40 00 15 01 24 00 18 01 66 00 1B 01 25 00 1E 01 5C 00 21 01 67 00 24 01 4F 00 27 01 41 00 2A 01 5D 00 2D 01 33 00 30 01 5E 00 33 01 6C 00 36 01 5F 00 39 01 6D 00 3C 01 50 00 3F 01 51 00 42 01 34 00 45 01 18 00 48 01 35 00 4B 01 0A 00 4E 01 26 00 51 01 19 00 54 01 42 00 57 01 0B 00 5A 01 43 00 5D 01 27 00 60 01 60 00 63 01 44 00 66 01 28 00 69 01 6E 00 6C 01 45 00 6F 01 52 00 72 01 1A 00 75 01 0C 00 78 01 36 00 7B 01 6F 00 7E 01 61 00 81 01 37 00 84 01 29 00 87 01 1B 00 8A 01 53 00 8D 01 0D 00 FF 7F 84");
Последний раз редактировалось Catastrophe 27 май 2019, 08:46, всего редактировалось 1 раз.
Вернуться к началу

Пред.След.

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

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

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

cron