From 052bacaa1546ed77c8c14d4d04f7c2f6b0b91f25 Mon Sep 17 00:00:00 2001 From: tmp64 Date: Sat, 19 Aug 2023 11:55:22 +0700 Subject: [PATCH 1/4] VTable: Convert GET_VTABLE_ENT to function --- src/wpnmod_hooks.h | 48 +++++++++++++++++++++---------------------- src/wpnmod_vtable.cpp | 2 +- src/wpnmod_vtable.h | 7 +++++-- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/wpnmod_hooks.h b/src/wpnmod_hooks.h index ec15533..c2afb41 100644 --- a/src/wpnmod_hooks.h +++ b/src/wpnmod_hooks.h @@ -265,7 +265,7 @@ inline BOOL CAN_DEPLOY(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_CanDeploy)])(pentItem->pvPrivateData, DUMMY_VAL); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_CanDeploy)])(pentItem->pvPrivateData, DUMMY_VAL); } // virtual BOOL Deploy(void); @@ -277,7 +277,7 @@ inline BOOL DEPLOY(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_Deploy)])(pentItem->pvPrivateData, DUMMY_VAL); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Deploy)])(pentItem->pvPrivateData, DUMMY_VAL); } // virtual BOOL CanHolster(void); @@ -289,7 +289,7 @@ inline BOOL CAN_HOLSTER( edict_t* pentItem ) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_CanHolster)])(pentItem->pvPrivateData, DUMMY_VAL); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_CanHolster)])(pentItem->pvPrivateData, DUMMY_VAL); } // virtual void Holster(int skiplocal = 0); @@ -301,7 +301,7 @@ inline void HOLSTER(edict_t* pentItem) { - reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_Holster)])(pentItem->pvPrivateData, DUMMY_VAL, 0); + reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Holster)])(pentItem->pvPrivateData, DUMMY_VAL, 0); } // virtual void ItemPostFrame(void); @@ -320,7 +320,7 @@ inline BOOL IS_USEABLE(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_IsUseable)])(pentItem->pvPrivateData, DUMMY_VAL); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_IsUseable)])(pentItem->pvPrivateData, DUMMY_VAL); } // virtual int AddToPlayer(CBasePlayer* pPlayer); @@ -332,7 +332,7 @@ inline int ADD_TO_PLAYER(edict_t* pentItem, edict_t* pentPlayer) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_AddToPlayer)])(pentItem->pvPrivateData, DUMMY_VAL, pentPlayer->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_AddToPlayer)])(pentItem->pvPrivateData, DUMMY_VAL, pentPlayer->pvPrivateData); } // virtual int ItemSlot(void); @@ -344,7 +344,7 @@ inline int ITEM_SLOT(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_ItemSlot)])(pentItem->pvPrivateData, DUMMY_VAL); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_ItemSlot)])(pentItem->pvPrivateData, DUMMY_VAL); } // virtual CBaseEntity* Respawn(void); @@ -356,7 +356,7 @@ inline void* RESPAWN(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_Respawn)])(pentItem->pvPrivateData, DUMMY_VAL); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Respawn)])(pentItem->pvPrivateData, DUMMY_VAL); } // void Spawn(void); @@ -384,28 +384,28 @@ // inline int GET_DAMAGE_DECAL(edict_t* pentEntity) { - return reinterpret_cast(GET_VTABLE_ENT(pentEntity)[GET_VTABLE_OFFSET(VO_DamageDecal)])(pentEntity->pvPrivateData, DUMMY_VAL, 0); + return reinterpret_cast(GetEntityVTable(pentEntity)[GET_VTABLE_OFFSET(VO_DamageDecal)])(pentEntity->pvPrivateData, DUMMY_VAL, 0); } // int Classify( void ); // inline int CLASSIFY(edict_t* pentEntity) { - return reinterpret_cast(GET_VTABLE_ENT(pentEntity)[GET_VTABLE_OFFSET(VO_Classify)])(pentEntity->pvPrivateData, DUMMY_VAL); + return reinterpret_cast(GetEntityVTable(pentEntity)[GET_VTABLE_OFFSET(VO_Classify)])(pentEntity->pvPrivateData, DUMMY_VAL); } // virtual void TraceAttack(entvars_t* pevAttacker, float flDamage, Vector vecDir, TraceResult* ptr, int bitsDamageType); // inline void TRACE_ATTACK(edict_t* pentVictim, edict_t* pentAttacker, float damage, Vector vecDir, TraceResult tr, int bitsDamageType) { - reinterpret_cast(GET_VTABLE_ENT(pentVictim)[GET_VTABLE_OFFSET(VO_TraceAttack)])(pentVictim->pvPrivateData, DUMMY_VAL, VARS(pentAttacker), damage, vecDir, &tr, bitsDamageType); + reinterpret_cast(GetEntityVTable(pentVictim)[GET_VTABLE_OFFSET(VO_TraceAttack)])(pentVictim->pvPrivateData, DUMMY_VAL, VARS(pentAttacker), damage, vecDir, &tr, bitsDamageType); } // virtual int TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType); // inline int TAKE_DAMAGE(edict_t* pentVictim, edict_t* pentInflictor, edict_t* pentAttacker, float damage, int bitsDamageType) { - return reinterpret_cast(GET_VTABLE_ENT(pentVictim)[GET_VTABLE_OFFSET(VO_TakeDamage)])(pentVictim->pvPrivateData, DUMMY_VAL, VARS(pentInflictor), VARS(pentAttacker), damage, bitsDamageType); + return reinterpret_cast(GetEntityVTable(pentVictim)[GET_VTABLE_OFFSET(VO_TakeDamage)])(pentVictim->pvPrivateData, DUMMY_VAL, VARS(pentInflictor), VARS(pentAttacker), damage, bitsDamageType); } #else @@ -467,7 +467,7 @@ inline BOOL CAN_DEPLOY(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_CanDeploy)])(pentItem->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_CanDeploy)])(pentItem->pvPrivateData); } // virtual BOOL Deploy(void); @@ -479,7 +479,7 @@ inline BOOL DEPLOY(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_Deploy)])(pentItem->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Deploy)])(pentItem->pvPrivateData); } // virtual BOOL CanHolster(void); @@ -491,7 +491,7 @@ inline BOOL CAN_HOLSTER(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_CanHolster)])(pentItem->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_CanHolster)])(pentItem->pvPrivateData); } // virtual void Holster(int skiplocal = 0); @@ -503,7 +503,7 @@ inline void HOLSTER(edict_t* pentItem) { - reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_Holster)])(pentItem->pvPrivateData, 0); + reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Holster)])(pentItem->pvPrivateData, 0); } // virtual void ItemPostFrame(void); @@ -522,7 +522,7 @@ inline BOOL IS_USEABLE(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_IsUseable)])(pentItem->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_IsUseable)])(pentItem->pvPrivateData); } // virtual int AddToPlayer(CBasePlayer* pPlayer); @@ -534,7 +534,7 @@ inline int ADD_TO_PLAYER(edict_t* pentItem, edict_t* pentPlayer) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_AddToPlayer)])(pentItem->pvPrivateData, pentPlayer->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_AddToPlayer)])(pentItem->pvPrivateData, pentPlayer->pvPrivateData); } // virtual int ItemSlot(void); @@ -546,7 +546,7 @@ inline int ITEM_SLOT(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_ItemSlot)])(pentItem->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_ItemSlot)])(pentItem->pvPrivateData); } // virtual CBaseEntity* Respawn(void); @@ -558,7 +558,7 @@ inline void* RESPAWN(edict_t* pentItem) { - return reinterpret_cast(GET_VTABLE_ENT(pentItem)[GET_VTABLE_OFFSET(VO_Respawn)])(pentItem->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Respawn)])(pentItem->pvPrivateData); } // void Spawn(void); @@ -586,28 +586,28 @@ // inline int GET_DAMAGE_DECAL(edict_t* pentEntity) { - return reinterpret_cast(GET_VTABLE_ENT(pentEntity)[GET_VTABLE_OFFSET(VO_DamageDecal)])(pentEntity->pvPrivateData, 0); + return reinterpret_cast(GetEntityVTable(pentEntity)[GET_VTABLE_OFFSET(VO_DamageDecal)])(pentEntity->pvPrivateData, 0); } // int Classify( void ); // inline int CLASSIFY(edict_t* pentEntity) { - return reinterpret_cast(GET_VTABLE_ENT(pentEntity)[GET_VTABLE_OFFSET(VO_Classify)])(pentEntity->pvPrivateData); + return reinterpret_cast(GetEntityVTable(pentEntity)[GET_VTABLE_OFFSET(VO_Classify)])(pentEntity->pvPrivateData); } // virtual void TraceAttack(entvars_t* pevAttacker, float flDamage, Vector vecDir, TraceResult* ptr, int bitsDamageType); // inline void TRACE_ATTACK(edict_t* pentVictim, edict_t* pentAttacker, float damage, Vector vecDir, TraceResult tr, int bitsDamageType) { - reinterpret_cast(GET_VTABLE_ENT(pentVictim)[GET_VTABLE_OFFSET(VO_TraceAttack)])(pentVictim->pvPrivateData, VARS(pentAttacker), damage, vecDir, &tr, bitsDamageType); + reinterpret_cast(GetEntityVTable(pentVictim)[GET_VTABLE_OFFSET(VO_TraceAttack)])(pentVictim->pvPrivateData, VARS(pentAttacker), damage, vecDir, &tr, bitsDamageType); } // virtual int TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType); // inline int TAKE_DAMAGE(edict_t* pentVictim, edict_t* pentInflictor, edict_t* pentAttacker, float damage, int bitsDamageType) { - return reinterpret_cast(GET_VTABLE_ENT(pentVictim)[GET_VTABLE_OFFSET(VO_TakeDamage)])(pentVictim->pvPrivateData, VARS(pentInflictor), VARS(pentAttacker), damage, bitsDamageType); + return reinterpret_cast(GetEntityVTable(pentVictim)[GET_VTABLE_OFFSET(VO_TakeDamage)])(pentVictim->pvPrivateData, VARS(pentInflictor), VARS(pentAttacker), damage, bitsDamageType); } #endif diff --git a/src/wpnmod_vtable.cpp b/src/wpnmod_vtable.cpp index df8ec45..7be3c12 100644 --- a/src/wpnmod_vtable.cpp +++ b/src/wpnmod_vtable.cpp @@ -175,7 +175,7 @@ bool HandleHookVirtual(VirtualHookData* hook, bool bRevert) return (hook->done = false); } - void** vtable = GET_VTABLE_ENT(pEdict); + void** vtable = GetEntityVTable(pEdict); if (vtable == NULL) { diff --git a/src/wpnmod_vtable.h b/src/wpnmod_vtable.h index 6d67ac5..561b0c1 100644 --- a/src/wpnmod_vtable.h +++ b/src/wpnmod_vtable.h @@ -56,8 +56,6 @@ #endif -#define GET_VTABLE_ENT(e) (*((void***)(((char*)e->pvPrivateData) + g_EntityVTableOffsetBase))) - enum VTableOffsets { VO_Spawn, @@ -111,4 +109,9 @@ extern void SetHookVirtual (VirtualHookData* hook); extern void UnsetHookVirtual (VirtualHookData* hook); extern bool HandleHookVirtual (VirtualHookData* hook, bool revert); +inline void** GetEntityVTable(edict_t* e) +{ + return *((void***)(((char*)e->pvPrivateData) + g_EntityVTableOffsetBase)); +} + #endif // _VTABLE_H From 9758334a5d94a528fef178d4a7d5d195b7d413bd Mon Sep 17 00:00:00 2001 From: tmp64 Date: Sat, 19 Aug 2023 12:02:33 +0700 Subject: [PATCH 2/4] Hooks: Add GetEntityVTableFunc --- src/wpnmod_hooks.h | 48 ++++++++++++++++++++++----------------------- src/wpnmod_vtable.h | 6 ++++++ 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/wpnmod_hooks.h b/src/wpnmod_hooks.h index c2afb41..53027e3 100644 --- a/src/wpnmod_hooks.h +++ b/src/wpnmod_hooks.h @@ -265,7 +265,7 @@ inline BOOL CAN_DEPLOY(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_CanDeploy)])(pentItem->pvPrivateData, DUMMY_VAL); + return GetEntityVTableFunc(pentItem, VO_CanDeploy)(pentItem->pvPrivateData, DUMMY_VAL); } // virtual BOOL Deploy(void); @@ -277,7 +277,7 @@ inline BOOL DEPLOY(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Deploy)])(pentItem->pvPrivateData, DUMMY_VAL); + return GetEntityVTableFunc(pentItem, VO_Deploy)(pentItem->pvPrivateData, DUMMY_VAL); } // virtual BOOL CanHolster(void); @@ -289,7 +289,7 @@ inline BOOL CAN_HOLSTER( edict_t* pentItem ) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_CanHolster)])(pentItem->pvPrivateData, DUMMY_VAL); + return GetEntityVTableFunc(pentItem, VO_CanHolster)(pentItem->pvPrivateData, DUMMY_VAL); } // virtual void Holster(int skiplocal = 0); @@ -301,7 +301,7 @@ inline void HOLSTER(edict_t* pentItem) { - reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Holster)])(pentItem->pvPrivateData, DUMMY_VAL, 0); + GetEntityVTableFunc(pentItem, VO_Holster)(pentItem->pvPrivateData, DUMMY_VAL, 0); } // virtual void ItemPostFrame(void); @@ -320,7 +320,7 @@ inline BOOL IS_USEABLE(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_IsUseable)])(pentItem->pvPrivateData, DUMMY_VAL); + return GetEntityVTableFunc(pentItem, VO_IsUseable)(pentItem->pvPrivateData, DUMMY_VAL); } // virtual int AddToPlayer(CBasePlayer* pPlayer); @@ -332,7 +332,7 @@ inline int ADD_TO_PLAYER(edict_t* pentItem, edict_t* pentPlayer) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_AddToPlayer)])(pentItem->pvPrivateData, DUMMY_VAL, pentPlayer->pvPrivateData); + return GetEntityVTableFunc(pentItem, VO_AddToPlayer)(pentItem->pvPrivateData, DUMMY_VAL, pentPlayer->pvPrivateData); } // virtual int ItemSlot(void); @@ -344,7 +344,7 @@ inline int ITEM_SLOT(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_ItemSlot)])(pentItem->pvPrivateData, DUMMY_VAL); + return GetEntityVTableFunc(pentItem, VO_ItemSlot)(pentItem->pvPrivateData, DUMMY_VAL); } // virtual CBaseEntity* Respawn(void); @@ -356,7 +356,7 @@ inline void* RESPAWN(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Respawn)])(pentItem->pvPrivateData, DUMMY_VAL); + return GetEntityVTableFunc(pentItem, VO_Respawn)(pentItem->pvPrivateData, DUMMY_VAL); } // void Spawn(void); @@ -384,28 +384,28 @@ // inline int GET_DAMAGE_DECAL(edict_t* pentEntity) { - return reinterpret_cast(GetEntityVTable(pentEntity)[GET_VTABLE_OFFSET(VO_DamageDecal)])(pentEntity->pvPrivateData, DUMMY_VAL, 0); + return GetEntityVTableFunc(pentEntity, VO_DamageDecal)(pentEntity->pvPrivateData, DUMMY_VAL, 0); } // int Classify( void ); // inline int CLASSIFY(edict_t* pentEntity) { - return reinterpret_cast(GetEntityVTable(pentEntity)[GET_VTABLE_OFFSET(VO_Classify)])(pentEntity->pvPrivateData, DUMMY_VAL); + return GetEntityVTableFunc(pentEntity, VO_Classify)(pentEntity->pvPrivateData, DUMMY_VAL); } // virtual void TraceAttack(entvars_t* pevAttacker, float flDamage, Vector vecDir, TraceResult* ptr, int bitsDamageType); // inline void TRACE_ATTACK(edict_t* pentVictim, edict_t* pentAttacker, float damage, Vector vecDir, TraceResult tr, int bitsDamageType) { - reinterpret_cast(GetEntityVTable(pentVictim)[GET_VTABLE_OFFSET(VO_TraceAttack)])(pentVictim->pvPrivateData, DUMMY_VAL, VARS(pentAttacker), damage, vecDir, &tr, bitsDamageType); + GetEntityVTableFunc(pentVictim, VO_TraceAttack)(pentVictim->pvPrivateData, DUMMY_VAL, VARS(pentAttacker), damage, vecDir, &tr, bitsDamageType); } // virtual int TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType); // inline int TAKE_DAMAGE(edict_t* pentVictim, edict_t* pentInflictor, edict_t* pentAttacker, float damage, int bitsDamageType) { - return reinterpret_cast(GetEntityVTable(pentVictim)[GET_VTABLE_OFFSET(VO_TakeDamage)])(pentVictim->pvPrivateData, DUMMY_VAL, VARS(pentInflictor), VARS(pentAttacker), damage, bitsDamageType); + return GetEntityVTableFunc(pentVictim, VO_TakeDamage)(pentVictim->pvPrivateData, DUMMY_VAL, VARS(pentInflictor), VARS(pentAttacker), damage, bitsDamageType); } #else @@ -467,7 +467,7 @@ inline BOOL CAN_DEPLOY(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_CanDeploy)])(pentItem->pvPrivateData); + return GetEntityVTableFunc(pentItem, VO_CanDeploy)(pentItem->pvPrivateData); } // virtual BOOL Deploy(void); @@ -479,7 +479,7 @@ inline BOOL DEPLOY(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Deploy)])(pentItem->pvPrivateData); + return GetEntityVTableFunc(pentItem, VO_Deploy)(pentItem->pvPrivateData); } // virtual BOOL CanHolster(void); @@ -491,7 +491,7 @@ inline BOOL CAN_HOLSTER(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_CanHolster)])(pentItem->pvPrivateData); + return GetEntityVTableFunc(pentItem, VO_CanHolster)(pentItem->pvPrivateData); } // virtual void Holster(int skiplocal = 0); @@ -503,7 +503,7 @@ inline void HOLSTER(edict_t* pentItem) { - reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Holster)])(pentItem->pvPrivateData, 0); + GetEntityVTableFunc(pentItem, VO_Holster)(pentItem->pvPrivateData, 0); } // virtual void ItemPostFrame(void); @@ -522,7 +522,7 @@ inline BOOL IS_USEABLE(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_IsUseable)])(pentItem->pvPrivateData); + return GetEntityVTableFunc(pentItem, VO_IsUseable)(pentItem->pvPrivateData); } // virtual int AddToPlayer(CBasePlayer* pPlayer); @@ -534,7 +534,7 @@ inline int ADD_TO_PLAYER(edict_t* pentItem, edict_t* pentPlayer) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_AddToPlayer)])(pentItem->pvPrivateData, pentPlayer->pvPrivateData); + return GetEntityVTableFunc(pentItem, VO_AddToPlayer)(pentItem->pvPrivateData, pentPlayer->pvPrivateData); } // virtual int ItemSlot(void); @@ -546,7 +546,7 @@ inline int ITEM_SLOT(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_ItemSlot)])(pentItem->pvPrivateData); + return GetEntityVTableFunc(pentItem, VO_ItemSlot)(pentItem->pvPrivateData); } // virtual CBaseEntity* Respawn(void); @@ -558,7 +558,7 @@ inline void* RESPAWN(edict_t* pentItem) { - return reinterpret_cast(GetEntityVTable(pentItem)[GET_VTABLE_OFFSET(VO_Respawn)])(pentItem->pvPrivateData); + return GetEntityVTableFunc(pentItem, VO_Respawn)(pentItem->pvPrivateData); } // void Spawn(void); @@ -586,28 +586,28 @@ // inline int GET_DAMAGE_DECAL(edict_t* pentEntity) { - return reinterpret_cast(GetEntityVTable(pentEntity)[GET_VTABLE_OFFSET(VO_DamageDecal)])(pentEntity->pvPrivateData, 0); + return GetEntityVTableFunc(pentEntity, VO_DamageDecal)(pentEntity->pvPrivateData, 0); } // int Classify( void ); // inline int CLASSIFY(edict_t* pentEntity) { - return reinterpret_cast(GetEntityVTable(pentEntity)[GET_VTABLE_OFFSET(VO_Classify)])(pentEntity->pvPrivateData); + return GetEntityVTableFunc(pentEntity, VO_Classify)(pentEntity->pvPrivateData); } // virtual void TraceAttack(entvars_t* pevAttacker, float flDamage, Vector vecDir, TraceResult* ptr, int bitsDamageType); // inline void TRACE_ATTACK(edict_t* pentVictim, edict_t* pentAttacker, float damage, Vector vecDir, TraceResult tr, int bitsDamageType) { - reinterpret_cast(GetEntityVTable(pentVictim)[GET_VTABLE_OFFSET(VO_TraceAttack)])(pentVictim->pvPrivateData, VARS(pentAttacker), damage, vecDir, &tr, bitsDamageType); + GetEntityVTableFunc(pentVictim, VO_TraceAttack)(pentVictim->pvPrivateData, VARS(pentAttacker), damage, vecDir, &tr, bitsDamageType); } // virtual int TakeDamage(entvars_t* pevInflictor, entvars_t* pevAttacker, float flDamage, int bitsDamageType); // inline int TAKE_DAMAGE(edict_t* pentVictim, edict_t* pentInflictor, edict_t* pentAttacker, float damage, int bitsDamageType) { - return reinterpret_cast(GetEntityVTable(pentVictim)[GET_VTABLE_OFFSET(VO_TakeDamage)])(pentVictim->pvPrivateData, VARS(pentInflictor), VARS(pentAttacker), damage, bitsDamageType); + return GetEntityVTableFunc(pentVictim, VO_TakeDamage)(pentVictim->pvPrivateData, VARS(pentInflictor), VARS(pentAttacker), damage, bitsDamageType); } #endif diff --git a/src/wpnmod_vtable.h b/src/wpnmod_vtable.h index 561b0c1..ec2783d 100644 --- a/src/wpnmod_vtable.h +++ b/src/wpnmod_vtable.h @@ -114,4 +114,10 @@ inline void** GetEntityVTable(edict_t* e) return *((void***)(((char*)e->pvPrivateData) + g_EntityVTableOffsetBase)); } +template +inline TFuncPtr GetEntityVTableFunc(edict_t* e, VTableOffsets offset) +{ + return reinterpret_cast(GetEntityVTable(e)[GET_VTABLE_OFFSET(offset)]); +} + #endif // _VTABLE_H From 3596f4dac3f382f895126b6d9700d14fd8b0cc0f Mon Sep 17 00:00:00 2001 From: tmp64 Date: Sat, 19 Aug 2023 12:09:42 +0700 Subject: [PATCH 3/4] Move IGameConfigPtr to a separate header --- src/CMakeLists.txt | 1 + src/sdk/amxx_gameconfigs.h | 65 ++++++++++++++++++++++++++++++++++++++ src/wpnmod_pvdata.cpp | 41 ++++++------------------ 3 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 src/sdk/amxx_gameconfigs.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a4c95c4..fb3a009 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ add_sources( + sdk/amxx_gameconfigs.h sdk/amxxmodule.cpp sdk/amxxmodule.h sdk/HLTypeConversion.h diff --git a/src/sdk/amxx_gameconfigs.h b/src/sdk/amxx_gameconfigs.h new file mode 100644 index 0000000..b491f32 --- /dev/null +++ b/src/sdk/amxx_gameconfigs.h @@ -0,0 +1,65 @@ +/* + * Half-Life Weapon Mod + * Copyright (c) 2012 - 2023 AGHL.RU Dev Team + * + * http://aghl.ru/forum/ - Russian Half-Life and Adrenaline Gamer Community + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#pragma once +#include +#include "sdk/amxxmodule.h" +#include "sdk/IGameConfigs.h" +#include "wpnmod_log.h" + + //! Deleter for IGameConfig pointers. +struct AmxxGameConfigDeleter +{ + void operator()(IGameConfig* pCfg) + { + MF_GetConfigManager()->CloseGameConfigFile(pCfg); + } +}; + +//! Smart pointer for IGameConfig. +using IGameConfigPtr = std::unique_ptr; + +//! Loads a game config file. Crashes if fails. +static IGameConfigPtr WpnMod_LoadGameConfigFile(const char* file) +{ + IGameConfig* pCfg = nullptr; + char error[256] = ""; + + if (!MF_GetConfigManager()->LoadGameConfigFile(file, &pCfg, error, sizeof(error))) + { + WPNMOD_LOG("Failed to load game config '%s': %s\n", file, error); + std::abort(); + } + + return IGameConfigPtr(pCfg, AmxxGameConfigDeleter()); +} diff --git a/src/wpnmod_pvdata.cpp b/src/wpnmod_pvdata.cpp index 02b7960..a2cd79a 100644 --- a/src/wpnmod_pvdata.cpp +++ b/src/wpnmod_pvdata.cpp @@ -31,51 +31,30 @@ * */ -#include -#include "sdk/IGameConfigs.h" +#include "sdk/amxx_gameconfigs.h" #include "wpnmod_pvdata.h" #include "wpnmod_memory.h" #include "wpnmod_config.h" #include "wpnmod_utils.h" +namespace +{ + +//! Class and field for which an offset must be loaded. struct OffsetInitializer { const char* szClassName; const char* szFieldName; }; -//! List of offsets. -TypeDescription GamePvDatasOffsets[pvData_End]; - //! List class and field name for each offset. -static OffsetInitializer g_OffsetInitializers[pvData_End]; - -//! Deleter for IGameConfig pointers. -struct GameConfigDeleter -{ - void operator()(IGameConfig* pCfg) - { - MF_GetConfigManager()->CloseGameConfigFile(pCfg); - } -}; +OffsetInitializer g_OffsetInitializers[pvData_End]; -//! Smart pointer for IGameConfig. -using IGameConfigPtr = std::unique_ptr; +} // namespace -//! Loads a game config file. Crashes if fails. -static IGameConfigPtr LoadGameConfigFile(const char* file) -{ - IGameConfig* pCfg = nullptr; - char error[256] = ""; - - if (!MF_GetConfigManager()->LoadGameConfigFile(file, &pCfg, error, sizeof(error))) - { - WPNMOD_LOG("Failed to load game config '%s': %s\n", file, error); - std::abort(); - } +//! List of offsets. +TypeDescription GamePvDatasOffsets[pvData_End]; - return IGameConfigPtr(pCfg, GameConfigDeleter()); -} void pvData_Init(void) { @@ -130,7 +109,7 @@ void pvData_Init(void) g_OffsetInitializers[pvData_szAnimExtention] = { "CBasePlayer", "m_szAnimExtention" }; // Load offsets - IGameConfigPtr pCfg = LoadGameConfigFile("common.games"); + IGameConfigPtr pCfg = WpnMod_LoadGameConfigFile("common.games"); bool anyNotFound = false; for (int i = 0; i < std::size(g_OffsetInitializers); i++) From d815a2a8178d3c2317dae546ba20f559e047ca4c Mon Sep 17 00:00:00 2001 From: tmp64 Date: Sat, 19 Aug 2023 13:08:13 +0700 Subject: [PATCH 4/4] VTable: Get offsets from AMXX Game Configs --- .../gamedata/weaponmod.games/master.games.txt | 11 ++ .../weaponmod.games/valve/offsets-vtable.txt | 62 +++++++ src/wpnmod_pvdata.cpp | 7 +- src/wpnmod_vtable.cpp | 152 ++++++++---------- src/wpnmod_vtable.h | 9 +- 5 files changed, 152 insertions(+), 89 deletions(-) create mode 100644 gamedir/amxmodx/data/gamedata/weaponmod.games/master.games.txt create mode 100644 gamedir/amxmodx/data/gamedata/weaponmod.games/valve/offsets-vtable.txt diff --git a/gamedir/amxmodx/data/gamedata/weaponmod.games/master.games.txt b/gamedir/amxmodx/data/gamedata/weaponmod.games/master.games.txt new file mode 100644 index 0000000..78cb67e --- /dev/null +++ b/gamedir/amxmodx/data/gamedata/weaponmod.games/master.games.txt @@ -0,0 +1,11 @@ +"Game Master" +{ + // + // Half-Life: Deathmatch + // + + "valve/offsets-vtable.txt" + { + "game" "valve" + } +} diff --git a/gamedir/amxmodx/data/gamedata/weaponmod.games/valve/offsets-vtable.txt b/gamedir/amxmodx/data/gamedata/weaponmod.games/valve/offsets-vtable.txt new file mode 100644 index 0000000..52b1ecd --- /dev/null +++ b/gamedir/amxmodx/data/gamedata/weaponmod.games/valve/offsets-vtable.txt @@ -0,0 +1,62 @@ +"Games" +{ + "#default" + { + "Offsets" + { + "AddAmmo" + { + "windows" "57" + "linux" "59" + } + + "AddToPlayer" + { + "windows" "58" + "linux" "60" + } + + "CanDeploy" + { + "windows" "61" + "linux" "63" + } + + "Deploy" + { + "windows" "62" + "linux" "64" + } + + "CanHolster" + { + "windows" "63" + "linux" "65" + } + + "Holster" + { + "windows" "64" + "linux" "66" + } + + "ItemPostFrame" + { + "windows" "67" + "linux" "69" + } + + "ItemSlot" + { + "windows" "75" + "linux" "77" + } + + "IsUseable" + { + "windows" "82" + "linux" "84" + } + } + } +} diff --git a/src/wpnmod_pvdata.cpp b/src/wpnmod_pvdata.cpp index a2cd79a..3dece00 100644 --- a/src/wpnmod_pvdata.cpp +++ b/src/wpnmod_pvdata.cpp @@ -37,6 +37,9 @@ #include "wpnmod_config.h" #include "wpnmod_utils.h" +//! List of offsets. +TypeDescription GamePvDatasOffsets[pvData_End]; + namespace { @@ -52,10 +55,6 @@ OffsetInitializer g_OffsetInitializers[pvData_End]; } // namespace -//! List of offsets. -TypeDescription GamePvDatasOffsets[pvData_End]; - - void pvData_Init(void) { // CBaseEntity diff --git a/src/wpnmod_vtable.cpp b/src/wpnmod_vtable.cpp index 7be3c12..c51c73a 100644 --- a/src/wpnmod_vtable.cpp +++ b/src/wpnmod_vtable.cpp @@ -31,6 +31,8 @@ * */ +#include +#include "sdk/amxx_gameconfigs.h" #include "wpnmod_vtable.h" #include "wpnmod_memory.h" #include "wpnmod_config.h" @@ -39,102 +41,88 @@ int g_EntityVTableOffsetPev = NULL; int g_EntityVTableOffsetBase = NULL; -// -// Default vtbl offsets for Bugfixed and improved HL release. -// -GameOffset GameVirtualOffsets[VO_End] = +//! List of VTable offsets. +TypeDescription GameVirtualOffsets[VO_End]; + +namespace +{ + +//! Method name which a VTable offset must be loaded. +struct OffsetInitializer { - {0, 2}, // Spawn - {1, 2}, // Precache - {8, 2}, // Classify - {10, 2}, // TraceAttack - {11, 2}, // TakeDamage - {28, 2}, // DamageDecal - {47, 2}, // Respawn - {57, 2}, // AddAmmo - {58, 2}, // AddToPlayer - {61, 2}, // CanDeploy - {62, 2}, // Deploy - {63, 2}, // CanHolster - {64, 2}, // Holster - {67, 2}, // ItemPostFrame - {75, 2}, // ItemSlot - {82, 2}, // IsUseable - {128, 2} // Player_PostThink + const char* szMethodName; }; +//! List class and field name for each offset. +OffsetInitializer g_OffsetInitializers[VO_End]; + +} // namespace + void Vtable_Init(void) { - // Default PEV and BASE offsets. - SetVTableOffsetPev(4); - SetVTableOffsetBase(0x0); - -#ifdef __linux__ - if (g_Memory.IsNewGCC()) + g_OffsetInitializers[VO_Spawn] = { "Spawn" }; + g_OffsetInitializers[VO_Precache] = { "Precache" }; + g_OffsetInitializers[VO_Classify] = { "Classify" }; + g_OffsetInitializers[VO_TraceAttack] = { "TraceAttack" }; + g_OffsetInitializers[VO_TakeDamage] = { "TakeDamage" }; + g_OffsetInitializers[VO_DamageDecal] = { "DamageDecal" }; + g_OffsetInitializers[VO_Respawn] = { "Respawn" }; + g_OffsetInitializers[VO_AddAmmo] = { "AddAmmo" }; + g_OffsetInitializers[VO_AddToPlayer] = { "AddToPlayer" }; + g_OffsetInitializers[VO_CanDeploy] = { "CanDeploy" }; + g_OffsetInitializers[VO_Deploy] = { "Deploy" }; + g_OffsetInitializers[VO_CanHolster] = { "CanHolster" }; + g_OffsetInitializers[VO_Holster] = { "Holster" }; + g_OffsetInitializers[VO_ItemPostFrame] = { "ItemPostFrame" }; + g_OffsetInitializers[VO_ItemSlot] = { "ItemSlot" }; + g_OffsetInitializers[VO_IsUseable] = { "IsUseable" }; + g_OffsetInitializers[VO_Player_PostThink] = { "Player_PostThink" }; + + // Load offsets + IGameConfigPtr pWpnModCfg = WpnMod_LoadGameConfigFile("weaponmod.games"); + IGameConfigPtr pAmxxCfg = WpnMod_LoadGameConfigFile("common.games"); + bool anyNotFound = false; + + for (int i = 0; i < std::size(g_OffsetInitializers); i++) { - for (int i = 0; i < VO_End; i++) - { - GameVirtualOffsets[i].iExtraOffset = 0; - } - } -#endif + const OffsetInitializer& init = g_OffsetInitializers[i]; + TypeDescription& offset = GameVirtualOffsets[i]; - // Bugfixed and improved HL release. - // Or usual Half-Life. - if (g_Config.GetSubMod() == SUBMOD_AGHLRU || g_Config.GetSubMod() == SUBMOD_VALVE) - { -#ifdef __linux__ - if (!g_Memory.IsNewGCC()) + // Convert to lower case + std::string methodNameLower = init.szMethodName; + std::for_each(methodNameLower.begin(), methodNameLower.end(), [](char& c) { c = tolower(c); }); + + bool isFound = + pWpnModCfg->GetOffset(init.szMethodName, &offset) || + pAmxxCfg->GetOffset(methodNameLower.c_str(), &offset); + + if (!isFound) { - SetVTableOffsetPev(0); - SetVTableOffsetBase(0x60); + WPNMOD_LOG("VTable Offset not found: %s\n", init.szMethodName); + anyNotFound = true; + continue; } -#endif } - // Opposing Force. - else if (g_Config.GetSubMod() == SUBMOD_GEARBOX) + + if (anyNotFound) { -#ifdef __linux__ - if (!g_Memory.IsNewGCC()) - { - SetVTableOffsetPev(0); - SetVTableOffsetBase(0x6C); - } -#endif - - // Override vtable offsets. - GameVirtualOffsets[VO_DamageDecal].iValue = 29; - GameVirtualOffsets[VO_Respawn].iValue = 48; - GameVirtualOffsets[VO_AddAmmo].iValue = 59; - GameVirtualOffsets[VO_AddToPlayer].iValue = 60; - GameVirtualOffsets[VO_CanDeploy].iValue = 63; - GameVirtualOffsets[VO_Deploy].iValue = 64; - GameVirtualOffsets[VO_CanHolster].iValue = 65; - GameVirtualOffsets[VO_Holster].iValue = 66; - GameVirtualOffsets[VO_ItemPostFrame].iValue = 69; - GameVirtualOffsets[VO_ItemSlot].iValue = 78; - GameVirtualOffsets[VO_IsUseable].iValue = 85; - GameVirtualOffsets[VO_Player_PostThink].iValue = 130; + WPNMOD_LOG("Failed to find some VTable offsets. The server will now crash. Goodbye.\n"); + std::abort(); } - else if (g_Config.GetSubMod() == SUBMOD_AG || g_Config.GetSubMod() == SUBMOD_MINIAG) + + // Load pev offset + IGameConfigPtr pEntityCfg = WpnMod_LoadGameConfigFile("common.games"); + TypeDescription pevOffset; + + if (!pEntityCfg->GetOffsetByClass("CBaseEntity", "pev", &pevOffset)) { -#ifdef __linux__ - SetVTableOffsetPev(0); - SetVTableOffsetBase(0x60); -#endif - // Override vtable offsets. - GameVirtualOffsets[VO_Respawn].iValue = 48; - GameVirtualOffsets[VO_AddAmmo].iValue = 58; - GameVirtualOffsets[VO_AddToPlayer].iValue = 59; - GameVirtualOffsets[VO_CanDeploy].iValue = 62; - GameVirtualOffsets[VO_Deploy].iValue = 63; - GameVirtualOffsets[VO_CanHolster].iValue = 64; - GameVirtualOffsets[VO_Holster].iValue = 65; - GameVirtualOffsets[VO_ItemPostFrame].iValue = 68; - GameVirtualOffsets[VO_ItemSlot].iValue = 76; - GameVirtualOffsets[VO_IsUseable].iValue = 83; - GameVirtualOffsets[VO_Player_PostThink].iValue = 130; + WPNMOD_LOG("CBaseEntity::pev offset not found\n"); + std::abort(); } + + // Default PEV and BASE offsets. + SetVTableOffsetPev(pevOffset.fieldOffset); + SetVTableOffsetBase(0x0); } void SetVTableOffsetPev(int iOffset) diff --git a/src/wpnmod_vtable.h b/src/wpnmod_vtable.h index ec2783d..bf663b0 100644 --- a/src/wpnmod_vtable.h +++ b/src/wpnmod_vtable.h @@ -40,7 +40,6 @@ #ifdef WIN32 #define DUMMY_VAL 0 - #define GET_VTABLE_OFFSET(x) GameVirtualOffsets[x].iValue typedef int DUMMY; @@ -52,7 +51,6 @@ #include #define ALIGN(ar) ((intptr_t)ar & ~(sysconf(_SC_PAGESIZE) - 1)) - #define GET_VTABLE_OFFSET(x) (GameVirtualOffsets[x].iValue + GameVirtualOffsets[x].iExtraOffset) #endif @@ -95,7 +93,7 @@ struct VirtualHookData bool done; }; -extern GameOffset GameVirtualOffsets[VO_End]; +extern TypeDescription GameVirtualOffsets[VO_End]; extern int g_EntityVTableOffsetPev; extern int g_EntityVTableOffsetBase; @@ -109,6 +107,11 @@ extern void SetHookVirtual (VirtualHookData* hook); extern void UnsetHookVirtual (VirtualHookData* hook); extern bool HandleHookVirtual (VirtualHookData* hook, bool revert); +inline int GET_VTABLE_OFFSET(int x) +{ + return GameVirtualOffsets[x].fieldOffset; +} + inline void** GetEntityVTable(edict_t* e) { return *((void***)(((char*)e->pvPrivateData) + g_EntityVTableOffsetBase));