Русское сообщество по скриптингу

Вызов/перехват takedamage и других...

Все вопросы по скриптингу для Metamod, помощь в редактировании плагинов.
Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только скриптинга для
Metamod.


Правила при создании новой темы:
1. При вставке кода плагина необходимо использовать тег [pawn], в противном случае, если тег [pawn] не отображает ваш код, можно использовать тег [code].
2. Любые изображения должны быть загружены, как вложения к вашему сообщению.
3. При описании проблемы или запросе на помощь в редактировании плагина обязательно выкладывайте исходник плагина.

Вызов/перехват takedamage и других...

Сообщение PRoSToTeM@ » 06 ноя 2011, 18:55

Как сделать вызов и перехват takedamage и других виртуальных функций?...
Аватара пользователя
PRoSToTeM@
Скриптер
 
Сообщения: 2498
Зарегистрирован: 26 мар 2010, 00:12
Благодарил (а): 438 раз.
Поблагодарили: 1125 раз.

Re: Вызов/перехват takedamage и других...

Сообщение KORD_12.7 » 07 ноя 2011, 12:20

Поддерживаю.

_http://aghl.ru/ - Half-Life и Adrenaline Gamer: за пределами возможного
Аватара пользователя
KORD_12.7
Скриптер
 
Сообщения: 298
Зарегистрирован: 28 сен 2009, 10:14
Откуда: Владивосток
Благодарил (а): 142 раз.
Поблагодарили: 257 раз.
Опыт программирования: Больше трех лет
Языки программирования: Half-Life
Opposing Force
Adrenaline Gamer
Counter-Strike

Re: Вызов/перехват takedamage и других...

Сообщение PRoSToTeM@ » 07 ноя 2011, 14:55

Накопал кое-что, спасибо проксу за ссыль.
Вы должны зарегистрироваться, чтобы видеть ссылки.
Аватара пользователя
PRoSToTeM@
Скриптер
 
Сообщения: 2498
Зарегистрирован: 26 мар 2010, 00:12
Благодарил (а): 438 раз.
Поблагодарили: 1125 раз.

Re: Вызов/перехват takedamage и других...

Сообщение DJ_WEST » 07 ноя 2011, 16:41

К примеру, на основе Hamsandwich takedamage прописывается индекс виртуальной функции в hamdata.ini. Который потом парсится в config_parser.cpp. В функции process_key:
[pawn]
  1.  

  2.         for (int i=0; i< HAM_LAST_ENTRY_DONT_USE_ME_LOL; i++)

  3.         {

  4.                 if (strncmp(data, hooklist[i].name, size)==0)

  5.                 {

  6.                         data+=size+1;

  7.  

  8.                         trim_line(data);

  9.                         int value=read_number(data);

  10.  

  11.                         hooklist[i].isset=1;

  12.                         hooklist[i].vtid=value;

  13.  

  14.  

  15.                         set=1;

  16.                         break;

  17.  

  18.                 }

  19.         }

  20.  
[/pawn]
Соответственно значения сохраняются в hooklist, используя enum из ham_const.h, к примеру:
[pawn]
  1. Ham_TakeDamage
[/pawn]
Если вести отсчет от 0, то Ham_TakeDamage - 9 в нашем enum'е.

Сама структура hooklist прописана в hooklist.h:
[pawn]
  1. typedef struct hook_s

  2. {

  3.         int isset;                                                              // whether or not this hook is registered with hamdata

  4.         int vtid;                                                               // vtable index of this function

  5.         const char *name;                                               // name used in the keys

  6.         bool isvoid;                                                    // whether or not the target trampoline uses voids

  7.         int  paramcount;                                                // how many parameters are in the func

  8.         void *targetfunc;                                               // the target hook

  9.         int (*makefunc)(AMX *, const char*);    // function that creates forwards

  10.         cell (*call)(AMX *, cell*);                             // function to call the vcall

  11. } hook_t;

  12.  

  13. extern hook_t hooklist[];
[/pawn]

Также в hook_native.cpp заполняется наш hooklist:
[pawn]
  1. hook_t hooklist[] =

  2. {

  3.         { V("spawn",                                    Void_Void) },

  4.         { V("precache",                                 Void_Void) },

  5.         { V("keyvalue",                                 Void_Int) },

  6.         { V("objectcaps",                               Int_Void) },

  7.         { V("activate",                                 Void_Void) },

  8.         { V("setobjectcollisionbox",    Void_Void) },

  9.         { V("classify",                                 Int_Void) },

  10.         { V("deathnotice",                              Void_Entvar) },

  11.         { V("traceattack",                              Void_Entvar_Float_Vector_Trace_Int) },

  12.         { V("takedamage",                               Int_Entvar_Entvar_Float_Int) },
[/pawn]
На основе define:
[pawn]
  1. #define V(__KEYNAME, __STUFF__) 0, 0, __KEYNAME, RT_##__STUFF__, PC_##__STUFF__, reinterpret_cast<void *>(Hook_##__STUFF__), Create_##__STUFF__, Call_##__STUFF__
[/pawn]

В результате чего еще будут функции, если рассматривать takedamage - Int_Entvar_Entvar_Float_Int с префиксом Call_, Hook_, Create_, который есть в call_funcs.cpp (.h), hook_callbacks.cpp (.h), hook_create.cpp (.h).
По идеи в Call происходит вызов функции, в Hook ее перехват.

Еще в ham_utils.h есть:
[pawn]
  1. inline void **GetVTable(void *pthis, int size)

  2. {

  3.         return *((void***)(((char*)pthis)+size));

  4. }

  5. inline void *GetVTableEntry(void *pthis, int ventry, int size)

  6. {

  7.         void **vtbl=GetVTable(pthis, size);

  8.  

  9.         return vtbl[ventry];

  10. }
[/pawn]

Которые используются другой функцией _GetFunction из call_funcs.cpp:
[pawn]
  1.  

  2. inline void *GetFunction(void *pthis, int id, bool &istramp)

  3. {

  4.         istramp=false;

  5.         void *func=GetVTableEntry(pthis, hooklist[id].vtid, Offsets.GetBase());

  6.  

  7.         // Check to see if it's a trampoline

  8.         CVector<Hook *>::iterator end=hooks[id].end();

  9.  

  10.         for (CVector<Hook *>::iterator i=hooks[id].begin();

  11.                  i!=end;

  12.                  ++i)

  13.         {

  14.                 if (func==(*i)->tramp)

  15.                 {

  16.                         istramp=true;

  17.                         return func;

  18.                 }

  19.         }

  20.  

  21.         return func;

  22. }

  23.  

  24. inline void *_GetFunction(void *pthis, int id)

  25. {

  26.         void **vtbl=GetVTable(pthis, Offsets.GetBase());

  27.  

  28.         int **ivtbl=(int **)vtbl;

  29.         void *func=ivtbl[hooklist[id].vtid];

  30.  

  31.         // Iterate through the hooks for the id, see if the function is found

  32.         CVector<Hook *>::iterator end=hooks[id].end();

  33.  

  34.         for (CVector<Hook *>::iterator i=hooks[id].begin();

  35.                  i!=end;

  36.                  ++i)

  37.         {

  38.                 // If the function points to a trampoline, then return the original

  39.                 // function.

  40.                 if (func==(*i)->tramp)

  41.                 {

  42.                         printf("Func=0x%08X\n",reinterpret_cast<unsigned int>((*i)->func));

  43.                         return (*i)->func;

  44.                 }

  45.         }

  46.  

  47.         // this is an original function

  48.         printf("Func=0x%08X\n",reinterpret_cast<unsigned int>(func));

  49.         return func;

  50. }
[/pawn]

GetFunction используется в SETUP:
[pawn]
  1. #define SETUP(NUMARGS)                                  \

  2.         if (((NUMARGS + 2) * sizeof(cell)) > (unsigned)params[0])       \

  3.         {                                                                       \

  4.                 MF_LogError(amx, AMX_ERR_NATIVE, "Bad arg count.  Expected %d, got %d.", NUMARGS + 2, params[0] / sizeof(cell));        \

  5.                 return 0;                                               \

  6.         }                                                                       \

  7.         int func=params[1];                                     \

  8.         int id=params[2];                                       \

  9.         CHECK_FUNCTION(func);                           \

  10.         CHECK_ENTITY(id);                                       \

  11.         void *pv=IndexToPrivate(id);            \

  12.         bool istramp;                                           \

  13.         void *__func=GetFunction(pv, func, istramp);    \

  14.         if (!istramp && !gDoForwards)           \

  15.         {                                                                       \

  16.                 gDoForwards=true;                               \

  17.         }
[/pawn]
Где получаем __func, а помним что у takdamage - Int_Entvar_Entvar_Float_Int, то находим ее с префиксом Call_ и смотрим:
[pawn]
  1. cell Call_Int_Entvar_Entvar_Float_Int(AMX *amx, cell *params)

  2. {

  3.         SETUP(4);

  4.  

  5.         int id3=*MF_GetAmxAddr(amx, params[3]);

  6.         int id4=*MF_GetAmxAddr(amx, params[4]);

  7.         float f5=amx_ctof2(*MF_GetAmxAddr(amx, params[5]));

  8.         int i6=*MF_GetAmxAddr(amx, params[6]);

  9.  

  10.         CHECK_ENTITY(id3);

  11.         CHECK_ENTITY(id4);

  12.  

  13.         entvars_t *ev3=&(INDEXENT_NEW(id3)->v);

  14.         entvars_t *ev4=&(INDEXENT_NEW(id4)->v);

  15.  

  16. #ifdef _WIN32

  17.         return reinterpret_cast<int (__fastcall *)(void *, int, entvars_t *, entvars_t *, float, int)>(__func)(pv, 0, ev3, ev4, f5, i6);

  18. #elif defined __linux__

  19.         return reinterpret_cast<int (*)(void *, entvars_t *, entvars_t *, float, int)>(__func)(pv, ev3, ev4, f5, i6);

  20. #endif

  21. }
[/pawn]
Здесь видно используется SETUP, а затем наш __func через reinterpret_cast.

Это лишь структура работы, чтобы более внятно понять весь механизм надо знать C++, чтобы понимать все действия в коде.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Вызов/перехват takedamage и других...

Сообщение PRoSToTeM@ » 07 ноя 2011, 17:33

DJ_WEST, спасибо что объяснил.

Добавлено спустя 20 секунд:
Сейчас буду пробовать.
Аватара пользователя
PRoSToTeM@
Скриптер
 
Сообщения: 2498
Зарегистрирован: 26 мар 2010, 00:12
Благодарил (а): 438 раз.
Поблагодарили: 1125 раз.

Re: Вызов/перехват takedamage и других...

Сообщение noo00oob » 07 ноя 2011, 18:11

Уменя хукнуть то получилось, а вот оригинальную вызвать не получается.
Один фрукт, страдающий недостачей времени, нашел его ради меня любимого и писал(а):
noo00oob, зачем родился на свет вообще? срать на форумах это понятно.. больше изъеба не найти как бэ? а то, что ты недоношенная скотина, сдерживайся, детка.
noo00oob
 
Сообщения: 1061
Зарегистрирован: 09 янв 2010, 21:52
Благодарил (а): 258 раз.
Поблагодарили: 395 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Half-Life

Re: Вызов/перехват takedamage и других...

Сообщение PRoSToTeM@ » 07 ноя 2011, 18:37

Ещё бы саму энтитю получить и аргументы)).
Аватара пользователя
PRoSToTeM@
Скриптер
 
Сообщения: 2498
Зарегистрирован: 26 мар 2010, 00:12
Благодарил (а): 438 раз.
Поблагодарили: 1125 раз.

Re: Вызов/перехват takedamage и других...

Сообщение noo00oob » 07 ноя 2011, 18:44

Тамж написано как её получить, правда токо для винды:
Код: Выделить всё
mov eax, [ecx + 4];  get this->pev
mov eax, [eax + 520]; get pev->pContainingEntity
mov pEdict, eax
Один фрукт, страдающий недостачей времени, нашел его ради меня любимого и писал(а):
noo00oob, зачем родился на свет вообще? срать на форумах это понятно.. больше изъеба не найти как бэ? а то, что ты недоношенная скотина, сдерживайся, детка.
noo00oob
 
Сообщения: 1061
Зарегистрирован: 09 янв 2010, 21:52
Благодарил (а): 258 раз.
Поблагодарили: 395 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Half-Life

Re: Вызов/перехват takedamage и других...

Сообщение PRoSToTeM@ » 07 ноя 2011, 18:49

Насколько я помню мне это валило сервер).
Аватара пользователя
PRoSToTeM@
Скриптер
 
Сообщения: 2498
Зарегистрирован: 26 мар 2010, 00:12
Благодарил (а): 438 раз.
Поблагодарили: 1125 раз.

Re: Вызов/перехват takedamage и других...

Сообщение noo00oob » 07 ноя 2011, 18:52

Ну вот те 100% рабочее, опять же токо для винды. Эдикт через ENT( pev ) получишь если надо.
Код: Выделить всё
entvars_t *pev;
__asm mov eax, [ ecx + 4 ];
__asm mov pev, eax;
Один фрукт, страдающий недостачей времени, нашел его ради меня любимого и писал(а):
noo00oob, зачем родился на свет вообще? срать на форумах это понятно.. больше изъеба не найти как бэ? а то, что ты недоношенная скотина, сдерживайся, детка.
noo00oob
 
Сообщения: 1061
Зарегистрирован: 09 янв 2010, 21:52
Благодарил (а): 258 раз.
Поблагодарили: 395 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Half-Life

След.

Вернуться в Скриптинг

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

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

cron