Hey ovidius,
i found your code snippet too and tried to use it in an metamod plugin but unfortunately i cant get it working.. i am trying to install the hook in ServerActivate_Post and i am using the base offset for tfc linux servers but the MakeHook function aborts because of vtable being NULL
Code:
#ifdef _WIN32
#define VirtFuncTakeDamage 10
#elif __linux__
#define VirtFuncTakeDamage 12
#endif
#ifdef _WIN32
#define PrivateToEdict(pPrivate) (*(entvars_t **)((char*)pPrivate + 4))->pContainingEntity
#elif __linux__
#define PrivateToEdict(pPrivate) (*(entvars_t **)pPrivate)->pContainingEntity
#endif
void *pOrigFuncTakeDamage = NULL;
#ifdef _WIN32
int __fastcall HookTakeDamage(void *pthis, int i, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamage)
#elif __linux__
int HookTakeDamage(void *pthis, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamage)
#endif
{
SERVER_PRINT("::TakeDamage prehook!\n");
#ifdef _WIN32
int iOrigRet = reinterpret_cast<int(__fastcall *)(void *, int, entvars_t *, entvars_t *, float, int)>(pOrigFuncTakeDamage)(pthis, 0, pevInflictor, pevAttacker, flDamage, bitsDamage);
#elif __linux__
int iOrigRet = reinterpret_cast<int(*)(void *, entvars_t *, entvars_t *, float, int)>(pOrigFuncTakeDamage)(pthis, pevInflictor, pevAttacker, flDamage, bitsDamage);
#endif
SERVER_PRINT("::TakeDamage posthook!\n");
return iOrigRet;
}
void MakeHookTakeDamage()
{
edict_t *pEdict = CREATE_ENTITY();
CALL_GAME_ENTITY(PLID, "func_breakable", &pEdict->v);
if (pEdict->pvPrivateData == NULL)
{
REMOVE_ENTITY(pEdict);
return;
}
#ifdef _WIN32
void **vtable = *((void***)((char*)pEdict->pvPrivateData));
#elif __linux__
void **vtable = *((void***)(((char*)pEdict->pvPrivateData) + 0x470)); // 0x470 is the tfc base offset (is this correct for func_breakables too?)
#endif
REMOVE_ENTITY(pEdict);
if (vtable == NULL)
return;
int **ivtable = (int **)vtable;
pOrigFuncTakeDamage = (void *)ivtable[VirtFuncTakeDamage];
#ifdef _WIN32
DWORD OldFlags;
VirtualProtect(&ivtable[VirtFuncTakeDamage], sizeof(int *), PAGE_READWRITE, &OldFlags);
#elif __linux__
mprotect(&ivtable[VirtFuncTakeDamage], sizeof(int*), PROT_READ | PROT_WRITE);
#endif
ivtable[VirtFuncTakeDamage] = (int *)HookTakeDamage;
}
Anyone has an idea why this could fail? I tried dumping pvPrivateData but it seems that its size is very small but i dont know why.
Would appreciate any help