Объявления

Друзья, если не получается зарегистрироваться, напишите на почту 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 » 08 мар 2021, 19:52

Шансы выпадения (веса заклинаний, если точнее) можно изменить, например, в afterInit(): o_Spell[spell_id].chance2get_var[town_class_id]; А возможность гарантированного получения зависит от алгоритма. Проще гарантировать самостоятельно с помощью хука на раздачу в слоты гильдии, чем с помощью шансов.
Вернуться к началу

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

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

Сообщение Rolex » 08 мар 2021, 20:16

AlexSpl писал(а):

Шансы выпадения (веса заклинаний, если точнее) можно изменить, например, в afterInit(): o_Spell[spell_id].chance2get_var[town_class_id];

Проверил на Городском портале в Замке вот это:
Код: Выделить всё
o_Spell[SPL_TOWN_PORTAL].chance2get_var[0] = 100;

Несмотря на то, что шанс выпадения (вес) я выставил на 100%, таким образом мы все равно не можем гарантировать на 100% то, что один из слотов в гильдии на 4 уровне будет занят Городским порталом. То есть по моим наблюдениям этот шанс стремится к 100% и приближается к ним при очень большом количестве "бросков". К примеру, первые 10 подряд бросков дают где-то 70% шанс, последующие 10 бросков дают уже 80%, а средний из 20 бросков уже где-то 75%, а еще последующие 10 бросков дают уже 90%, а средний из 30 дает уже где-то 80%. Подобное я наблюдал при выпадении Морали и Удачи. AlexSpl, а можете объяснить, если не сложно, почему так происходит, просто интересно.

AlexSpl писал(а):

А возможность гарантированного получения зависит от алгоритма. Проще гарантировать самостоятельно с помощью хука на раздачу в слоты гильдии, чем с помощью шансов.

А подскажите, как это сделать на примере с хуком для Медлительности и Городского портала?
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

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

Сообщение RoseKavalier » 09 мар 2021, 02:44

`chance2get` is not an odd of getting, it's a weight.
* Town spell generation code (0x5BEA00) checks all spells of level 4 (or whatever level it's currently generating) and adds all the chances together (total_weight).
* Then you have Rand(1, total_weight)
* Loop back through all spells again, removing the weight of each spell of the correct level, until you hit <= 0
Вернуться к началу

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

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

Сообщение Rolex » 09 мар 2021, 10:46

То есть chance2get - это не вероятность, а вес. А total_weight - это общий вес всех заклинаний определенного уровня. Это все что я понял. Последнее предложение не совсем понятно. Типа проходимся в цикле по всем заклинаниям генерируемого уровня и обнуляем их вес...
Вернуться к началу

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 » 09 мар 2021, 11:06

Цитата:
А подскажите, как это сделать на примере с хуком для Медлительности и Городского портала?

Можно поставить хук здесь: 0x5BEC79. Указатель на _Town_ будет в esi. Заменить выпавшее заклинание: town->spells[level][slot] = spell_id; Не забудьте проверить, чтобы на уровне не было два или более одинаковых.
Вернуться к началу

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

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

Сообщение Rolex » 09 мар 2021, 11:48

AlexSpl писал(а):

Указатель на _Town_ будет в esi.

Нам же для начала нужно получить town_class_id города через o_TownMgr-> для начала, так же?
Вот так только:
int town = *(int*)(c->esi);
Но должен же быть указатель:
_Town_ * town = o_TownMgr->...?

AlexSpl писал(а):

Заменить выпавшее заклинание: town->spells[level][slot] = spell_id;

А левелы и слоты нумеруються с 0 или 1?
Вернуться к началу

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 » 09 мар 2021, 12:10

_Town_* town = (_Town_*)c->esi; А дальше см. структуру _Town_ в homm3.h. Там можно получить класс/тип города (town->type) и всё остальное.

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

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

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

Сообщение Rolex » 10 мар 2021, 13:22

Поразбирался в общем я со спеллами. Все что нужно было в принципе сделал.

Кстати, в Ученом мы забыли учесть один случай, когда Ученый предлагает такое заклинание, которое уже есть в Книге заклинаний героя. В таком случае мы также вместо основного бонуса получаем дефолтный.

Я исправил свой пост (может кому пригодится), добавил в проверку:
Код: Выделить всё
hero->spell[ScholarSpell]


То есть вместо этого:
Код: Выделить всё
if (o_ActivePlayer->selected_hero_id != ID_NONE && (!hero->DoesWearArtifact(AID_SPELL_BOOK) || o_Spell[ScholarSpell].level > hero->second_skill[HSS_WISDOM] + 2))


Стало это:
Код: Выделить всё
if (o_ActivePlayer->selected_hero_id != ID_NONE && (!hero->DoesWearArtifact(AID_SPELL_BOOK) || o_Spell[ScholarSpell].level > hero->second_skill[HSS_WISDOM] + 2 || hero->spell[ScholarSpell]))
Последний раз редактировалось Rolex 10 мар 2021, 13:52, всего редактировалось 2 раз(а).
Вернуться к началу

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

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

Сообщение Rolex » 10 мар 2021, 13:24

Взялся сейчас прокачивать самое бесполезное заклинаний 5-го уровня - Волшебное зеркало. Хоть оно и 5-го уровня его реальная польза на уровне заклинаний 1-2 уровня. Команда HotA вроде как в готовящемся обновлении тоже планирует его усилить. Но как именно - неизвестно. Да и когда это обновление выйдет пока тоже никто не знает.

У меня пока такие идеи:
1) Поднять вероятность отражения в два раза с 20%/30%/40% до 40%/60%/80%.
2) Поднять вероятность отражения с 20%/30%/40% до 50%/75%/100%.
3) Поднять вероятность отражения с 20%/30%/40% до 50%/100%/100% и при этом на Эксперте сделать Magic Mirror массовым спеллом.

Последний вариант был успешно реализован:

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

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

using namespace std;

Patcher* _P;
PatcherInstance* _PI;

static _bool_ plugin_On = 0;

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

SpellDesc NewMagicMirror =
{
   "{Магическое зеркало}\n\nЦелевой отряд способен отразить вражеское заклинание на самый сильный отряд противника (вместо случайного) с вероятностью в 50%.",
   "{Базовое Магическое зеркало}\n\nЦелевой отряд способен отразить вражеское заклинание на самый сильный отряд противника (вместо случайного) с вероятностью в 50%.",
   "{Продвинутое Магическое зеркало}\n\nЦелевой отряд способен отразить вражеское заклинание на самый сильный отряд противника (вместо случайного).",
   "{Экспертное Магическое зеркало}\n\nВсе дружественные отряды способны отразить вражеское заклинание на все или самые сильные отряды противника (вместо случайного)."
};


int __stdcall afterInit(LoHook* h, HookContext* c)
{
   o_Spell[SPL_MAGIC_MIRROR].effect[0] = 50;
   o_Spell[SPL_MAGIC_MIRROR].effect[1] = 50;
   o_Spell[SPL_MAGIC_MIRROR].effect[2] = 100;
   o_Spell[SPL_MAGIC_MIRROR].effect[3] = 100;

   *(SpellDesc*)(o_Spell + SPL_MAGIC_MIRROR)->description = NewMagicMirror;

   return EXEC_DEFAULT;
}

char __stdcall IsSpellSingleTarget(HiHook *h, int spell, int ssLevel)
{
   if (spell == SPL_MAGIC_MIRROR && ssLevel == 3) return FALSE; else
      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.NewMagicMirror");

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

   return TRUE;
}


Но у Magic Mirror есть еще одно слабое место - это отражение на случайно выбранный отряд противника. Вот здесь его также хотелось бы усилить.
Идея состоит в том, чтобы поставить хук в то место, где срабатывает оригинальный алгоритм случайного выбора вражеского отряда и переписать на свой так, чтобы выбирался не случайный отряд, а самый сильный отряд противника.

Должна быть формула по которой можно рассчитать силу существа исходя из его базовых навыков Атаки и Защиты, Урона (если min != max, то берем (float)(min + max / 2)) и его Здоровья, если ее нет, то, думаю, ее можно вывести. После того, как мы получаем силу монстра, мы умножает ее на кол-во существ в отряде, тем самым получаем некий коэф., который будет обозначать силу отряда.
То есть понятно, что если мы имеем базовый прирост всех существ, то самым сильным отрядом окажеться отряд самого высокого уровня. Но если кол-во существ более низкого уровня увеличится, то здесь уже не все так очевидно. Определение силы отряда умножением его здоровья на кол-во существ в отряде в корне не верно. Так как в таком случае мы игнорируем урон и навыки атаки и защиты.

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

Задача усложняется для Экспертного уровня, ведь здесь уже все отряды под Зеркалом.

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

На Эксперте у нас 3 случая:
1) Когда кол-во отрядов героя РАВНО кол-ву отрядов противника. Тут все просто и вычислять ничего ненужно, только реализовать отражение все на все.

2) Когда кол-во отрядов героя СТРОГО БОЛЬШЕ кол-ва отрядов противника. Тут как бы хотелось бы сделать так, чтобы часть отрядов просто отражала накладываемый спелл, получается в никуда, а вот та часть, которая соответствует кол-ву отрядов противника, отражала как раз на вражеские отряды.

3) Когда кол-во отрядов героя СТРОГО МЕНЬШЕ кол-ва отрядов противника. И самое сложное: вот здесь нам нужно уже будет при отражении из имеющегося кол-ва отрядов противника выбрать такое кол-во самых сильных вражеских отрядов, которое будет соответствует кол-ву отрядов героя. Получается нам нужно изначально вычислить массив (длинной в кол-во отрядов противника) с силой отрядов противника, после отсортировать его по убыванию коэф и взять первые N-значений, где N - кол-во отрядов в войске нашего героя.

Вот если бы все это сделать, получилось бы просто шикарное заклинание 5-го уровня. AlexSpl, без вашей помощи здесь не обойтись. Все что я мог лично сделать - уже сделал (код выше).
Последний раз редактировалось Rolex 12 мар 2021, 19:22, всего редактировалось 2 раз(а).
Вернуться к началу

offlineRoseKavalier  
Мастер
Мастер
 
Сообщения: 331
Зарегистрирован: 23 сен 2017, 17:00
Пол: Не указан
Поблагодарили: 234 раз.

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

Сообщение RoseKavalier » 10 мар 2021, 16:00

When calculating effect of offensive spell, AI value is something similar to this:
Код: Выделить всё
spell_effect * (100 - 2 * magic_mirror_chance)

Anything above 50% reflect essentially results in AI never casting offensive spells against that unit :smile2:
Вернуться к началу

Пред.След.

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

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

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