Объявления

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

RMG SOD

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

Re: RMG SOD

Сообщение as239 » 14 ноя 2019, 13:43

А как понять какой тип имеет параметр функции?
Вот как igrik понял что int a3 имеет тип _RMGMapItems_?
Вернуться к началу

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

Re: RMG SOD

Сообщение AlexSpl » 14 ноя 2019, 13:52

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

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

Re: RMG SOD

Сообщение as239 » 16 ноя 2019, 12:12

Получилось полностью убрать блоки, через изменение порядка формирования дорог, но есть проблемы:
1. пустые дороги визуально выглядят не очень
2. не получается нормально поменять порядок формирования дорог и объектов в подземелье.

По п.1 помогло бы понимание - охраняется ли объект или нет, и если нет, то смело ставить его рядом с дорогой.
Но в RMGMapItems_00531D80_CantPlace это никак не понять.
Кстати в это новом проекте, пока не наблюдаю изменение плотности центра, при использовании RMGMapItems_00531D80_CantPlace.

По п.2 вообще идей нет что можно сделать.

Алгоритм изменения порядка формирования дорог и объектов:
- перед генерацией объектов:
устанавливаем всем клеткам с маской 011, маску 000, запоминаем их
устанавливаем всем клеткам с маской 010, маску 110, запоминаем их
формируем дороги
восстанавливаем маски клеток
всем дорожным клеткам устанавливаем mustBeBlocked = 0, чтобы на дорогах не генерились объекты

Используемая маска клетки: isBlocked, mustBeBlocked, canBeBlocked.
Вложения
NoBlocks.zip
DLL
(5.05 КБ) Скачиваний: 7
NoBlocksSource.zip
Code source
(6.36 КБ) Скачиваний: 10
Вернуться к началу

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

Re: RMG SOD

Сообщение as239 » 28 ноя 2019, 16:11

Поле "zoneInfo" в структуре "RMG_ZoneGenerator" имеет тип "RMG_Zone".
В SDK сейчас стоит тип "PUINT8".
Последний раз редактировалось as239 28 ноя 2019, 16:21, всего редактировалось 1 раз.
Вернуться к началу

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

Re: RMG SOD

Сообщение as239 » 28 ноя 2019, 16:19

С блоками на поверхности все получилось.
Помог ручной контроль маски проходимости в RMGMapItems_00531D80_CantPlace.
Здесь проверяется пересекает ли объект дорогу.

Код: Выделить всё
bool IsRoadsOverlay(int Nbyte, RMG_ObjectPropsRef *a2, int x, int y, int z){

   H3Bitfield passable = a2->prototype->passable[Nbyte];
   int Ymax = 1;
   int BitMax = 15;
   if (Nbyte == 0)  {
      BitMax = 31;
      Ymax = 3;
   }
   for (int iy = 0; iy <= Ymax; iy++)
   {
      int UpBit = BitMax - iy * 8;
      for (int ix = 0; ix <= 7; ix++)
      {
         if (passable.GetState(UpBit - ix) == 1) continue;
         int addx = x - ix;
         int addy = y - iy;
         if (MapSize == 0 || addx >= MapSize || addy >= MapSize || addx < 0 || addy < 0)  continue;
         RMG_MapItem *addxyz = rmg->map.GetMapItem(addx, addy, z);
         if (addxyz->GetRoad() != 0) return 1;
      }
   }
   return 0;
}
......
      if (IsRoadsOverlay(1, a2, x, y, z)) return 1;
      if (IsRoadsOverlay(0, a2, x, y, z)) return 1;


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

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

Re: RMG SOD

Сообщение RoseKavalier » 30 ноя 2019, 16:48

RMG_00543ED0 places rock terrain underground where needed.
Here I cancelled the subroutine:
Изображение

A look at RMG_00543ED0 helps us decipher the format of sub_005B79B0:
unsigned int __thiscall sub_005B79B0(H3SmartPointer *a1, int a2, int a3, unsigned int a4, unsigned int a5)

I've seen the "H3SmartPointer" type a few times, it's essentially
Код: Выделить всё
template <typename T>
   struct H3SmartPointer
   {      
   protected:
      // * +0
      BOOL8 m_used;
      h3unk _f_01[3];
      T* m_data;
   public:
      T* get() { return m_data; }
      T* operator->() { return get(); }
   };

In this case the m_data is a 68-byte allocated structure by the constructor sub_5B7570 which looks to have some binary trees.
sub_5B7570(H3SmartPointer& This, arg2,terrain_type, arg4)
No clue what arg4 does, I tried changing its value and couldn't see any effects. It seems like it's always 4.

To call the constructor there is another structure that is needed (arg2)
Код: Выделить всё
struct RMG_MapInfo
{
   h3func* vTable;
   BOOL8 has_map; // looks like a smart pointer, just not implemented code-wise yet
protected:
   h3unk _f_05[3];
public:
   RMG_MapItem* underground_map;
   int width;
   int height;
   BOOL underground;
public:
   RMG_MapInfo(RMG_Main* main, BOOL underground = TRUE);
   ~RMG_MapInfo();
};


inline RMG_MapInfo::RMG_MapInfo(RMG_Main* main, BOOL underground) :
vTable((h3func*)0x6409DC), has_map(0), underground_map(), width(main->map.mapWidth), height(main->map.mapHeight), underground(underground)
{
   underground_map = &main->map.mapItems[width * height];
}


You can try to initiate the smartpointer with a dummy structure like so:
Код: Выделить всё
struct Foo
{
   int data[2];

   Foo(RMG_MapInfo& info, int terrain)
   {
      THISCALL_4(Foo*, 0x57B7570, this, &info, terrain, 4);
   }
   ~Foo()
   {
      THISCALL_1(VOID, 0x5B7610, this);
   }
   VOID Draw(int x, int y, int width, int height)
   {
      THISCALL_5(VOID, 0x5B79B0, this, x, y, width, height);
   }
};


I don't know if this is of any help to you but with the above you could theoretically do:
Код: Выделить всё
void Test(RMG_Main* main)
{
   RMG_MapInfo info(main, TRUE);
   Foo bar(info, 9);

   bar.Draw(23, 24, 1, 1);
}
Последний раз редактировалось RoseKavalier 30 ноя 2019, 17:31, всего редактировалось 2 раз(а).
Вернуться к началу

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

Re: RMG SOD

Сообщение RoseKavalier » 30 ноя 2019, 17:28

IMO the logic that comes before the sub_5B79B0 call at 543F82 should reveal how to get whether a tile needs to be rock.
Код: Выделить всё
Given RMG_MapItem* mi...
auto& data = mi->tileData;
if (!data.isBlocked && data.mustBeBlocked && mi->GetLand() != NH3Terrains::ROCK && !data.shore)
     // rock terrain


However even this condition is not quite sufficient to guarantee this mapitem will be rock terrain.
Изображение
Вернуться к началу

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

Re: RMG SOD

Сообщение as239 » 01 дек 2019, 08:47

Looks like no needs to do something with RMG_00543ED0 the problem is different.
My main goal is to change the order of the formation of roads, it gives a lot of opportunities.
But i have problems with it in the underground.
F.e. template 6LM10A. Here is the scheme:
http://forum.heroesworld.ru/showpost.ph ... stcount=21
Here is the right connections from the red without any program changes:
 
Изображение

The road from red goes to neutral zone, which have3 monoliths: one to the teal AI, another to the tan AI and another to the local treasure.

Here is my best result:
 
Изображение

The connection are wrong.
And also there is a problem with some roads:
 
Изображение

Tile x 113 y 108 z 1 has mask 010, tile x 113 y 107 z 1 has mask 110.
I need to block tile with mask 010 otherwise there will be completely wrong roads zones connections.
And of course it causes this problem with road display.

I tried many options, and now I have no idea what else can be done.
I tried to visually understand the location of the zones and the values ​​of the mask in this stage, but this is so far from the real map.
mask:
 
Изображение

zones:
 
Изображение


The main code is simple here is:
Код: Выделить всё
   for (int lvl = 0; lvl < NumLvl; lvl++)
   {
      for (int x = 0; x < MapSize; x++)
      {
         for (int y = 0; y < MapSize; y++)
         {
            RMG_MapItem *xyz = rmg->map.GetMapItem(x, y, lvl);
            //if (lvl == 1)
            //{
            //   sprintf(h3_TextBuffer, "%d,%d,%d%d%d,%d", x, y, xyz->tileData.isBlocked, xyz->tileData.mustBeBlocked, xyz->tileData.canBeBlocked, xyz->zone.zone1);
            //   out << h3_TextBuffer << std::endl;
            //}
            //continue;
            if (xyz->tileData.isBlocked == 0 && xyz->tileData.mustBeBlocked == 1 && xyz->tileData.canBeBlocked == 1 && lvl == 0) {
               xyz->tileData.isBlocked = 0;   ///must be clear
               xyz->tileData.mustBeBlocked = 0;//must be blocled
               xyz->tileData.canBeBlocked = 0; //may be blocked or clear
               Map011.push_back(xyz);
            }
            else if (xyz->tileData.isBlocked == 0 && xyz->tileData.mustBeBlocked == 1 && xyz->tileData.canBeBlocked == 0 && lvl == 0) {
               xyz->tileData.isBlocked = 1;
               xyz->tileData.mustBeBlocked = 1;
               xyz->tileData.canBeBlocked = 0;
               //Map010.push_back(xyz);
            }
            else if ( xyz->tileData.isBlocked == 0 && xyz->tileData.mustBeBlocked == 1 && xyz->tileData.canBeBlocked == 1 && lvl == 1 ) {
               xyz->tileData.isBlocked = 0;
               xyz->tileData.mustBeBlocked = 0;
               xyz->tileData.canBeBlocked = 0;
               Map011.push_back(xyz);
            }
            else if (xyz->tileData.isBlocked == 0 && xyz->tileData.mustBeBlocked == 1 && xyz->tileData.canBeBlocked == 0 && lvl == 1 ) {
                  xyz->tileData.isBlocked = 0;
                  xyz->tileData.mustBeBlocked = 0;
                  xyz->tileData.canBeBlocked = 0;
                  Map010und.push_back(xyz);
            }

         }
      }
   }


In the attachment, the source code with the described example.
I would be grateful for any help, how to get the right roads connections in the underground.
Вложения
RMG_sourse_code.zip
(8.63 КБ) Скачиваний: 7
Вернуться к началу

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

Re: RMG SOD

Сообщение as239 » 13 дек 2019, 14:34

А как получить типы дорог, указанные при старте игры?
Нигде не нашел.
Вернуться к началу

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

Re: RMG SOD

Сообщение RoseKavalier » 13 дек 2019, 18:01

0x54878B
Код: Выделить всё
road = rand() % 3 + 1;
Вернуться к началу

Пред.След.

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

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

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

cron