PHP Code:
#include <extdll.h>
#include <meta_api.h>
#include <stdarg.h>
#include <cbase.h>
#ifdef __linux__
#include <sys/mman.h>
#include <malloc.h>
#endif
#if _MSC_VER
#if _MSC_VER >= 1400
#define stricmp _stricmp
#endif
#endif
#ifdef __linux__
#define stricmp strcasecmp
#endif
#ifdef _WIN32
#define VirtFuncSpawn 0
#define VirtFuncTakeDamage 12
#define VirtFuncKilled 14
#elif __linux__
#define VirtFuncSpawn 2
#define VirtFuncTakeDamage 14
#define VirtFuncKilled 16
#endif
#ifdef _WIN32
#define PrivateToEdict(pPrivate) (*(entvars_t **)((char*)pPrivate + 4))->pContainingEntity
#elif __linux__
#define PrivateToEdict(pPrivate) (*(entvars_t **)pPrivate)->pContainingEntity
#endif
#if defined __linux__
#define EXTRAOFFSET 5 // offsets 5 higher in Linux builds
#else
#define EXTRAOFFSET 0 // no change in Windows builds
#endif // defined __linux__
#define OFFSET_TEAM 114 + EXTRAOFFSET
plugin_info_t Plugin_info =
{
META_INTERFACE_VERSION, // ifvers
"WPMG", // name
"Alpha", // version
"2011/11/7", // date
"WPMG Team", // author
"http://www.wpmg.ru", // url
"WPMG", // logtag, all caps please
PT_ANYTIME, // (when) loadable
PT_ANYPAUSE // (when) unloadable
};
meta_globals_t *gpMetaGlobals;
mutil_funcs_t *gpMetaUtilFuncs;
enginefuncs_t g_engfuncs;
globalvars_t *gpGlobals;
#ifdef _WIN32
void __fastcall HookSpawn(void *pthis)
#elif __linux__
void HookSpawn(void *pthis)
#endif
{
#ifdef _WIN32
reinterpret_cast<int (__fastcall *)(void *, int)>(pOrigFuncSpawn)(pthis, 0);
#elif __linux__
reinterpret_cast<int (*)(void *)>(pOrigFuncSpawn)(pthis);
#endif
}
#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
{
#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
return iOrigRet;
}
#ifdef _WIN32
int __fastcall HookKilled( void *pthis, int i, entvars_t *pevAttacker, int iGib )
#elif __linux__
int HookKilled( void *pthis, entvars_t *pevAttacker, int iGib )
#endif
{
#ifdef _WIN32
int iOrigRet = reinterpret_cast<int (__fastcall *)(void *, int, entvars_t *, int)>(pOrigFuncKilled)(pthis, 0, pevAttacker, iGib);
#elif __linux__
int iOrigRet = reinterpret_cast<int (*)(void *, entvars_t *, int)>(pOrigFuncKilled)(pthis, pevAttacker, iGib);
#endif
return iOrigRet;
}
void MakeHookSpawn()
{
edict_t *pEdict = CREATE_ENTITY();
CALL_GAME_ENTITY(PLID, "player", &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) + 0x94));
#endif
REMOVE_ENTITY(pEdict);
if(vtable == NULL)
return;
int **ivtable = (int **)vtable;
pOrigFuncSpawn = (void *)ivtable[VirtFuncSpawn];
#ifdef _WIN32
DWORD OldFlags;
VirtualProtect(&ivtable[VirtFuncSpawn], sizeof(int *), PAGE_READWRITE, &OldFlags);
#elif __linux__
mprotect(&ivtable[VirtFuncSpawn], sizeof(int*), PROT_READ | PROT_WRITE);
#endif
ivtable[VirtFuncSpawn] = (int *)HookSpawn;
}
void MakeHookTakeDamage()
{
edict_t *pEdict = CREATE_ENTITY();
CALL_GAME_ENTITY(PLID, "player", &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) + 0x94));
#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;
}
void MakeHookKilled()
{
edict_t *pEdict = CREATE_ENTITY();
CALL_GAME_ENTITY(PLID, "player", &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) + 0x94));
#endif
REMOVE_ENTITY(pEdict);
if(vtable == NULL)
return;
int **ivtable = (int **)vtable;
pOrigFuncKilled = (void *)ivtable[VirtFuncKilled];
#ifdef _WIN32
DWORD OldFlags;
VirtualProtect(&ivtable[VirtFuncKilled], sizeof(int *), PAGE_READWRITE, &OldFlags);
#elif __linux__
mprotect(&ivtable[VirtFuncKilled], sizeof(int*), PROT_READ | PROT_WRITE);
#endif
ivtable[VirtFuncKilled] = (int *)HookKilled;
}
void ServerActivatePost(edict_t *pEdictList, int edictCount, int clientMax)
{
if (g_bActivated)
RETURN_META(MRES_IGNORED);
MakeHookSpawn();
MakeHookTakeDamage();
MakeHookKilled();
g_bActivated = true;
RETURN_META(MRES_IGNORED);
}
void ServerDeactivatePost()
{
if (!g_bInitialized)
RETURN_META(MRES_IGNORED);
g_bInitialized = false;
RETURN_META(MRES_IGNORED);
}
void ClientCommandPost(edict_t *pEntity)
{
const char *szArg;
szArg = CMD_ARGV(0);
if (stricmp(szArg, "say"))
RETURN_META(MRES_IGNORED);
szArg = CMD_ARGV(1);
if (stricmp(szArg, "/damage"))
RETURN_META(MRES_IGNORED);
#ifdef _WIN32
reinterpret_cast<int (__fastcall *)(void *, int, entvars_t *, entvars_t *, float, int)>((*((void***)((char*)pEntity->pvPrivateData)))[VirtFuncTakeDamage])(pEntity->pvPrivateData, 0, &(pEntity->v), &(pEntity->v), 50.0, DMG_SLASH);
#elif defined __linux__
reinterpret_cast<int (*)(void *, entvars_t *, entvars_t *, float, int)>((*((void***)(((char*)pEntity->pvPrivateData) + 0x94)))[VirtFuncTakeDamage])(pEntity->pvPrivateData, &(pEntity->v), &(pEntity->v), 50.0, DMG_SLASH);
#endif
RETURN_META(MRES_IGNORED);
}
int SpawnPre(edict_t *pEnt)
{
if (g_bInitialized)
RETURN_META_VALUE(MRES_IGNORED, 0);
g_bActivated = false;
g_bInitialized = true;
RETURN_META_VALUE(MRES_IGNORED, 0);
}
C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo, mutil_funcs_t *pMetaUtilFuncs)
{
gpMetaUtilFuncs = pMetaUtilFuncs;
*pPlugInfo = &Plugin_info;
return(TRUE);
}
static META_FUNCTIONS gMetaFunctionTable;
C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals, gamedll_funcs_t *pGamedllFuncs)
{
gpMetaGlobals = pMGlobals;
gMetaFunctionTable.pfnGetEntityAPI2 = GetEntityAPI2;
gMetaFunctionTable.pfnGetEntityAPI2_Post = GetEntityAPI2_Post;
memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS));
return(TRUE);
}
#ifdef __linux__
// linux prototype
C_DLLEXPORT void GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
{
#else
#ifdef _MSC_VER
// MSVC: Simulate __stdcall calling convention
C_DLLEXPORT __declspec(naked) void GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
{
__asm // Prolog
{
// Save ebp
push ebp
// Set stack frame pointer
mov ebp, esp
// Allocate space for local variables
// The MSVC compiler gives us the needed size in __LOCAL_SIZE.
sub esp, __LOCAL_SIZE
// Push registers
push ebx
push esi
push edi
}
#else // _MSC_VER
#ifdef __GNUC__
// GCC can also work with this
C_DLLEXPORT void __stdcall GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals)
{
#else // __GNUC__
// compiler not known
#error There is no support (yet) for your compiler. Please use MSVC or GCC compilers or contact the AMX Mod X dev team.
#endif // __GNUC__
#endif // _MSC_VER
#endif // __linux__
// ** Function core <--
memcpy(&g_engfuncs, pengfuncsFromEngine, sizeof(enginefuncs_t));
gpGlobals = pGlobals;
// --> ** Function core
#ifdef _MSC_VER
// Epilog
if (sizeof(int*) == 8)
{ // 64 bit
__asm
{
// Pop registers
pop edi
pop esi
pop ebx
// Restore stack frame pointer
mov esp, ebp
// Restore ebp
pop ebp
// 2 * sizeof(int*) = 16 on 64 bit
ret 16
}
}
else
{ // 32 bit
__asm
{
// Pop registers
pop edi
pop esi
pop ebx
// Restore stack frame pointer
mov esp, ebp
// Restore ebp
pop ebp
// 2 * sizeof(int*) = 8 on 32 bit
ret 8
}
}
#endif // #ifdef _MSC_VER
}
DLL_FUNCTIONS gFunctionTable;
C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
{
memset(&gFunctionTable, 0, sizeof(DLL_FUNCTIONS));
gFunctionTable.pfnSpawn = SpawnPre;
memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
return 1;
}
DLL_FUNCTIONS gFunctionTable_Post;
C_DLLEXPORT int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
{
memset(&gFunctionTable_Post, 0, sizeof(DLL_FUNCTIONS));
gFunctionTable_Post.pfnServerActivate = ServerActivatePost;
gFunctionTable_Post.pfnServerDeactivate = ServerDeactivatePost;
gFunctionTable_Post.pfnClientCommand = ClientCommandPost;
memcpy(pFunctionTable, &gFunctionTable_Post, sizeof(DLL_FUNCTIONS));
return 1;
}