Veteran Member
Join Date: Dec 2004
Location: UK
|
04-24-2006
, 14:00
|
#2
|
I used some code from PM that he uses in SourceHook for calling virtual functions, I've since converted it into macros for easy use.
You will need to tweak the macros to use what ever kind code you yourself use to supply vfunc offsets. The macros use a similar kind of style to SourceMM in declaring the number of parameters and whether it's a void return type. This works on both linux and windows though the vfunc indexes tend to differ by 1 between the two, I can't remember off hand which way round it is.
Mani
Code:
.h file
extern const QAngle &CBaseEntity_EyeAngles(CBaseEntity *pThisPtr);
extern void CBaseEntity_Teleport(CBaseEntity *pThisPtr, const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity);
extern Vector CBaseEntity_EyePosition (CBaseEntity *pThisPtr);
extern void CBaseEntity_GetVelocity(CBaseEntity *pThisPtr, Vector *vVelocity, AngularImpulse *vAngVelocity = NULL);
extern CBaseCombatCharacter *CBaseEntity_MyCombatCharacterPointer(CBaseEntity *pThisPtr);
extern void CBaseEntity_SetModelIndex(CBaseEntity *pThisPtr, int iIndex);
extern void CBasePlayer_Ignite(CBasePlayer *pThisPtr, float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false );
extern bool CBasePlayer_RemovePlayerItem(CBasePlayer *pThisPtr, CBaseCombatWeapon *pItem);
extern void CBasePlayer_WeaponDrop(CBasePlayer *pThisPtr, CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL);
extern CBaseEntity *CBasePlayer_GiveNamedItem(CBasePlayer *pThisPtr, const char *szName, int iSubType = 0 );
extern int CBaseCombatWeapon_GetPrimaryAmmoType(CBaseCombatWeapon *pThisPtr);
extern int CBaseCombatWeapon_GetSecondaryAmmoType(CBaseCombatWeapon *pThisPtr);
extern const char *CBaseCombatWeapon_GetName(CBaseCombatWeapon *pThisPtr);
extern CBaseCombatWeapon *CBaseCombatCharacter_Weapon_GetSlot(CBaseCombatCharacter *pThisPtr, int slot);
extern void CBaseCombatCharacter_Weapon_Switch(CBaseCombatCharacter *pThisPtr, CBaseCombatWeapon *pWeapon, int viewmodelindex = 0);
extern void CBaseCombatCharacter_GiveAmmo(CBaseCombatCharacter *pThisPtr, int iCount, int iAmmoIndex, bool bSuppressSound = false );
Code:
.cpp file
class ManiEmptyClass {};
#ifdef __linux__
#define VFUNC_OS_DEP void *addr; } u; u.addr = func;
#else
#define VFUNC_OS_DEP struct {void *addr; intptr_t adjustor;} s; } u; u.s.addr = func; u.s.adjustor = 0;
#endif
#define VFUNC_SETUP_PTR(_vfunc_index) \
{ \
void **this_ptr = *(void ***)&pThisPtr; \
void **vtable = *(void ***)pThisPtr; \
void *func = vtable[gpManiGameType->GetVFuncIndex(_vfunc_index)]
// Macros for defining functions to call vfuncs via offset.
#define VFUNC_CALL0(_vfunc_index, _return_type, _class_type, _func_name ) \
_return_type _func_name(_class_type *pThisPtr) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)();}
#define VFUNC_CALL1(_vfunc_index, _return_type, _class_type, _func_name, _param1) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1);}
#define VFUNC_CALL2(_vfunc_index, _return_type, _class_type, _func_name, _param1, _param2) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1, _param2); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2);}
#define VFUNC_CALL3(_vfunc_index, _return_type, _class_type, _func_name, _param1, _param2, _param3) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3);}
#define VFUNC_CALL4(_vfunc_index, _return_type, _class_type, _func_name, _param1, _param2, _param3, _param4) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4);}
#define VFUNC_CALL5(_vfunc_index, _return_type, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5);}
#define VFUNC_CALL6(_vfunc_index, _return_type, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5, _param6) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5, _param6 p6) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5, _param6); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5, p6);}
#define VFUNC_CALL7(_vfunc_index, _return_type, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5, _param6, _param7) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5, _param6 p6, _param7 p7) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5, _param6, _param7); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5, p6, p7);}
#define VFUNC_CALL8(_vfunc_index, _return_type, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5, _param6, _param7, _param8) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5, _param6 p6, _param7 p7, _param8 p8) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5, _param6, _param7, _param8); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5, p6, p7, p8);}
#define VFUNC_CALL9(_vfunc_index, _return_type, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5, _param6, _param7, _param8, _param9) \
_return_type _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5, _param6 p6, _param7 p7, _param8 p8, _param9) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { _return_type (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5, _param6, _param7, _param8, _param9); \
VFUNC_OS_DEP \
return (_return_type) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5, p6, p7, p8, p9);}
#define VFUNC_CALL0_void(_vfunc_index, _class_type, _func_name ) \
void _func_name(_class_type *pThisPtr) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)();}
#define VFUNC_CALL1_void(_vfunc_index, _class_type, _func_name, _param1) \
void _func_name(_class_type *pThisPtr, _param1 p1) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1);}
#define VFUNC_CALL2_void(_vfunc_index, _class_type, _func_name, _param1, _param2) \
void _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1, _param2); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2);}
#define VFUNC_CALL3_void(_vfunc_index, _class_type, _func_name, _param1, _param2, _param3) \
void _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3);}
#define VFUNC_CALL4_void(_vfunc_index, _class_type, _func_name, _param1, _param2, _param3, _param4) \
void _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4);}
#define VFUNC_CALL5_void(_vfunc_index, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5) \
void _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5);}
#define VFUNC_CALL6_void(_vfunc_index, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5, _param6) \
void _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5, _param6 p6) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5, _param6); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5, p6);}
#define VFUNC_CALL7_void(_vfunc_index, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5, _param6, _param7) \
void _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5, _param6 p6, _param7 p7) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5, _param6, _param7); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5, p6, p7);}
#define VFUNC_CALL8_void(_vfunc_index, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5, _param6, _param7, _param8) \
void _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5, _param6 p6, _param7 p7, _param8 p8) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5, _param6, _param7, _param8); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5, p6, p7, p8);}
#define VFUNC_CALL9_void(_vfunc_index, _class_type, _func_name, _param1, _param2, _param3, _param4, _param5, _param6, _param7, _param8, _param9) \
void _func_name(_class_type *pThisPtr, _param1 p1, _param2 p2, _param3 p3, _param4 p4, _param5 p5, _param6 p6, _param7 p7, _param8 p8, _param9) \
VFUNC_SETUP_PTR(_vfunc_index); \
union { void (ManiEmptyClass::*mfpnew)(_param1, _param2, _param3, _param4, _param5, _param6, _param7, _param8, _param9); \
VFUNC_OS_DEP \
(void) (reinterpret_cast<ManiEmptyClass*>(this_ptr)->*u.mfpnew)(p1, p2, p3, p4, p5, p6, p7, p8, p9);}
// Actual use of the macros.
// virtual const QAngle &EyeAngles( void );
VFUNC_CALL0(MANI_VFUNC_EYE_ANGLES, const QAngle &, CBaseEntity, CBaseEntity_EyeAngles)
// virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
VFUNC_CALL3_void(MANI_VFUNC_TELEPORT, CBaseEntity, CBaseEntity_Teleport, const Vector *, const QAngle *, const Vector *)
// virtual Vector EyePosition( void );
VFUNC_CALL0(MANI_VFUNC_EYE_POSITION, Vector, CBaseEntity, CBaseEntity_EyePosition)
//virtual void GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity = NULL);
VFUNC_CALL2_void(MANI_VFUNC_GET_VELOCITY, CBaseEntity, CBaseEntity_GetVelocity, Vector *, AngularImpulse *)
// virtual CBaseCombatCharacter *MyCombatCharacterPointer( void );
VFUNC_CALL0(MANI_VFUNC_MY_COMBAT_CHARACTER, CBaseCombatCharacter *, CBaseEntity, CBaseEntity_MyCombatCharacterPointer)
// virtual void SetModelIndex( int index );
VFUNC_CALL1_void(MANI_VFUNC_SET_MODEL_INDEX, CBaseEntity, CBaseEntity_SetModelIndex, int)
// virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false );
VFUNC_CALL4_void(MANI_VFUNC_IGNITE, CBasePlayer, CBasePlayer_Ignite, float, bool, float, bool)
// virtual bool RemovePlayerItem( CBaseCombatWeapon *pItem )
VFUNC_CALL1(MANI_VFUNC_REMOVE_PLAYER_ITEM, bool, CBasePlayer, CBasePlayer_RemovePlayerItem, CBaseCombatWeapon *)
// virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL );
VFUNC_CALL3_void(MANI_VFUNC_WEAPON_DROP, CBasePlayer, CBasePlayer_WeaponDrop, CBaseCombatWeapon *, const Vector *, const Vector *)
// virtual CBaseEntity *GiveNamedItem( const char *szName, int iSubType = 0 );
VFUNC_CALL2(MANI_VFUNC_GIVE_ITEM, CBaseEntity *, CBasePlayer, CBasePlayer_GiveNamedItem, const char *, int)
// virtual CBaseCombatWeapon *Weapon_GetSlot( int slot ) const;
VFUNC_CALL1(MANI_VFUNC_GET_WEAPON_SLOT, CBaseCombatWeapon *, CBaseCombatCharacter, CBaseCombatCharacter_Weapon_GetSlot, int)
// virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0 );
VFUNC_CALL2_void(MANI_VFUNC_WEAPON_SWITCH, CBaseCombatCharacter, CBaseCombatCharacter_Weapon_Switch, CBaseCombatWeapon *, int)
// virtual int GiveAmmo( int iCount, int iAmmoIndex, bool bSuppressSound = false );
VFUNC_CALL3_void(MANI_VFUNC_GIVE_AMMO, CBaseCombatCharacter, CBaseCombatCharacter_GiveAmmo, int, int, bool)
// virtual int GetPrimaryAmmoType( void );
VFUNC_CALL0(MANI_VFUNC_GET_PRIMARY_AMMO_TYPE, int, CBaseCombatWeapon, CBaseCombatWeapon_GetPrimaryAmmoType)
// virtual int GetSecondaryAmmoType( void );
VFUNC_CALL0(MANI_VFUNC_GET_SECONDARY_AMMO_TYPE, int, CBaseCombatWeapon, CBaseCombatWeapon_GetSecondaryAmmoType)
// virtual char const *GetName( void );
VFUNC_CALL0(MANI_VFUNC_WEAPON_GET_NAME, const char *, CBaseCombatWeapon, CBaseCombatWeapon_GetName)
__________________
|
|