Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Хуки на исполняемый код из ERA
DF2 :: ФОРУМЫ > Игровые форумы > Heroes of Might & Magic III > Моды
feanor
http://wforum.heroes35.net/showthread.php?...=85765#pid85765
©Berserker
Цитата
ERM Hooker v1.0.0
Era plugin allows to easily install and remove code hooks which execute corresponding ERM handlers.
{code block address} => {erm function receiving the context}

API:
(*
ErmHandlerFunc receives two SN:X arguments: (Context pointer, ExecuteOverwrittenCode? = 1)
If you set ExecuteOverwrittenCode to 0, be sure to change context.RetAddr
Context structure (offsets in brackets):
: EDI (0), ESI (4), EBP (8), ESP (12), EBX (16), EDX (20), ECX (24), EAX (28)
: RetAddr (32)

Returns non-zero value on success. Fails if another hook is set at the same address.
*)
function SetHook (Addr: pointer; ErmHandlerFunc: integer): longbool; stdcall;
(*
Removes erm hook at specified address. Returns true if hook existed.
*)
function UnsetHook (Addr: pointer): longbool; stdcall;
(*
Prints list of hooks in "Debug\Era\erm hooks.txt"
*)
procedure PrintHooks; stdcall;

All hooks are automatically removed on the following events: new game start, game loading, game leaving (Era 2.55+).

Plugin supports both Era 2.46 and Era 2.55+. For 2.55+ it handles OnGenerateDebugInfoEvent (you can generate list of hooks by pressing F11) and OnGameLeave event.

Example of usage:
Цитата
!?FU102777;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/5933074/102778; 0x5a8812

!?GM0;
!!FU102777:P;

!?PI;
!!FU102777:P;

!?FU102778;
!!IF:M^Hi from hook!^;

igrik
Можно также собрать небольшую базу хуков штоле:
thanks feanor
Код
4854731 [адрес хука]
   !?FU[номер функции];
   !!SN:X?y3/0;             // выполнять ли затёртые команды, говорим НЕТ
   !!VRy4:Sy3 +32;             // RetAddr (32)
   !!IF:Q1^Посетить?^;         // Вопрос
   !!UN&1:Cy4/4/4854918;     // Да
   !!UN&-1:Cy4/4/4854782;     // Нет
© Gavek
Код
4899236 [адрес хука]
   !?FU[номер функции];
   !!SN:X?y3/0;
   !!VRy4:Sy3 +32;
   !!IF:Q1^Посетить ли склеп?^;
   !!UN&1:Cy4/4/4899301; yes
   !!UN&-1:Cy4/4/4899429; no

thanks gamecreator
5090948[адрес хука]
Код
!?FU[номер функции];
   !!SN:X?y3/0;             // выполнять ли затёртые команды, говорим НЕТ
   !!VRy4:Sy3 +32;             // y4 указывает на адрес возврата, подменяем его
   !!UN:Cy4/4/5090961;         // адрес команды возврата

thanks Bes
можно эмулировать одетость почти любого арта на герое
Код
5084256 [адрес хука]
   !?FU[номер функции];
   !!SN:X?y2;                 // системный параметр хука
; получить номер арта
   !!VRy3:Sy2 +12;             // перейти к [ESP]
   !!UN:Cy3/4/?y4;             // прочитать содержимое [ESP]
   !!VRy5:Sy4 +8;             // перейти к [ESP +8]
   !!UN:Cy5/4/?y6;             // прочитать содержимое [ESP +8] (номер арта)
        
; получить номер героя
   !!VRy9:Sy2 +24;              // перейти к [ECX]
   !!UN:Cy9/4/?y10;          // прочитать содержимое [ECX]
   !!VRy11:Sy10 :1170 -63638;// получить номер героя
        
   *--------------------------------------------
; тут можно типо приодеть героя, даже если на нем нет этих артов
; для сравнения исхомых артов y6=[номер арта] y11=[номер героя]
   !!VRy20:S72; [установил свой арт, который типо одет на кукле]   тест на крыльях ангела
   !!VRy21:S52; [установил номер героя, на котором типо одет арт]  тест на октавии
   *--------------------------------------------
        
   !!if&y6=y20/y11=y21:;  условие сравнения артов
   !!SN:X?y2/0;            // получить первый параметр хука и запретить выполенние следующих за хуком внутриигровых команд
   !!VRy14:Sy2 +32;        // указывает на адрес возврата, подменяем его]
   !!UN:Cy14/4/5084351;    // адрес команды следующей за вызовом функции
   !!VRy19:Sy2 +28;        // перейти к [EAX]
   !!UN:Cy19/4/1;            // установить [EAX] равным 1, типо арт есть
   !!en:;

thanks feanor
Код
!?FU37100;
; Установка расширенных специалистов по монстрам
; 5137296 [адрес хука]
!!FU37101:P28/132/500/3/10/10/10/10;
!?FU37101;
; x1 - номер героя
; x2 - номер монстра
; x3 - здоровье
; x4 - скорость
; x5 - атака
; x6 - защита
; x7 - мин.урон
; x8 - макс.урон
!!SN:X?y1;
; EDI (0), ESI (4), EBP (8), ESP (12), EBX (16), EDX (20), ECX (24), EAX (28)
; RetAddr (32)
!!VRy2:Sy1 +24;             // перейти к [ECX]
!!UN:Cy2/4/?y3;             // прочитать содержимое [ECX]
!!VRy4:Sy3 +26;             // перейти к номеру героя [ECX +26]
!!UN:Cy4/4/?y5;             // узнать номер героя
!!FU&y5<>x1:E;              // если не нужный герой, то выход

!!VRy2:Sy1 +12;             // перейти к [ESP]                
!!UN:Cy2/4/?y3;             // прочитать содержимое [ESP]
!!VRy4:Sy3 +8;              // перейти к номеру монстра [ESP +8]
!!UN:Cy4/4/?y5;             // узнать номер монстра
!!FU&y5<>x2:E;              // если не нужный монстр, то выход

!!VRy5:Sy3 +12;             // перейти к структуре монстра [ESP +12]
!!UN:Cy5/4/?y6;             // прочитать содержимое [ESP +12]

!!VRy7:Sy6 +76;             // перейти к hit_points
!!UN:Cy7/4/?y8;             // прочитать hit_points
!!VRy8:+x3;                 // увеличить
!!UN:Cy7/4/y8;              // записать новое кол-во hit_points

!!VRy7:Sy6 +80;             // перейти к _speed_
!!UN:Cy7/4/?y8;             // прочитать _speed_
!!VRy8:+x4;                 // увеличить
!!UN:Cy7/4/y8;              // записать новый _speed_

!!VRy7:Sy6 +84;             // перейти к _attack_
!!UN:Cy7/4/?y8;             // прочитать _attack_
!!VRy8:+x5;                 // увеличить
!!UN:Cy7/4/y8;              // записать новый _attack_

!!VRy7:Sy6 +88;             // перейти к _defence_
!!UN:Cy7/4/?y8;             // прочитать _defence_
!!VRy8:+x6;                 // увеличить
!!UN:Cy7/4/y8;              // записать новый _defence_

!!VRy7:Sy6 +92;             // перейти к _damage_min_
!!UN:Cy7/4/?y8;             // прочитать _damage_min_
!!VRy8:+x7;                 // увеличить
!!UN:Cy7/4/y8;              // записать новый _damage_min_

!!VRy7:Sy6 +96;             // перейти к _damage_max_
!!UN:Cy7/4/?y8;             // прочитать _damage_max_
!!VRy8:+x8;                 // увеличить
!!UN:Cy7/4/y8;              // записать новый _damage_max_
; и т.д.

thanks feanor
Код
5128624 [адрес хука]
   !?FU[номер функции];
   !!SN:X?y1;
; EDI (0), ESI (4), EBP (8), ESP (12), EBX (16), EDX (20), ECX (24), EAX (28)
; RetAddr (32)
   !!VRy2:Sy1 +24;             // перейти к [ECX]
   !!UN:Cy2/4/?y3;             // прочитать содержимое [ECX]
   !!VRy4:Sy3 +26;             // перейти к номеру героя [ECX +26]
   !!UN:Cy4/4/?y5;             // узнать номер героя
   !!HEy5:Fd/d/d/?y10;         // узнать параметр знания
   !!VRy2:Sy1 +16;             // перейти к [EBX]
   !!VRy10:-1;                 // короче нуно отнять еденицу
   !!UN:Cy2/4/dy10;         // добавить к [EBX] добавить приход маны

Код
4254704 [адрес хука]
!?FU[номер функции];
!!SN:X?y3/0;
!!VRy4:Sy3 +32;
!!UN:Cy4/4/4256154;
Код
ZVSE
** Скрипт первентивного удара у Лазурных драконов
!?PI;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/4463326/36896;

!?GM0;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/4463326/36896;

!?FU36896;                  [перед ударом]
!!BG:N?y2 E?y4;                 [номер атакующего и получающего стеков]
!!BMy4:T?y3;                    [тип монстра защитника]
!!BMy2:T?y5;                    [тип монстра атакующего]
!!FU&y3<>132|y5=132:E;          [только, если Лазурик]

!!BMy4:G62/?y62/d;              [проверить на ослепление]
!!BMy4:G70/?y70/d;              [проверить на окаменение]
!!BMy4:G74/?y74/d;              [проверить на паралич]
!!FU|y62>0/y70>0/y74>0:E;       [выход, если закл.есть на стеке]

!!UN:C6919200/4/?y10;           [комбатмэнеджер]
!!VRy11:Sy4 *1352 +21708 +y10;  [стек защитника как атакующий]
!!VRy21:Sy2 *1352 +21708 +y10;  [стек атакующего как получающий]
!!SN:E4461360/2/y11/y21/2;      [нанести удар]
!!VRy11:+1216; !!UN:Cy11/1/1;   [не отвечать на атаку]

!!BMy2:N?y5;   !!FU&y5>0:E;     [выход, если атакующие еще остались живы]
!!BMy2:F?y5;                    [а если мертвы ...]
!!VRy5:|32768 -32768;           [забрать у стека двойной удар]
!!BMy2:Fy5;                     [хотя может быть полубаг после их воскрешения]
!!SN:X?y1/0;                    [и + отменить ответный удар]
!!VRy1:+32;                     [переход к адресу возврата]
!!UN:Cy1/4/4463493;             [установить прыжок в 0x441B85]
** end
Код
ZVSE
** Скрипт ответного выстрела
!?PI;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/4456318/36894;  [после первого выстрела]
!!SN:Ey2/1/4456338/36895;  [перед вторым выстрелом (а-ля грандэльфы)]

!?GM0;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/4456318/36894;  [после первого выстрела]
!!SN:Ey2/1/4456338/36895;  [перед вторым выстрелом (а-ля грандэльфы)]

!?FU36894;                 [после первого выстрела]
!!BG:E?y3 A?y4 N?y5;             [номер стека получающего и наносящего урон]
!!BMy3&y3>-1:N?y2;               [проверка на жив ли получающий урон]
!!FU|y4<>7/y3=-1/y3=y5/y2<1:E;   [если выстрел, если стеки не одинаковые и жив ли получающий]
!!BMy3:F?y1;                     [получить флаги получающего]
!!VRy1:&4;                       [проверить его на стрелка]
!!BMy3:G-48/?y2/d;               [есть ли у него выстрелы]
!!FU|y1<1/y2<1:E;                [выход, если не стрелок или нет боезапаса]
!!UN:C6919200/4/?y10;            [комбатмэнеджер]
!!VRy11:Sy3 *1352 +21708 +y10;   [структура атакующего стек]
!!VRy21:Sy5 *1352 +21708 +y10;   [структура стека цель]
!!SN:E4453920/2/y11/y21;         [выстрелить]

!?FU36895;                 [перед вторым выстрелом (а-ля грандэльфы)]
!!SN:X?y1;                       [параметры хука]
!!VRy2:Sy1 +4;   !!UN:Cy2/4/?y3; [структура атакующего монстра]
!!VRy4:Sy3 +76;  !!UN:Cy4/4/?y5; [узнать их кол-во]
!!FU&y5>0:E;                     [выход, если после ответки еще хоть один жив]
!!SN:X?y1/0;                     [если нет, то отменить второй выстрел]
!!VRy1:+32;                      [переход к адресу возврата]
!!UN:Cy1/4/4456346;              [установить прыжок в 0x43FF9A]
** end
Код
ZVSE

** Скрипт: Изменение специальности (тип 1) по существам.
**         Бонус = Уровень героя - уровень монстра.
!?PI;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/5137688/26003;   [0x004E6518]

!?GM0;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/5137688/26003;   [0x004E6518]

!?FU26003;
!!SN:X?y1/0;
; [получаем параметры героя]
!!VRy2:Sy1 +28; [EAX]    !!UN:Cy2/4/?y3;  [структура героя]
!!VRy3:+85; [EAX+0x55]   !!UN:Cy3/4/?y4;  [узнать уровень героя]
; [получаем параметры монстра]
!!VRy5:Sy1 +4;  [ESI]    !!UN:Cy5/4/?y6;  [структура монстра]
!!VRy7:Sy6 +4;  [ESI+4]  !!UN:Cy7/4/?y7;  [уровень монстра]
!!VRy7:+1;                                [переводим в привычный уровень монстра]
; [бонус от специальности]
!!VRy10:Sy4 -y7;                          [разница уровня героя и монстра]
!!VRy10&y10<0:S0;                         [проверка на отрицательное значение]
; [устанавливаем бонусы]
!!VRy11:Sy6 +84;       !!UN:Cy11/4/dy10;  [бонус к атаке]
!!VRy12:Sy6 +88;       !!UN:Cy12/4/dy10;  [бонус к защите]

!!VRy99:Sy1 +32; !!UN:Cy99/4/5137828;  [возврат в 0x004E65A4]
** end
Код
ZVSE

** Скрипт: Изменение специальности (тип 5): скорость.
** Бонус теперь не фиксированный, а может устанавливаться
** через HE:X5/[бонус скорости] для каждого отдельновзятого героя
!?PI;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/5138023/26005;
!?GM0;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/5138023/26005;
!?FU26005;
!!SN:X?y1;              !!UN:Cy1/4/?y11;   [EDI] хранит бонус к скорости
!!VRy2:Sy1 +28;         !!UN:Cy2/4/?y12;   [EAX] указатель на таблицу специальностей
!!VRy3:Sy1 +20;         !!UN:Cy3/4/?y13;   [EDX] смещение на нужного героя
!!VRy4:Sy13 *8 +y12;    !!UN:Cy4/4/?y14;   [первый параметр (=5) в HE:X[5]/[2]
!!VRy5:Sy13 *8 +y12 +4; !!UN:Cy5/4/?y15;   [второй параметр (=2) в HE:X[5]/[2]
!!VRy15:-2;             !!UN:Cy1/4/dy15;   [установить наш бонус с вычетом 2 (от стандатного кода)]
** end
Код
!?PI;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/6241544/26000;

!?GM0;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/6241544/26000;

!?FU26000;
!!SN:X?y1;
; показ бонуса к морали
!!UN:Cy1/4/?y50;
!!VRy50:+1256;
!!UN:Cy50/1/?y51;
!!VRy51&y51<-3:S-3;
!!VRz9&y51=0:S^ ^;
!!VRz9&y51>0:S^+^;    !!VRy51&y51>3:S3;
!!VRz12:S^%Z9%Y51^;
!!VRy25:S12*512 +9597416;  получить адрес z переменной
!!SN:E6386834/1/80; !!VRy10:Sv1;
!!SN:E6014624/2/y10/46/209/20/20/y25/6687924/4/-1/10/0/8;
!!VRv10:Sv1;
!!VRy26:S10*4 +8943204;
!!VRy4:Sy1 +16;  ebx
!!UN:Cy4/4/?y4;
!!VRy5:Sy4 +8;   ebx+8
!!UN:Cy5/4/?y5;
!!SN:E6283984/2/y4/y5/1/y26;  AddItemToList
; показ бонуса к удаче
!!UN:Cy1/4/?y52;
!!VRy52:+1260;
!!UN:Cy52/1/?y53;
!!VRy53&y53<-3:S-3;
!!VRz10&y53=0:S^ ^;
!!VRz10&y53>0:S^+^;  !!VRy53&y53>3:S3;
!!VRz13:S^%Z10%Y53^;
!!VRy35:S13*512 +9597416;  получить адрес z переменной
!!SN:E6386834/1/80; !!VRy30:Sv1;
!!SN:E6014624/2/y30/99/209/20/20/y35/6687924/4/-1/10/0/8;
!!VRv11:Sv1;
!!VRy36:S11*4 +8943204;
!!VRy4:Sy1 +16;  ebx
!!UN:Cy4/4/?y4;
!!VRy5:Sy4 +8;   ebx+8
!!UN:Cy5/4/?y5;
!!SN:E6283984/2/y4/y5/1/y36;  AddItemToList
** end
Код
!?PI;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/6253538/26001;

!?GM0;
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/6253538/26001;

!?FU26001;
; показ продолжительности заклинаний:
!!SN:X?y1;
!!VRy3:Sy1 +4;     !!UN:Cy3/4/?y13;   // ESI
                   !!UN:Cy13/4/?y43;  // получить номер закла (-1 если его нет)
!!VRy23:Sy13 +12;  !!UN:Cy23/4/?y33;  // получить продолжительность заклинания
!!FU|y43<0/y43=47/y43=59/y43=72/y33<1:E;
!!VRz13:S^x%Y33^;
!!VRy25:S13*512 +9597416; адрес z переменной
!!VRy70:Sy1 +8;   !!UN:Cy70/4/?y71;
!!VRy78:Sy71 -28;  !!UN:Cy78/4/?y78;
!!VRy79:Sy71 -32;  !!UN:Cy79/4/?y79;  !!VRy69:S3003 -y79;
!!VRy81:Sy71 -40;  !!UN:Cy81/4/?y81;  !!VRy82:Sy81+48;
                                      !!VRy84:Sy81+56;  !!UN:Cy84/4/?y85;
!!SN:E6386834/1/80; !!VRy10:Sv1;
!!SN:E6014624/2/y10/y78/202/46/20/y25/6687924/4/y69/10/0/8;
!!VRv15:Sv1;
!!VRy26:S15*4 +8943204;
!!SN:E6283984/2/y82/y85/1/y26;  AddItemToList
** end
Richter
Цитата(igrik @ 17 Jan 2015, 12:03) *
Можно также собрать небольшую базу хуков штоле:

Код
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;       получить адрес плагинахука
!!SN:L^era.dll^/?y3 Ay3/^PluginExists^/?y4 Ey4/1/^erm_hooker^; проверка на наличие плагина хука
!!SN&v1>0:Ey2/1/[адрес функции]/[номер функции]; работает, только если есть планиг хука

Если в правильно понял,то
!?PI;
!!SN:L^erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:L^era.dll^/?y3 Ay3/^PluginExists^/?y4 Ey4/1/?v1;
!!SN&v1>0:Ey2/1/4854731/31865;

Пишет не верный синтаксис для команды !!SN
Останавливается на строке Ey4/1/?v1, тоже самое если Ey4/1/^erm_hooker^. Etm_hooker.era на месте
!!SN:L^erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/4854731/31865;
Без проверки хука работает, может не так понял
igrik
Вообще то должно работать. Проверьте еще раз правильно ли скопировали код.
Richter
Для сокровищницы если первый раз отменить, бой уже не вызывается, наверно параметры надо обратно менять?
feanor
Цитата
Можно также собрать небольшую базу хуков штоле:
Надо, да
Но я ленивай, так что могу только подогнать адресов функций для экспериментов
Richter
Цитата(feanor @ 17 Jan 2015, 21:10) *
Цитата
Можно также собрать небольшую базу хуков штоле:
Надо, да
Но я ленивай, так что могу только подогнать адресов функций для экспериментов

Поможете найти функции для всех типов сокровищниц, как для 16 типа определили?
igrik
Цитата(feanor @ 17 Jan 2015, 19:10) *
Но я ленивай, так что могу только подогнать адресов функций для экспериментов

это уже интересно!
feanor
Например
0x4E6390 - расчет бонусов героя к отряду монстров (от артефактов, атаки-защиты, спецы и так далее). Покрывает все случаи, от боя до отображения в окне юнита.
Параметры - ecx - структура героя, первый стековый ([esp+4]) - номер существа, второй стековый ([esp+8]) - структура монстра, которую и нужно менять

Формат структуры монстра описан в начале темы инж.анализа, повторю:

CODE
NOALIGN struct _CreatureInfo_ : public _Struct_
{
_int_ town;
_int_ level;
_char_* sound_name;
_char_* def_name;
_int_ flags;
_char_* name_single;
_char_* name_plural;
_char_* specification_description;

//_int_ cost_wood;
//_int_ cost_mercury;
//_int_ cost_ore;
//_int_ cost_sulfur;
//_int_ cost_crystal;
//_int_ cost_jems;
//_int_ cost_gold;
union
{
_Resources_ cost_n;
_int_ cost[7];
};

_int_ fight_value;
_int_ AI_value;
_int_ growth;
_int_ horde_growth;
_int_ hit_points;
_int_ speed;
_int_ attack;
_int_ defence;
_int_ damage_min;
_int_ damage_max;
_int_ shots;
_int_ spells_count;
_int_ advmap_low;
_int_ advmap_high;
};
feanor
0x4E27C0 - проверка на возможность положить артефакт в слот.
Можно врезаться в начало, посмотреть параметры (ecx - структура героя, [esp+4] - номер артефакта, [esp+8] - слот), при необходимости изменить - записать в eax 0 или 1 и прыгнуть на ret (004E2AA9)



Код
//----- (004E27C0) --------------------------------------------------------
// Slot=-1 - check all slots
char __thiscall MayThisArtBePlacedToThisSlot(_Hero_ *this, int art, unsigned int slot)
igrik
Цитата
Параметры - ecx - структура героя, первый стековый ([esp+4]) - номер существа, второй стековый ([esp+8]) - структура монстра, которую и нужно менять

как получить номер героя я пока так и не понял, а вот по существам поправочка:
; первый стековый ([esp+8]) - номер существа,
; второй стековый ([esp+12]) - структура монстра
feanor
Цитата
как получить номер героя я пока так и не понял


у тебя описалова структуры чтоль нет?

[ecx+26]

CODE
struct _Hero_
{
_int16_ x; // +0
_int16_ y; // +2
_int16_ z; // +4
_byte_ visible; // +6
_dword_ mui_xyz; // +7
_byte_ field_0B; // +11
// miu = map_item under hero
_dword_ miu_object_type; // +12
_dword_ miu_object_c_flag; // +16
_dword_ miu_setup; // +20
_word_ spell_points; // +24
_dword_ id; // +26
_dword_ id_wtf; // +30
_int8_ owner_id; // +34
_char_ name[13]; // +35
_dword_ _class; // +48
_byte_ pic; // +52
_dword_ aim_x; // +53
_dword_ aim_y; // +57
_word_ aim_z; // +61
_int16_ last_magic_level; // +61. Последний из уровней, на переходе на который предложили магию стихии.
_byte_ field_41[3]; // +65
_byte_ x_0; // +68
_byte_ y_0; // +69
_byte_ run; // +70
_byte_ field_47; // +71
_byte_ flags; // +72
_dword_ movement_points_max; // +73
_dword_ movement_points; // +77
_dword_ expa; // +81
_word_ level; // +85
_dword_ visited[10]; // +87
_byte_ field_7F[16]; // +127
_byte_ random_number_for_level_up_seed; // +143
_int8_ last_wisdom_level; // +144. Последний из уровней, на переходе на который предложили мудрость.
_Army_ army; // +145
_byte_ second_skill[28]; // +201
_byte_ second_skill_show[28]; // +229
_dword_ second_skill_count; // +257
_dword_ temp_mod_flags; // + 261
_byte_ field_109[4]; // +265
_byte_ dd_cast_this_turn; // +269
_dword_ disguise; // +270
_dword_ field_112; // +274
_dword_ field_116; // +278
_byte_ d_morale_1; // +282
_byte_ d_luck; // +283
_byte_ is_sleeping_byte11C; // +284
_byte_ field_11E[16]; // +284
_Artifact_ doll_art[19]; // +301
_byte_ free_add_slots; // +453
_byte_ locked_slot[14]; // +454
_Artifact_ backpack_art[64]; // +468
_byte_ backpack_arts_count; // +980
_dword_ sex; // +981
_bool8_ has_biography; // +985
_HStringF_ biography; // +986
_bool8_ has_spell[70]; // +1002
_bool8_ has_spell_with_arts[70]; // +1072
//_byte_ primary_skill[4];
_byte_ attack; // +1142
_byte_ defence; // +1141
_byte_ power; // +1142
_byte_ knowledge; // +1143
_byte_ field_47A[24]; // +1144
}
igrik
не а, не нашел в инженерном анализе
Richter
Как можно открыть диалог любого существа, кто нить знает?
igrik
Тут закопано
Код
!?FU[номер функции];
; © Master Of Puppets
; x1 - герой (0) или город (1)
; x2 - номер героя или города
; x3 - номер слота
; x4 - наличие кнопки "Уволить": 1 - да, 0 - нет
; x5 - закрыть диалог при отпускании мыши: 1 - да, 0 - нет
; x6/x7 - координаты выводимого окна
!!UN:C6933756/4/?y5;
!!OW:C?y2;
!!VRy1:Sy2*360;
!!VRy5:-y1;
!!UN:C6919480/4/?y10;
!!if&x1=0;  если герой
  !!VRy1:Sx2*1170+y5+3041;
  !!VRy3:Sx3*4+y1;
  !!UN:Cy3/4/<0;
  !!FU&1:E;
  !!VRy3:Sy1-145;
  !!SN:E5007632/2/y10/y1/x3/y3/0/x6/x7/x4/x5;
!!en;
!!if&x1=1;  если город
  !!VRy1:Sy5+2884;
  !!UN:Cy1/4/?y2;
  !!VRy1:Sx2*360+y2+224;
  !!VRy3:Sx3*4+y1;
  !!UN:Cy3/4/<0;
  !!FU&1:E;
  !!VRy3:Sy1-224;
  !!SN:E5007632/2/y10/y1/x3/y3/0/x6/x7/x4/x5;
!!en;
feanor
Вот что меня определенно раздражает в хукалке, дак это невозможность ставить второй хук на то же место, как в патчере.
Ну и высокоуровневости хотелось бы, сплайсы, например, с вызовом замещаемой функции.
Richter
Код
!?FU[номер функции];
; © Master Of Puppets
; x1 - герой (0) или город (1)
; x2 - номер героя или города
; x3 - номер слота
...
...

Это отличная функция от Master Of Puppets! Правда её уже пользую. Нужно, чтобы неслотового существа диалог открывался, а любого). Копался в декомпиляте, который вы выложили. Там функция такая есть, только вот самому мне её на ERM не сделать.
major
С этим плагином при запуске h3era сразу выпадает "Runtime error 217 at ####" (адреса всегда разные).
Richter
Подскажите пожалуйста, где поставить хук, чтобы можно было подменить изображение специальности героя без использования !#UN:G2/#/#/#;?
XEPOMAHT
Цитата(Richter @ 20 Jan 2019, 21:51) *
Подскажите пожалуйста, где поставить хук, чтобы можно было подменить изображение специальности героя без использования !#UN:G2/#/#/#;?


Такое без хуков делается: в нужном тебе триггере получаешь адреса следующих данных: HeroSpecWoG[номер_твоего_героя].SpecPicInd[0] и HeroSpecWoG[номер_твоего_героя].SpecPicInd[1] и заменяешь в них номера картинок специализаций.

Можно и поставить хук на 4Е1F2А, но это уже вог сам сделал за тебя.
Richter
Цитата(XEPOMAHT @ 21 Jan 2019, 02:00) *
Можно и поставить хук на 4Е1F2А...


Вылет "без объяснения причин".
Цитата(XEPOMAHT @ 21 Jan 2019, 02:00) *
...в нужном тебе триггере получаешь адреса следующих данных: HeroSpecWoG[номер_твоего_героя].SpecPicInd[0] и HeroSpecWoG[номер_твоего_героя].SpecPicInd[1] и заменяешь в них номера картинок специализаций.

Как это делается? Триггер !?CM2;
XEPOMAHT
Цитата(Richter @ 21 Jan 2019, 05:53) *
Вылет "без объяснения причин".


Написано ж, хук на 4Е1F2А. Зачем вы поставили его на 5FF3A0? Вам нужно перехватить вызов процедуры, а не саму процедуру (т.е. должно быть "mov dword [4Е1F2B], адрес_вашей_функции"). И выход из вашей функции должен уходить на дальнейший код (т.е. на 4E1F2F) со сдвигом стека. Соответственно, вызов функции, изменяющий элемент диалога с нужными вам параметрами (т.е. с нужным вам номером спрайта специализации), вы тоже должны сделать в вашем хуке, иначе картинка специализации просто не появится в диалоге.

Цитата(Richter @ 21 Jan 2019, 05:53) *
Как это делается? Триггер !?CM2;


Любой триггер, идущий после заполнения данными по-умолчанию таблицы HeroSpecWoG. Да хоть в Триггер_Перед_показом_карты.
Richter
Цитата(XEPOMAHT @ 21 Jan 2019, 11:46) *
Написано ж, хук на 4Е1F2А..

Точно, без инициативы никуда) Исправил. Правда ничего похожего на нужное значение не обнаружено.
Цитата(XEPOMAHT @ 21 Jan 2019, 11:46) *
Любой триггер, идущий после заполнения данными по-умолчанию таблицы HeroSpecWoG. Да хоть в Триггер_Перед_показом_карты.

Про это всё равно не понятно)
А где в WoG на UN:G2 хук стоит?
XEPOMAHT
Цитата(Richter @ 21 Jan 2019, 10:46) *
Правда ничего похожего на нужное значение не обнаружено.


Его нужно самому записывать в стек и вызывать соответствующую функцию, устанавливающую элемент диалога. Само по себе оно в твоём коде не появится.

Цитата(Richter @ 21 Jan 2019, 10:46) *
А где в WoG на UN:G2 хук стоит?


Зачем там нужен хук, если UN:G2 изменяет только воговскую таблицу HSpecNames и никак не влияет на оригинальный код?

Код
        case 2:  // Спец.Героев 2/номер_героя/тип_текста(3-картинка)/zvar(номер картинки спец+1)
          t=Mp->n[1];  if((t<0)||(t>=HERNUM)){ MError("\"!!UN:G\"-wrong hero number."); RETURN(0) }
          t2=Mp->n[2]; if((t2<0)||(t2>3)){ MError("\"!!UN:G\"-wrong herospec text type number (0...3)."); RETURN(0) }
          if(t2==3){ // картинка
            v=HSpecNames[t].PicNum-1;
            if(Apply(&v,4,Mp,3)) break;
            HSpecNames[t].PicNum=v+1;
            break;
          }
          v=HSpecNames[t].Var[t2];
          if(Apply(&v,4,Mp,3)) break;
          HSpecNames[t].Var[t2]=v;
          if(v!=0){
            if((v<1)||(v>1000)){ MError("\"UN:G\"-wrong z var index (1...1000)."); RETURN(0) }
            switch(t2){
              case 0: // short
                HSpecTable[t].SpShort=ERMString[v-1];
                break;
              case 1: // full
                HSpecTable[t].SpFull=ERMString[v-1];
                break;
              case 2: // descr
                HSpecTable[t].SpDescr=ERMString[v-1];
            }
          }else{
            switch(t2){
              case 0: // short
                HSpecTable[t].SpShort=HSpecBack[t].SpShort;
                break;
              case 1: // full
                HSpecTable[t].SpFull=HSpecBack[t].SpFull;
                break;
              case 2: // descr
                HSpecTable[t].SpDescr=HSpecBack[t].SpDescr;
                break;
            }
          }
          break;
        default: MError("\"!!UN:G\"-wrong first parameter."); RETURN(0)
      }
      break;
Richter
Цитата(XEPOMAHT @ 21 Jan 2019, 13:09) *
Его нужно самому записывать в стек и вызывать соответствующую функцию

Программистом не являюсь пока что.
Как то картинка появляется в диалоге, а мне просто нужен доступ к её номеру в пределах функции обновления, для изменения.
Например регистр EDX используемый в адресе 4E1F2F уже содержит номер картинки ,сам номер в динамическом адресе. Изменения в последнем ничего не дают, видимо потому что после call.
XEPOMAHT
Цитата(Richter @ 21 Jan 2019, 11:56) *
Например регистр EDX используемый в адресе 4E1F2F уже содержит номер картинки ,сам номер в динамическом адресе.


EDX в этой функции может содержать номер героя ИЛИ адрес структуры героя (т.к. функция его использующая - универсальная). Менять - не советую - будут вылеты.

Проще делать БЕЗ ХУКОВ (что за мания ставить хуки, когда можно сделать без них).
Richter
Мания, потому что результата хочется, а тут уже кто как умеет). Сможете подсказать как получить значение?
feanor
По-моему, в !?CM2 хук вообще не поможет, потому что картинка уже нарисована и является частью диалога героя.
Надо, видимо, сообщение отправлять.
igrik
Цитата(Richter @ 21 Jan 2019, 12:44) *
Мания, потому что результата хочется, а тут уже кто как умеет). Сможете подсказать как получить значение?

Код
!?FU77004; триггер ЭРА (открытие окна героя)
!!VRy2:S<номер_героя> *16 +10787776;
!!UN:Cy2/4/?y3;
!!VRy3:-1;
!!IF:M^Номер картинки %Y3^;

; заменяем картинку специализации (на стрелковые башни)
!!UN:Cy2/4/357;   номер картинки 356 +1


И вот сразу работающий скрипт при любом клике в окне героя
Код
!?CM2;         [клик в окне героя №28 (Мальком)]
!!VRy2:S28 *16 +10787776;  [таблица HSpecNames[hero_number].PicNum]
!!CM:I?y3;                 [оплучаем id элемента клика]
!!FU|y3<1/y3>356:E;        [выход, если вышли за границы диапазона картинок]
!!VRy3:+1;                 [+1 к номеру картинки (так работает WoG)]
!!UN:Cy2/4/y3;             [установили номер картинки]
!!UN:R3/-1;                [обновили диалог героя]
Richter
Получить, изменить предлагаемые вторичные навыки при повышении уровня героя.
Код
!?FU303045;          
!!SN:L^EraPlugins\erm_hooker.era^/?y1 Ay1/^SetHook^/?y2;
!!SN:Ey2/1/5090856/x1;
!?FU318945;
!!SN:X?y1;
; EDI (0), ESI (4), EBP (8), ESP (12), EBX (16), EDX (20), ECX (24), EAX (28)
; RetAddr (32)
!!VRy2:Sy1 +0;     переход к EDI        
!!VRy4:Sy1 +4;     переход к ESI    
!!UN:Cy2/4/?y3;   узнать EDI (правый навык)
!!UN:Cy4/4/?y5;   узнать ESI (левый навык)
!!UN:Cy2/4/0; установить правый навык на поиск пути
!!UN:Cy4/4/0; установить левый навык на поиск пути

!?HL-1;Триггер повышения уровня
!!FU303045:P318945; Выполнить функцию
Richter
Цитата(igrik @ 21 Jan 2019, 16:46) *
Код
!?FU77004; триггер ЭРА (открытие окна героя)
!!VRy2:S<номер_героя> *16 +10787776;
!!UN:Cy2/4/?y3;
!!VRy3:-1;
!!IF:M^Номер картинки %Y3^;


К сожалению на получение картинки специализации героя не работает, выдаёт значение -1 в триггерах !?FU77004, !?CM2;
На установку работает хорошо. Подскажите как узнать картинку специализации героя плиз.

Разобрался, специализации соответствуют порядковым номерам героя. Вопрос отпадает.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.