Объявления
Поздравляем
Roman2211


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

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

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

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

Сообщение Rolex » 12 мар 2021, 12:52

AlexSpl писал(а):

См. как определён stack в _BattleMgr_ (какой у него тип). Вы же должны поместить в eax указатель на stack.

Я понял из вашего предыдущего сообщения, что должен быть указатель.

Но чтобы присвоить c->eax указатель нужно его привести к *(_BattleStack_**) вот так:
Код: Выделить всё
*(_BattleStack_**)c->eax = &o_BattleMgr->stack[o_BattleMgr->current_side][pos];


или же &_BattleMgr к *(int*) вот так:
Код: Выделить всё
c->eax = *(int*)&o_BattleMgr->stack[o_BattleMgr->current_side][pos];


Но в обоих случаях я получаю вылет.

По стеку в _BattleMgr_ вот все что есть:
Код: Выделить всё
struct _BattleMgr_; // Размер: 82156
#define o_BattleMgr (*(_BattleMgr_**)0x699420)
...
 //_BattleStack_ stack[42]; //+ 21708
 _BattleStack_ stack[2][21]; //+ 21708

 _byte_ field_1329C[28]; // + 0x1329C
 _int32_ unk_side; // +78520 0x132B8
 _int32_ current_stack_ix; // +78524 0x132BC
 _int32_ current_side; // +78528 0x132C0
Вернуться к началу

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

Правильно так:

Код: Выделить всё
c->eax = (int)&o_BattleMgr->stack[o_BattleMgr->current_side][pos];

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

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

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

Сообщение Rolex » 12 мар 2021, 14:12

Я в курсе, что указатель - это адрес объекта. Немного знаком с указателями.

Как я помню, например, &x - это адрес (указатель) ячейки памяти, где хранится значение переменной x.
*&x - разыменования, получение значения ячейки памяти перемнной x.
int *x = &y; - объявление и инициализация перемнной x адресом значения переменной y.
x - адрес
*x - значение по хранящемуся адресу
&y - адрес y (если y обычная переменная).

Это все, что я знаю об указателях. :smile14:

Самое интересное, что вариант:
Код: Выделить всё
c->eax = (int)&o_BattleMgr->stack[o_BattleMgr->current_side][pos];

у меня был закомментирован, но я не успел его протестировать. :smile7:

А вот в этом я немного запутался: *(int**) и *(int*)

Но ведь вот это тоже адрес (как я написал выше), а не значение, так же?
Код: Выделить всё
*(int*)&o_BattleMgr->stack[o_BattleMgr->current_side][pos];

Просто в данном случае мы берем адрес o_BattleMgr->stack[o_BattleMgr->current_side][pos] и разыменовываем его как адрес переменной типа int.

Тогда как это:
Код: Выделить всё
(int)&o_BattleMgr->stack[o_BattleMgr->current_side][pos];

Просто явное преобразования адреса объекта к типу int.

Верно? Если я не прав, поправьте меня.
Вернуться к началу

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

(int)&x - это адрес x, а *(int*)&x - это целое число, которое находится по адресу x, т.е. само x (или первые четыре байта x, если x, например, структура или экземпляр объекта).
Вернуться к началу

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

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

Сообщение Rolex » 12 мар 2021, 19:02

Значить все таки значение. Ну ок, буду знать.

Все таки я добил это отражение на один отряд. Не думал, что у меня получится это сделать. Причем сделал так, как описывал. То есть у нас есть массив (вектор) значений с силой каждого стека, отсортированный по убыванию с сохраненим индексов. В x[i].first хранится боевая мощь отряда, а в x[i].second - порядковый номер отряда. После сортировки в x[0].second - хранится порядковый номер самого сильного отряда, x[1].second - второго по силе и тд. При выборе отряда мы также проверяем наш отряд на то, являестя ли он Черным драконом или Элементалем магии или наложена ли на него Антимагия, и если да, то переходим к следующему по силе отряду.

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

#include "stdafx.h"
#include "HotA\homm3.h"
#include <utility>
#include <iostream>
#include <vector>
#include <algorithm>

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] = 40;
   o_Spell[SPL_MAGIC_MIRROR].effect[1] = 40;
   o_Spell[SPL_MAGIC_MIRROR].effect[2] = 50;
   o_Spell[SPL_MAGIC_MIRROR].effect[3] = 50;

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

   return EXEC_DEFAULT;
}

bool my_cmp(const pair<int, int>& a, const pair<int, int>& b)
{
   return a.first > b.first;
}

int __stdcall NewTarget(LoHook* h, HookContext* c)
{   
   int pos = 0;
   vector <pair<int, int> > combatPowerOfStacks;

   combatPowerOfStacks.resize(o_BattleMgr->stacks_count[o_BattleMgr->current_side]);
   
   for (int i = 0; i < combatPowerOfStacks.size(); ++i)
   {
      _BattleStack_* stack = &o_BattleMgr->stack[o_BattleMgr->current_side][i];      
      combatPowerOfStacks[i].first = o_pCreatureInfo[stack->creature_id].fight_value * stack->count_current;
      combatPowerOfStacks[i].second = i;   
   }
   
   sort(combatPowerOfStacks.begin(), combatPowerOfStacks.end(), my_cmp);
   
   for (int i = 0; i < combatPowerOfStacks.size(); ++i)
   {
      _BattleStack_* stack = &o_BattleMgr->stack[o_BattleMgr->current_side][combatPowerOfStacks[i].second];
            
      if (stack->creature_id == CID_BLACK_DRAGON || stack->creature_id == CID_MAGIC_ELEMENTAL || stack->active_spell_duration[SPL_ANTI_MAGIC]) continue; else
      {
         pos = combatPowerOfStacks[i].second;
         break;
      }
   }

    c->eax = (int)&o_BattleMgr->stack[o_BattleMgr->current_side][pos];

   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);
         _PI->WriteLoHook(0x5A05CC, NewTarget);
      }
   }

   return TRUE;
}


AlexSpl писал(а):

Проверить заклинания, которые висят на отряде, можно через тот же _BattleStack_. ID заклинания в *(int*)(c->ebp + 8).

Не пригодилось.

AlexSpl писал(а):

* OK. Кое-что, требующееся для решения задачи, Вам неизвестно, но я предлагаю хотя бы понять, что именно Вам неизвестно.

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

AlexSpl писал(а):

Попробуйте для начала самостоятельно реализовать перенаправление для одного стека. А потом, может быть, разберёмся и с массовым.

Ну что ж свою часть работы я с горем пополам, но выполнил, теперь ваша очередь. AI пока не трогаем. :smile2:

Rolex писал(а):

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

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

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

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

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

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

Под Magic Mirror в общем случае могут находиться несколько отрядов. Площадные заклинания мы, как я понял из FizMiG, не отражаем, ибо иначе всё было бы очень сложно: кастанули Inferno на три отряда под Magic Mirror, а в ответ получили три каста Inferno :smile12: Отражённые заклы обратно тоже не отражаем. Остаётся реализовать массовую анимацию сработавших Magic Mirror и массовую анимацию отражённого заклинания. Это мы делали (см. палатку с массхилом). В случае с отражённым заклом одной массовой анимации будет недостаточно: нужно делать массовый каст, чтобы наложились эффекты. Тут очень было бы удобно, если бы вот это:

Код: Выделить всё
// Отмечаем отряды, для которых необходима анимация (в цикле)
o_BattleMgr->Field<char>(0x547C + 20 * o_BattleMgr->current_side + stackID) = 1;

работало и для эффектов заклинаний. Но нужно проверять (смотреть, как именно реализован массовый каст). Звучит сложно, поэтому даже не знаю, браться ли за такую задачу :smile5:
Последний раз редактировалось AlexSpl 14 мар 2021, 16:16, всего редактировалось 1 раз.
Вернуться к началу

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

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

Сообщение Rolex » 12 мар 2021, 21:28

AlexSpl писал(а):

Площадные заклинания мы, как я понял из FizMiG, не отражаем, ибо иначе всё было бы очень сложно: кастанули Inferno на три отряда под Magic Mirror, а в ответ получили три каста Inferno :smile12:

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

AlexSpl писал(а):

Отражённые заклы обратно тоже не отражаем.

Иначе было бы забавно - бесконечный цикл отражений и ... taskkill /f /im Heroes3.exe

AlexSpl писал(а):

Но нужно проверять (смотреть, как именно реализован массовый каст). Звучит сложно, поэтому даже не знаю, браться ли за такую задачу :smile5:

Сложно, но интересно. Хорошие вещи простыми не бывают. Вспомните вон даже вашу с Ben80 Маскировку, над которой вы бились целый месяц. Но оно того стояло. :smile2:
Последний раз редактировалось Rolex 13 мар 2021, 10:48, всего редактировалось 2 раз(а).
Вернуться к началу

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

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

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

Интересно, что при одинаковом кол-ве AI (o_pCreatureInfo[creature_id].fight_value) оценивает как Черных, так и Золотых драконов выше, чем Архангелов, причем Черных ценит выше Золотых.
Решил свести 5 архов против 5 черных драков. Навыки атаки и защиты у героев одинаковы, вторичные вроде Нападения или Доспехов, которые могут повлиять на исход отсутствуют. Мораль и Удача нейтральные.

В первом бою первыми атакуют Архангелы, во втором - Черные драконы. В итоге архи в хлам разносят драконов. Независмо от того, кто ходит первым Архангелов остается 3. Если сравнвать 1 к 1 у архов еще остается примерно от 60 до 90 здоровья. То есть дракону потребуется еще 2 атаки (если он ходит первым) и 3 атаки (если ходит вторым).
По навыкам атаки и защиты, а также урону Архангелы сильнейшие среди всех замковых существ 7-го уровня (кроме здоровья). Но абилка многое решает. Единственный кто может победить Архангелов в бою - это Древние чудища. Несмотря на то, что у них очень низкие навыки атаки и защиты и средний урон, абилка решает - минус 80% защиты врага. И Архидьяволы за счет своей абилки - безответной атаки и высоких навыков атаки и защиты попадают в тройку.

Реальный рейтинг силы ул. существ 7-го уровня:
1) Древние чудища
2) Архангелы
3) Архидьяволы
4) Титаны
5) Золотые драконы
6) Черные драконы
7) Гидры Хаоса
8) Призрачные драконы
9) Фениксы

Рейтинг силы ул. существ 7-го уровня для AI:
1) Черные драконы
2) Золотые драконы
3) Архангелы
4) Древние чудища
5) Гидры Хаоса
6) Архидьяволы
7) Титаны
8) Фениксы
9) Призрачные драконы

При этом Черные и Золотые драконы на одном уровне. Победит тот, кто первым начнет атаку. В своем рейтинге я поставил Золотых выше в первую очередь потому, что в бою они будут ходить первыми. Меньшее кол-во здоровья (250 против 300) компенсируется более высокими навыками атаки и защиты (27 против 25). Но AI оценивает выше Черных драконов. Более того, для AI Черные драконы - это самые сильные существа среди всех замковых существ.
Последний раз редактировалось Rolex 13 мар 2021, 13:06, всего редактировалось 2 раз(а).
Вернуться к началу

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

Чёрные и Золотые драконы так высоко из-за иммунитета к залинаниям. Бой один на один говорит далеко не обо всех раскладах. Как насчёт боя Чёрного дракона против Древнего чудища под командованием совершенно идентичных героев с Армагеддоном? :smile2:
Вернуться к началу

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

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

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

На самом деле иммунитет к залинаниям - это ни хорошо и ни плохо. Ведь у драконов иммунитет не только к отрицательным заклинаниям, но и к положительным. Я точно также могу сказать, а как на счет боя Древних чудищ под Молитвой или Благословением против Черных драконов. Если даже без магии Древние чудища не оставляют и шанса драконам. Но целью была проверка силы в максимально равных условиях БЕЗ использования какой-либо магии.
Вернуться к началу

Пред.След.

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

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

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