Объявления

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

RMG SOD

Герои Меча и Магии III: Возрождение Эрафии, Герои Меча и Магии III Дыхание Смерти, Герои Меча и Магии III Клинок Армагеддона, Герои Меча и Магии III Хроники Героев
offlineas239  
Мастер
Мастер
 
Сообщения: 323
Зарегистрирован: 29 дек 2018, 14:17
Пол: Не указан
Поблагодарили: 13 раз.

RMG SOD

Сообщение as239 » 22 июл 2019, 07:04

Хотел бы продолжить в этой теме изучение RMG SOD.
Есть конкретная задача, которую хотелось бы решить при этом - исправление генерации дорог на шаблоне Jebus Cross.
С SDK от RoseKavalier, появляются какие-то шансы на это.

Вот показательный пример - карта с Seed =777777777 :
Код: Выделить всё
int __stdcall SetSeed2(LoHook* h, HookContext* c)
{
   c->eax = 777777777;
    return EXEC_DEFAULT;
}
....
_PI->WriteLoHook(0x536637, SetSeed2 );

Здесь мы имеем и проход на смежный респ, которого быть не должно, и отсутствие дороги в центр, которая, естественно, должна быть:
 
Изображение


Первое что хотелось бы попробовать сделать - это добавить на отмеченные тайлы непроходимый одноклеточный объект, например - бревно.
По идее, это сразу же должно полностью исправить генерацию, очень бы хотелось это проверить.
Но мне нужен пример кода добавления объекта на RMG tile.
Я так понимаю, это нужно делать через RMG_MapItem->objects, но я не понимаю как, т.к. там есть вложенные структуры и поля, которые я не знаю как заполнять.

Добавлять блок планирую здесь, прямо перед созданием дорожной сети:
Код: Выделить всё
bool FirstRoad = false;
_LHF_(TestRMG)
{

   if (FirstRoad) return EXEC_DEFAULT;

   RMG_Main * rmg = (RMG_Main *)c->esi;
   RMG_MapItem * xyz = rmg->map.GetMapItem(6, 67, 0);
   //AddBlock(xyz);
   FirstRoad = true;
   return EXEC_DEFAULT;
}
....
_PI->WriteLoHook(0x548530, TestRMG );
Вернуться к началу

offlineas239  
Мастер
Мастер
 
Сообщения: 323
Зарегистрирован: 29 дек 2018, 14:17
Пол: Не указан
Поблагодарили: 13 раз.

Re: RMG SOD

Сообщение as239 » 25 июл 2019, 15:00

Получилось кое-что найти - если установить атрибут mustBeBlocked = 0, то дорога по этому тайлу не пойдет.
Сделал алгоритм сброса этого атрибута по всем смежным тайлам зон, кроме центра и эту генерацию он исправил.
 
Изображение

Однако на некоторых генерациях алгоритм не срабатывает.
Чтобы разобраться почему, мне нужно научиться генерировать карты по известному seed.
Кто-нибудь знает как это правильно делать?
Код выше генерирует одинаковую карту, но ее seed не равен установленному, так что он здесь помочь не может.
Вернуться к началу

offlineas239  
Мастер
Мастер
 
Сообщения: 323
Зарегистрирован: 29 дек 2018, 14:17
Пол: Не указан
Поблагодарили: 13 раз.

Re: RMG SOD

Сообщение as239 » 29 июл 2019, 17:19

Невозможность создания карты по заданному seed. Обошел тем, что при каждой перегенерации, в коде меняю исходный seed , и уже потом анализирую карту, зная seed, с которым смогу ее создать.
Удалось хорошо отладить алгоритмы закрытия смежных зон и выходов в центр.
Но есть еще проблемы, например раскрытый из-за шахты, смежный проход между красным и синим:
 
Изображение

Выделенный тайл, корректно находится алгоритмом закрытия смежных зон и mustBeBlocked у него установлен в 0.
Но ньюанс в том, что самая первая дорога, которая строится от красного к синему, игнорирует значения mustBeBlocked.
Соответственно, здесь есть два варианта:
1. Как-то научить видеть первую дорогу значение mustBeBlocked, так как это делают последующие дороги.
2. Просто не создавать шахты на границах, чтобы потом алгоритм их открытия не делал лишних проходов.

По п.1 у меня вообще нет идей.
По п.2 начал разбираться, на завис здесь RMG_ToPlaceMines_00546450:
 
Изображение

Это процедура создания шахт.
Но я никак не могу найти точку, где есть координаты шахты и возможность выйти из этой точки без создания шахты.
Вернуться к началу

offlineas239  
Мастер
Мастер
 
Сообщения: 323
Зарегистрирован: 29 дек 2018, 14:17
Пол: Не указан
Поблагодарили: 13 раз.

Re: RMG SOD

Сообщение as239 » 31 июл 2019, 15:50

Багнутые проходы от шахт вроде победил, причем без удаления шахты.
 
Изображение


Теперь для исправления еще одного ньюанса, мне очень нужно получить координаты стартового города красного игрока.
Облазил всю struct RMG_Main, но никак не получается вытащить.
Вернуться к началу

offlineigrik  
Посвященный
Посвященный
 
Сообщения: 69
Зарегистрирован: 14 сен 2017, 12:35
Пол: Не указан
Поблагодарили: 53 раз.

Re: RMG SOD

Сообщение igrik » 01 авг 2019, 15:39

Ты уверен, что дороги начинают рисоваться от стартового города красного? Я вот не особо уверен. Потому что когда создаётся случайная карта, и первый игрок-человек начинает за другой цвет (скажем зелёный), то первым активным игроком будет именно зелёный, а не красный.

Как мне кажется, дороги начинают рисоваться от первого города в структуре _GameMgr_.
Если да, то координаты первого города можно получить так:

Код: Выделить всё
_Town_* firstTownOnMap = (_Town_*)o_GameMgr->Field<int>(0x21614);
_byte_ id = firstTownOnMap->id;
_byte_ x = firstTownOnMap->x;
_byte_ y = firstTownOnMap->y;
_byte_ z = firstTownOnMap->z;
Вернуться к началу

offlineas239  
Мастер
Мастер
 
Сообщения: 323
Зарегистрирован: 29 дек 2018, 14:17
Пол: Не указан
Поблагодарили: 13 раз.

Re: RMG SOD

Сообщение as239 » 01 авг 2019, 17:24

Цитата:
Ты уверен, что дороги начинают рисоваться от стартового города красного? Я вот не особо уверен. Потому что когда создаётся случайная карта, и первый игрок-человек начинает за другой цвет (скажем зелёный), то первым активным игроком будет именно зелёный, а не красный.

Да ты прав.

Цитата:
Как мне кажется, дороги начинают рисоваться от первого города в структуре _GameMgr_.
Если да, то координаты первого города можно получить так:

Этот код не подойдет т.к. в момент постройки дорог (0x548530) эта структура еще не инициализирована.

Я решил этот вопрос так:
Код: Выделить всё
int __stdcall RMG_WriteRoad_005328A0(HiHook* hook, int *this1, POINT *a2, char roadType)
{
   int ret = THISCALL_3(int, hook->GetDefaultFunc(), this1, a2, roadType);
   LastRoadXYZ = (RMG_MapItem*)ret;
   return ret;
}

Запоминаю, каждый тайл дороги, т.о. в цикле построения дорог всегда знаю где закончилась прошлая.

В принципе, структуру генераций я отладил - 10 из 10 генерируются с правильными дорогами без багов.
Теперь хотелось бы разобраться с охранами проходов.
Там есть 2-е проблемы:
- иногда генерируются слишком много охран вплотную к друг другу, хотелось бы сделать чтобы они разделялись одним пустым тайлом
- иногда охрана оказывается далековато от дороги

Пока не очень понимаю как. Вот здесь создаются монстры:
Код: Выделить всё
RMG_ObjectMonster * __stdcall RMG_00541010_MonsterGeneration(HiHook* hook, _RMGStruct_ *this1, int a2, int a3){
   RMG_ObjectMonster *ret = THISCALL_3(RMG_ObjectMonster*, hook->GetDefaultFunc(), this1, a2, a3);
   if (a2==106750) //Это охрана прохода
   {
      GOcount++;
   }
   return ret;
}

Но во-первых их надо отделить от остальных монстров. Условие по value мне не очень нравится.
А во-вторых монстр здесь создается с пустыми координатами (x =-1, y = -1, z=-1).
Где ставятся реальные координаты я не понимаю.
Вернуться к началу

offlineEranikus  
имя: Максим
 
Сообщения: 3
Зарегистрирован: 02 авг 2019, 10:45
Пол: Мужчина
Поблагодарили: 2 раз.

Re: RMG SOD

Сообщение Eranikus » 02 авг 2019, 11:18

Молодец as239, очень актуальной проблемой занимаешься. Хотел помнить об кучках ГО, но вижу ты уже этим занялся, но все равно добавлю скрин недавней игры.

Выход с респа через 4 ГО
 
Изображение
Вернуться к началу

offlineas239  
Мастер
Мастер
 
Сообщения: 323
Зарегистрирован: 29 дек 2018, 14:17
Пол: Не указан
Поблагодарили: 13 раз.

Re: RMG SOD

Сообщение as239 » 02 авг 2019, 14:20

Вот здесь 0x548530, в цикле строятся дороги до городов (координаты города: x,y,z):
Код: Выделить всё
char __stdcall RMG_Road(HiHook* hook, _RMGStruct_ *this1, int x, int y, int z, int roadType)
{
   char ret = THISCALL_5(char, hook->GetDefaultFunc(), this1, x, y, z, roadType);
}

Как достать этот список городов, и можно ли управлять его порядком?

Обновлено:
Вот нашел - города выдаются правильно:
Код: Выделить всё
void GetTowns(){
   H3Vector<RMG_Object*> positions = rmg->positions;
   RMG_Object *obj;
   for (int i =0; i < positions.Count(); i++){
      obj = *positions[i];
      if (obj->properties->prototype->type != 98 ) continue;
      sprintf(h3_TextBuffer, "x %d y %d", obj->x, obj->y);
      F_MessageBox(h3_TextBuffer);
   }
}

но потом вылет, на этой строке:
Код: Выделить всё
      obj = *positions[i];

Count() разве не количество элементов в векторе возвращает?
Вернуться к началу

offlineas239  
Мастер
Мастер
 
Сообщения: 323
Зарегистрирован: 29 дек 2018, 14:17
Пол: Не указан
Поблагодарили: 13 раз.

Re: RMG SOD

Сообщение as239 » 03 авг 2019, 06:24

Обход вектора объектов вроде сделал:
Код: Выделить всё
   auto *positions = &rmg->positions;
   RMG_Object *obj;
   for (obj = *positions->First(); obj <= *positions->Last(); obj++){
      if (!obj) continue;
                if (obj->properties->prototype->type != 98) continue;
   }


Но как теперь правильно получить свойства объекта. Это строка непосредственно ошибку не выдает:
Код: Выделить всё
                if (obj->properties->prototype->type != 98) continue;

Однако, если после нее сделать вывод сообщения, то будет вылет.
Что-то с ней не так.
Вернуться к началу

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

Re: RMG SOD

Сообщение RoseKavalier » 05 авг 2019, 20:48

Good work so far!
I'm afraid I'm a bit too busy to look into RMG properly at the moment but I will watch the thread in the future.

Keep in mind some of the selected names for RMG structures are far from definite and or maybe just wrong.
Вернуться к началу

След.

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

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

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