2013-02-08 05:43:33 +01:00
|
|
|
/**
|
|
|
|
* vim: set ts=4 :
|
|
|
|
* =============================================================================
|
|
|
|
* Source SDK Hooks Extension
|
|
|
|
* Copyright (C) 2010-2012 Nicholas Hastings
|
|
|
|
* Copyright (C) 2009-2010 Erik Minekus
|
|
|
|
* =============================================================================
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License, version 3.0, as published by the
|
|
|
|
* Free Software Foundation.
|
|
|
|
*
|
|
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* As a special exception, AlliedModders LLC gives you permission to link the
|
|
|
|
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
|
|
|
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
|
|
|
* by the Valve Corporation. You must obey the GNU General Public License in
|
|
|
|
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
|
|
|
* this exception to all derivative works. AlliedModders LLC defines further
|
|
|
|
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
|
|
|
* or <http://www.sourcemod.net/license.php>.
|
|
|
|
*
|
|
|
|
* Version: $Id$
|
|
|
|
*/
|
|
|
|
|
2013-02-09 17:37:51 +01:00
|
|
|
#include <sourcemod_version.h>
|
2013-02-08 05:43:33 +01:00
|
|
|
#include "extension.h"
|
|
|
|
#include "compat_wrappers.h"
|
|
|
|
#include "macros.h"
|
|
|
|
#include "natives.h"
|
|
|
|
#include <sm_platform.h>
|
|
|
|
#include <const.h>
|
|
|
|
|
|
|
|
|
|
|
|
//#define SDKHOOKSDEBUG
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Globals
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Order MUST match SDKHookType enum
|
|
|
|
HookTypeData g_HookTypes[SDKHook_MAXHOOKS] =
|
|
|
|
{
|
|
|
|
// Hook name DT required Supported (always false til later)
|
|
|
|
{"EndTouch", "", false},
|
|
|
|
{"FireBulletsPost", "", false},
|
|
|
|
{"OnTakeDamage", "", false},
|
|
|
|
{"OnTakeDamagePost", "", false},
|
|
|
|
{"PreThink", "DT_BasePlayer", false},
|
|
|
|
{"PostThink", "DT_BasePlayer", false},
|
|
|
|
{"SetTransmit", "", false},
|
|
|
|
{"Spawn", "", false},
|
|
|
|
{"StartTouch", "", false},
|
|
|
|
{"Think", "", false},
|
|
|
|
{"Touch", "", false},
|
|
|
|
{"TraceAttack", "", false},
|
|
|
|
{"TraceAttackPost", "", false},
|
|
|
|
{"WeaponCanSwitchTo", "DT_BaseCombatCharacter", false},
|
|
|
|
{"WeaponCanUse", "DT_BaseCombatCharacter", false},
|
|
|
|
{"WeaponDrop", "DT_BaseCombatCharacter", false},
|
|
|
|
{"WeaponEquip", "DT_BaseCombatCharacter", false},
|
|
|
|
{"WeaponSwitch", "DT_BaseCombatCharacter", false},
|
|
|
|
{"ShouldCollide", "", false},
|
|
|
|
{"PreThinkPost", "DT_BasePlayer", false},
|
|
|
|
{"PostThinkPost", "DT_BasePlayer", false},
|
|
|
|
{"ThinkPost", "", false},
|
|
|
|
{"EndTouchPost", "", false},
|
|
|
|
{"GroundEntChangedPost", "", false},
|
|
|
|
{"SpawnPost", "", false},
|
|
|
|
{"StartTouchPost", "", false},
|
|
|
|
{"TouchPost", "", false},
|
|
|
|
{"VPhysicsUpdate", "", false},
|
|
|
|
{"VPhysicsUpdatePost", "", false},
|
|
|
|
{"WeaponCanSwitchToPost", "DT_BaseCombatCharacter", false},
|
|
|
|
{"WeaponCanUsePost", "DT_BaseCombatCharacter", false},
|
|
|
|
{"WeaponDropPost", "DT_BaseCombatCharacter", false},
|
|
|
|
{"WeaponEquipPost", "DT_BaseCombatCharacter", false},
|
|
|
|
{"WeaponSwitchPost", "DT_BaseCombatCharacter", false},
|
|
|
|
{"Use", "", false},
|
|
|
|
{"UsePost", "", false},
|
|
|
|
{"Reload", "DT_BaseCombatWeapon", false},
|
|
|
|
{"ReloadPost", "DT_BaseCombatWeapon", false},
|
|
|
|
{"GetMaxHealth", "", false},
|
2014-08-01 12:23:19 +02:00
|
|
|
{"Blocked", "", false},
|
|
|
|
{"BlockedPost", "", false},
|
2014-09-03 23:45:34 +02:00
|
|
|
{"OnTakeDamageAlive", "DT_BaseCombatCharacter", false},
|
|
|
|
{"OnTakeDamageAlivePost", "DT_BaseCombatCharacter", false},
|
2015-11-26 16:32:32 +01:00
|
|
|
|
|
|
|
// There is no DT for CBaseMultiplayerPlayer. Going up a level
|
|
|
|
{"CanBeAutobalanced", "DT_BasePlayer", false},
|
2013-02-08 05:43:33 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
SDKHooks g_Interface;
|
|
|
|
SMEXT_LINK(&g_Interface);
|
|
|
|
|
|
|
|
CGlobalVars *gpGlobals;
|
2014-03-24 05:11:06 +01:00
|
|
|
ke::Vector<CVTableList *> g_HookList[SDKHook_MAXHOOKS];
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
CBitVec<NUM_ENT_ENTRIES> m_EntityExists;
|
|
|
|
|
|
|
|
IBinTools *g_pBinTools = NULL;
|
|
|
|
ICvar *icvar = NULL;
|
|
|
|
|
2014-04-24 04:19:28 +02:00
|
|
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
|
|
IServerTools *servertools = NULL;
|
|
|
|
#endif
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
// global hooks and forwards
|
|
|
|
IForward *g_pOnEntityCreated = NULL;
|
|
|
|
IForward *g_pOnEntityDestroyed = NULL;
|
|
|
|
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
int g_hookOnGetGameDescription = 0;
|
|
|
|
IForward *g_pOnGetGameNameDescription = NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int g_hookOnGetMapEntitiesString = 0;
|
|
|
|
int g_hookOnLevelInit = 0;
|
|
|
|
IForward *g_pOnLevelInit = NULL;
|
|
|
|
|
|
|
|
IGameConfig *g_pGameConf = NULL;
|
|
|
|
|
|
|
|
char g_szMapEntities[2097152];
|
|
|
|
|
2014-02-08 04:11:31 +01:00
|
|
|
CUtlVector<IEntityListener *> *EntListeners()
|
|
|
|
{
|
|
|
|
void *gEntList = gamehelpers->GetGlobalEntityList();
|
|
|
|
if (gEntList)
|
|
|
|
{
|
|
|
|
int offset = -1; /* 65572 */
|
|
|
|
if (g_pGameConf->GetOffset("EntityListeners", &offset))
|
|
|
|
{
|
|
|
|
return (CUtlVector<IEntityListener *> *)((intptr_t) gEntList + offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
void *entListeners;
|
|
|
|
if (g_pGameConf->GetAddress("EntityListenersPtr", &entListeners))
|
|
|
|
{
|
|
|
|
return (CUtlVector<IEntityListener *> *)entListeners;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* IServerGameDLL & IVEngineServer Hooks
|
|
|
|
*/
|
|
|
|
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, const char *, const char *, const char *, const char *, bool, bool);
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
SH_DECL_HOOK0(IServerGameDLL, GetGameDescription, SH_NOATTRIB, 0, const char *);
|
|
|
|
#endif
|
|
|
|
SH_DECL_HOOK0(IVEngineServer, GetMapEntitiesString, SH_NOATTRIB, 0, const char *);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* CBaseEntity Hooks
|
|
|
|
*/
|
|
|
|
SH_DECL_MANUALHOOK1_void(EndTouch, 0, 0, 0, CBaseEntity *);
|
|
|
|
SH_DECL_MANUALHOOK1_void(FireBullets, 0, 0, 0, FireBulletsInfo_t const&);
|
|
|
|
#ifdef GETMAXHEALTH_IS_VIRTUAL
|
|
|
|
SH_DECL_MANUALHOOK0(GetMaxHealth, 0, 0, 0, int);
|
|
|
|
#endif
|
2014-05-05 17:40:42 +02:00
|
|
|
SH_DECL_MANUALHOOK1_void(GroundEntChanged, 0, 0, 0, void *);
|
2013-02-08 05:43:33 +01:00
|
|
|
SH_DECL_MANUALHOOK1(OnTakeDamage, 0, 0, 0, int, CTakeDamageInfoHack &);
|
2014-10-14 23:47:44 +02:00
|
|
|
SH_DECL_MANUALHOOK1(OnTakeDamage_Alive, 0, 0, 0, int, CTakeDamageInfoHack &);
|
2013-02-08 05:43:33 +01:00
|
|
|
SH_DECL_MANUALHOOK0_void(PreThink, 0, 0, 0);
|
|
|
|
SH_DECL_MANUALHOOK0_void(PostThink, 0, 0, 0);
|
|
|
|
SH_DECL_MANUALHOOK0(Reload, 0, 0, 0, bool);
|
|
|
|
SH_DECL_MANUALHOOK2_void(SetTransmit, 0, 0, 0, CCheckTransmitInfo *, bool);
|
|
|
|
SH_DECL_MANUALHOOK2(ShouldCollide, 0, 0, 0, bool, int, int);
|
2013-12-28 14:19:34 +01:00
|
|
|
#if SOURCE_ENGINE == SE_DOTA
|
|
|
|
SH_DECL_MANUALHOOK1_void(Spawn, 0, 0, 0, CEntityKeyValues *);
|
|
|
|
#else
|
2013-02-08 05:43:33 +01:00
|
|
|
SH_DECL_MANUALHOOK0_void(Spawn, 0, 0, 0);
|
2013-12-28 14:19:34 +01:00
|
|
|
#endif
|
2013-02-08 05:43:33 +01:00
|
|
|
SH_DECL_MANUALHOOK1_void(StartTouch, 0, 0, 0, CBaseEntity *);
|
|
|
|
SH_DECL_MANUALHOOK0_void(Think, 0, 0, 0);
|
|
|
|
SH_DECL_MANUALHOOK1_void(Touch, 0, 0, 0, CBaseEntity *);
|
2015-05-07 03:12:13 +02:00
|
|
|
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|
|
|
|
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013
|
2014-03-09 04:06:29 +01:00
|
|
|
SH_DECL_MANUALHOOK4_void(TraceAttack, 0, 0, 0, CTakeDamageInfoHack &, const Vector &, CGameTrace *, CDmgAccumulator *);
|
2013-02-08 05:43:33 +01:00
|
|
|
#else
|
|
|
|
SH_DECL_MANUALHOOK3_void(TraceAttack, 0, 0, 0, CTakeDamageInfoHack &, const Vector &, CGameTrace *);
|
|
|
|
#endif
|
|
|
|
SH_DECL_MANUALHOOK4_void(Use, 0, 0, 0, CBaseEntity *, CBaseEntity *, USE_TYPE, float);
|
|
|
|
SH_DECL_MANUALHOOK1_void(VPhysicsUpdate, 0, 0, 0, IPhysicsObject *);
|
|
|
|
SH_DECL_MANUALHOOK1(Weapon_CanSwitchTo, 0, 0, 0, bool, CBaseCombatWeapon *);
|
|
|
|
SH_DECL_MANUALHOOK1(Weapon_CanUse, 0, 0, 0, bool, CBaseCombatWeapon *);
|
|
|
|
SH_DECL_MANUALHOOK3_void(Weapon_Drop, 0, 0, 0, CBaseCombatWeapon *, const Vector *, const Vector *);
|
|
|
|
SH_DECL_MANUALHOOK1_void(Weapon_Equip, 0, 0, 0, CBaseCombatWeapon *);
|
|
|
|
SH_DECL_MANUALHOOK2(Weapon_Switch, 0, 0, 0, bool, CBaseCombatWeapon *, int);
|
2014-08-01 12:23:19 +02:00
|
|
|
SH_DECL_MANUALHOOK1_void(Blocked, 0, 0, 0, CBaseEntity *);
|
2015-11-26 16:32:32 +01:00
|
|
|
SH_DECL_MANUALHOOK0(CanBeAutobalanced, 0, 0, 0, bool);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Forwards
|
|
|
|
*/
|
|
|
|
bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
|
|
|
{
|
|
|
|
char buffer[256];
|
|
|
|
g_pSM->BuildPath(Path_SM, buffer, sizeof(buffer)-1, "/extensions/sdkhooks.ext." PLATFORM_LIB_EXT);
|
|
|
|
if (libsys->PathExists(buffer) && libsys->IsPathFile(buffer))
|
|
|
|
{
|
|
|
|
g_pSM->Format(error, maxlength-1, "SDKHooks 2.x cannot load while old version (sdkhooks.ext." PLATFORM_LIB_EXT ") is still in extensions dir");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_pSM->BuildPath(Path_SM, buffer, sizeof(buffer)-1, "/gamedata/sdkhooks.games.txt");
|
|
|
|
if (libsys->PathExists(buffer) && libsys->IsPathFile(buffer))
|
|
|
|
{
|
|
|
|
g_pSM->Format(error, maxlength-1, "SDKHooks 2.x cannot load while old gamedata file (sdkhooks.games.txt) is still in gamedata dir");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer[0] = '\0';
|
|
|
|
if (!gameconfs->LoadGameConfigFile("sdkhooks.games", &g_pGameConf, buffer, sizeof(buffer)))
|
|
|
|
{
|
|
|
|
if (buffer[0])
|
|
|
|
{
|
|
|
|
g_pSM->Format(error, maxlength, "Could not read sdkhooks.games gamedata: %s", buffer);
|
|
|
|
}
|
2014-12-31 02:56:28 +01:00
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-08 04:11:31 +01:00
|
|
|
CUtlVector<IEntityListener *> *entListeners = EntListeners();
|
|
|
|
if (!entListeners)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-02-08 04:11:31 +01:00
|
|
|
g_pSM->Format(error, maxlength, "Failed to setup entity listeners");
|
2013-02-08 05:43:33 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-08 04:11:31 +01:00
|
|
|
entListeners->AddToTail(this);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-12-31 02:56:28 +01:00
|
|
|
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
|
|
|
sharesys->AddNatives(myself, g_Natives);
|
|
|
|
sharesys->RegisterLibrary(myself, "sdkhooks");
|
|
|
|
sharesys->AddInterface(myself, &g_Interface);
|
|
|
|
sharesys->AddCapabilityProvider(myself, this, "SDKHook_DmgCustomInOTD");
|
|
|
|
sharesys->AddCapabilityProvider(myself, this, "SDKHook_LogicalEntSupport");
|
|
|
|
|
|
|
|
playerhelpers->AddClientListener(&g_Interface);
|
|
|
|
|
|
|
|
plsys->AddPluginsListener(&g_Interface);
|
|
|
|
|
|
|
|
g_pOnEntityCreated = forwards->CreateForward("OnEntityCreated", ET_Ignore, 2, NULL, Param_Cell, Param_String);
|
|
|
|
g_pOnEntityDestroyed = forwards->CreateForward("OnEntityDestroyed", ET_Ignore, 1, NULL, Param_Cell);
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
g_pOnGetGameNameDescription = forwards->CreateForward("OnGetGameDescription", ET_Hook, 2, NULL, Param_String);
|
|
|
|
#endif
|
|
|
|
g_pOnLevelInit = forwards->CreateForward("OnLevelInit", ET_Hook, 2, NULL, Param_String, Param_String);
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
SetupHooks();
|
|
|
|
|
|
|
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
|
|
|
int index;
|
|
|
|
CBaseHandle hndl;
|
|
|
|
for (IHandleEntity *pEnt = (IHandleEntity *)servertools->FirstEntity(); pEnt; pEnt = (IHandleEntity *)servertools->NextEntity((CBaseEntity *)pEnt))
|
|
|
|
{
|
|
|
|
hndl = pEnt->GetRefEHandle();
|
2014-03-24 05:11:06 +01:00
|
|
|
if (!hndl.IsValid())
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
index = hndl.GetEntryIndex();
|
|
|
|
m_EntityExists.Set(index);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
for (int i = 0; i < NUM_ENT_ENTRIES; i++)
|
|
|
|
{
|
|
|
|
if (gamehelpers->ReferenceToEntity(i) != NULL)
|
|
|
|
m_EntityExists.Set(i);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void HookLevelInit()
|
|
|
|
{
|
|
|
|
assert(g_hookOnLevelInit == 0);
|
2013-03-17 03:15:25 +01:00
|
|
|
g_hookOnLevelInit = SH_ADD_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(&g_Interface, &SDKHooks::Hook_LevelInit), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
assert(g_hookOnGetMapEntitiesString == 0);
|
2013-03-17 03:15:25 +01:00
|
|
|
g_hookOnGetMapEntitiesString = SH_ADD_HOOK(IVEngineServer, GetMapEntitiesString, engine, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GetMapEntitiesString), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
inline void HookGetGameDescription()
|
|
|
|
{
|
|
|
|
assert(g_hookOnGetGameDescription == 0);
|
2013-03-17 03:15:25 +01:00
|
|
|
g_hookOnGetGameDescription = SH_ADD_HOOK(IServerGameDLL, GetGameDescription, gamedll, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GetGameDescription), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void SDKHooks::SDK_OnAllLoaded()
|
|
|
|
{
|
|
|
|
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
|
|
|
|
|
|
|
|
if (!g_pBinTools)
|
|
|
|
{
|
|
|
|
g_pSM->LogError(myself, "Could not find interface: " SMINTERFACE_BINTOOLS_NAME);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (g_pOnLevelInit->GetFunctionCount() > 0)
|
|
|
|
HookLevelInit();
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
if (g_pOnGetGameNameDescription->GetFunctionCount() > 0)
|
|
|
|
HookGetGameDescription();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#define KILL_HOOK_IF_ACTIVE(hook) \
|
|
|
|
if (hook != 0) \
|
|
|
|
{ \
|
|
|
|
SH_REMOVE_HOOK_ID(hook); \
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::SDK_OnUnload()
|
|
|
|
{
|
|
|
|
// Remove left over hooks
|
2014-03-24 05:11:06 +01:00
|
|
|
Unhook(reinterpret_cast<SourcePawn::IPluginContext *>(NULL));
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
KILL_HOOK_IF_ACTIVE(g_hookOnLevelInit);
|
|
|
|
KILL_HOOK_IF_ACTIVE(g_hookOnGetMapEntitiesString);
|
|
|
|
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
KILL_HOOK_IF_ACTIVE(g_hookOnGetGameDescription);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
forwards->ReleaseForward(g_pOnEntityCreated);
|
|
|
|
forwards->ReleaseForward(g_pOnEntityDestroyed);
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
forwards->ReleaseForward(g_pOnGetGameNameDescription);
|
|
|
|
#endif
|
|
|
|
forwards->ReleaseForward(g_pOnLevelInit);
|
|
|
|
|
|
|
|
plsys->RemovePluginsListener(&g_Interface);
|
|
|
|
|
|
|
|
playerhelpers->RemoveClientListener(&g_Interface);
|
|
|
|
|
|
|
|
sharesys->DropCapabilityProvider(myself, this, "SDKHook_DmgCustomInOTD");
|
|
|
|
sharesys->DropCapabilityProvider(myself, this, "SDKHook_LogicalEntSupport");
|
|
|
|
|
2014-02-08 04:11:31 +01:00
|
|
|
CUtlVector<IEntityListener *> *entListeners = EntListeners();
|
|
|
|
entListeners->FindAndRemove(this);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
gameconfs->CloseGameConfigFile(g_pGameConf);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
|
|
|
{
|
|
|
|
GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
|
|
|
|
|
|
|
|
#if SOURCE_ENGINE >= SE_ORANGEBOX
|
2014-04-24 04:19:28 +02:00
|
|
|
GET_V_IFACE_ANY(GetServerFactory, servertools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION);
|
2013-02-08 05:43:33 +01:00
|
|
|
g_pCVar = icvar;
|
|
|
|
#endif
|
|
|
|
CONVAR_REGISTER(this);
|
|
|
|
|
|
|
|
gpGlobals = ismm->GetCGlobals();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-02-09 17:37:51 +01:00
|
|
|
const char *SDKHooks::GetExtensionVerString()
|
|
|
|
{
|
2013-12-30 23:51:00 +01:00
|
|
|
return SOURCEMOD_VERSION;
|
2013-02-09 17:37:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *SDKHooks::GetExtensionDateString()
|
|
|
|
{
|
2013-12-30 23:51:00 +01:00
|
|
|
return SOURCEMOD_BUILD_TIME;
|
2013-02-09 17:37:51 +01:00
|
|
|
}
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
void SDKHooks::OnPluginLoaded(IPlugin *plugin)
|
|
|
|
{
|
|
|
|
if (g_pOnLevelInit->GetFunctionCount() > 0 && g_hookOnLevelInit == 0)
|
|
|
|
HookLevelInit();
|
|
|
|
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
if (g_pOnGetGameNameDescription->GetFunctionCount() > 0 && g_hookOnGetGameDescription == 0)
|
|
|
|
HookGetGameDescription();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::OnPluginUnloaded(IPlugin *plugin)
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
Unhook(plugin->GetBaseContext());
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
if (g_pOnLevelInit->GetFunctionCount() == 0)
|
|
|
|
{
|
|
|
|
KILL_HOOK_IF_ACTIVE(g_hookOnLevelInit);
|
|
|
|
KILL_HOOK_IF_ACTIVE(g_hookOnGetMapEntitiesString);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
if (g_pOnGetGameNameDescription->GetFunctionCount() == 0)
|
|
|
|
KILL_HOOK_IF_ACTIVE(g_hookOnGetGameDescription);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::OnClientPutInServer(int client)
|
|
|
|
{
|
|
|
|
CBaseEntity *pPlayer = gamehelpers->ReferenceToEntity(client);
|
|
|
|
|
2014-05-11 04:21:42 +02:00
|
|
|
HandleEntityCreated(pPlayer, client);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
2014-05-11 04:21:38 +02:00
|
|
|
void SDKHooks::OnClientDisconnecting(int client)
|
|
|
|
{
|
|
|
|
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(client);
|
|
|
|
|
|
|
|
HandleEntityDeleted(pEntity, client);
|
|
|
|
}
|
|
|
|
|
2013-08-04 16:03:40 +02:00
|
|
|
void SDKHooks::AddEntityListener(ISMEntityListener *listener)
|
|
|
|
{
|
|
|
|
m_EntListeners.push_back(listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::RemoveEntityListener(ISMEntityListener *listener)
|
|
|
|
{
|
|
|
|
m_EntListeners.remove(listener);
|
|
|
|
}
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
bool SDKHooks::RegisterConCommandBase(ConCommandBase *pVar)
|
|
|
|
{
|
|
|
|
/* Always call META_REGCVAR instead of going through the engine. */
|
|
|
|
return META_REGCVAR(pVar);
|
|
|
|
}
|
|
|
|
|
|
|
|
FeatureStatus SDKHooks::GetFeatureStatus(FeatureType type, const char *name)
|
|
|
|
{
|
|
|
|
return FeatureStatus_Available;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Functions
|
|
|
|
*/
|
2014-07-29 00:51:34 +02:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
static void PopulateCallbackList(const ke::Vector<HookList> &source, ke::Vector<IPluginFunction *> &destination, int entity)
|
2014-07-29 00:51:34 +02:00
|
|
|
{
|
2014-07-29 11:48:13 +02:00
|
|
|
destination.ensure(8); /* Skip trivial allocations as AMTL uses length<<1. */
|
2014-07-29 00:51:34 +02:00
|
|
|
for (size_t iter = 0; iter < source.length(); ++iter)
|
|
|
|
{
|
|
|
|
if (source[iter].entity != entity)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2014-07-29 11:46:49 +02:00
|
|
|
destination.append(source[iter].callback);
|
2014-07-29 00:51:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
cell_t SDKHooks::Call(int entity, SDKHookType type, int other)
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
return Call(gamehelpers->ReferenceToEntity(entity), type, gamehelpers->ReferenceToEntity(other));
|
|
|
|
}
|
|
|
|
|
|
|
|
cell_t SDKHooks::Call(CBaseEntity *pEnt, SDKHookType type, int other)
|
|
|
|
{
|
|
|
|
return Call(pEnt, type, gamehelpers->ReferenceToEntity(other));
|
|
|
|
}
|
|
|
|
|
|
|
|
cell_t SDKHooks::Call(CBaseEntity *pEnt, SDKHookType type, CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
cell_t ret = Pl_Continue;
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEnt);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEnt);
|
|
|
|
int other = gamehelpers->EntityToBCompatRef(pOther);
|
2014-07-29 00:51:34 +02:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
2013-02-08 05:43:33 +01:00
|
|
|
callback->PushCell(other);
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
cell_t res;
|
|
|
|
callback->Execute(&res);
|
|
|
|
if(res > ret)
|
|
|
|
{
|
|
|
|
ret = res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::SetupHooks()
|
|
|
|
{
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
// gamedata pre post
|
|
|
|
// (pre is not necessarily a prehook, just named without "Post" appeneded)
|
|
|
|
|
|
|
|
CHECKOFFSET(EndTouch, true, true);
|
|
|
|
CHECKOFFSET(FireBullets, false, true);
|
|
|
|
CHECKOFFSET(GroundEntChanged, false, true);
|
|
|
|
CHECKOFFSET(OnTakeDamage, true, true);
|
2014-10-14 23:36:55 +02:00
|
|
|
CHECKOFFSET(OnTakeDamage_Alive,true, true);
|
2013-02-08 05:43:33 +01:00
|
|
|
CHECKOFFSET(PreThink, true, true);
|
|
|
|
CHECKOFFSET(PostThink, true, true);
|
|
|
|
CHECKOFFSET(Reload, true, true);
|
|
|
|
CHECKOFFSET(SetTransmit, true, false);
|
|
|
|
CHECKOFFSET(ShouldCollide, true, false);
|
|
|
|
CHECKOFFSET(Spawn, true, true);
|
|
|
|
CHECKOFFSET(StartTouch, true, true);
|
|
|
|
CHECKOFFSET(Think, true, true);
|
|
|
|
CHECKOFFSET(Touch, true, true);
|
|
|
|
CHECKOFFSET(TraceAttack, true, true);
|
|
|
|
CHECKOFFSET(Use, true, true);
|
|
|
|
CHECKOFFSET_W(CanSwitchTo, true, true);
|
|
|
|
CHECKOFFSET_W(CanUse, true, true);
|
|
|
|
CHECKOFFSET_W(Drop, true, true);
|
|
|
|
CHECKOFFSET_W(Equip, true, true);
|
|
|
|
CHECKOFFSET_W(Switch, true, true);
|
|
|
|
CHECKOFFSET(VPhysicsUpdate, true, true);
|
2014-08-01 12:23:19 +02:00
|
|
|
CHECKOFFSET(Blocked, true, true);
|
2015-11-26 16:32:32 +01:00
|
|
|
CHECKOFFSET(CanBeAutobalanced, true, false);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
// this one is in a class all its own -_-
|
|
|
|
offset = 0;
|
|
|
|
g_pGameConf->GetOffset("GroundEntChanged", &offset);
|
|
|
|
if (offset > 0)
|
|
|
|
{
|
|
|
|
SH_MANUALHOOK_RECONFIGURE(GroundEntChanged, offset, 0, 0);
|
|
|
|
g_HookTypes[SDKHook_GroundEntChangedPost].supported = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef GETMAXHEALTH_IS_VIRTUAL
|
|
|
|
CHECKOFFSET(GetMaxHealth, true, false);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callback)
|
|
|
|
{
|
|
|
|
if(!g_HookTypes[type].supported)
|
|
|
|
return HookRet_NotSupported;
|
|
|
|
|
2014-03-22 03:09:15 +01:00
|
|
|
CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(entity);
|
2013-02-08 05:43:33 +01:00
|
|
|
if(!pEnt)
|
|
|
|
return HookRet_InvalidEntity;
|
|
|
|
if(type < 0 || type >= SDKHook_MAXHOOKS)
|
|
|
|
return HookRet_InvalidHookType;
|
|
|
|
|
|
|
|
if (!!strcmp(g_HookTypes[type].dtReq, ""))
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
IServerUnknown *pUnk = (IServerUnknown *)pEnt;
|
|
|
|
|
|
|
|
IServerNetworkable *pNet = pUnk->GetNetworkable();
|
2013-08-25 03:59:52 +02:00
|
|
|
if (pNet && !UTIL_ContainsDataTable(pNet->GetServerClass()->m_pTable, g_HookTypes[type].dtReq))
|
2013-02-08 05:43:33 +01:00
|
|
|
return HookRet_BadEntForHookType;
|
|
|
|
}
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
size_t entry;
|
|
|
|
CVTableHook vhook(pEnt);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
|
|
|
|
for (entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook == vtablehooklist[entry]->vtablehook)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-03-24 05:11:06 +01:00
|
|
|
|
|
|
|
if (entry == vtablehooklist.length())
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
int hookid = 0;
|
2013-02-08 05:43:33 +01:00
|
|
|
switch(type)
|
|
|
|
{
|
|
|
|
case SDKHook_EndTouch:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(EndTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_EndTouch), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_EndTouchPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(EndTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_EndTouchPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_FireBulletsPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(FireBullets, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_FireBulletsPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
#ifdef GETMAXHEALTH_IS_VIRTUAL
|
|
|
|
case SDKHook_GetMaxHealth:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(GetMaxHealth, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GetMaxHealth), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case SDKHook_GroundEntChangedPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(GroundEntChanged, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GroundEntChangedPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_OnTakeDamage:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_OnTakeDamagePost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamagePost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
2014-10-14 23:47:44 +02:00
|
|
|
case SDKHook_OnTakeDamage_Alive:
|
|
|
|
hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage_Alive, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage_Alive), false);
|
2014-09-03 23:45:34 +02:00
|
|
|
break;
|
2014-10-14 23:47:44 +02:00
|
|
|
case SDKHook_OnTakeDamage_AlivePost:
|
|
|
|
hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage_Alive, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage_AlivePost), true);
|
2014-09-03 23:45:34 +02:00
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
case SDKHook_PreThink:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(PreThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PreThink), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_PreThinkPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(PreThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PreThinkPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_PostThink:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(PostThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PostThink), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_PostThinkPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(PostThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PostThinkPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_Reload:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Reload, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Reload), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_ReloadPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Reload, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ReloadPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_SetTransmit:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(SetTransmit, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_SetTransmit), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_Spawn:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Spawn, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Spawn), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_SpawnPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Spawn, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_SpawnPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_StartTouch:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(StartTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_StartTouch), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_StartTouchPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(StartTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_StartTouchPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_Think:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Think, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Think), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_ThinkPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Think, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ThinkPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_Touch:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Touch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Touch), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_TouchPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Touch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TouchPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_TraceAttack:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(TraceAttack, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TraceAttack), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_TraceAttackPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(TraceAttack, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TraceAttackPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_Use:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Use, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Use), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_UsePost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Use, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_UsePost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_VPhysicsUpdate:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(VPhysicsUpdate, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_VPhysicsUpdate), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_VPhysicsUpdatePost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(VPhysicsUpdate, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_VPhysicsUpdatePost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponCanSwitchTo:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_CanSwitchTo, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanSwitchTo), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponCanSwitchToPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_CanSwitchTo, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanSwitchToPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponCanUse:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_CanUse, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanUse), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponCanUsePost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_CanUse, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanUsePost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponDrop:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_Drop, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponDrop), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponDropPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_Drop, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponDropPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponEquip:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_Equip, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponEquip), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponEquipPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_Equip, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponEquipPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponSwitch:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_Switch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponSwitch), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_WeaponSwitchPost:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Weapon_Switch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponSwitchPost), true);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
|
|
|
case SDKHook_ShouldCollide:
|
2014-03-24 05:11:06 +01:00
|
|
|
hookid = SH_ADD_MANUALVPHOOK(ShouldCollide, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ShouldCollide), false);
|
2013-02-08 05:43:33 +01:00
|
|
|
break;
|
2014-08-01 12:23:19 +02:00
|
|
|
case SDKHook_Blocked:
|
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Blocked, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Blocked), false);
|
|
|
|
break;
|
|
|
|
case SDKHook_BlockedPost:
|
|
|
|
hookid = SH_ADD_MANUALVPHOOK(Blocked, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_BlockedPost), true);
|
|
|
|
break;
|
2015-11-26 16:32:32 +01:00
|
|
|
case SDKHook_CanBeAutobalanced:
|
|
|
|
hookid = SH_ADD_MANUALVPHOOK(CanBeAutobalanced, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_CanBeAutobalanced), false);
|
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
vhook.SetHookID(hookid);
|
|
|
|
|
|
|
|
CVTableList *vtablelist = new CVTableList;
|
|
|
|
vtablelist->vtablehook = new CVTableHook(vhook);
|
|
|
|
vtablehooklist.append(vtablelist);
|
|
|
|
}
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
// Add hook to hook list
|
|
|
|
HookList hook;
|
2014-03-24 05:11:06 +01:00
|
|
|
hook.entity = gamehelpers->EntityToBCompatRef(pEnt);
|
2013-02-08 05:43:33 +01:00
|
|
|
hook.callback = callback;
|
2014-03-24 05:11:06 +01:00
|
|
|
vtablehooklist[entry]->hooks.append(hook);
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
return HookRet_Successful;
|
|
|
|
}
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
void SDKHooks::Unhook(CBaseEntity *pEntity)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (pEntity == NULL)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
return;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
for (size_t type = 0; type < SDKHook_MAXHOOKS; ++type)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
|
|
|
|
for (size_t listentry = 0; listentry < vtablehooklist.length(); ++listentry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
ke::Vector<HookList> &pawnhooks = vtablehooklist[listentry]->hooks;
|
|
|
|
for (size_t entry = 0; entry < pawnhooks.length(); ++entry)
|
|
|
|
{
|
|
|
|
if (entity != pawnhooks[entry].entity)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
pawnhooks.remove(entry--);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pawnhooks.length() == 0)
|
|
|
|
{
|
|
|
|
delete vtablehooklist[listentry];
|
|
|
|
vtablehooklist.remove(listentry--);
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
}
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Unhook(IPluginContext *pContext)
|
|
|
|
{
|
|
|
|
for (size_t type = 0; type < SDKHook_MAXHOOKS; ++type)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
|
|
|
|
for (size_t listentry = 0; listentry < vtablehooklist.length(); ++listentry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
ke::Vector<HookList> &pawnhooks = vtablehooklist[listentry]->hooks;
|
|
|
|
for (size_t entry = 0; entry < pawnhooks.length(); ++entry)
|
|
|
|
{
|
|
|
|
if (pContext != NULL && pContext != pawnhooks[entry].callback->GetParentRuntime()->GetDefaultContext())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
pawnhooks.remove(entry--);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pawnhooks.length() == 0)
|
|
|
|
{
|
|
|
|
delete vtablehooklist[listentry];
|
|
|
|
vtablehooklist.remove(listentry--);
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
void SDKHooks::Unhook(int entity, SDKHookType type, IPluginFunction *pCallback)
|
|
|
|
{
|
|
|
|
CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(entity);
|
|
|
|
if (pEntity == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
|
|
|
|
for (size_t listentry = 0; listentry < vtablehooklist.length(); ++listentry)
|
|
|
|
{
|
|
|
|
if (vhook != vtablehooklist[listentry]->vtablehook)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
|
|
|
|
ke::Vector<HookList> &pawnhooks = vtablehooklist[listentry]->hooks;
|
|
|
|
for (size_t entry = 0; entry < pawnhooks.length(); ++entry)
|
|
|
|
{
|
|
|
|
HookList &hookentry = pawnhooks[entry];
|
|
|
|
if (entity != hookentry.entity || pCallback != hookentry.callback)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
pawnhooks.remove(entry--);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pawnhooks.length() == 0)
|
|
|
|
{
|
|
|
|
delete vtablehooklist[listentry];
|
|
|
|
vtablehooklist.remove(listentry);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* IEntityFactoryDictionary, IServerGameDLL & IVEngineServer Hook Handlers
|
|
|
|
*/
|
|
|
|
void SDKHooks::OnEntityCreated(CBaseEntity *pEntity)
|
|
|
|
{
|
|
|
|
// Call OnEntityCreated forward
|
2014-05-11 04:21:42 +02:00
|
|
|
int ref = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
int index = gamehelpers->ReferenceToIndex(ref);
|
2014-05-11 04:21:42 +02:00
|
|
|
|
|
|
|
// This can be -1 for player ents before any players have connected
|
2014-05-21 05:33:50 +02:00
|
|
|
if ((unsigned)index == INVALID_EHANDLE_INDEX || m_EntityExists.IsBitSet(index) || (index > 0 && index <= playerhelpers->GetMaxClients()))
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-11 04:21:42 +02:00
|
|
|
HandleEntityCreated(pEntity, ref);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef GAMEDESC_CAN_CHANGE
|
|
|
|
const char *SDKHooks::Hook_GetGameDescription()
|
|
|
|
{
|
|
|
|
static char szGameDesc[64];
|
|
|
|
cell_t result = Pl_Continue;
|
|
|
|
|
|
|
|
g_pSM->Format(szGameDesc, sizeof(szGameDesc), "%s",
|
|
|
|
SH_CALL(gamedll, &IServerGameDLL::GetGameDescription)());
|
|
|
|
|
|
|
|
// Call OnGetGameDescription forward
|
|
|
|
g_pOnGetGameNameDescription->PushStringEx(szGameDesc, sizeof(szGameDesc), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
|
|
|
g_pOnGetGameNameDescription->Execute(&result);
|
|
|
|
|
|
|
|
if(result == Pl_Changed)
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, szGameDesc);
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
const char *SDKHooks::Hook_GetMapEntitiesString()
|
|
|
|
{
|
|
|
|
if(g_szMapEntities[0])
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, g_szMapEntities);
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
|
|
|
|
{
|
|
|
|
strcpy(g_szMapEntities, pMapEntities);
|
|
|
|
cell_t result = Pl_Continue;
|
|
|
|
|
|
|
|
// Call OnLevelInit forward
|
|
|
|
g_pOnLevelInit->PushString(pMapName);
|
|
|
|
g_pOnLevelInit->PushStringEx(g_szMapEntities, sizeof(g_szMapEntities), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
|
|
|
|
g_pOnLevelInit->Execute(&result);
|
|
|
|
|
|
|
|
if(result == Pl_Changed)
|
|
|
|
RETURN_META_VALUE_NEWPARAMS(MRES_HANDLED, true, &IServerGameDLL::LevelInit, (pMapName, g_szMapEntities, pOldLevel, pLandmarkName, loadGame, background));
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* CBaseEntity Hook Handlers
|
|
|
|
*/
|
2015-11-26 16:32:32 +01:00
|
|
|
bool SDKHooks::Hook_CanBeAutobalanced()
|
|
|
|
{
|
|
|
|
CBaseEntity *pPlayer = META_IFACEPTR(CBaseEntity);
|
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pPlayer);
|
|
|
|
|
|
|
|
bool origRet = SH_MCALL(pPlayer, CanBeAutobalanced)();
|
|
|
|
bool newRet = origRet;
|
|
|
|
|
|
|
|
CVTableHook vhook(pPlayer);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_CanBeAutobalanced];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
|
|
|
{
|
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
|
|
|
{
|
|
|
|
cell_t res;
|
|
|
|
IPluginFunction *callback = callbackList[entry];
|
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCell(origRet);
|
|
|
|
callback->Execute(&res);
|
|
|
|
|
|
|
|
// Only update our new ret if different from original
|
|
|
|
// (so if multiple plugins returning different answers,
|
|
|
|
// the one(s) that changed it win)
|
|
|
|
if ((res != 0) != origRet)
|
|
|
|
newRet = !origRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, newRet);
|
|
|
|
}
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
void SDKHooks::Hook_EndTouch(CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_EndTouch, pOther);
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_EndTouchPost(CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_EndTouchPost, pOther);
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_FireBulletsPost(const FireBulletsInfo_t &info)
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(entity);
|
|
|
|
if(!pPlayer)
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
|
|
|
|
IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
|
|
|
|
if(!pInfo)
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_FireBulletsPost];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
const char *weapon = pInfo->GetWeaponName();
|
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCell(info.m_iShots);
|
|
|
|
callback->PushString(weapon?weapon:"");
|
|
|
|
callback->Execute(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef GETMAXHEALTH_IS_VIRTUAL
|
|
|
|
int SDKHooks::Hook_GetMaxHealth()
|
|
|
|
{
|
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
|
|
|
int original_max = SH_MCALL(pEntity, GetMaxHealth)();
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_GetMaxHealth];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
|
|
|
|
int new_max = original_max;
|
|
|
|
|
|
|
|
cell_t res = Pl_Continue;
|
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCellByRef(&new_max);
|
|
|
|
callback->Execute(&res);
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
if (res >= Pl_Changed)
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, new_max);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, original_max);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-05-05 17:40:42 +02:00
|
|
|
void SDKHooks::Hook_GroundEntChangedPost(void *pVar)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_GroundEntChangedPost);
|
|
|
|
}
|
|
|
|
|
2014-09-03 23:45:34 +02:00
|
|
|
int SDKHooks::HandleOnTakeDamageHook(CTakeDamageInfoHack &info, SDKHookType hookType)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
2014-09-03 23:45:34 +02:00
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[hookType];
|
2014-03-24 05:11:06 +01:00
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
int attacker = info.GetAttacker();
|
|
|
|
int inflictor = info.GetInflictor();
|
|
|
|
float damage = info.GetDamage();
|
|
|
|
int damagetype = info.GetDamageType();
|
|
|
|
int weapon = info.GetWeapon();
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
Vector force = info.GetDamageForce();
|
2014-09-03 23:45:34 +02:00
|
|
|
cell_t damageForce[3] = { sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z) };
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
Vector pos = info.GetDamagePosition();
|
2014-09-03 23:45:34 +02:00
|
|
|
cell_t damagePosition[3] = { sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z) };
|
2014-03-24 05:11:06 +01:00
|
|
|
|
|
|
|
cell_t res, ret = Pl_Continue;
|
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCellByRef(&attacker);
|
|
|
|
callback->PushCellByRef(&inflictor);
|
|
|
|
callback->PushFloatByRef(&damage);
|
|
|
|
callback->PushCellByRef(&damagetype);
|
|
|
|
callback->PushCellByRef(&weapon);
|
|
|
|
callback->PushArray(damageForce, 3, SM_PARAM_COPYBACK);
|
2014-09-03 23:45:34 +02:00
|
|
|
callback->PushArray(damagePosition, 3, SM_PARAM_COPYBACK);
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(info.GetDamageCustom());
|
|
|
|
callback->Execute(&res);
|
|
|
|
|
2014-09-03 23:45:34 +02:00
|
|
|
if (res >= ret)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
|
|
|
ret = res;
|
2014-09-03 23:45:34 +02:00
|
|
|
if (ret == Pl_Changed)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
|
|
|
CBaseEntity *pEntAttacker = gamehelpers->ReferenceToEntity(attacker);
|
2014-09-03 23:45:34 +02:00
|
|
|
if (!pEntAttacker)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2015-11-18 02:24:31 +01:00
|
|
|
callback->GetParentContext()->BlamePluginError(callback, "Callback-provided entity %d for attacker is invalid", attacker);
|
2014-03-24 05:11:06 +01:00
|
|
|
RETURN_META_VALUE(MRES_IGNORED, 0);
|
|
|
|
}
|
|
|
|
CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor);
|
2014-09-03 23:45:34 +02:00
|
|
|
if (!pEntInflictor)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2015-11-18 02:24:31 +01:00
|
|
|
callback->GetParentContext()->BlamePluginError(callback, "Callback-provided entity %d for inflictor is invalid", inflictor);
|
2014-03-24 05:11:06 +01:00
|
|
|
RETURN_META_VALUE(MRES_IGNORED, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
info.SetAttacker(pEntAttacker);
|
|
|
|
info.SetInflictor(pEntInflictor);
|
|
|
|
info.SetDamage(damage);
|
|
|
|
info.SetDamageType(damagetype);
|
|
|
|
info.SetWeapon(gamehelpers->ReferenceToEntity(weapon));
|
|
|
|
info.SetDamageForce(
|
|
|
|
sp_ctof(damageForce[0]),
|
|
|
|
sp_ctof(damageForce[1]),
|
|
|
|
sp_ctof(damageForce[2]));
|
|
|
|
info.SetDamagePosition(
|
|
|
|
sp_ctof(damagePosition[0]),
|
|
|
|
sp_ctof(damagePosition[1]),
|
|
|
|
sp_ctof(damagePosition[2]));
|
|
|
|
}
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
2014-09-03 23:45:34 +02:00
|
|
|
|
|
|
|
if (ret >= Pl_Handled)
|
2014-03-24 05:11:06 +01:00
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, 1);
|
|
|
|
|
2014-09-03 23:45:34 +02:00
|
|
|
if (ret == Pl_Changed)
|
|
|
|
RETURN_META_VALUE(MRES_HANDLED, 1);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, 0);
|
|
|
|
}
|
|
|
|
|
2014-09-03 23:45:34 +02:00
|
|
|
int SDKHooks::HandleOnTakeDamageHookPost(CTakeDamageInfoHack &info, SDKHookType hookType)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
2014-09-03 23:45:34 +02:00
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[hookType];
|
2014-03-24 05:11:06 +01:00
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCell(info.GetAttacker());
|
|
|
|
callback->PushCell(info.GetInflictor());
|
|
|
|
callback->PushFloat(info.GetDamage());
|
|
|
|
callback->PushCell(info.GetDamageType());
|
|
|
|
callback->PushCell(info.GetWeapon());
|
|
|
|
|
|
|
|
Vector force = info.GetDamageForce();
|
2014-09-03 23:45:34 +02:00
|
|
|
cell_t damageForce[3] = { sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z) };
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushArray(damageForce, 3);
|
|
|
|
|
|
|
|
Vector pos = info.GetDamagePosition();
|
2014-09-03 23:45:34 +02:00
|
|
|
cell_t damagePosition[3] = { sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z) };
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushArray(damagePosition, 3);
|
|
|
|
|
|
|
|
callback->PushCell(info.GetDamageCustom());
|
|
|
|
|
|
|
|
callback->Execute(NULL);
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, 0);
|
|
|
|
}
|
|
|
|
|
2014-09-03 23:45:34 +02:00
|
|
|
int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
|
|
|
|
{
|
|
|
|
return HandleOnTakeDamageHook(info, SDKHook_OnTakeDamage);
|
|
|
|
}
|
|
|
|
|
|
|
|
int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info)
|
|
|
|
{
|
|
|
|
return HandleOnTakeDamageHookPost(info, SDKHook_OnTakeDamagePost);
|
|
|
|
}
|
|
|
|
|
2014-10-14 23:47:44 +02:00
|
|
|
int SDKHooks::Hook_OnTakeDamage_Alive(CTakeDamageInfoHack &info)
|
2014-09-03 23:45:34 +02:00
|
|
|
{
|
2014-10-14 23:47:44 +02:00
|
|
|
return HandleOnTakeDamageHook(info, SDKHook_OnTakeDamage_Alive);
|
2014-09-03 23:45:34 +02:00
|
|
|
}
|
|
|
|
|
2014-10-14 23:47:44 +02:00
|
|
|
int SDKHooks::Hook_OnTakeDamage_AlivePost(CTakeDamageInfoHack &info)
|
2014-09-03 23:45:34 +02:00
|
|
|
{
|
2014-10-14 23:47:44 +02:00
|
|
|
return HandleOnTakeDamageHookPost(info, SDKHook_OnTakeDamage_AlivePost);
|
2014-09-03 23:45:34 +02:00
|
|
|
}
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
void SDKHooks::Hook_PreThink()
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThink);
|
2014-01-27 16:09:47 +01:00
|
|
|
RETURN_META(MRES_IGNORED);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_PreThinkPost()
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThinkPost);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_PostThink()
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_PostThink);
|
2014-01-27 16:09:47 +01:00
|
|
|
RETURN_META(MRES_IGNORED);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_PostThinkPost()
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_PostThinkPost);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_Reload()
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_Reload];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
cell_t res = Pl_Continue;
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->Execute(&res);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res >= Pl_Handled)
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_ReloadPost()
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
2014-07-16 20:40:52 +02:00
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_ReloadPost];
|
2014-03-24 05:11:06 +01:00
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
cell_t origreturn = META_RESULT_ORIG_RET(bool) ? 1 : 0;
|
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCell(origreturn);
|
|
|
|
callback->Execute(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_SetTransmit(CCheckTransmitInfo *pInfo, bool bAlways)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_SetTransmit, gamehelpers->IndexOfEdict(pInfo->m_pClientEnt));
|
|
|
|
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_ShouldCollide(int collisionGroup, int contentsMask)
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_ShouldCollide];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
cell_t origRet = ((META_RESULT_STATUS >= MRES_OVERRIDE)?(META_RESULT_OVERRIDE_RET(bool)):(META_RESULT_ORIG_RET(bool))) ? 1 : 0;
|
|
|
|
cell_t res = 0;
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCell(collisionGroup);
|
|
|
|
callback->PushCell(contentsMask);
|
|
|
|
callback->PushCell(origRet);
|
|
|
|
callback->Execute(&res);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ret = false;
|
|
|
|
if (res != 0)
|
|
|
|
{
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, ret);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
2013-12-28 14:19:34 +01:00
|
|
|
#if SOURCE_ENGINE == SE_DOTA
|
|
|
|
void SDKHooks::Hook_Spawn(CEntityKeyValues *kv)
|
|
|
|
#else
|
2013-02-08 05:43:33 +01:00
|
|
|
void SDKHooks::Hook_Spawn()
|
2013-12-28 14:19:34 +01:00
|
|
|
#endif
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_Spawn];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
cell_t res = Pl_Continue;
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->Execute(&res);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
2013-12-28 14:19:34 +01:00
|
|
|
#if SOURCE_ENGINE == SE_DOTA
|
|
|
|
void SDKHooks::Hook_SpawnPost(CEntityKeyValues *kv)
|
|
|
|
#else
|
2013-02-08 05:43:33 +01:00
|
|
|
void SDKHooks::Hook_SpawnPost()
|
2013-12-28 14:19:34 +01:00
|
|
|
#endif
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_SpawnPost);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_StartTouch(CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_StartTouch, pOther);
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_StartTouchPost(CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_StartTouchPost, pOther);
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_Think()
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_Think);
|
2014-01-27 16:09:47 +01:00
|
|
|
RETURN_META(MRES_IGNORED);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_ThinkPost()
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_ThinkPost);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_Touch(CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_Touch, pOther);
|
|
|
|
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_TouchPost(CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_TouchPost, pOther);
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
2015-05-07 03:12:13 +02:00
|
|
|
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|
|
|
|
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013
|
2014-03-09 04:06:29 +01:00
|
|
|
void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator)
|
2013-02-08 05:43:33 +01:00
|
|
|
#else
|
|
|
|
void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr)
|
|
|
|
#endif
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_TraceAttack];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
int attacker = info.GetAttacker();
|
|
|
|
int inflictor = info.GetInflictor();
|
|
|
|
float damage = info.GetDamage();
|
|
|
|
int damagetype = info.GetDamageType();
|
|
|
|
int ammotype = info.GetAmmoType();
|
|
|
|
cell_t res, ret = Pl_Continue;
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCellByRef(&attacker);
|
|
|
|
callback->PushCellByRef(&inflictor);
|
|
|
|
callback->PushFloatByRef(&damage);
|
|
|
|
callback->PushCellByRef(&damagetype);
|
|
|
|
callback->PushCellByRef(&ammotype);
|
|
|
|
callback->PushCell(ptr->hitbox);
|
|
|
|
callback->PushCell(ptr->hitgroup);
|
|
|
|
callback->Execute(&res);
|
|
|
|
|
|
|
|
if(res > ret)
|
|
|
|
{
|
|
|
|
ret = res;
|
|
|
|
|
|
|
|
if(ret == Pl_Changed)
|
|
|
|
{
|
|
|
|
CBaseEntity *pEntAttacker = gamehelpers->ReferenceToEntity(attacker);
|
|
|
|
if(!pEntAttacker)
|
|
|
|
{
|
2015-11-18 02:24:31 +01:00
|
|
|
callback->GetParentContext()->BlamePluginError(callback, "Callback-provided entity %d for attacker is invalid", attacker);
|
2014-03-24 05:11:06 +01:00
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor);
|
|
|
|
if(!pEntInflictor)
|
|
|
|
{
|
2015-11-18 02:24:31 +01:00
|
|
|
callback->GetParentContext()->BlamePluginError(callback, "Callback-provided entity %d for inflictor is invalid", inflictor);
|
2014-03-24 05:11:06 +01:00
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
info.SetAttacker(pEntAttacker);
|
|
|
|
info.SetInflictor(pEntInflictor);
|
|
|
|
info.SetDamage(damage);
|
|
|
|
info.SetDamageType(damagetype);
|
|
|
|
info.SetAmmoType(ammotype);
|
|
|
|
}
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
if(ret >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
if(ret == Pl_Changed)
|
|
|
|
RETURN_META(MRES_HANDLED);
|
|
|
|
|
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
2015-05-07 03:12:13 +02:00
|
|
|
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 \
|
|
|
|
|| SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013
|
2014-03-09 04:06:29 +01:00
|
|
|
void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator)
|
2013-02-08 05:43:33 +01:00
|
|
|
#else
|
|
|
|
void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr)
|
|
|
|
#endif
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_TraceAttackPost];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCell(info.GetAttacker());
|
|
|
|
callback->PushCell(info.GetInflictor());
|
|
|
|
callback->PushFloat(info.GetDamage());
|
|
|
|
callback->PushCell(info.GetDamageType());
|
|
|
|
callback->PushCell(info.GetAmmoType());
|
|
|
|
callback->PushCell(ptr->hitbox);
|
|
|
|
callback->PushCell(ptr->hitgroup);
|
|
|
|
callback->Execute(NULL);
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_Use];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
int activator = gamehelpers->EntityToBCompatRef(pActivator);
|
|
|
|
int caller = gamehelpers->EntityToBCompatRef(pCaller);
|
|
|
|
cell_t ret = Pl_Continue;
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCell(activator);
|
|
|
|
callback->PushCell(caller);
|
|
|
|
callback->PushCell(useType);
|
|
|
|
callback->PushFloat(value);
|
|
|
|
callback->Execute(&ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2013-02-08 05:43:33 +01:00
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
|
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-03-24 05:11:06 +01:00
|
|
|
CVTableHook vhook(pEntity);
|
|
|
|
ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_UsePost];
|
|
|
|
for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
|
2013-02-08 05:43:33 +01:00
|
|
|
{
|
2014-03-24 05:11:06 +01:00
|
|
|
if (vhook != vtablehooklist[entry]->vtablehook)
|
|
|
|
{
|
2013-02-08 05:43:33 +01:00
|
|
|
continue;
|
2014-03-24 05:11:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int entity = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
int activator = gamehelpers->EntityToBCompatRef(pActivator);
|
|
|
|
int caller = gamehelpers->EntityToBCompatRef(pCaller);
|
2013-02-08 05:43:33 +01:00
|
|
|
|
2014-07-31 00:34:51 +02:00
|
|
|
ke::Vector<IPluginFunction *> callbackList;
|
|
|
|
PopulateCallbackList(vtablehooklist[entry]->hooks, callbackList, entity);
|
|
|
|
for (entry = 0; entry < callbackList.length(); ++entry)
|
2014-03-24 05:11:06 +01:00
|
|
|
{
|
2014-07-31 00:34:51 +02:00
|
|
|
IPluginFunction *callback = callbackList[entry];
|
2014-03-24 05:11:06 +01:00
|
|
|
callback->PushCell(entity);
|
|
|
|
callback->PushCell(activator);
|
|
|
|
callback->PushCell(caller);
|
|
|
|
callback->PushCell(useType);
|
|
|
|
callback->PushFloat(value);
|
|
|
|
callback->Execute(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::OnEntityDeleted(CBaseEntity *pEntity)
|
|
|
|
{
|
2014-05-11 04:21:42 +02:00
|
|
|
int ref = gamehelpers->EntityToBCompatRef(pEntity);
|
|
|
|
int index = gamehelpers->ReferenceToIndex(ref);
|
|
|
|
|
|
|
|
// This can be -1 for player ents before any players have connected
|
2014-05-21 05:33:50 +02:00
|
|
|
if ((unsigned)index == INVALID_EHANDLE_INDEX || (index > 0 && index <= playerhelpers->GetMaxClients()))
|
2013-08-04 16:03:40 +02:00
|
|
|
{
|
2014-05-11 04:21:38 +02:00
|
|
|
return;
|
2013-08-04 16:03:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-11 04:21:42 +02:00
|
|
|
HandleEntityDeleted(pEntity, ref);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_VPhysicsUpdate(IPhysicsObject *pPhysics)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdate);
|
2014-01-27 16:09:47 +01:00
|
|
|
RETURN_META(MRES_IGNORED);
|
2013-02-08 05:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_VPhysicsUpdatePost(IPhysicsObject *pPhysics)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdatePost);
|
|
|
|
}
|
|
|
|
|
2014-08-01 12:23:19 +02:00
|
|
|
void SDKHooks::Hook_Blocked(CBaseEntity *pOther)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_Blocked, pOther);
|
|
|
|
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_BlockedPost(CBaseEntity *pOther)
|
|
|
|
{
|
2014-09-02 20:01:18 +02:00
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_BlockedPost, pOther);
|
2014-08-01 12:23:19 +02:00
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
2013-02-08 05:43:33 +01:00
|
|
|
bool SDKHooks::Hook_WeaponCanSwitchTo(CBaseCombatWeapon *pWeapon)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchTo, pWeapon);
|
|
|
|
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_WeaponCanSwitchToPost(CBaseCombatWeapon *pWeapon)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchToPost, pWeapon);
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_WeaponCanUse(CBaseCombatWeapon *pWeapon)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanUse, pWeapon);
|
|
|
|
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_WeaponCanUsePost(CBaseCombatWeapon *pWeapon)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanUsePost, pWeapon);
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_WeaponDrop(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponDrop, pWeapon);
|
|
|
|
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_WeaponDropPost(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponDropPost, pWeapon);
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_WeaponEquip(CBaseCombatWeapon *pWeapon)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponEquip, pWeapon);
|
|
|
|
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META(MRES_SUPERCEDE);
|
|
|
|
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SDKHooks::Hook_WeaponEquipPost(CBaseCombatWeapon *pWeapon)
|
|
|
|
{
|
|
|
|
Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponEquipPost, pWeapon);
|
|
|
|
RETURN_META(MRES_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_WeaponSwitch(CBaseCombatWeapon *pWeapon, int viewmodelindex)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponSwitch, pWeapon);
|
|
|
|
|
|
|
|
if(result >= Pl_Handled)
|
|
|
|
RETURN_META_VALUE(MRES_SUPERCEDE, false);
|
|
|
|
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SDKHooks::Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelindex)
|
|
|
|
{
|
|
|
|
cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponSwitchPost, pWeapon);
|
|
|
|
RETURN_META_VALUE(MRES_IGNORED, true);
|
|
|
|
}
|
2014-05-11 04:21:38 +02:00
|
|
|
|
2014-05-11 04:21:42 +02:00
|
|
|
void SDKHooks::HandleEntityCreated(CBaseEntity *pEntity, int ref)
|
|
|
|
{
|
|
|
|
const char *pName = gamehelpers->GetEntityClassname(pEntity);
|
|
|
|
|
|
|
|
// Send OnEntityCreated to SM listeners
|
|
|
|
SourceHook::List<ISMEntityListener *>::iterator iter;
|
|
|
|
ISMEntityListener *pListener = NULL;
|
|
|
|
for (iter = m_EntListeners.begin(); iter != m_EntListeners.end(); iter++)
|
|
|
|
{
|
|
|
|
pListener = (*iter);
|
|
|
|
pListener->OnEntityCreated(pEntity, pName ? pName : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call OnEntityCreated forward
|
|
|
|
g_pOnEntityCreated->PushCell(ref);
|
|
|
|
g_pOnEntityCreated->PushString(pName ? pName : "");
|
|
|
|
g_pOnEntityCreated->Execute(NULL);
|
|
|
|
|
|
|
|
m_EntityExists.Set(gamehelpers->ReferenceToIndex(ref));
|
|
|
|
}
|
|
|
|
|
2014-05-11 04:21:38 +02:00
|
|
|
void SDKHooks::HandleEntityDeleted(CBaseEntity *pEntity, int ref)
|
|
|
|
{
|
|
|
|
// Send OnEntityDestroyed to SM listeners
|
|
|
|
SourceHook::List<ISMEntityListener *>::iterator iter;
|
|
|
|
ISMEntityListener *pListener = NULL;
|
|
|
|
for (iter = m_EntListeners.begin(); iter != m_EntListeners.end(); iter++)
|
|
|
|
{
|
|
|
|
pListener = (*iter);
|
|
|
|
pListener->OnEntityDestroyed(pEntity);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call OnEntityDestroyed forward
|
|
|
|
g_pOnEntityDestroyed->PushCell(ref);
|
|
|
|
g_pOnEntityDestroyed->Execute(NULL);
|
|
|
|
|
|
|
|
Unhook(pEntity);
|
|
|
|
|
|
|
|
m_EntityExists.Set(gamehelpers->ReferenceToIndex(ref), false);
|
|
|
|
}
|