Hi,
I'm trying to write my own extension to simulate a player killing another player.
I have a native to apply damage to an entity but the call to TakeDamage at the end of teh function causes the server to crash! Any help would be appreciated! I tried using virtual functions also but the result is the same.
Tested under linux only:
...
Code:
typedef void (*TakeDamageFunction)(const CTakeDamageInfo &);
TakeDamageFunction g_funcTakeDamage;
...
Code:
// hack: implementation of CTakeDamageInfo constructor
CTakeDamageInfo::CTakeDamageInfo(CBaseEntity *pInflictor, CBaseEntity *pAttacker, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType, Vector *reportedPosition)
{
m_hInflictor = pInflictor;
pAttacker = (pAttacker != NULL) ? pAttacker : pInflictor;
m_vecDamageForce = damageForce;
m_vecDamagePosition = damagePosition;
m_flDamage = flDamage;
m_bitsDamageType = bitsDamageType;
m_iDamageCustom = iKillType;
m_flBaseDamage = BASEDAMAGE_NOT_SPECIFIED;
if(reportedPosition != NULL)
m_vecReportedPosition = *reportedPosition;
m_flMaxDamage = flDamage;
m_iAmmoType = -1;
}
...
Code:
cell_t ApplyDamage(IPluginContext *pContext, const cell_t *params)
{
int iParam=1;
cell_t nEntity = params[iParam++];
cell_t nAttacker = params[iParam++];
cell_t nInflictor = params[iParam++];
float fDamage = (float) params[iParam++];
cell_t nDamageType = params[iParam++];
CBaseEntity *pEntity = GetBaseEntityByIndex(nEntity);
CBaseEntity *pAttacker = GetBaseEntityByIndex(nAttacker);
CBaseEntity *pInflictor = GetBaseEntityByIndex(nInflictor);
if(pEntity == NULL || pAttacker == NULL || pInflictor == NULL)
return false;
Vector vecOrigin(0.0f, 0.0f, 0.0f);
CTakeDamageInfo TDI(pInflictor, pAttacker, vecOrigin, vecOrigin, fDamage, nDamageType, /*iKillType*/0);
#define USE_VFUNCTS
#ifdef USE_VFUNCTS
void **this_ptr = *(void ***)&pEntity;
void **vtable = *(void ***)pEntity;
void *func = vtable[g_nOnTakeDamageOffset];
class VfuncEmptyClass {};
union {void (VfuncEmptyClass::*mfpnew)(CTakeDamageInfo const &);
#ifndef __linux__
void *addr; } u; u.addr = func;
#else // GCC's member function pointers all contain a this pointer adjustor. You'd probably set it to 0
struct {void *addr; intptr_t adjustor;} s; } u; u.s.addr = func; u.s.adjustor = 0;
#endif
(reinterpret_cast<VfuncEmptyClass*>(this_ptr)->*u.mfpnew)(TDI);
#else
#ifdef WIN32
g_funcTakeDamage(pEntity /*this*/, 0 /*dummy*/, TDI);
#else
// (g_funcTakeDamage)(pEntity, TDI);
(g_funcTakeDamage)(TDI);
#endif
#endif
return true;
}
Full sourcecode of extension and test plugin: