From 97383028e5ce28ff723eeb462d16b27f38d46317 Mon Sep 17 00:00:00 2001 From: Nick Hastings Date: Tue, 12 Oct 2021 20:34:55 -0400 Subject: [PATCH] Add option to not bypass hooks with TakeDamage and DropWeapon natives. --- extensions/sdkhooks/extension.cpp | 19 +++++++- extensions/sdkhooks/extension.h | 11 ++++- extensions/sdkhooks/natives.cpp | 78 +++++++++++++++++++++++++++++-- plugins/include/sdkhooks.inc | 7 ++- 4 files changed, 105 insertions(+), 10 deletions(-) diff --git a/extensions/sdkhooks/extension.cpp b/extensions/sdkhooks/extension.cpp index ff2ca9ee..2326e94e 100644 --- a/extensions/sdkhooks/extension.cpp +++ b/extensions/sdkhooks/extension.cpp @@ -37,7 +37,7 @@ #include "natives.h" #include #include - +#include //#define SDKHOOKSDEBUG @@ -317,6 +317,23 @@ void SDKHooks::SDK_OnAllLoaded() #endif } +bool SDKHooks::QueryRunning(char* error, size_t maxlength) +{ + SM_CHECK_IFACE(BINTOOLS, g_pBinTools); + + return true; +} + +bool SDKHooks::QueryInterfaceDrop(SMInterface* pInterface) +{ + if (pInterface == g_pBinTools) + { + return false; + } + + return IExtensionInterface::QueryInterfaceDrop(pInterface); +} + #define KILL_HOOK_IF_ACTIVE(hook) \ if (hook != 0) \ { \ diff --git a/extensions/sdkhooks/extension.h b/extensions/sdkhooks/extension.h index 13417726..1d0a9968 100644 --- a/extensions/sdkhooks/extension.h +++ b/extensions/sdkhooks/extension.h @@ -3,7 +3,6 @@ #include "smsdk_ext.h" #include -#include #include #include #include @@ -107,6 +106,10 @@ class IPhysicsObject; class CDmgAccumulator; typedef CBaseEntity CBaseCombatWeapon; +namespace SourceMod { + class IBinTools; +} + struct HookList { public: @@ -184,7 +187,9 @@ public: * @param maxlength Size of error message buffer. * @return True if working, false otherwise. */ - //virtual bool QueryRunning(char *error, size_t maxlength); + virtual bool QueryRunning(char *error, size_t maxlength); + + virtual bool QueryInterfaceDrop(SMInterface* pInterface); /** Returns version string */ virtual const char *GetExtensionVerString(); @@ -350,5 +355,7 @@ extern ICvar *icvar; #if SOURCE_ENGINE >= SE_ORANGEBOX extern IServerTools *servertools; #endif +extern SourceMod::IBinTools *g_pBinTools; +extern IGameConfig *g_pGameConf; #endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/sdkhooks/natives.cpp b/extensions/sdkhooks/natives.cpp index ed3ee77e..8b927103 100644 --- a/extensions/sdkhooks/natives.cpp +++ b/extensions/sdkhooks/natives.cpp @@ -33,6 +33,10 @@ #include "extension.h" #include "natives.h" #include +#include +#include + +using namespace SourceMod; SH_DECL_MANUALEXTERN1(OnTakeDamage, int, CTakeDamageInfoHack &); SH_DECL_MANUALEXTERN3_void(Weapon_Drop, CBaseCombatWeapon *, const Vector *, const Vector *); @@ -170,7 +174,44 @@ cell_t Native_TakeDamage(IPluginContext *pContext, const cell_t *params) } CTakeDamageInfoHack info(pInflictor, pAttacker, flDamage, iDamageType, pWeapon, vecDamageForce, vecDamagePosition); - SH_MCALL(pVictim, OnTakeDamage)((CTakeDamageInfoHack &)info); + + if (params[0] < 9 || params[9] != 0) + { + SH_MCALL(pVictim, OnTakeDamage)((CTakeDamageInfoHack&)info); + } + else + { + static ICallWrapper *pCall = nullptr; + if (!pCall) + { + int offset; + if (!g_pGameConf->GetOffset("OnTakeDamage", &offset)) + { + return pContext->ThrowNativeError("Could not find OnTakeDamage offset"); + } + + PassInfo pass[2]; + pass[0].type = PassType_Object; + pass[0].size = sizeof(CTakeDamageInfoHack &); + pass[0].flags = PASSFLAG_BYREF | PASSFLAG_OCTOR; + pass[1].type = PassType_Basic; + pass[1].size = sizeof(int); + pass[1].flags = PASSFLAG_BYVAL; + + pCall = g_pBinTools->CreateVCall(offset, 0, 0, &pass[1], &pass[0], 1); + } + + // Can't ArgBuffer here until we upgrade our Clang version on the Linux builder + unsigned char vstk[sizeof(CBaseEntity *) + sizeof(CTakeDamageInfoHack &)]; + unsigned char* vptr = vstk; + + *(CBaseEntity **)vptr = pVictim; + vptr += sizeof(CBaseEntity *); + *(CTakeDamageInfoHack *&)vptr = info; + + int ret; + pCall->Execute(vstk, &ret); + } return 0; } @@ -225,6 +266,7 @@ cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params) } Vector vecVelocity; + Vector *pVecVelocity = nullptr; if ((err = pContext->LocalToPhysAddr(params[4], &addr)) != SP_ERROR_NONE) { return pContext->ThrowNativeError("Could not read vecVelocity vector"); @@ -236,14 +278,40 @@ cell_t Native_DropWeapon(IPluginContext *pContext, const cell_t *params) sp_ctof(addr[0]), sp_ctof(addr[1]), sp_ctof(addr[2])); + pVecVelocity = &vecVelocity; + } + + if (params[0] < 5 || params[5] != 0) + { + SH_MCALL(pPlayer, Weapon_Drop)((CBaseCombatWeapon*)pWeapon, &vecTarget, pVecVelocity); } else { - SH_MCALL(pPlayer, Weapon_Drop)((CBaseCombatWeapon *)pWeapon, &vecTarget, NULL); - return 0; - } + static ICallWrapper* pCall = nullptr; + if (!pCall) + { + int offset; + if (!g_pGameConf->GetOffset("Weapon_Drop", &offset)) + { + return pContext->ThrowNativeError("Could not find Weapon_Drop offset"); + } - SH_MCALL(pPlayer, Weapon_Drop)((CBaseCombatWeapon *)pWeapon, &vecTarget, &vecVelocity); + PassInfo pass[2]; + pass[0].type = PassType_Basic; + pass[0].size = sizeof(CBaseEntity *); + pass[0].flags = PASSFLAG_BYVAL; + pass[1].type = PassType_Basic; + pass[1].size = sizeof(Vector *); + pass[1].flags = PASSFLAG_BYVAL; + pass[2].type = PassType_Basic; + pass[2].size = sizeof(Vector *); + pass[2].flags = PASSFLAG_BYVAL; + + pCall = g_pBinTools->CreateVCall(offset, 0, 0, nullptr, pass, 3); + } + + pCall->Execute(ArgBuffer(pPlayer, pWeapon, &vecTarget, pVecVelocity), nullptr); + } return 0; } diff --git a/plugins/include/sdkhooks.inc b/plugins/include/sdkhooks.inc index b3cea620..1c80cf3b 100644 --- a/plugins/include/sdkhooks.inc +++ b/plugins/include/sdkhooks.inc @@ -416,11 +416,13 @@ native void SDKUnhook(int entity, SDKHookType type, SDKHookCB callback); * @param weapon Weapon index (orangebox and later) or -1 for unspecified * @param damageForce Velocity of damage force * @param damagePosition Origin of damage + * @param bypassHooks If true, bypass SDK hooks on OnTakeDamage * @error Invalid entity, attacker, inflictor, or weapon entity. */ native void SDKHooks_TakeDamage(int entity, int inflictor, int attacker, float damage, int damageType=DMG_GENERIC, int weapon=-1, - const float damageForce[3]=NULL_VECTOR, const float damagePosition[3]=NULL_VECTOR); + const float damageForce[3]=NULL_VECTOR, const float damagePosition[3]=NULL_VECTOR, + bool bypassHooks = true); /** * Forces a client to drop the specified weapon @@ -429,10 +431,11 @@ native void SDKHooks_TakeDamage(int entity, int inflictor, int attacker, * @param weapon Weapon entity index. * @param vecTarget Location to toss weapon to, or NULL_VECTOR for default. * @param vecVelocity Velocity at which to toss weapon, or NULL_VECTOR for default. + * @param bypassHooks If true, bypass SDK hooks on Weapon Drop * @error Invalid client or weapon entity, weapon not owned by client. */ native void SDKHooks_DropWeapon(int client, int weapon, const float vecTarget[3]=NULL_VECTOR, - const float vecVelocity[3]=NULL_VECTOR); + const float vecVelocity[3]=NULL_VECTOR, bool bypassHooks = true); /** * Do not edit below this line!