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


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

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

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

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

Сообщение Ben80 » 15 июн 2019, 17:06

I put H3Base.h into /includes and succesfully compiled, but have got crash during HD mod map generation.
Problem with MSVCR90. So, I have to upgrade Visual Studio 2008 - then H3Base.h will work.

I would like to erase substring from "Template" (including "Template") up to "Random seed".

 Код
Код: Выделить всё
int __stdcall hideTemplateName(LoHook* h, HookContext* c)
{
    H3String* desc = (H3String*)(*(int*)0x699538 + 0x1FB4C + 4);

   if(char* pChar = desc->String())
   {
      std::string str(pChar);
      if(str.find("Random seed") != -1)
      {
         int x1 = str.find("Template");
         int x2 = str.find("Random seed");
         desc->Remove(x1, x2);
      }
   }   
      
   return EXEC_DEFAULT;
}


Код: Выделить всё
Exception

{

   Module:    MSVCR90.dll

   Adress:      0x72F9B9CC

   Code:        EXCEPTION_ACCESS_VIOLATION

   Flags:       0x00000000

   Information: read of address: 0x000000C1

}
Последний раз редактировалось Ben80 16 июн 2019, 04:49, всего редактировалось 3 раз(а).
Вернуться к началу

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 » 15 июн 2019, 17:11

Тут всё просто: игра позволяет сделать активным любого героя по ЛКМ, если ни один герой не активен. Мы добавляем ещё одну проверку: если зажат Shift, считать, что ни один герой неактивен. При этом никакие поля (типа selected_hero_id) мы не меняем.

* * *
Я пробовал ставить хайхук на ProcessAdvMapKeyPress(), который устанавливал selected_hero_id в -1 при зажатии шифта. Всё работало, но активный герой исчезал с карты. Я думаю, нужно смотреть в сторону mouseManager, чтобы он тоже считал, что ни один герой не активен, несмотря на значение поля selected_hero_id.

Текущая идея такая: поставить брейкпоинт на чтение поля selected_hero_id. Наверняка его значение проверяется при наведении курсора на героя. Если это так, то будет достаточно ещё одного похожего лоухука.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 15 июн 2019, 18:22

@RoseKavalier

В конечном итоге пришлось перенести адрес хука.
В сетевой игре мой хук, установленный внутри NewGame, приводил к непонятным ошибкам.

Может быть, это как-то связано с тем, что на NewGame установлен HiHook самого HD мода.
Вернуться к началу

offlineigrik  
Подмастерье
Подмастерье
 
Сообщения: 108
Зарегистрирован: 14 сен 2017, 12:35
Пол: Не указан
Поблагодарили: 84 раз.

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

Сообщение igrik » 16 июн 2019, 04:48

AlexSpl писал(а):

Текущая идея такая: поставить брейкпоинт на чтение поля selected_hero_id. Наверняка его значение проверяется при наведении курсора на героя. Если это так, то будет достаточно ещё одного похожего лоухука.

AlexSpl, я конечно щас такое спрошу)))
Расскажи детально как ставить hardware breakpoint (на Olly 2.01), на примере: чтение поля selected_hero_id (как я понимаю это свойство o_GameMgr->Player->selected_hero_id).
Вот никогда не умел ставить такие брекпоинты и до сих пор не догоняю как это сделать.
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 16 июн 2019, 04:57

Ставишь точку останова где-нибудь до того, как начался интересующий тебя код (чтобы структуры игры уже определили свое местоположение в памяти).
Находишь в окне дампа OllyDbg (внизу слева) адрес, соответствующий o_GameMgr->Player->selected_hero_id.
И правой кнопкой на этом адресе - Breakpoint->Hardware или Breakpoint->Memory
Продолжаешь выполнение программы.
Последний раз редактировалось Ben80 16 июн 2019, 05:41, всего редактировалось 1 раз.
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

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

Сообщение as239 » 16 июн 2019, 05:13

Найти значение флаг HW rules, не получилось - нашел в памяти эту строку, поставил Breakpoint->Hardware, в итоге попадаю в процедуру вывода диалога и как там найти значение флага - не понятно.

Как обходной вариант, мне поможет название шаблона, как его получить?
В homm3.h нашел только полную строку - с датой и именем игрока.

У RoseKavaleir, вроде есть то что нужно, но не могу проверить - вылетает при выводе сообщения:
Код: Выделить всё
   RMG_Template *ааа;
   h3_MessageBox(aaa->name.String());
Вернуться к началу

offlineas239  
имя: Анатолий
Ветеран
Ветеран
 
Сообщения: 527
Зарегистрирован: 29 дек 2018, 14:17
Пол: Мужчина
Поблагодарили: 38 раз.

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

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

@RoseKavaleir

Having crash with this code, whats wrong with it?
Код: Выделить всё
int __stdcall AddFirstAidHP(LoHook* h, HookContext* c)
{
   H3Hero *hero = (H3Hero*)(c->arg_n(1));
   if (!hero) return EXEC_DEFAULT;
   int FisrtAidLevel = hero->secSkill[ NH3Skills::FIRST_AID ];
   c->eax = c->eax + FisrtAidLevel; //CRASH HERE!
   
//   sprintf(buffer,"First Aid Level: %d", FisrtAidLevel); //CRASH HERE!
//   h3_MessageBox(h3_TextBuffer);

    return EXEC_DEFAULT;
}
pi->WriteLoHook(0x4E6723, AddFirstAidHP );
Вернуться к началу

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

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

Сообщение RoseKavalier » 16 июн 2019, 13:59

Code
This line is wrong, arg_n() returns *(int*)(ebp + 4 * (n + 1)), i.e. PUSH arguments.
Код: Выделить всё
H3Hero *hero = (H3Hero*)(c->arg_n(1));

In this function, H3Hero is a THIS argument, it is passed to the function through ECX and at the start of the functions it will be passed to another register (ESI, EDI or EBX usually) for the remainder of the scope of the function.
Try c->local_n(1) instead, it's maybe still in a register but I didn't run the game to check... speaking of which:

Цитата:
h3_MessageBox(aaa->name.String());

There is no safety check in String() whether the string exists (if (!str) return ""), the name has not necessarily been assigned when you checked this.

Breakpoints in Olly.

INT3 Breakpoints
These breakpoints are placed over code that will be run.
It will cover only the length of the instruction selected.

Setting a breakpoint : click on an address and press F2
Clearing a breakpoint : same as setting

Memory Breakpoints
These breakpoints are placed over memory, where data is read and written to.

Setting a breakpoint : click on an address and press SHIFT+F3
Clearing a breakpoint : F2

Conditional Breakpoints
These are more advanced format of the INT3 breakpoint where you can add extra specifications.

Setting a breakpoint : click on an address and press SHIFT+F2
Clearing a breakpoint : F2

Few examples...

0x4F6C00 (textbox)

Press F2, now every time a textbox is made, the code will stop and you can examine registers...
 
Изображение
Изображение


You can move forward one step with F7 which is called 'STEP INTO', that is if there is a CALL instruction, it will go to the called function and always go deeper in the rabbit hole.
There is a similar action with F8 which is called 'STEP OVER'. It's the same thing as STEP INTO, except it... steps over CALL instructions.

To resume the game normally, press the PLAY button (4th from left) or F9.
There's another fun one: CTRL+F9 which automatically runs the remainder of the function, stopping at RETN instruction.

Okay... so now about Conditional Breakpoint.
I want the game to stop at 0x4F6C00 ONLY when I right-click a textbox.
From understanding that RMC textbox requires second argument to be 4 and that this function is __fastcall (which uses both ECX and EDX) then the conditional breakpoint becomes
Код: Выделить всё
EDX == 4

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


Now it only stops here if EDX is 4, i.e. RMC textbox.
 
Изображение


That's the base! There are more advanced techniques but this alone kept me busy a while when I learned them :smile4:
Вернуться к началу

offlineBen80  
имя: Сергей
Эксперт
Эксперт
 
Сообщения: 1318
Зарегистрирован: 18 июн 2017, 06:49
Пол: Не указан
Поблагодарили: 336 раз.

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

Сообщение Ben80 » 16 июн 2019, 15:18

@RoseKavalier,

Thanks, I have compiled Dll with H3Base.h included (without Bersy's recipe, simply I have found error in my code).

Now I return back address of my hook.
So, it seems my old code (without H3Base.h) made all needed work but give some error/warning to system and it leads to instable work of HD mod.
But it is interesting what is "system" in this case ? Is it simply code execution or HD mode have some special checks for errors (let me remind that my LoHook inside procedure, which is HiHook'ed by HD mod).
Вернуться к началу

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

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

Сообщение RoseKavalier » 16 июн 2019, 17:08

@Ben80
Inspect RMG_WriteHeader_54A1A0 to patch it directly to h3m file, text source is 0x6828BC.
Try this:
Код: Выделить всё
static const PCHAR mapDesc = "Map created by the Random Map Generator.  Random seed was %i, size %i, levels %i, humans %i, computers %i, water %s, monsters %i";

pi->WriteDword(0x54A2E0 + 1, mapDesc); // replace sprintf string template
pi->WriteByte(0x54A2D9, 0x90); // nop PUSH template name
pi->WriteByte(0x54A2EE + 2, ByteAt(0x54A2EE + 2) - 4); // remove 1 instruction from __cdecl stack management
Вернуться к началу

Пред.След.

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

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

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