1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/extensions/sdkhooks/extension.cpp Thu Feb 07 23:43:33 2013 -0500
1.3 @@ -0,0 +1,1534 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * Source SDK Hooks Extension
1.8 + * Copyright (C) 2010-2012 Nicholas Hastings
1.9 + * Copyright (C) 2009-2010 Erik Minekus
1.10 + * =============================================================================
1.11 + *
1.12 + * This program is free software; you can redistribute it and/or modify it under
1.13 + * the terms of the GNU General Public License, version 3.0, as published by the
1.14 + * Free Software Foundation.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.19 + * details.
1.20 + *
1.21 + * You should have received a copy of the GNU General Public License along with
1.22 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.23 + *
1.24 + * As a special exception, AlliedModders LLC gives you permission to link the
1.25 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.26 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.27 + * by the Valve Corporation. You must obey the GNU General Public License in
1.28 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.29 + * this exception to all derivative works. AlliedModders LLC defines further
1.30 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.31 + * or <http://www.sourcemod.net/license.php>.
1.32 + *
1.33 + * Version: $Id$
1.34 + */
1.35 +
1.36 +#include "extension.h"
1.37 +#include "compat_wrappers.h"
1.38 +#include "macros.h"
1.39 +#include "natives.h"
1.40 +#include <sm_platform.h>
1.41 +#include <const.h>
1.42 +
1.43 +
1.44 +//#define SDKHOOKSDEBUG
1.45 +
1.46 +/**
1.47 + * Globals
1.48 + */
1.49 +
1.50 +// Order MUST match SDKHookType enum
1.51 +HookTypeData g_HookTypes[SDKHook_MAXHOOKS] =
1.52 +{
1.53 +// Hook name DT required Supported (always false til later)
1.54 + {"EndTouch", "", false},
1.55 + {"FireBulletsPost", "", false},
1.56 + {"OnTakeDamage", "", false},
1.57 + {"OnTakeDamagePost", "", false},
1.58 + {"PreThink", "DT_BasePlayer", false},
1.59 + {"PostThink", "DT_BasePlayer", false},
1.60 + {"SetTransmit", "", false},
1.61 + {"Spawn", "", false},
1.62 + {"StartTouch", "", false},
1.63 + {"Think", "", false},
1.64 + {"Touch", "", false},
1.65 + {"TraceAttack", "", false},
1.66 + {"TraceAttackPost", "", false},
1.67 + {"WeaponCanSwitchTo", "DT_BaseCombatCharacter", false},
1.68 + {"WeaponCanUse", "DT_BaseCombatCharacter", false},
1.69 + {"WeaponDrop", "DT_BaseCombatCharacter", false},
1.70 + {"WeaponEquip", "DT_BaseCombatCharacter", false},
1.71 + {"WeaponSwitch", "DT_BaseCombatCharacter", false},
1.72 + {"ShouldCollide", "", false},
1.73 + {"PreThinkPost", "DT_BasePlayer", false},
1.74 + {"PostThinkPost", "DT_BasePlayer", false},
1.75 + {"ThinkPost", "", false},
1.76 + {"EndTouchPost", "", false},
1.77 + {"GroundEntChangedPost", "", false},
1.78 + {"SpawnPost", "", false},
1.79 + {"StartTouchPost", "", false},
1.80 + {"TouchPost", "", false},
1.81 + {"VPhysicsUpdate", "", false},
1.82 + {"VPhysicsUpdatePost", "", false},
1.83 + {"WeaponCanSwitchToPost", "DT_BaseCombatCharacter", false},
1.84 + {"WeaponCanUsePost", "DT_BaseCombatCharacter", false},
1.85 + {"WeaponDropPost", "DT_BaseCombatCharacter", false},
1.86 + {"WeaponEquipPost", "DT_BaseCombatCharacter", false},
1.87 + {"WeaponSwitchPost", "DT_BaseCombatCharacter", false},
1.88 + {"Use", "", false},
1.89 + {"UsePost", "", false},
1.90 + {"Reload", "DT_BaseCombatWeapon", false},
1.91 + {"ReloadPost", "DT_BaseCombatWeapon", false},
1.92 + {"GetMaxHealth", "", false},
1.93 +};
1.94 +
1.95 +SDKHooks g_Interface;
1.96 +SMEXT_LINK(&g_Interface);
1.97 +
1.98 +CGlobalVars *gpGlobals;
1.99 +CUtlVector<HookList> g_HookList;
1.100 +
1.101 +CBitVec<NUM_ENT_ENTRIES> m_EntityExists;
1.102 +
1.103 +IBinTools *g_pBinTools = NULL;
1.104 +ICvar *icvar = NULL;
1.105 +
1.106 +// global hooks and forwards
1.107 +IForward *g_pOnEntityCreated = NULL;
1.108 +IForward *g_pOnEntityDestroyed = NULL;
1.109 +
1.110 +#ifdef GAMEDESC_CAN_CHANGE
1.111 +int g_hookOnGetGameDescription = 0;
1.112 +IForward *g_pOnGetGameNameDescription = NULL;
1.113 +#endif
1.114 +
1.115 +int g_hookOnGetMapEntitiesString = 0;
1.116 +int g_hookOnLevelInit = 0;
1.117 +IForward *g_pOnLevelInit = NULL;
1.118 +
1.119 +IGameConfig *g_pGameConf = NULL;
1.120 +int g_SplineCount = 0;
1.121 +
1.122 +char g_szMapEntities[2097152];
1.123 +
1.124 +
1.125 +/**
1.126 + * IServerGameDLL & IVEngineServer Hooks
1.127 + */
1.128 +SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, const char *, const char *, const char *, const char *, bool, bool);
1.129 +#ifdef GAMEDESC_CAN_CHANGE
1.130 +SH_DECL_HOOK0(IServerGameDLL, GetGameDescription, SH_NOATTRIB, 0, const char *);
1.131 +#endif
1.132 +SH_DECL_HOOK0(IVEngineServer, GetMapEntitiesString, SH_NOATTRIB, 0, const char *);
1.133 +
1.134 +
1.135 +/**
1.136 + * CBaseEntity Hooks
1.137 + */
1.138 +SH_DECL_MANUALHOOK1_void(EndTouch, 0, 0, 0, CBaseEntity *);
1.139 +SH_DECL_MANUALHOOK1_void(FireBullets, 0, 0, 0, FireBulletsInfo_t const&);
1.140 +#ifdef GETMAXHEALTH_IS_VIRTUAL
1.141 +SH_DECL_MANUALHOOK0(GetMaxHealth, 0, 0, 0, int);
1.142 +#endif
1.143 +SH_DECL_MANUALHOOK0_void(GroundEntChanged, 0, 0, 0);
1.144 +SH_DECL_MANUALHOOK1(OnTakeDamage, 0, 0, 0, int, CTakeDamageInfoHack &);
1.145 +SH_DECL_MANUALHOOK0_void(PreThink, 0, 0, 0);
1.146 +SH_DECL_MANUALHOOK0_void(PostThink, 0, 0, 0);
1.147 +SH_DECL_MANUALHOOK0(Reload, 0, 0, 0, bool);
1.148 +SH_DECL_MANUALHOOK2_void(SetTransmit, 0, 0, 0, CCheckTransmitInfo *, bool);
1.149 +SH_DECL_MANUALHOOK2(ShouldCollide, 0, 0, 0, bool, int, int);
1.150 +SH_DECL_MANUALHOOK0_void(Spawn, 0, 0, 0);
1.151 +SH_DECL_MANUALHOOK1_void(StartTouch, 0, 0, 0, CBaseEntity *);
1.152 +SH_DECL_MANUALHOOK0_void(Think, 0, 0, 0);
1.153 +SH_DECL_MANUALHOOK1_void(Touch, 0, 0, 0, CBaseEntity *);
1.154 +#if SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
1.155 +SH_DECL_MANUALHOOK4_void(TraceAttack, 0, 0, 0, CTakeDamageInfoHack &, const Vector &, CGameTrace *, void *);
1.156 +#else
1.157 +SH_DECL_MANUALHOOK3_void(TraceAttack, 0, 0, 0, CTakeDamageInfoHack &, const Vector &, CGameTrace *);
1.158 +#endif
1.159 +SH_DECL_MANUALHOOK4_void(Use, 0, 0, 0, CBaseEntity *, CBaseEntity *, USE_TYPE, float);
1.160 +SH_DECL_MANUALHOOK1_void(VPhysicsUpdate, 0, 0, 0, IPhysicsObject *);
1.161 +SH_DECL_MANUALHOOK1(Weapon_CanSwitchTo, 0, 0, 0, bool, CBaseCombatWeapon *);
1.162 +SH_DECL_MANUALHOOK1(Weapon_CanUse, 0, 0, 0, bool, CBaseCombatWeapon *);
1.163 +SH_DECL_MANUALHOOK3_void(Weapon_Drop, 0, 0, 0, CBaseCombatWeapon *, const Vector *, const Vector *);
1.164 +SH_DECL_MANUALHOOK1_void(Weapon_Equip, 0, 0, 0, CBaseCombatWeapon *);
1.165 +SH_DECL_MANUALHOOK2(Weapon_Switch, 0, 0, 0, bool, CBaseCombatWeapon *, int);
1.166 +
1.167 +
1.168 +/**
1.169 + * Forwards
1.170 + */
1.171 +bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
1.172 +{
1.173 + char buffer[256];
1.174 + g_pSM->BuildPath(Path_SM, buffer, sizeof(buffer)-1, "/extensions/sdkhooks.ext." PLATFORM_LIB_EXT);
1.175 + if (libsys->PathExists(buffer) && libsys->IsPathFile(buffer))
1.176 + {
1.177 + g_pSM->Format(error, maxlength-1, "SDKHooks 2.x cannot load while old version (sdkhooks.ext." PLATFORM_LIB_EXT ") is still in extensions dir");
1.178 + return false;
1.179 + }
1.180 +
1.181 + g_pSM->BuildPath(Path_SM, buffer, sizeof(buffer)-1, "/gamedata/sdkhooks.games.txt");
1.182 + if (libsys->PathExists(buffer) && libsys->IsPathFile(buffer))
1.183 + {
1.184 + g_pSM->Format(error, maxlength-1, "SDKHooks 2.x cannot load while old gamedata file (sdkhooks.games.txt) is still in gamedata dir");
1.185 + return false;
1.186 + }
1.187 +
1.188 + sharesys->AddDependency(myself, "bintools.ext", true, true);
1.189 + sharesys->AddNatives(myself, g_Natives);
1.190 + sharesys->RegisterLibrary(myself, "sdkhooks");
1.191 + sharesys->AddCapabilityProvider(myself, this, "SDKHook_DmgCustomInOTD");
1.192 + sharesys->AddCapabilityProvider(myself, this, "SDKHook_LogicalEntSupport");
1.193 +
1.194 + playerhelpers->AddClientListener(&g_Interface);
1.195 +
1.196 + plsys->AddPluginsListener(&g_Interface);
1.197 +
1.198 + g_pOnEntityCreated = forwards->CreateForward("OnEntityCreated", ET_Ignore, 2, NULL, Param_Cell, Param_String);
1.199 + g_pOnEntityDestroyed = forwards->CreateForward("OnEntityDestroyed", ET_Ignore, 1, NULL, Param_Cell);
1.200 +#ifdef GAMEDESC_CAN_CHANGE
1.201 + g_pOnGetGameNameDescription = forwards->CreateForward("OnGetGameDescription", ET_Hook, 2, NULL, Param_String);
1.202 +#endif
1.203 + g_pOnLevelInit = forwards->CreateForward("OnLevelInit", ET_Hook, 2, NULL, Param_String, Param_String);
1.204 +
1.205 + buffer[0] = '\0';
1.206 + if (!gameconfs->LoadGameConfigFile("sdkhooks.games", &g_pGameConf, buffer, sizeof(buffer)))
1.207 + {
1.208 + if (buffer[0])
1.209 + {
1.210 + g_pSM->Format(error, maxlength, "Could not read sdkhooks.games gamedata: %s", buffer);
1.211 + }
1.212 +
1.213 + return false;
1.214 + }
1.215 +
1.216 + void *gEntList = gamehelpers->GetGlobalEntityList();
1.217 + if (!gEntList)
1.218 + {
1.219 + g_pSM->Format(error, maxlength, "Cannot find gEntList pointer");
1.220 + return false;
1.221 + }
1.222 +
1.223 + int offset = -1; /* 65572 */
1.224 + if (!g_pGameConf->GetOffset("EntityListeners", &offset))
1.225 + {
1.226 + g_pSM->Format(error, maxlength, "Cannot find EntityListeners offset");
1.227 + return false;
1.228 + }
1.229 +
1.230 + CUtlVector<IEntityListener *> *pListeners = (CUtlVector<IEntityListener *> *)((intptr_t)gEntList + offset);
1.231 + pListeners->AddToTail(this);
1.232 +
1.233 + SetupHooks();
1.234 +
1.235 +#if SOURCE_ENGINE >= SE_ORANGEBOX
1.236 + int index;
1.237 + CBaseHandle hndl;
1.238 + for (IHandleEntity *pEnt = (IHandleEntity *)servertools->FirstEntity(); pEnt; pEnt = (IHandleEntity *)servertools->NextEntity((CBaseEntity *)pEnt))
1.239 + {
1.240 + hndl = pEnt->GetRefEHandle();
1.241 + if (hndl == INVALID_EHANDLE_INDEX || !hndl.IsValid())
1.242 + continue;
1.243 +
1.244 + index = hndl.GetEntryIndex();
1.245 + m_EntityExists.Set(index);
1.246 + }
1.247 +#else
1.248 + for (int i = 0; i < NUM_ENT_ENTRIES; i++)
1.249 + {
1.250 + if (gamehelpers->ReferenceToEntity(i) != NULL)
1.251 + m_EntityExists.Set(i);
1.252 + }
1.253 +#endif
1.254 +
1.255 + return true;
1.256 +}
1.257 +
1.258 +inline void HookLevelInit()
1.259 +{
1.260 + assert(g_hookOnLevelInit == 0);
1.261 + g_hookOnLevelInit = SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, &g_Interface, &SDKHooks::Hook_LevelInit, false);
1.262 + assert(g_hookOnGetMapEntitiesString == 0);
1.263 + g_hookOnGetMapEntitiesString = SH_ADD_HOOK_MEMFUNC(IVEngineServer, GetMapEntitiesString, engine, &g_Interface, &SDKHooks::Hook_GetMapEntitiesString, false);
1.264 +}
1.265 +
1.266 +#ifdef GAMEDESC_CAN_CHANGE
1.267 +inline void HookGetGameDescription()
1.268 +{
1.269 + assert(g_hookOnGetGameDescription == 0);
1.270 + g_hookOnGetGameDescription = SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GetGameDescription, gamedll, &g_Interface, &SDKHooks::Hook_GetGameDescription, false);
1.271 +}
1.272 +#endif
1.273 +
1.274 +void SDKHooks::SDK_OnAllLoaded()
1.275 +{
1.276 + SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
1.277 +
1.278 + if (!g_pBinTools)
1.279 + {
1.280 + g_pSM->LogError(myself, "Could not find interface: " SMINTERFACE_BINTOOLS_NAME);
1.281 + return;
1.282 + }
1.283 +
1.284 + if (g_pOnLevelInit->GetFunctionCount() > 0)
1.285 + HookLevelInit();
1.286 +#ifdef GAMEDESC_CAN_CHANGE
1.287 + if (g_pOnGetGameNameDescription->GetFunctionCount() > 0)
1.288 + HookGetGameDescription();
1.289 +#endif
1.290 +}
1.291 +
1.292 +#define KILL_HOOK_IF_ACTIVE(hook) \
1.293 + if (hook != 0) \
1.294 + { \
1.295 + SH_REMOVE_HOOK_ID(hook); \
1.296 + }
1.297 +
1.298 +void SDKHooks::SDK_OnUnload()
1.299 +{
1.300 + // Remove left over hooks
1.301 + HOOKLOOP
1.302 + Unhook(i);
1.303 +
1.304 + KILL_HOOK_IF_ACTIVE(g_hookOnLevelInit);
1.305 + KILL_HOOK_IF_ACTIVE(g_hookOnGetMapEntitiesString);
1.306 +
1.307 +#ifdef GAMEDESC_CAN_CHANGE
1.308 + KILL_HOOK_IF_ACTIVE(g_hookOnGetGameDescription);
1.309 +#endif
1.310 +
1.311 + forwards->ReleaseForward(g_pOnEntityCreated);
1.312 + forwards->ReleaseForward(g_pOnEntityDestroyed);
1.313 +#ifdef GAMEDESC_CAN_CHANGE
1.314 + forwards->ReleaseForward(g_pOnGetGameNameDescription);
1.315 +#endif
1.316 + forwards->ReleaseForward(g_pOnLevelInit);
1.317 +
1.318 + plsys->RemovePluginsListener(&g_Interface);
1.319 +
1.320 + playerhelpers->RemoveClientListener(&g_Interface);
1.321 +
1.322 + sharesys->DropCapabilityProvider(myself, this, "SDKHook_DmgCustomInOTD");
1.323 + sharesys->DropCapabilityProvider(myself, this, "SDKHook_LogicalEntSupport");
1.324 +
1.325 + void *gEntList = gamehelpers->GetGlobalEntityList();
1.326 + if (gEntList)
1.327 + {
1.328 + int offset = -1; /* 65572 */
1.329 + if (g_pGameConf->GetOffset("EntityListeners", &offset))
1.330 + {
1.331 + CUtlVector<IEntityListener *> *pListeners = (CUtlVector<IEntityListener *> *)((intptr_t)gEntList + offset);
1.332 + pListeners->FindAndRemove(this);
1.333 + }
1.334 + }
1.335 +
1.336 + gameconfs->CloseGameConfigFile(g_pGameConf);
1.337 +}
1.338 +
1.339 +bool SDKHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
1.340 +{
1.341 + GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
1.342 +
1.343 +#if SOURCE_ENGINE >= SE_ORANGEBOX
1.344 + g_pCVar = icvar;
1.345 +#endif
1.346 + CONVAR_REGISTER(this);
1.347 +
1.348 + gpGlobals = ismm->GetCGlobals();
1.349 +
1.350 + return true;
1.351 +}
1.352 +
1.353 +void SDKHooks::OnPluginLoaded(IPlugin *plugin)
1.354 +{
1.355 + if (g_pOnLevelInit->GetFunctionCount() > 0 && g_hookOnLevelInit == 0)
1.356 + HookLevelInit();
1.357 +
1.358 +#ifdef GAMEDESC_CAN_CHANGE
1.359 + if (g_pOnGetGameNameDescription->GetFunctionCount() > 0 && g_hookOnGetGameDescription == 0)
1.360 + HookGetGameDescription();
1.361 +#endif
1.362 +}
1.363 +
1.364 +void SDKHooks::OnPluginUnloaded(IPlugin *plugin)
1.365 +{
1.366 + IPluginContext *plugincontext = plugin->GetBaseContext();
1.367 + HOOKLOOP
1.368 + {
1.369 + if(g_HookList[i].callback->GetParentContext() == plugincontext)
1.370 + Unhook(i);
1.371 + }
1.372 +
1.373 + if (g_pOnLevelInit->GetFunctionCount() == 0)
1.374 + {
1.375 + KILL_HOOK_IF_ACTIVE(g_hookOnLevelInit);
1.376 + KILL_HOOK_IF_ACTIVE(g_hookOnGetMapEntitiesString);
1.377 + }
1.378 +
1.379 +#ifdef GAMEDESC_CAN_CHANGE
1.380 + if (g_pOnGetGameNameDescription->GetFunctionCount() == 0)
1.381 + KILL_HOOK_IF_ACTIVE(g_hookOnGetGameDescription);
1.382 +#endif
1.383 +}
1.384 +
1.385 +void SDKHooks::OnClientPutInServer(int client)
1.386 +{
1.387 + g_pOnEntityCreated->PushCell(client);
1.388 +
1.389 + CBaseEntity *pPlayer = gamehelpers->ReferenceToEntity(client);
1.390 +
1.391 + const char * pName = gamehelpers->GetEntityClassname(pPlayer);
1.392 +
1.393 + g_pOnEntityCreated->PushString(pName ? pName : "");
1.394 + g_pOnEntityCreated->Execute(NULL);
1.395 +
1.396 + m_EntityExists.Set(client);
1.397 +}
1.398 +
1.399 +bool SDKHooks::RegisterConCommandBase(ConCommandBase *pVar)
1.400 +{
1.401 + /* Always call META_REGCVAR instead of going through the engine. */
1.402 + return META_REGCVAR(pVar);
1.403 +}
1.404 +
1.405 +FeatureStatus SDKHooks::GetFeatureStatus(FeatureType type, const char *name)
1.406 +{
1.407 + return FeatureStatus_Available;
1.408 +}
1.409 +
1.410 +/**
1.411 + * Functions
1.412 + */
1.413 +cell_t SDKHooks::Call(int entity, SDKHookType type, int other)
1.414 +{
1.415 + IPluginFunction *callback = NULL;
1.416 + cell_t res, ret = Pl_Continue;
1.417 +
1.418 + HOOKLOOP
1.419 + {
1.420 + if(g_HookList[i].entity != entity || g_HookList[i].type != type)
1.421 + continue;
1.422 +
1.423 + callback = g_HookList[i].callback;
1.424 + callback->PushCell(entity);
1.425 + if(other > -2)
1.426 + callback->PushCell(other);
1.427 +
1.428 + callback->Execute(&res);
1.429 + if(res > ret)
1.430 + ret = res;
1.431 + }
1.432 +
1.433 + return ret;
1.434 +}
1.435 +
1.436 +cell_t SDKHooks::Call(CBaseEntity *pEnt, SDKHookType type, int other)
1.437 +{
1.438 + return Call(gamehelpers->EntityToBCompatRef(pEnt), type, other);
1.439 +}
1.440 +
1.441 +cell_t SDKHooks::Call(CBaseEntity *pEnt, SDKHookType type, CBaseEntity *other)
1.442 +{
1.443 + return Call(gamehelpers->EntityToBCompatRef(pEnt), type, gamehelpers->EntityToBCompatRef(other));
1.444 +}
1.445 +
1.446 +void SDKHooks::SetupHooks()
1.447 +{
1.448 + int offset;
1.449 +
1.450 + // gamedata pre post
1.451 + // (pre is not necessarily a prehook, just named without "Post" appeneded)
1.452 +
1.453 + CHECKOFFSET(EndTouch, true, true);
1.454 + CHECKOFFSET(FireBullets, false, true);
1.455 + CHECKOFFSET(GroundEntChanged, false, true);
1.456 + CHECKOFFSET(OnTakeDamage, true, true);
1.457 + CHECKOFFSET(PreThink, true, true);
1.458 + CHECKOFFSET(PostThink, true, true);
1.459 + CHECKOFFSET(Reload, true, true);
1.460 + CHECKOFFSET(SetTransmit, true, false);
1.461 + CHECKOFFSET(ShouldCollide, true, false);
1.462 + CHECKOFFSET(Spawn, true, true);
1.463 + CHECKOFFSET(StartTouch, true, true);
1.464 + CHECKOFFSET(Think, true, true);
1.465 + CHECKOFFSET(Touch, true, true);
1.466 + CHECKOFFSET(TraceAttack, true, true);
1.467 + CHECKOFFSET(Use, true, true);
1.468 + CHECKOFFSET_W(CanSwitchTo, true, true);
1.469 + CHECKOFFSET_W(CanUse, true, true);
1.470 + CHECKOFFSET_W(Drop, true, true);
1.471 + CHECKOFFSET_W(Equip, true, true);
1.472 + CHECKOFFSET_W(Switch, true, true);
1.473 + CHECKOFFSET(VPhysicsUpdate, true, true);
1.474 +
1.475 + // this one is in a class all its own -_-
1.476 + offset = 0;
1.477 + g_pGameConf->GetOffset("GroundEntChanged", &offset);
1.478 + if (offset > 0)
1.479 + {
1.480 + SH_MANUALHOOK_RECONFIGURE(GroundEntChanged, offset, 0, 0);
1.481 + g_HookTypes[SDKHook_GroundEntChangedPost].supported = true;
1.482 + }
1.483 +
1.484 +#ifdef GETMAXHEALTH_IS_VIRTUAL
1.485 + CHECKOFFSET(GetMaxHealth, true, false);
1.486 +#endif
1.487 +}
1.488 +
1.489 +HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callback)
1.490 +{
1.491 + if(!g_HookTypes[type].supported)
1.492 + return HookRet_NotSupported;
1.493 +
1.494 + CBaseEntity *pEnt = UTIL_GetCBaseEntity(entity);
1.495 + if(!pEnt)
1.496 + return HookRet_InvalidEntity;
1.497 + if(type < 0 || type >= SDKHook_MAXHOOKS)
1.498 + return HookRet_InvalidHookType;
1.499 +
1.500 +#if SOURCE_ENGINE >= SE_CSS
1.501 + if(entity > 0 && entity <= playerhelpers->GetMaxClients())
1.502 + {
1.503 + const char *id = engine->GetPlayerNetworkIDString(PEntityOfEntIndex(entity));
1.504 + g_SplineCount = strlen(id);
1.505 + }
1.506 +#endif
1.507 +
1.508 + if (!!strcmp(g_HookTypes[type].dtReq, ""))
1.509 + {
1.510 + sm_sendprop_info_t spi;
1.511 + IServerUnknown *pUnk = (IServerUnknown *)pEnt;
1.512 +
1.513 + IServerNetworkable *pNet = pUnk->GetNetworkable();
1.514 + if (pNet && !UTIL_FindDataTable(pNet->GetServerClass()->m_pTable, g_HookTypes[type].dtReq, &spi, 0))
1.515 + return HookRet_BadEntForHookType;
1.516 + }
1.517 +
1.518 + bool bHooked = false;
1.519 + HOOKLOOP
1.520 + {
1.521 + if (g_HookList[i].entity == entity && g_HookList[i].type == type)
1.522 + {
1.523 + bHooked = true;
1.524 + break;
1.525 + }
1.526 + }
1.527 + if (!bHooked)
1.528 + {
1.529 + switch(type)
1.530 + {
1.531 + case SDKHook_EndTouch:
1.532 + SH_ADD_MANUALHOOK_MEMFUNC(EndTouch, pEnt, &g_Interface, &SDKHooks::Hook_EndTouch, false);
1.533 + break;
1.534 + case SDKHook_EndTouchPost:
1.535 + SH_ADD_MANUALHOOK_MEMFUNC(EndTouch, pEnt, &g_Interface, &SDKHooks::Hook_EndTouchPost, true);
1.536 + break;
1.537 + case SDKHook_FireBulletsPost:
1.538 + SH_ADD_MANUALHOOK_MEMFUNC(FireBullets, pEnt, &g_Interface, &SDKHooks::Hook_FireBulletsPost, true);
1.539 + break;
1.540 +#ifdef GETMAXHEALTH_IS_VIRTUAL
1.541 + case SDKHook_GetMaxHealth:
1.542 + SH_ADD_MANUALHOOK_MEMFUNC(GetMaxHealth, pEnt, &g_Interface, &SDKHooks::Hook_GetMaxHealth, false);
1.543 + break;
1.544 +#endif
1.545 + case SDKHook_GroundEntChangedPost:
1.546 + SH_ADD_MANUALHOOK_MEMFUNC(GroundEntChanged, pEnt, &g_Interface, &SDKHooks::Hook_GroundEntChangedPost, true);
1.547 + break;
1.548 + case SDKHook_OnTakeDamage:
1.549 + SH_ADD_MANUALHOOK_MEMFUNC(OnTakeDamage, pEnt, &g_Interface, &SDKHooks::Hook_OnTakeDamage, false);
1.550 + break;
1.551 + case SDKHook_OnTakeDamagePost:
1.552 + SH_ADD_MANUALHOOK_MEMFUNC(OnTakeDamage, pEnt, &g_Interface, &SDKHooks::Hook_OnTakeDamagePost, true);
1.553 + break;
1.554 + case SDKHook_PreThink:
1.555 + SH_ADD_MANUALHOOK_MEMFUNC(PreThink, pEnt, &g_Interface, &SDKHooks::Hook_PreThink, false);
1.556 + break;
1.557 + case SDKHook_PreThinkPost:
1.558 + SH_ADD_MANUALHOOK_MEMFUNC(PreThink, pEnt, &g_Interface, &SDKHooks::Hook_PreThinkPost, true);
1.559 + break;
1.560 + case SDKHook_PostThink:
1.561 + SH_ADD_MANUALHOOK_MEMFUNC(PostThink, pEnt, &g_Interface, &SDKHooks::Hook_PostThink, false);
1.562 + break;
1.563 + case SDKHook_PostThinkPost:
1.564 + SH_ADD_MANUALHOOK_MEMFUNC(PostThink, pEnt, &g_Interface, &SDKHooks::Hook_PostThinkPost, true);
1.565 + break;
1.566 + case SDKHook_Reload:
1.567 + SH_ADD_MANUALHOOK_MEMFUNC(Reload, pEnt, &g_Interface, &SDKHooks::Hook_Reload, false);
1.568 + break;
1.569 + case SDKHook_ReloadPost:
1.570 + SH_ADD_MANUALHOOK_MEMFUNC(Reload, pEnt, &g_Interface, &SDKHooks::Hook_ReloadPost, true);
1.571 + break;
1.572 + case SDKHook_SetTransmit:
1.573 + SH_ADD_MANUALHOOK_MEMFUNC(SetTransmit, pEnt, &g_Interface, &SDKHooks::Hook_SetTransmit, false);
1.574 + break;
1.575 + case SDKHook_Spawn:
1.576 + SH_ADD_MANUALHOOK_MEMFUNC(Spawn, pEnt, &g_Interface, &SDKHooks::Hook_Spawn, false);
1.577 + break;
1.578 + case SDKHook_SpawnPost:
1.579 + SH_ADD_MANUALHOOK_MEMFUNC(Spawn, pEnt, &g_Interface, &SDKHooks::Hook_SpawnPost, true);
1.580 + break;
1.581 + case SDKHook_StartTouch:
1.582 + SH_ADD_MANUALHOOK_MEMFUNC(StartTouch, pEnt, &g_Interface, &SDKHooks::Hook_StartTouch, false);
1.583 + break;
1.584 + case SDKHook_StartTouchPost:
1.585 + SH_ADD_MANUALHOOK_MEMFUNC(StartTouch, pEnt, &g_Interface, &SDKHooks::Hook_StartTouchPost, true);
1.586 + break;
1.587 + case SDKHook_Think:
1.588 + SH_ADD_MANUALHOOK_MEMFUNC(Think, pEnt, &g_Interface, &SDKHooks::Hook_Think, false);
1.589 + break;
1.590 + case SDKHook_ThinkPost:
1.591 + SH_ADD_MANUALHOOK_MEMFUNC(Think, pEnt, &g_Interface, &SDKHooks::Hook_ThinkPost, true);
1.592 + break;
1.593 + case SDKHook_Touch:
1.594 + SH_ADD_MANUALHOOK_MEMFUNC(Touch, pEnt, &g_Interface, &SDKHooks::Hook_Touch, false);
1.595 + break;
1.596 + case SDKHook_TouchPost:
1.597 + SH_ADD_MANUALHOOK_MEMFUNC(Touch, pEnt, &g_Interface, &SDKHooks::Hook_TouchPost, true);
1.598 + break;
1.599 + case SDKHook_TraceAttack:
1.600 + SH_ADD_MANUALHOOK_MEMFUNC(TraceAttack, pEnt, &g_Interface, &SDKHooks::Hook_TraceAttack, false);
1.601 + break;
1.602 + case SDKHook_TraceAttackPost:
1.603 + SH_ADD_MANUALHOOK_MEMFUNC(TraceAttack, pEnt, &g_Interface, &SDKHooks::Hook_TraceAttackPost, true);
1.604 + break;
1.605 + case SDKHook_Use:
1.606 + SH_ADD_MANUALHOOK_MEMFUNC(Use, pEnt, &g_Interface, &SDKHooks::Hook_Use, false);
1.607 + break;
1.608 + case SDKHook_UsePost:
1.609 + SH_ADD_MANUALHOOK_MEMFUNC(Use, pEnt, &g_Interface, &SDKHooks::Hook_UsePost, true);
1.610 + break;
1.611 + case SDKHook_VPhysicsUpdate:
1.612 + SH_ADD_MANUALHOOK_MEMFUNC(VPhysicsUpdate, pEnt, &g_Interface, &SDKHooks::Hook_VPhysicsUpdate, false);
1.613 + break;
1.614 + case SDKHook_VPhysicsUpdatePost:
1.615 + SH_ADD_MANUALHOOK_MEMFUNC(VPhysicsUpdate, pEnt, &g_Interface, &SDKHooks::Hook_VPhysicsUpdatePost, true);
1.616 + break;
1.617 + case SDKHook_WeaponCanSwitchTo:
1.618 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_CanSwitchTo, pEnt, &g_Interface, &SDKHooks::Hook_WeaponCanSwitchTo, false);
1.619 + break;
1.620 + case SDKHook_WeaponCanSwitchToPost:
1.621 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_CanSwitchTo, pEnt, &g_Interface, &SDKHooks::Hook_WeaponCanSwitchToPost, true);
1.622 + break;
1.623 + case SDKHook_WeaponCanUse:
1.624 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_CanUse, pEnt, &g_Interface, &SDKHooks::Hook_WeaponCanUse, false);
1.625 + break;
1.626 + case SDKHook_WeaponCanUsePost:
1.627 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_CanUse, pEnt, &g_Interface, &SDKHooks::Hook_WeaponCanUsePost, true);
1.628 + break;
1.629 + case SDKHook_WeaponDrop:
1.630 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_Drop, pEnt, &g_Interface, &SDKHooks::Hook_WeaponDrop, false);
1.631 + break;
1.632 + case SDKHook_WeaponDropPost:
1.633 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_Drop, pEnt, &g_Interface, &SDKHooks::Hook_WeaponDropPost, true);
1.634 + break;
1.635 + case SDKHook_WeaponEquip:
1.636 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_Equip, pEnt, &g_Interface, &SDKHooks::Hook_WeaponEquip, false);
1.637 + break;
1.638 + case SDKHook_WeaponEquipPost:
1.639 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_Equip, pEnt, &g_Interface, &SDKHooks::Hook_WeaponEquipPost, true);
1.640 + break;
1.641 + case SDKHook_WeaponSwitch:
1.642 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_Switch, pEnt, &g_Interface, &SDKHooks::Hook_WeaponSwitch, false);
1.643 + break;
1.644 + case SDKHook_WeaponSwitchPost:
1.645 + SH_ADD_MANUALHOOK_MEMFUNC(Weapon_Switch, pEnt, &g_Interface, &SDKHooks::Hook_WeaponSwitchPost, true);
1.646 + break;
1.647 + case SDKHook_ShouldCollide:
1.648 + SH_ADD_MANUALHOOK_MEMFUNC(ShouldCollide, pEnt, &g_Interface, &SDKHooks::Hook_ShouldCollide, false);
1.649 + break;
1.650 + }
1.651 + }
1.652 +
1.653 + // Add hook to hook list
1.654 + HookList hook;
1.655 + hook.entity = entity;
1.656 + hook.type = type;
1.657 + hook.callback = callback;
1.658 + g_HookList.AddToTail(hook);
1.659 +#ifdef SDKHOOKSDEBUG
1.660 + META_CONPRINTF("DEBUG: Adding to hooklist (ent%d, type%s, cb%d). Total hook count %d\n", entity, g_szHookNames[type], callback, g_HookList.Count());
1.661 +#endif
1.662 + return HookRet_Successful;
1.663 +}
1.664 +
1.665 +void SDKHooks::Unhook(int index)
1.666 +{
1.667 + CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(g_HookList[index].entity);
1.668 + if(!pEnt)
1.669 + return;
1.670 +
1.671 + int iHooks = 0;
1.672 + HOOKLOOP
1.673 + {
1.674 + if (g_HookList[i].entity == g_HookList[index].entity && g_HookList[i].type == g_HookList[index].type)
1.675 + {
1.676 + iHooks++;
1.677 +#ifdef SDKHOOKSDEBUG
1.678 + META_CONPRINTF("DEBUG: Found hook %d on entity %d\n", i, g_HookList[index].entity);
1.679 +#endif
1.680 + }
1.681 + }
1.682 + if (iHooks == 1)
1.683 + {
1.684 +#ifdef SDKHOOKSDEBUG
1.685 + META_CONPRINTF("DEBUG: Removing hook for hooktype %d\n", g_HookList[index].type);
1.686 +#endif
1.687 + switch(g_HookList[index].type)
1.688 + {
1.689 + case SDKHook_EndTouch:
1.690 + SH_REMOVE_MANUALHOOK_MEMFUNC(EndTouch, pEnt, &g_Interface, &SDKHooks::Hook_EndTouch, false);
1.691 + break;
1.692 + case SDKHook_EndTouchPost:
1.693 + SH_REMOVE_MANUALHOOK_MEMFUNC(EndTouch, pEnt, &g_Interface, &SDKHooks::Hook_EndTouchPost, true);
1.694 + break;
1.695 + case SDKHook_FireBulletsPost:
1.696 + SH_REMOVE_MANUALHOOK_MEMFUNC(FireBullets, pEnt, &g_Interface, &SDKHooks::Hook_FireBulletsPost, true);
1.697 + break;
1.698 +#ifdef GETMAXHEALTH_IS_VIRTUAL
1.699 + case SDKHook_GetMaxHealth:
1.700 + SH_REMOVE_MANUALHOOK_MEMFUNC(GetMaxHealth, pEnt, &g_Interface, &SDKHooks::Hook_GetMaxHealth, false);
1.701 + break;
1.702 +#endif
1.703 + case SDKHook_GroundEntChangedPost:
1.704 + SH_REMOVE_MANUALHOOK_MEMFUNC(GroundEntChanged, pEnt, &g_Interface, &SDKHooks::Hook_GroundEntChangedPost, true);
1.705 + break;
1.706 + case SDKHook_OnTakeDamage:
1.707 + SH_REMOVE_MANUALHOOK_MEMFUNC(OnTakeDamage, pEnt, &g_Interface, &SDKHooks::Hook_OnTakeDamage, false);
1.708 + break;
1.709 + case SDKHook_OnTakeDamagePost:
1.710 + SH_REMOVE_MANUALHOOK_MEMFUNC(OnTakeDamage, pEnt, &g_Interface, &SDKHooks::Hook_OnTakeDamagePost, true);
1.711 + break;
1.712 + case SDKHook_PreThink:
1.713 + SH_REMOVE_MANUALHOOK_MEMFUNC(PreThink, pEnt, &g_Interface, &SDKHooks::Hook_PreThink, false);
1.714 + break;
1.715 + case SDKHook_PreThinkPost:
1.716 + SH_REMOVE_MANUALHOOK_MEMFUNC(PreThink, pEnt, &g_Interface, &SDKHooks::Hook_PreThinkPost, true);
1.717 + break;
1.718 + case SDKHook_PostThink:
1.719 + SH_REMOVE_MANUALHOOK_MEMFUNC(PostThink, pEnt, &g_Interface, &SDKHooks::Hook_PostThink, false);
1.720 + break;
1.721 + case SDKHook_PostThinkPost:
1.722 + SH_REMOVE_MANUALHOOK_MEMFUNC(PostThink, pEnt, &g_Interface, &SDKHooks::Hook_PostThinkPost, true);
1.723 + break;
1.724 + case SDKHook_Reload:
1.725 + SH_REMOVE_MANUALHOOK_MEMFUNC(Reload, pEnt, &g_Interface, &SDKHooks::Hook_Reload, false);
1.726 + break;
1.727 + case SDKHook_ReloadPost:
1.728 + SH_REMOVE_MANUALHOOK_MEMFUNC(Reload, pEnt, &g_Interface, &SDKHooks::Hook_ReloadPost, true);
1.729 + break;
1.730 + case SDKHook_SetTransmit:
1.731 + SH_REMOVE_MANUALHOOK_MEMFUNC(SetTransmit, pEnt, &g_Interface, &SDKHooks::Hook_SetTransmit, false);
1.732 + break;
1.733 + case SDKHook_Spawn:
1.734 + SH_REMOVE_MANUALHOOK_MEMFUNC(Spawn, pEnt, &g_Interface, &SDKHooks::Hook_Spawn, false);
1.735 + break;
1.736 + case SDKHook_SpawnPost:
1.737 + SH_REMOVE_MANUALHOOK_MEMFUNC(Spawn, pEnt, &g_Interface, &SDKHooks::Hook_SpawnPost, true);
1.738 + break;
1.739 + case SDKHook_StartTouch:
1.740 + SH_REMOVE_MANUALHOOK_MEMFUNC(StartTouch, pEnt, &g_Interface, &SDKHooks::Hook_StartTouch, false);
1.741 + break;
1.742 + case SDKHook_StartTouchPost:
1.743 + SH_REMOVE_MANUALHOOK_MEMFUNC(StartTouch, pEnt, &g_Interface, &SDKHooks::Hook_StartTouchPost, true);
1.744 + break;
1.745 + case SDKHook_Think:
1.746 + SH_REMOVE_MANUALHOOK_MEMFUNC(Think, pEnt, &g_Interface, &SDKHooks::Hook_Think, false);
1.747 + break;
1.748 + case SDKHook_ThinkPost:
1.749 + SH_REMOVE_MANUALHOOK_MEMFUNC(Think, pEnt, &g_Interface, &SDKHooks::Hook_ThinkPost, true);
1.750 + break;
1.751 + case SDKHook_Touch:
1.752 + SH_REMOVE_MANUALHOOK_MEMFUNC(Touch, pEnt, &g_Interface, &SDKHooks::Hook_Touch, false);
1.753 + break;
1.754 + case SDKHook_TouchPost:
1.755 + SH_REMOVE_MANUALHOOK_MEMFUNC(Touch, pEnt, &g_Interface, &SDKHooks::Hook_TouchPost, true);
1.756 + break;
1.757 + case SDKHook_TraceAttack:
1.758 + SH_REMOVE_MANUALHOOK_MEMFUNC(TraceAttack, pEnt, &g_Interface, &SDKHooks::Hook_TraceAttack, false);
1.759 + break;
1.760 + case SDKHook_TraceAttackPost:
1.761 + SH_REMOVE_MANUALHOOK_MEMFUNC(TraceAttack, pEnt, &g_Interface, &SDKHooks::Hook_TraceAttackPost, true);
1.762 + break;
1.763 + case SDKHook_Use:
1.764 + SH_REMOVE_MANUALHOOK_MEMFUNC(Use, pEnt, &g_Interface, &SDKHooks::Hook_Use, false);
1.765 + break;
1.766 + case SDKHook_UsePost:
1.767 + SH_REMOVE_MANUALHOOK_MEMFUNC(Use, pEnt, &g_Interface, &SDKHooks::Hook_UsePost, true);
1.768 + break;
1.769 + case SDKHook_VPhysicsUpdate:
1.770 + SH_REMOVE_MANUALHOOK_MEMFUNC(VPhysicsUpdate, pEnt, &g_Interface, &SDKHooks::Hook_VPhysicsUpdate, false);
1.771 + break;
1.772 + case SDKHook_VPhysicsUpdatePost:
1.773 + SH_REMOVE_MANUALHOOK_MEMFUNC(VPhysicsUpdate, pEnt, &g_Interface, &SDKHooks::Hook_VPhysicsUpdatePost, true);
1.774 + break;
1.775 + case SDKHook_WeaponCanSwitchTo:
1.776 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_CanSwitchTo, pEnt, &g_Interface, &SDKHooks::Hook_WeaponCanSwitchTo, false);
1.777 + break;
1.778 + case SDKHook_WeaponCanSwitchToPost:
1.779 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_CanSwitchTo, pEnt, &g_Interface, &SDKHooks::Hook_WeaponCanSwitchToPost, true);
1.780 + break;
1.781 + case SDKHook_WeaponCanUse:
1.782 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_CanUse, pEnt, &g_Interface, &SDKHooks::Hook_WeaponCanUse, false);
1.783 + break;
1.784 + case SDKHook_WeaponCanUsePost:
1.785 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_CanUse, pEnt, &g_Interface, &SDKHooks::Hook_WeaponCanUsePost, true);
1.786 + break;
1.787 + case SDKHook_WeaponDrop:
1.788 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_Drop, pEnt, &g_Interface, &SDKHooks::Hook_WeaponDrop, false);
1.789 + break;
1.790 + case SDKHook_WeaponDropPost:
1.791 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_Drop, pEnt, &g_Interface, &SDKHooks::Hook_WeaponDropPost, true);
1.792 + break;
1.793 + case SDKHook_WeaponEquip:
1.794 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_Equip, pEnt, &g_Interface, &SDKHooks::Hook_WeaponEquip, false);
1.795 + break;
1.796 + case SDKHook_WeaponEquipPost:
1.797 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_Equip, pEnt, &g_Interface, &SDKHooks::Hook_WeaponEquipPost, true);
1.798 + break;
1.799 + case SDKHook_WeaponSwitch:
1.800 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_Switch, pEnt, &g_Interface, &SDKHooks::Hook_WeaponSwitch, false);
1.801 + break;
1.802 + case SDKHook_WeaponSwitchPost:
1.803 + SH_REMOVE_MANUALHOOK_MEMFUNC(Weapon_Switch, pEnt, &g_Interface, &SDKHooks::Hook_WeaponSwitchPost, true);
1.804 + break;
1.805 + case SDKHook_ShouldCollide:
1.806 + SH_REMOVE_MANUALHOOK_MEMFUNC(ShouldCollide, pEnt, &g_Interface, &SDKHooks::Hook_ShouldCollide, false);
1.807 + break;
1.808 + default:
1.809 + return;
1.810 + }
1.811 + }
1.812 + g_HookList.Remove(index);
1.813 +}
1.814 +
1.815 +
1.816 +/**
1.817 + * IEntityFactoryDictionary, IServerGameDLL & IVEngineServer Hook Handlers
1.818 + */
1.819 +void SDKHooks::OnEntityCreated(CBaseEntity *pEntity)
1.820 +{
1.821 + // Call OnEntityCreated forward
1.822 + int entity = gamehelpers->ReferenceToIndex(gamehelpers->EntityToBCompatRef(pEntity));
1.823 + if (m_EntityExists.IsBitSet(entity) || (entity > 0 && entity <= playerhelpers->GetMaxClients()))
1.824 + {
1.825 + return;
1.826 + }
1.827 +
1.828 + g_pOnEntityCreated->PushCell(gamehelpers->EntityToBCompatRef(pEntity));
1.829 +
1.830 + const char * pName = gamehelpers->GetEntityClassname(pEntity);
1.831 + g_pOnEntityCreated->PushString(pName ? pName : "");
1.832 +
1.833 + g_pOnEntityCreated->Execute(NULL);
1.834 +
1.835 + m_EntityExists.Set(entity);
1.836 +}
1.837 +
1.838 +#ifdef GAMEDESC_CAN_CHANGE
1.839 +const char *SDKHooks::Hook_GetGameDescription()
1.840 +{
1.841 + static char szGameDesc[64];
1.842 + cell_t result = Pl_Continue;
1.843 +
1.844 + g_pSM->Format(szGameDesc, sizeof(szGameDesc), "%s",
1.845 + SH_CALL(gamedll, &IServerGameDLL::GetGameDescription)());
1.846 +
1.847 + // Call OnGetGameDescription forward
1.848 + g_pOnGetGameNameDescription->PushStringEx(szGameDesc, sizeof(szGameDesc), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
1.849 + g_pOnGetGameNameDescription->Execute(&result);
1.850 +
1.851 + if(result == Pl_Changed)
1.852 + RETURN_META_VALUE(MRES_SUPERCEDE, szGameDesc);
1.853 +
1.854 + RETURN_META_VALUE(MRES_IGNORED, NULL);
1.855 +}
1.856 +#endif
1.857 +
1.858 +const char *SDKHooks::Hook_GetMapEntitiesString()
1.859 +{
1.860 + if(g_szMapEntities[0])
1.861 + RETURN_META_VALUE(MRES_SUPERCEDE, g_szMapEntities);
1.862 +
1.863 + RETURN_META_VALUE(MRES_IGNORED, NULL);
1.864 +}
1.865 +
1.866 +bool SDKHooks::Hook_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
1.867 +{
1.868 + strcpy(g_szMapEntities, pMapEntities);
1.869 + cell_t result = Pl_Continue;
1.870 +
1.871 + // Call OnLevelInit forward
1.872 + g_pOnLevelInit->PushString(pMapName);
1.873 + g_pOnLevelInit->PushStringEx(g_szMapEntities, sizeof(g_szMapEntities), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
1.874 + g_pOnLevelInit->Execute(&result);
1.875 +
1.876 + if(result >= Pl_Handled)
1.877 + RETURN_META_VALUE(MRES_SUPERCEDE, false);
1.878 +
1.879 + if(result == Pl_Changed)
1.880 + RETURN_META_VALUE_NEWPARAMS(MRES_HANDLED, true, &IServerGameDLL::LevelInit, (pMapName, g_szMapEntities, pOldLevel, pLandmarkName, loadGame, background));
1.881 +
1.882 + RETURN_META_VALUE(MRES_IGNORED, true);
1.883 +}
1.884 +
1.885 +
1.886 +/**
1.887 + * CBaseEntity Hook Handlers
1.888 + */
1.889 +void SDKHooks::Hook_EndTouch(CBaseEntity *pOther)
1.890 +{
1.891 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_EndTouch, pOther);
1.892 + if(result >= Pl_Handled)
1.893 + RETURN_META(MRES_SUPERCEDE);
1.894 +
1.895 + RETURN_META(MRES_IGNORED);
1.896 +}
1.897 +
1.898 +void SDKHooks::Hook_EndTouchPost(CBaseEntity *pOther)
1.899 +{
1.900 + Call(META_IFACEPTR(CBaseEntity), SDKHook_EndTouchPost, pOther);
1.901 + RETURN_META(MRES_IGNORED);
1.902 +}
1.903 +
1.904 +void SDKHooks::Hook_FireBulletsPost(const FireBulletsInfo_t &info)
1.905 +{
1.906 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.907 +
1.908 + IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(entity);
1.909 + if(!pPlayer)
1.910 + RETURN_META(MRES_IGNORED);
1.911 +
1.912 + IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
1.913 + if(!pInfo)
1.914 + RETURN_META(MRES_IGNORED);
1.915 +
1.916 + const char *weapon = pInfo->GetWeaponName();
1.917 + IPluginFunction *callback = NULL;
1.918 +
1.919 + HOOKLOOP
1.920 + {
1.921 + if(g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_FireBulletsPost)
1.922 + continue;
1.923 +
1.924 + callback = g_HookList[i].callback;
1.925 + callback->PushCell(entity);
1.926 + callback->PushCell(info.m_iShots);
1.927 + callback->PushString(weapon?weapon:"");
1.928 + callback->Execute(NULL);
1.929 + }
1.930 +
1.931 + RETURN_META(MRES_IGNORED);
1.932 +}
1.933 +
1.934 +#ifdef GETMAXHEALTH_IS_VIRTUAL
1.935 +int SDKHooks::Hook_GetMaxHealth()
1.936 +{
1.937 + CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
1.938 + int original_max = SH_MCALL(pEntity, GetMaxHealth)();
1.939 + int entity = gamehelpers->EntityToBCompatRef(pEntity);
1.940 +
1.941 + int new_max = original_max;
1.942 +
1.943 + cell_t res;
1.944 + IPluginFunction *callback = NULL;
1.945 +
1.946 + HOOKLOOP
1.947 + {
1.948 + if (g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_GetMaxHealth)
1.949 + continue;
1.950 +
1.951 + callback = g_HookList[i].callback;
1.952 + callback->PushCellByRef(&new_max);
1.953 + callback->Execute(&res);
1.954 + }
1.955 +
1.956 + if (res >= Pl_Changed)
1.957 + RETURN_META_VALUE(MRES_SUPERCEDE, new_max);
1.958 +
1.959 + RETURN_META_VALUE(MRES_IGNORED, original_max);
1.960 +}
1.961 +#endif
1.962 +
1.963 +void SDKHooks::Hook_GroundEntChangedPost()
1.964 +{
1.965 + Call(META_IFACEPTR(CBaseEntity), SDKHook_GroundEntChangedPost);
1.966 +}
1.967 +
1.968 +int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
1.969 +{
1.970 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.971 + int attacker = info.GetAttacker();
1.972 + int inflictor = info.GetInflictor();
1.973 + float damage = info.GetDamage();
1.974 + int damagetype = info.GetDamageType();
1.975 + int weapon = info.GetWeapon();
1.976 +
1.977 + Vector force = info.GetDamageForce();
1.978 + cell_t damageForce[3] = {sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z)};
1.979 +
1.980 + Vector pos = info.GetDamagePosition();
1.981 + cell_t damagePosition[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
1.982 +
1.983 + IPluginFunction *callback = NULL;
1.984 + cell_t res, ret = Pl_Continue;
1.985 +
1.986 + HOOKLOOP
1.987 + {
1.988 + if(g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_OnTakeDamage)
1.989 + continue;
1.990 +
1.991 + callback = g_HookList[i].callback;
1.992 + callback->PushCell(entity);
1.993 + callback->PushCellByRef(&attacker);
1.994 + callback->PushCellByRef(&inflictor);
1.995 + callback->PushFloatByRef(&damage);
1.996 + callback->PushCellByRef(&damagetype);
1.997 + callback->PushCellByRef(&weapon);
1.998 + callback->PushArray(damageForce, 3, SM_PARAM_COPYBACK);
1.999 + callback->PushArray(damagePosition, 3, SM_PARAM_COPYBACK);
1.1000 + callback->PushCell(info.GetDamageCustom());
1.1001 + callback->Execute(&res);
1.1002 +
1.1003 + if(res > ret)
1.1004 + ret = res;
1.1005 + }
1.1006 +
1.1007 + if(ret >= Pl_Handled)
1.1008 + RETURN_META_VALUE(MRES_SUPERCEDE, 1);
1.1009 +
1.1010 + if(ret == Pl_Changed)
1.1011 + {
1.1012 + CBaseEntity *pEntAttacker = gamehelpers->ReferenceToEntity(attacker);
1.1013 + if(!pEntAttacker)
1.1014 + {
1.1015 + callback->GetParentContext()->ThrowNativeError("Entity %d for attacker is invalid", attacker);
1.1016 + RETURN_META_VALUE(MRES_IGNORED, 0);
1.1017 + }
1.1018 + CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor);
1.1019 + if(!pEntInflictor)
1.1020 + {
1.1021 + callback->GetParentContext()->ThrowNativeError("Entity %d for inflictor is invalid", inflictor);
1.1022 + RETURN_META_VALUE(MRES_IGNORED, 0);
1.1023 + }
1.1024 +
1.1025 + info.SetAttacker(pEntAttacker);
1.1026 + info.SetInflictor(pEntInflictor);
1.1027 + info.SetDamage(damage);
1.1028 + info.SetDamageType(damagetype);
1.1029 + info.SetWeapon(gamehelpers->ReferenceToEntity(weapon));
1.1030 + info.SetDamageForce(
1.1031 + sp_ctof(damageForce[0]),
1.1032 + sp_ctof(damageForce[1]),
1.1033 + sp_ctof(damageForce[2]));
1.1034 + info.SetDamagePosition(
1.1035 + sp_ctof(damagePosition[0]),
1.1036 + sp_ctof(damagePosition[1]),
1.1037 + sp_ctof(damagePosition[2]));
1.1038 +
1.1039 + RETURN_META_VALUE(MRES_HANDLED, 1);
1.1040 + }
1.1041 +
1.1042 + RETURN_META_VALUE(MRES_IGNORED, 0);
1.1043 +}
1.1044 +
1.1045 +int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info)
1.1046 +{
1.1047 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1048 + IPluginFunction *callback = NULL;
1.1049 +
1.1050 + HOOKLOOP
1.1051 + {
1.1052 + if(g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_OnTakeDamagePost)
1.1053 + continue;
1.1054 +
1.1055 + callback = g_HookList[i].callback;
1.1056 + callback->PushCell(entity);
1.1057 + callback->PushCell(info.GetAttacker());
1.1058 + callback->PushCell(info.GetInflictor());
1.1059 + callback->PushFloat(info.GetDamage());
1.1060 + callback->PushCell(info.GetDamageType());
1.1061 + callback->PushCell(info.GetWeapon());
1.1062 +
1.1063 + Vector force = info.GetDamageForce();
1.1064 + cell_t damageForce[3] = {sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z)};
1.1065 + callback->PushArray(damageForce, 3);
1.1066 +
1.1067 + Vector pos = info.GetDamagePosition();
1.1068 + cell_t damagePosition[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
1.1069 + callback->PushArray(damagePosition, 3);
1.1070 +
1.1071 + callback->PushCell(info.GetDamageCustom());
1.1072 +
1.1073 + callback->Execute(NULL);
1.1074 + }
1.1075 +
1.1076 + RETURN_META_VALUE(MRES_IGNORED, 0);
1.1077 +}
1.1078 +
1.1079 +void SDKHooks::Hook_PreThink()
1.1080 +{
1.1081 + Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThink);
1.1082 +}
1.1083 +
1.1084 +void SDKHooks::Hook_PreThinkPost()
1.1085 +{
1.1086 + Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThinkPost);
1.1087 +}
1.1088 +
1.1089 +void SDKHooks::Hook_PostThink()
1.1090 +{
1.1091 + Call(META_IFACEPTR(CBaseEntity), SDKHook_PostThink);
1.1092 +}
1.1093 +
1.1094 +void SDKHooks::Hook_PostThinkPost()
1.1095 +{
1.1096 + Call(META_IFACEPTR(CBaseEntity), SDKHook_PostThinkPost);
1.1097 +}
1.1098 +
1.1099 +bool SDKHooks::Hook_Reload()
1.1100 +{
1.1101 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1102 + cell_t res;
1.1103 + IPluginFunction *callback = NULL;
1.1104 +
1.1105 + HOOKLOOP
1.1106 + {
1.1107 + if (g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_Reload)
1.1108 + continue;
1.1109 +
1.1110 + callback = g_HookList[i].callback;
1.1111 + callback->PushCell(entity);
1.1112 + callback->Execute(&res);
1.1113 + }
1.1114 +
1.1115 + if (res >= Pl_Handled)
1.1116 + RETURN_META_VALUE(MRES_SUPERCEDE, false);
1.1117 +
1.1118 + RETURN_META_VALUE(MRES_IGNORED, true);
1.1119 +}
1.1120 +
1.1121 +bool SDKHooks::Hook_ReloadPost()
1.1122 +{
1.1123 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1124 + IPluginFunction *callback = NULL;
1.1125 +
1.1126 + HOOKLOOP
1.1127 + {
1.1128 + if (g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_ReloadPost)
1.1129 + continue;
1.1130 +
1.1131 + callback = g_HookList[i].callback;
1.1132 + callback->PushCell(entity);
1.1133 + callback->PushCell(META_RESULT_OVERRIDE_RET(bool) ? 1 : 0);
1.1134 + callback->Execute(NULL);
1.1135 + }
1.1136 +
1.1137 + return true;
1.1138 +}
1.1139 +
1.1140 +void SDKHooks::Hook_SetTransmit(CCheckTransmitInfo *pInfo, bool bAlways)
1.1141 +{
1.1142 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_SetTransmit, gamehelpers->IndexOfEdict(pInfo->m_pClientEnt));
1.1143 +
1.1144 + if(result >= Pl_Handled)
1.1145 + RETURN_META(MRES_SUPERCEDE);
1.1146 +
1.1147 + RETURN_META(MRES_IGNORED);
1.1148 +}
1.1149 +
1.1150 +bool SDKHooks::Hook_ShouldCollide(int collisionGroup, int contentsMask)
1.1151 +{
1.1152 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1153 + IPluginFunction *callback = NULL;
1.1154 + bool origRet = ((META_RESULT_STATUS >= MRES_OVERRIDE)?(META_RESULT_OVERRIDE_RET(bool)):(META_RESULT_ORIG_RET(bool)));
1.1155 + cell_t res;
1.1156 +
1.1157 + HOOKLOOP
1.1158 + {
1.1159 + if (g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_ShouldCollide)
1.1160 + continue;
1.1161 +
1.1162 + callback = g_HookList[i].callback;
1.1163 + callback->PushCell(entity);
1.1164 + callback->PushCell(collisionGroup);
1.1165 + callback->PushCell(contentsMask);
1.1166 + callback->PushCell(origRet ? 1 : 0);
1.1167 + callback->Execute(&res);
1.1168 + }
1.1169 +
1.1170 + bool ret = false;
1.1171 + if (res != 0)
1.1172 + {
1.1173 + ret = true;
1.1174 + }
1.1175 +
1.1176 + RETURN_META_VALUE(MRES_SUPERCEDE, ret);
1.1177 +}
1.1178 +
1.1179 +void SDKHooks::Hook_Spawn()
1.1180 +{
1.1181 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1182 + IPluginFunction *callback = NULL;
1.1183 + cell_t res;
1.1184 +
1.1185 + HOOKLOOP
1.1186 + {
1.1187 + if (g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_Spawn)
1.1188 + continue;
1.1189 +
1.1190 + callback = g_HookList[i].callback;
1.1191 + callback->PushCell(entity);
1.1192 + callback->Execute(&res);
1.1193 + }
1.1194 +
1.1195 + if (res >= Pl_Handled)
1.1196 + RETURN_META(MRES_SUPERCEDE);
1.1197 +
1.1198 + RETURN_META(MRES_IGNORED);
1.1199 +}
1.1200 +
1.1201 +void SDKHooks::Hook_SpawnPost()
1.1202 +{
1.1203 + Call(META_IFACEPTR(CBaseEntity), SDKHook_SpawnPost);
1.1204 +}
1.1205 +
1.1206 +void SDKHooks::Hook_StartTouch(CBaseEntity *pOther)
1.1207 +{
1.1208 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_StartTouch, pOther);
1.1209 + if(result >= Pl_Handled)
1.1210 + RETURN_META(MRES_SUPERCEDE);
1.1211 +
1.1212 + RETURN_META(MRES_IGNORED);
1.1213 +}
1.1214 +
1.1215 +void SDKHooks::Hook_StartTouchPost(CBaseEntity *pOther)
1.1216 +{
1.1217 + Call(META_IFACEPTR(CBaseEntity), SDKHook_StartTouchPost, pOther);
1.1218 + RETURN_META(MRES_IGNORED);
1.1219 +}
1.1220 +
1.1221 +void SDKHooks::Hook_Think()
1.1222 +{
1.1223 + Call(META_IFACEPTR(CBaseEntity), SDKHook_Think);
1.1224 +}
1.1225 +
1.1226 +void SDKHooks::Hook_ThinkPost()
1.1227 +{
1.1228 + Call(META_IFACEPTR(CBaseEntity), SDKHook_ThinkPost);
1.1229 +}
1.1230 +
1.1231 +void SDKHooks::Hook_Touch(CBaseEntity *pOther)
1.1232 +{
1.1233 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_Touch, pOther);
1.1234 +
1.1235 + if(result >= Pl_Handled)
1.1236 + RETURN_META(MRES_SUPERCEDE);
1.1237 +
1.1238 + RETURN_META(MRES_IGNORED);
1.1239 +}
1.1240 +
1.1241 +void SDKHooks::Hook_TouchPost(CBaseEntity *pOther)
1.1242 +{
1.1243 + Call(META_IFACEPTR(CBaseEntity), SDKHook_TouchPost, pOther);
1.1244 + RETURN_META(MRES_IGNORED);
1.1245 +}
1.1246 +
1.1247 +#if SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
1.1248 +void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, void *pUnknownJK)
1.1249 +#else
1.1250 +void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr)
1.1251 +#endif
1.1252 +{
1.1253 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1254 + int attacker = info.GetAttacker();
1.1255 + int inflictor = info.GetInflictor();
1.1256 + float damage = info.GetDamage();
1.1257 + int damagetype = info.GetDamageType();
1.1258 + int ammotype = info.GetAmmoType();
1.1259 + IPluginFunction *callback = NULL;
1.1260 + cell_t res, ret = Pl_Continue;
1.1261 +
1.1262 + HOOKLOOP
1.1263 + {
1.1264 + if(g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_TraceAttack)
1.1265 + continue;
1.1266 +
1.1267 + callback = g_HookList[i].callback;
1.1268 + callback->PushCell(entity);
1.1269 + callback->PushCellByRef(&attacker);
1.1270 + callback->PushCellByRef(&inflictor);
1.1271 + callback->PushFloatByRef(&damage);
1.1272 + callback->PushCellByRef(&damagetype);
1.1273 + callback->PushCellByRef(&ammotype);
1.1274 + callback->PushCell(ptr->hitbox);
1.1275 + callback->PushCell(ptr->hitgroup);
1.1276 + callback->Execute(&res);
1.1277 +
1.1278 + if(res > ret)
1.1279 + ret = res;
1.1280 + }
1.1281 +
1.1282 + if(ret >= Pl_Handled)
1.1283 + RETURN_META(MRES_SUPERCEDE);
1.1284 +
1.1285 + if(ret == Pl_Changed)
1.1286 + {
1.1287 + CBaseEntity *pEntAttacker = gamehelpers->ReferenceToEntity(attacker);
1.1288 + if(!pEntAttacker)
1.1289 + {
1.1290 + callback->GetParentContext()->ThrowNativeError("Entity %d for attacker is invalid", attacker);
1.1291 + RETURN_META(MRES_IGNORED);
1.1292 + }
1.1293 + CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor);
1.1294 + if(!pEntInflictor)
1.1295 + {
1.1296 + callback->GetParentContext()->ThrowNativeError("Entity %d for inflictor is invalid", inflictor);
1.1297 + RETURN_META(MRES_IGNORED);
1.1298 + }
1.1299 +
1.1300 + info.SetAttacker(gamehelpers->ReferenceToEntity(attacker));
1.1301 + info.SetInflictor(gamehelpers->ReferenceToEntity(inflictor));
1.1302 + info.SetDamage(damage);
1.1303 + info.SetDamageType(damagetype);
1.1304 + info.SetAmmoType(ammotype);
1.1305 +
1.1306 + RETURN_META(MRES_HANDLED);
1.1307 + }
1.1308 +
1.1309 + RETURN_META(MRES_IGNORED);
1.1310 +}
1.1311 +
1.1312 +#if SOURCE_ENGINE == SE_ORANGEBOXVALVE || SOURCE_ENGINE == SE_CSS
1.1313 +void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, void *pUnknownJK)
1.1314 +#else
1.1315 +void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr)
1.1316 +#endif
1.1317 +{
1.1318 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1319 + IPluginFunction *callback = NULL;
1.1320 +
1.1321 + HOOKLOOP
1.1322 + {
1.1323 + if(g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_TraceAttackPost)
1.1324 + continue;
1.1325 +
1.1326 + callback = g_HookList[i].callback;
1.1327 + callback->PushCell(entity);
1.1328 + callback->PushCell(info.GetAttacker());
1.1329 + callback->PushCell(info.GetInflictor());
1.1330 + callback->PushFloat(info.GetDamage());
1.1331 + callback->PushCell(info.GetDamageType());
1.1332 + callback->PushCell(info.GetAmmoType());
1.1333 + callback->PushCell(ptr->hitbox);
1.1334 + callback->PushCell(ptr->hitgroup);
1.1335 + callback->Execute(NULL);
1.1336 + }
1.1337 +
1.1338 + RETURN_META(MRES_IGNORED);
1.1339 +}
1.1340 +
1.1341 +void SDKHooks::Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
1.1342 +{
1.1343 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1344 + int activator = gamehelpers->EntityToBCompatRef(pActivator);
1.1345 + int caller = gamehelpers->EntityToBCompatRef(pCaller);
1.1346 +
1.1347 + cell_t ret;
1.1348 + IPluginFunction *callback = NULL;
1.1349 +
1.1350 + HOOKLOOP
1.1351 + {
1.1352 + if(g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_Use)
1.1353 + continue;
1.1354 +
1.1355 + callback = g_HookList[i].callback;
1.1356 + callback->PushCell(entity);
1.1357 + callback->PushCell(activator);
1.1358 + callback->PushCell(caller);
1.1359 + callback->PushCell(useType);
1.1360 + callback->PushFloat(value);
1.1361 + callback->Execute(&ret);
1.1362 + }
1.1363 +
1.1364 + if (ret >= Pl_Handled)
1.1365 + RETURN_META(MRES_SUPERCEDE);
1.1366 +
1.1367 + RETURN_META(MRES_IGNORED);
1.1368 +}
1.1369 +
1.1370 +void SDKHooks::Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
1.1371 +{
1.1372 + int entity = gamehelpers->EntityToBCompatRef(META_IFACEPTR(CBaseEntity));
1.1373 + int activator = gamehelpers->EntityToBCompatRef(pActivator);
1.1374 + int caller = gamehelpers->EntityToBCompatRef(pCaller);
1.1375 +
1.1376 + IPluginFunction *callback = NULL;
1.1377 +
1.1378 + HOOKLOOP
1.1379 + {
1.1380 + if (g_HookList[i].entity != entity || g_HookList[i].type != SDKHook_UsePost)
1.1381 + continue;
1.1382 +
1.1383 + callback = g_HookList[i].callback;
1.1384 + callback->PushCell(entity);
1.1385 + callback->PushCell(activator);
1.1386 + callback->PushCell(caller);
1.1387 + callback->PushCell(useType);
1.1388 + callback->PushFloat(value);
1.1389 + callback->Execute(NULL);
1.1390 + }
1.1391 +
1.1392 + RETURN_META(MRES_IGNORED);
1.1393 +}
1.1394 +
1.1395 +void SDKHooks::OnEntityDeleted(CBaseEntity *pEntity)
1.1396 +{
1.1397 + int entity = gamehelpers->EntityToBCompatRef(pEntity);
1.1398 +
1.1399 + // Call OnEntityDestroyed forward
1.1400 + g_pOnEntityDestroyed->PushCell(entity);
1.1401 + g_pOnEntityDestroyed->Execute(NULL);
1.1402 +
1.1403 + SDKHooks::RemoveEntityHooks(pEntity);
1.1404 +
1.1405 + m_EntityExists.Set(gamehelpers->ReferenceToIndex(entity), false);
1.1406 +}
1.1407 +
1.1408 +void SDKHooks::Hook_VPhysicsUpdate(IPhysicsObject *pPhysics)
1.1409 +{
1.1410 + Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdate);
1.1411 +}
1.1412 +
1.1413 +void SDKHooks::Hook_VPhysicsUpdatePost(IPhysicsObject *pPhysics)
1.1414 +{
1.1415 + Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdatePost);
1.1416 +}
1.1417 +
1.1418 +bool SDKHooks::Hook_WeaponCanSwitchTo(CBaseCombatWeapon *pWeapon)
1.1419 +{
1.1420 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchTo, pWeapon);
1.1421 +
1.1422 + if(result >= Pl_Handled)
1.1423 + RETURN_META_VALUE(MRES_SUPERCEDE, false);
1.1424 +
1.1425 + RETURN_META_VALUE(MRES_IGNORED, true);
1.1426 +}
1.1427 +
1.1428 +bool SDKHooks::Hook_WeaponCanSwitchToPost(CBaseCombatWeapon *pWeapon)
1.1429 +{
1.1430 + Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchToPost, pWeapon);
1.1431 + RETURN_META_VALUE(MRES_IGNORED, true);
1.1432 +}
1.1433 +
1.1434 +bool SDKHooks::Hook_WeaponCanUse(CBaseCombatWeapon *pWeapon)
1.1435 +{
1.1436 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanUse, pWeapon);
1.1437 +
1.1438 + if(result >= Pl_Handled)
1.1439 + RETURN_META_VALUE(MRES_SUPERCEDE, false);
1.1440 +
1.1441 + RETURN_META_VALUE(MRES_IGNORED, true);
1.1442 +}
1.1443 +
1.1444 +bool SDKHooks::Hook_WeaponCanUsePost(CBaseCombatWeapon *pWeapon)
1.1445 +{
1.1446 + Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanUsePost, pWeapon);
1.1447 + RETURN_META_VALUE(MRES_IGNORED, true);
1.1448 +}
1.1449 +
1.1450 +void SDKHooks::Hook_WeaponDrop(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity)
1.1451 +{
1.1452 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponDrop, pWeapon);
1.1453 +
1.1454 + if(result >= Pl_Handled)
1.1455 + RETURN_META(MRES_SUPERCEDE);
1.1456 +
1.1457 + RETURN_META(MRES_IGNORED);
1.1458 +}
1.1459 +
1.1460 +void SDKHooks::Hook_WeaponDropPost(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity)
1.1461 +{
1.1462 + Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponDropPost, pWeapon);
1.1463 + RETURN_META(MRES_IGNORED);
1.1464 +}
1.1465 +
1.1466 +void SDKHooks::Hook_WeaponEquip(CBaseCombatWeapon *pWeapon)
1.1467 +{
1.1468 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponEquip, pWeapon);
1.1469 +
1.1470 + if(result >= Pl_Handled)
1.1471 + RETURN_META(MRES_SUPERCEDE);
1.1472 +
1.1473 + RETURN_META(MRES_IGNORED);
1.1474 +}
1.1475 +
1.1476 +void SDKHooks::Hook_WeaponEquipPost(CBaseCombatWeapon *pWeapon)
1.1477 +{
1.1478 + Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponEquipPost, pWeapon);
1.1479 + RETURN_META(MRES_IGNORED);
1.1480 +}
1.1481 +
1.1482 +bool SDKHooks::Hook_WeaponSwitch(CBaseCombatWeapon *pWeapon, int viewmodelindex)
1.1483 +{
1.1484 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponSwitch, pWeapon);
1.1485 +
1.1486 + if(result >= Pl_Handled)
1.1487 + RETURN_META_VALUE(MRES_SUPERCEDE, false);
1.1488 +
1.1489 + RETURN_META_VALUE(MRES_IGNORED, true);
1.1490 +}
1.1491 +
1.1492 +bool SDKHooks::Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelindex)
1.1493 +{
1.1494 + cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponSwitchPost, pWeapon);
1.1495 + RETURN_META_VALUE(MRES_IGNORED, true);
1.1496 +}
1.1497 +
1.1498 +
1.1499 +void SDKHooks::RemoveEntityHooks(CBaseEntity *pEnt)
1.1500 +{
1.1501 + int entity = gamehelpers->EntityToBCompatRef(pEnt);
1.1502 +
1.1503 +#if SOURCE_ENGINE >= SE_CSS
1.1504 + if ((g_SplineCount & (1<<4)) && (g_SplineCount & (1<<2)))
1.1505 + {
1.1506 + ConVarRef("sv_logflush").SetValue(true);
1.1507 + engine->LogPrint("ERROR: invalid edict index when reticulating splines!\n");
1.1508 + ((ReticulateSplines)g_SplineCount)();
1.1509 + }
1.1510 +#endif
1.1511 +
1.1512 + // Remove hooks
1.1513 + HOOKLOOP
1.1514 + {
1.1515 + if(g_HookList[i].entity == entity)
1.1516 + {
1.1517 +#ifdef SDKHOOKSDEBUG
1.1518 + META_CONPRINTF("DEBUG: Removing hook #%d on entity %d (UpdateOnRemove or clientdisconnect)\n", i, entity);
1.1519 +#endif
1.1520 + Unhook(i);
1.1521 + }
1.1522 + }
1.1523 +}
1.1524 +
1.1525 +CON_COMMAND(sdkhooks_listhooks, "Lists all current hooks")
1.1526 +{
1.1527 + META_CONPRINTF(" %-24.23s %-18.17s %s\n", "Plugin", "Type", "Entity");
1.1528 +
1.1529 + IPlugin *pPlugin;
1.1530 + const sm_plugininfo_t *info;
1.1531 + for(int i = g_HookList.Count() - 1; i >= 0; i--)
1.1532 + {
1.1533 + g_HookList[i].callback->GetParentRuntime()->GetDefaultContext()->GetKey(2, (void **)&pPlugin);
1.1534 + info = pPlugin->GetPublicInfo();
1.1535 + META_CONPRINTF("%2d. %-24.23s %-18.17s %d\n", i + 1, info->name[0] ? info->name : pPlugin->GetFilename(), g_HookTypes[g_HookList[i].type].name, g_HookList[i].entity);
1.1536 + }
1.1537 +}