extensions/sdkhooks/extension.cpp
author Kyle Sanderson <kyle.leet@gmail.com>
Sun Mar 23 22:11:06 2014 -0600 (2014-03-23)
changeset 4297 c05238822c32
parent 4294 fa845b627daf
child 4333 862af2b45ac0
permissions -rw-r--r--
Change SDKHooks to VTable Hooks (bug 6070, r=psychonic).
skamonkey@3767
     1
/**
skamonkey@3767
     2
 * vim: set ts=4 :
skamonkey@3767
     3
 * =============================================================================
skamonkey@3767
     4
 * Source SDK Hooks Extension
skamonkey@3767
     5
 * Copyright (C) 2010-2012 Nicholas Hastings
skamonkey@3767
     6
 * Copyright (C) 2009-2010 Erik Minekus
skamonkey@3767
     7
 * =============================================================================
skamonkey@3767
     8
 *
skamonkey@3767
     9
 * This program is free software; you can redistribute it and/or modify it under
skamonkey@3767
    10
 * the terms of the GNU General Public License, version 3.0, as published by the
skamonkey@3767
    11
 * Free Software Foundation.
skamonkey@3767
    12
 * 
skamonkey@3767
    13
 * This program is distributed in the hope that it will be useful, but WITHOUT
skamonkey@3767
    14
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
skamonkey@3767
    15
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
skamonkey@3767
    16
 * details.
skamonkey@3767
    17
 *
skamonkey@3767
    18
 * You should have received a copy of the GNU General Public License along with
skamonkey@3767
    19
 * this program.  If not, see <http://www.gnu.org/licenses/>.
skamonkey@3767
    20
 *
skamonkey@3767
    21
 * As a special exception, AlliedModders LLC gives you permission to link the
skamonkey@3767
    22
 * code of this program (as well as its derivative works) to "Half-Life 2," the
skamonkey@3767
    23
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
skamonkey@3767
    24
 * by the Valve Corporation.  You must obey the GNU General Public License in
skamonkey@3767
    25
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
skamonkey@3767
    26
 * this exception to all derivative works.  AlliedModders LLC defines further
skamonkey@3767
    27
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
skamonkey@3767
    28
 * or <http://www.sourcemod.net/license.php>.
skamonkey@3767
    29
 *
skamonkey@3767
    30
 * Version: $Id$
skamonkey@3767
    31
 */
skamonkey@3767
    32
januk@3774
    33
#include <sourcemod_version.h>
skamonkey@3767
    34
#include "extension.h"
skamonkey@3767
    35
#include "compat_wrappers.h"
skamonkey@3767
    36
#include "macros.h"
skamonkey@3767
    37
#include "natives.h"
skamonkey@3767
    38
#include <sm_platform.h>
skamonkey@3767
    39
#include <const.h>
skamonkey@3767
    40
skamonkey@3767
    41
skamonkey@3767
    42
//#define SDKHOOKSDEBUG
skamonkey@3767
    43
skamonkey@3767
    44
/**
skamonkey@3767
    45
 * Globals
skamonkey@3767
    46
 */
skamonkey@3767
    47
skamonkey@3767
    48
// Order MUST match SDKHookType enum
skamonkey@3767
    49
HookTypeData g_HookTypes[SDKHook_MAXHOOKS] = 
skamonkey@3767
    50
{
skamonkey@3767
    51
//   Hook name                DT required               Supported (always false til later)
skamonkey@3767
    52
	{"EndTouch",              "",                       false},
skamonkey@3767
    53
	{"FireBulletsPost",       "",                       false},
skamonkey@3767
    54
	{"OnTakeDamage",          "",                       false},
skamonkey@3767
    55
	{"OnTakeDamagePost",      "",                       false},
skamonkey@3767
    56
	{"PreThink",              "DT_BasePlayer",          false},
skamonkey@3767
    57
	{"PostThink",             "DT_BasePlayer",          false},
skamonkey@3767
    58
	{"SetTransmit",           "",                       false},
skamonkey@3767
    59
	{"Spawn",                 "",                       false},
skamonkey@3767
    60
	{"StartTouch",            "",                       false},
skamonkey@3767
    61
	{"Think",                 "",                       false},
skamonkey@3767
    62
	{"Touch",                 "",                       false},
skamonkey@3767
    63
	{"TraceAttack",           "",                       false},
skamonkey@3767
    64
	{"TraceAttackPost",       "",                       false},
skamonkey@3767
    65
	{"WeaponCanSwitchTo",     "DT_BaseCombatCharacter", false},
skamonkey@3767
    66
	{"WeaponCanUse",          "DT_BaseCombatCharacter", false},
skamonkey@3767
    67
	{"WeaponDrop",            "DT_BaseCombatCharacter", false},
skamonkey@3767
    68
	{"WeaponEquip",           "DT_BaseCombatCharacter", false},
skamonkey@3767
    69
	{"WeaponSwitch",          "DT_BaseCombatCharacter", false},
skamonkey@3767
    70
	{"ShouldCollide",         "",                       false},
skamonkey@3767
    71
	{"PreThinkPost",          "DT_BasePlayer",          false},
skamonkey@3767
    72
	{"PostThinkPost",         "DT_BasePlayer",          false},
skamonkey@3767
    73
	{"ThinkPost",             "",                       false},
skamonkey@3767
    74
	{"EndTouchPost",          "",                       false},
skamonkey@3767
    75
	{"GroundEntChangedPost",  "",                       false},
skamonkey@3767
    76
	{"SpawnPost",             "",                       false},
skamonkey@3767
    77
	{"StartTouchPost",        "",                       false},
skamonkey@3767
    78
	{"TouchPost",             "",                       false},
skamonkey@3767
    79
	{"VPhysicsUpdate",        "",                       false},
skamonkey@3767
    80
	{"VPhysicsUpdatePost",    "",                       false},
skamonkey@3767
    81
	{"WeaponCanSwitchToPost", "DT_BaseCombatCharacter", false},
skamonkey@3767
    82
	{"WeaponCanUsePost",      "DT_BaseCombatCharacter", false},
skamonkey@3767
    83
	{"WeaponDropPost",        "DT_BaseCombatCharacter", false},
skamonkey@3767
    84
	{"WeaponEquipPost",       "DT_BaseCombatCharacter", false},
skamonkey@3767
    85
	{"WeaponSwitchPost",      "DT_BaseCombatCharacter", false},
skamonkey@3767
    86
	{"Use",                   "",                       false},
skamonkey@3767
    87
	{"UsePost",               "",                       false},
skamonkey@3767
    88
	{"Reload",                "DT_BaseCombatWeapon",    false},
skamonkey@3767
    89
	{"ReloadPost",            "DT_BaseCombatWeapon",    false},
skamonkey@3767
    90
	{"GetMaxHealth",          "",                       false},
skamonkey@3767
    91
};
skamonkey@3767
    92
skamonkey@3767
    93
SDKHooks g_Interface;
skamonkey@3767
    94
SMEXT_LINK(&g_Interface);
skamonkey@3767
    95
skamonkey@3767
    96
CGlobalVars *gpGlobals;
kyle@4297
    97
ke::Vector<CVTableList *> g_HookList[SDKHook_MAXHOOKS];
skamonkey@3767
    98
skamonkey@3767
    99
CBitVec<NUM_ENT_ENTRIES> m_EntityExists;
skamonkey@3767
   100
skamonkey@3767
   101
IBinTools *g_pBinTools = NULL;
skamonkey@3767
   102
ICvar *icvar = NULL;
skamonkey@3767
   103
skamonkey@3767
   104
// global hooks and forwards
skamonkey@3767
   105
IForward *g_pOnEntityCreated = NULL;
skamonkey@3767
   106
IForward *g_pOnEntityDestroyed = NULL;
skamonkey@3767
   107
skamonkey@3767
   108
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   109
int g_hookOnGetGameDescription = 0;
skamonkey@3767
   110
IForward *g_pOnGetGameNameDescription = NULL;
skamonkey@3767
   111
#endif
skamonkey@3767
   112
skamonkey@3767
   113
int g_hookOnGetMapEntitiesString = 0;
skamonkey@3767
   114
int g_hookOnLevelInit = 0;
skamonkey@3767
   115
IForward *g_pOnLevelInit = NULL;
skamonkey@3767
   116
skamonkey@3767
   117
IGameConfig *g_pGameConf = NULL;
skamonkey@3767
   118
skamonkey@3767
   119
char g_szMapEntities[2097152];
skamonkey@3767
   120
skamonkey@4231
   121
CUtlVector<IEntityListener *> *EntListeners()
skamonkey@4231
   122
{
skamonkey@4231
   123
	void *gEntList = gamehelpers->GetGlobalEntityList();
skamonkey@4231
   124
	if (gEntList)
skamonkey@4231
   125
	{
skamonkey@4231
   126
		int offset = -1; /* 65572 */
skamonkey@4231
   127
		if (g_pGameConf->GetOffset("EntityListeners", &offset))
skamonkey@4231
   128
		{
skamonkey@4231
   129
			return (CUtlVector<IEntityListener *> *)((intptr_t) gEntList + offset);
skamonkey@4231
   130
		}
skamonkey@4231
   131
	}
skamonkey@4231
   132
	else
skamonkey@4231
   133
	{
skamonkey@4231
   134
		void *entListeners;
skamonkey@4231
   135
		if (g_pGameConf->GetAddress("EntityListenersPtr", &entListeners))
skamonkey@4231
   136
		{
skamonkey@4231
   137
			return (CUtlVector<IEntityListener *> *)entListeners;
skamonkey@4231
   138
		}
skamonkey@4231
   139
	}
skamonkey@4231
   140
skamonkey@4231
   141
	return NULL;
skamonkey@4231
   142
}
skamonkey@4231
   143
skamonkey@3767
   144
skamonkey@3767
   145
/**
skamonkey@3767
   146
 * IServerGameDLL & IVEngineServer Hooks
skamonkey@3767
   147
 */
skamonkey@3767
   148
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, const char *, const char *, const char *, const char *, bool, bool);
skamonkey@3767
   149
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   150
SH_DECL_HOOK0(IServerGameDLL, GetGameDescription, SH_NOATTRIB, 0, const char *);
skamonkey@3767
   151
#endif
skamonkey@3767
   152
SH_DECL_HOOK0(IVEngineServer, GetMapEntitiesString, SH_NOATTRIB, 0, const char *);
skamonkey@3767
   153
skamonkey@3767
   154
skamonkey@3767
   155
/**
skamonkey@3767
   156
 * CBaseEntity Hooks
skamonkey@3767
   157
 */
skamonkey@3767
   158
SH_DECL_MANUALHOOK1_void(EndTouch, 0, 0, 0, CBaseEntity *);
skamonkey@3767
   159
SH_DECL_MANUALHOOK1_void(FireBullets, 0, 0, 0, FireBulletsInfo_t const&);
skamonkey@3767
   160
#ifdef GETMAXHEALTH_IS_VIRTUAL
skamonkey@3767
   161
SH_DECL_MANUALHOOK0(GetMaxHealth, 0, 0, 0, int);
skamonkey@3767
   162
#endif
skamonkey@3767
   163
SH_DECL_MANUALHOOK0_void(GroundEntChanged, 0, 0, 0);
skamonkey@3767
   164
SH_DECL_MANUALHOOK1(OnTakeDamage, 0, 0, 0, int, CTakeDamageInfoHack &);
skamonkey@3767
   165
SH_DECL_MANUALHOOK0_void(PreThink, 0, 0, 0);
skamonkey@3767
   166
SH_DECL_MANUALHOOK0_void(PostThink, 0, 0, 0);
skamonkey@3767
   167
SH_DECL_MANUALHOOK0(Reload, 0, 0, 0, bool);
skamonkey@3767
   168
SH_DECL_MANUALHOOK2_void(SetTransmit, 0, 0, 0, CCheckTransmitInfo *, bool);
skamonkey@3767
   169
SH_DECL_MANUALHOOK2(ShouldCollide, 0, 0, 0, bool, int, int);
skamonkey@4180
   170
#if SOURCE_ENGINE == SE_DOTA
skamonkey@4180
   171
SH_DECL_MANUALHOOK1_void(Spawn, 0, 0, 0, CEntityKeyValues *);
skamonkey@4180
   172
#else
skamonkey@3767
   173
SH_DECL_MANUALHOOK0_void(Spawn, 0, 0, 0);
skamonkey@4180
   174
#endif
skamonkey@3767
   175
SH_DECL_MANUALHOOK1_void(StartTouch, 0, 0, 0, CBaseEntity *);
skamonkey@3767
   176
SH_DECL_MANUALHOOK0_void(Think, 0, 0, 0);
skamonkey@3767
   177
SH_DECL_MANUALHOOK1_void(Touch, 0, 0, 0, CBaseEntity *);
skamonkey@4281
   178
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_SDK2013
skamonkey@4281
   179
SH_DECL_MANUALHOOK4_void(TraceAttack, 0, 0, 0, CTakeDamageInfoHack &, const Vector &, CGameTrace *, CDmgAccumulator *);
skamonkey@3767
   180
#else
skamonkey@3767
   181
SH_DECL_MANUALHOOK3_void(TraceAttack, 0, 0, 0, CTakeDamageInfoHack &, const Vector &, CGameTrace *);
skamonkey@3767
   182
#endif
skamonkey@3767
   183
SH_DECL_MANUALHOOK4_void(Use, 0, 0, 0, CBaseEntity *, CBaseEntity *, USE_TYPE, float);
skamonkey@3767
   184
SH_DECL_MANUALHOOK1_void(VPhysicsUpdate, 0, 0, 0, IPhysicsObject *);
skamonkey@3767
   185
SH_DECL_MANUALHOOK1(Weapon_CanSwitchTo, 0, 0, 0, bool, CBaseCombatWeapon *);
skamonkey@3767
   186
SH_DECL_MANUALHOOK1(Weapon_CanUse, 0, 0, 0, bool, CBaseCombatWeapon *);
skamonkey@3767
   187
SH_DECL_MANUALHOOK3_void(Weapon_Drop, 0, 0, 0, CBaseCombatWeapon *, const Vector *, const Vector *);
skamonkey@3767
   188
SH_DECL_MANUALHOOK1_void(Weapon_Equip, 0, 0, 0, CBaseCombatWeapon *);
skamonkey@3767
   189
SH_DECL_MANUALHOOK2(Weapon_Switch, 0, 0, 0, bool, CBaseCombatWeapon *, int);
skamonkey@3767
   190
skamonkey@3767
   191
skamonkey@3767
   192
/**
skamonkey@3767
   193
 * Forwards
skamonkey@3767
   194
 */
skamonkey@3767
   195
bool SDKHooks::SDK_OnLoad(char *error, size_t maxlength, bool late)
skamonkey@3767
   196
{
skamonkey@3767
   197
	char buffer[256];
skamonkey@3767
   198
	g_pSM->BuildPath(Path_SM, buffer, sizeof(buffer)-1, "/extensions/sdkhooks.ext." PLATFORM_LIB_EXT);
skamonkey@3767
   199
	if (libsys->PathExists(buffer) && libsys->IsPathFile(buffer))
skamonkey@3767
   200
	{
skamonkey@3767
   201
		g_pSM->Format(error, maxlength-1, "SDKHooks 2.x cannot load while old version (sdkhooks.ext." PLATFORM_LIB_EXT ") is still in extensions dir");
skamonkey@3767
   202
		return false;
skamonkey@3767
   203
	}
skamonkey@3767
   204
skamonkey@3767
   205
	g_pSM->BuildPath(Path_SM, buffer, sizeof(buffer)-1, "/gamedata/sdkhooks.games.txt");
skamonkey@3767
   206
	if (libsys->PathExists(buffer) && libsys->IsPathFile(buffer))
skamonkey@3767
   207
	{
skamonkey@3767
   208
		g_pSM->Format(error, maxlength-1, "SDKHooks 2.x cannot load while old gamedata file (sdkhooks.games.txt) is still in gamedata dir");
skamonkey@3767
   209
		return false;
skamonkey@3767
   210
	}
skamonkey@3767
   211
skamonkey@3767
   212
	sharesys->AddDependency(myself, "bintools.ext", true, true);
skamonkey@3767
   213
	sharesys->AddNatives(myself, g_Natives);
skamonkey@3767
   214
	sharesys->RegisterLibrary(myself, "sdkhooks");
aangione@3971
   215
	sharesys->AddInterface(myself, &g_Interface);
skamonkey@3767
   216
	sharesys->AddCapabilityProvider(myself, this, "SDKHook_DmgCustomInOTD");
skamonkey@3767
   217
	sharesys->AddCapabilityProvider(myself, this, "SDKHook_LogicalEntSupport");
skamonkey@3767
   218
skamonkey@3767
   219
	playerhelpers->AddClientListener(&g_Interface);
skamonkey@3767
   220
	
skamonkey@3767
   221
	plsys->AddPluginsListener(&g_Interface);
skamonkey@3767
   222
skamonkey@3767
   223
	g_pOnEntityCreated = forwards->CreateForward("OnEntityCreated", ET_Ignore, 2, NULL, Param_Cell, Param_String);
skamonkey@3767
   224
	g_pOnEntityDestroyed = forwards->CreateForward("OnEntityDestroyed", ET_Ignore, 1, NULL, Param_Cell);
skamonkey@3767
   225
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   226
	g_pOnGetGameNameDescription = forwards->CreateForward("OnGetGameDescription", ET_Hook, 2, NULL, Param_String);
skamonkey@3767
   227
#endif
skamonkey@3767
   228
	g_pOnLevelInit = forwards->CreateForward("OnLevelInit", ET_Hook, 2, NULL, Param_String, Param_String);
skamonkey@3767
   229
skamonkey@3767
   230
	buffer[0] = '\0';
skamonkey@3767
   231
	if (!gameconfs->LoadGameConfigFile("sdkhooks.games", &g_pGameConf, buffer, sizeof(buffer)))
skamonkey@3767
   232
	{
skamonkey@3767
   233
		if (buffer[0])
skamonkey@3767
   234
		{
skamonkey@3767
   235
			g_pSM->Format(error, maxlength, "Could not read sdkhooks.games gamedata: %s", buffer);
skamonkey@3767
   236
		}
skamonkey@3767
   237
		
skamonkey@3767
   238
		return false;
skamonkey@3767
   239
	}
skamonkey@3767
   240
skamonkey@4231
   241
	CUtlVector<IEntityListener *> *entListeners = EntListeners();
skamonkey@4231
   242
	if (!entListeners)
skamonkey@3767
   243
	{
skamonkey@4231
   244
		g_pSM->Format(error, maxlength, "Failed to setup entity listeners");
skamonkey@3767
   245
		return false;
skamonkey@3767
   246
	}
skamonkey@3767
   247
skamonkey@4231
   248
	entListeners->AddToTail(this);
skamonkey@3767
   249
skamonkey@3767
   250
	SetupHooks();
skamonkey@3767
   251
skamonkey@3767
   252
#if SOURCE_ENGINE >= SE_ORANGEBOX
skamonkey@3767
   253
	int index;
skamonkey@3767
   254
	CBaseHandle hndl;
skamonkey@3767
   255
	for (IHandleEntity *pEnt = (IHandleEntity *)servertools->FirstEntity(); pEnt; pEnt = (IHandleEntity *)servertools->NextEntity((CBaseEntity *)pEnt))
skamonkey@3767
   256
	{
skamonkey@3767
   257
		hndl = pEnt->GetRefEHandle();
kyle@4297
   258
		if (!hndl.IsValid())
skamonkey@3767
   259
			continue;
skamonkey@3767
   260
		
skamonkey@3767
   261
		index = hndl.GetEntryIndex();
skamonkey@3767
   262
		m_EntityExists.Set(index);
skamonkey@3767
   263
	}
skamonkey@3767
   264
#else
skamonkey@3767
   265
	for (int i = 0; i < NUM_ENT_ENTRIES; i++)
skamonkey@3767
   266
	{
skamonkey@3767
   267
		if (gamehelpers->ReferenceToEntity(i) != NULL)
skamonkey@3767
   268
			m_EntityExists.Set(i);
skamonkey@3767
   269
	}
skamonkey@3767
   270
#endif
skamonkey@3767
   271
skamonkey@3767
   272
	return true;
skamonkey@3767
   273
}
skamonkey@3767
   274
skamonkey@3767
   275
inline void HookLevelInit()
skamonkey@3767
   276
{
skamonkey@3767
   277
	assert(g_hookOnLevelInit == 0);
kyle@3819
   278
	g_hookOnLevelInit = SH_ADD_HOOK(IServerGameDLL, LevelInit, gamedll, SH_MEMBER(&g_Interface, &SDKHooks::Hook_LevelInit), false);
skamonkey@3767
   279
	assert(g_hookOnGetMapEntitiesString == 0);
kyle@3819
   280
	g_hookOnGetMapEntitiesString = SH_ADD_HOOK(IVEngineServer, GetMapEntitiesString, engine, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GetMapEntitiesString), false);
skamonkey@3767
   281
}
skamonkey@3767
   282
skamonkey@3767
   283
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   284
inline void HookGetGameDescription()
skamonkey@3767
   285
{
skamonkey@3767
   286
	assert(g_hookOnGetGameDescription == 0);
kyle@3819
   287
	g_hookOnGetGameDescription = SH_ADD_HOOK(IServerGameDLL, GetGameDescription, gamedll, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GetGameDescription), false);
skamonkey@3767
   288
}
skamonkey@3767
   289
#endif
skamonkey@3767
   290
skamonkey@3767
   291
void SDKHooks::SDK_OnAllLoaded()
skamonkey@3767
   292
{
skamonkey@3767
   293
	SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
skamonkey@3767
   294
skamonkey@3767
   295
	if (!g_pBinTools)
skamonkey@3767
   296
	{
skamonkey@3767
   297
		g_pSM->LogError(myself, "Could not find interface: " SMINTERFACE_BINTOOLS_NAME);
skamonkey@3767
   298
		return;
skamonkey@3767
   299
	}
skamonkey@3767
   300
skamonkey@3767
   301
	if (g_pOnLevelInit->GetFunctionCount() > 0)
skamonkey@3767
   302
		HookLevelInit();
skamonkey@3767
   303
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   304
	if (g_pOnGetGameNameDescription->GetFunctionCount() > 0)
skamonkey@3767
   305
		HookGetGameDescription();
skamonkey@3767
   306
#endif
skamonkey@3767
   307
}
skamonkey@3767
   308
skamonkey@3767
   309
#define KILL_HOOK_IF_ACTIVE(hook) \
skamonkey@3767
   310
	if (hook != 0) \
skamonkey@3767
   311
	{ \
skamonkey@3767
   312
		SH_REMOVE_HOOK_ID(hook); \
skamonkey@3767
   313
	}
skamonkey@3767
   314
skamonkey@3767
   315
void SDKHooks::SDK_OnUnload()
skamonkey@3767
   316
{
skamonkey@3767
   317
	// Remove left over hooks
kyle@4297
   318
	Unhook(reinterpret_cast<SourcePawn::IPluginContext *>(NULL));
skamonkey@3767
   319
skamonkey@3767
   320
	KILL_HOOK_IF_ACTIVE(g_hookOnLevelInit);
skamonkey@3767
   321
	KILL_HOOK_IF_ACTIVE(g_hookOnGetMapEntitiesString);
skamonkey@3767
   322
skamonkey@3767
   323
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   324
	KILL_HOOK_IF_ACTIVE(g_hookOnGetGameDescription);
skamonkey@3767
   325
#endif
skamonkey@3767
   326
skamonkey@3767
   327
	forwards->ReleaseForward(g_pOnEntityCreated);
skamonkey@3767
   328
	forwards->ReleaseForward(g_pOnEntityDestroyed);
skamonkey@3767
   329
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   330
	forwards->ReleaseForward(g_pOnGetGameNameDescription);
skamonkey@3767
   331
#endif
skamonkey@3767
   332
	forwards->ReleaseForward(g_pOnLevelInit);
skamonkey@3767
   333
skamonkey@3767
   334
	plsys->RemovePluginsListener(&g_Interface);
skamonkey@3767
   335
skamonkey@3767
   336
	playerhelpers->RemoveClientListener(&g_Interface);
skamonkey@3767
   337
skamonkey@3767
   338
	sharesys->DropCapabilityProvider(myself, this, "SDKHook_DmgCustomInOTD");
skamonkey@3767
   339
	sharesys->DropCapabilityProvider(myself, this, "SDKHook_LogicalEntSupport");
skamonkey@3767
   340
skamonkey@4231
   341
	CUtlVector<IEntityListener *> *entListeners = EntListeners();
skamonkey@4231
   342
	entListeners->FindAndRemove(this);
skamonkey@3767
   343
skamonkey@3767
   344
	gameconfs->CloseGameConfigFile(g_pGameConf);
skamonkey@3767
   345
}
skamonkey@3767
   346
skamonkey@3767
   347
bool SDKHooks::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
skamonkey@3767
   348
{
skamonkey@3767
   349
	GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION);
skamonkey@3767
   350
skamonkey@3767
   351
#if SOURCE_ENGINE >= SE_ORANGEBOX
skamonkey@3767
   352
	g_pCVar = icvar;
skamonkey@3767
   353
#endif
skamonkey@3767
   354
	CONVAR_REGISTER(this);
skamonkey@3767
   355
	
skamonkey@3767
   356
	gpGlobals = ismm->GetCGlobals();
skamonkey@3767
   357
skamonkey@3767
   358
	return true;
skamonkey@3767
   359
}
skamonkey@3767
   360
januk@3774
   361
const char *SDKHooks::GetExtensionVerString()
januk@3774
   362
{
dvander@4188
   363
	return SOURCEMOD_VERSION;
januk@3774
   364
}
januk@3774
   365
januk@3774
   366
const char *SDKHooks::GetExtensionDateString()
januk@3774
   367
{
dvander@4188
   368
	return SOURCEMOD_BUILD_TIME;
januk@3774
   369
}
januk@3774
   370
skamonkey@3767
   371
void SDKHooks::OnPluginLoaded(IPlugin *plugin)
skamonkey@3767
   372
{
skamonkey@3767
   373
	if (g_pOnLevelInit->GetFunctionCount() > 0 && g_hookOnLevelInit == 0)
skamonkey@3767
   374
		HookLevelInit();
skamonkey@3767
   375
skamonkey@3767
   376
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   377
	if (g_pOnGetGameNameDescription->GetFunctionCount() > 0 && g_hookOnGetGameDescription == 0)
skamonkey@3767
   378
		HookGetGameDescription();
skamonkey@3767
   379
#endif
skamonkey@3767
   380
}
skamonkey@3767
   381
skamonkey@3767
   382
void SDKHooks::OnPluginUnloaded(IPlugin *plugin)
skamonkey@3767
   383
{
kyle@4297
   384
	Unhook(plugin->GetBaseContext());
skamonkey@3767
   385
skamonkey@3767
   386
	if (g_pOnLevelInit->GetFunctionCount() == 0)
skamonkey@3767
   387
	{
skamonkey@3767
   388
		KILL_HOOK_IF_ACTIVE(g_hookOnLevelInit);
skamonkey@3767
   389
		KILL_HOOK_IF_ACTIVE(g_hookOnGetMapEntitiesString);
skamonkey@3767
   390
	}
skamonkey@3767
   391
skamonkey@3767
   392
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   393
	if (g_pOnGetGameNameDescription->GetFunctionCount() == 0)
skamonkey@3767
   394
		KILL_HOOK_IF_ACTIVE(g_hookOnGetGameDescription);
skamonkey@3767
   395
#endif
skamonkey@3767
   396
}
skamonkey@3767
   397
skamonkey@3767
   398
void SDKHooks::OnClientPutInServer(int client)
skamonkey@3767
   399
{
aangione@3971
   400
	CBaseEntity *pPlayer = gamehelpers->ReferenceToEntity(client);
aangione@3971
   401
	const char *pName = gamehelpers->GetEntityClassname(pPlayer);
skamonkey@3767
   402
aangione@3971
   403
	// Send OnEntityCreated to SM listeners
aangione@3971
   404
	SourceHook::List<ISMEntityListener *>::iterator iter;
aangione@3971
   405
	ISMEntityListener *pListener = NULL;
aangione@3971
   406
	for (iter=m_EntListeners.begin(); iter!=m_EntListeners.end(); iter++)
aangione@3971
   407
	{
aangione@3971
   408
		pListener = (*iter);
aangione@3971
   409
		pListener->OnEntityCreated(pPlayer, pName ? pName : "");
aangione@3971
   410
	}
skamonkey@3767
   411
aangione@3971
   412
	// Call OnEntityCreated forward
aangione@3971
   413
	g_pOnEntityCreated->PushCell(client);
skamonkey@3767
   414
	g_pOnEntityCreated->PushString(pName ? pName : "");
skamonkey@3767
   415
	g_pOnEntityCreated->Execute(NULL);
skamonkey@3767
   416
skamonkey@3767
   417
	m_EntityExists.Set(client);
skamonkey@3767
   418
}
skamonkey@3767
   419
aangione@3971
   420
void SDKHooks::AddEntityListener(ISMEntityListener *listener)
aangione@3971
   421
{
aangione@3971
   422
	m_EntListeners.push_back(listener);
aangione@3971
   423
}
aangione@3971
   424
aangione@3971
   425
void SDKHooks::RemoveEntityListener(ISMEntityListener *listener)
aangione@3971
   426
{
aangione@3971
   427
	m_EntListeners.remove(listener);
aangione@3971
   428
}
aangione@3971
   429
skamonkey@3767
   430
bool SDKHooks::RegisterConCommandBase(ConCommandBase *pVar)
skamonkey@3767
   431
{
skamonkey@3767
   432
	/* Always call META_REGCVAR instead of going through the engine. */
skamonkey@3767
   433
	return META_REGCVAR(pVar);
skamonkey@3767
   434
}
skamonkey@3767
   435
skamonkey@3767
   436
FeatureStatus SDKHooks::GetFeatureStatus(FeatureType type, const char *name)
skamonkey@3767
   437
{
skamonkey@3767
   438
	return FeatureStatus_Available;
skamonkey@3767
   439
}
skamonkey@3767
   440
skamonkey@3767
   441
/**
skamonkey@3767
   442
 * Functions
skamonkey@3767
   443
 */
skamonkey@3767
   444
cell_t SDKHooks::Call(int entity, SDKHookType type, int other)
skamonkey@3767
   445
{
kyle@4297
   446
	return Call(gamehelpers->ReferenceToEntity(entity), type, gamehelpers->ReferenceToEntity(other));
skamonkey@3767
   447
}
skamonkey@3767
   448
skamonkey@3767
   449
cell_t SDKHooks::Call(CBaseEntity *pEnt, SDKHookType type, int other)
skamonkey@3767
   450
{
kyle@4297
   451
	return Call(pEnt, type, gamehelpers->ReferenceToEntity(other));
skamonkey@3767
   452
}
skamonkey@3767
   453
kyle@4297
   454
cell_t SDKHooks::Call(CBaseEntity *pEnt, SDKHookType type, CBaseEntity *pOther)
skamonkey@3767
   455
{
kyle@4297
   456
	cell_t ret = Pl_Continue;
kyle@4297
   457
kyle@4297
   458
	CVTableHook vhook(pEnt);
kyle@4297
   459
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
kyle@4297
   460
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
kyle@4297
   461
	{
kyle@4297
   462
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
   463
		{
kyle@4297
   464
			continue;
kyle@4297
   465
		}
kyle@4297
   466
kyle@4297
   467
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
   468
		int entity = gamehelpers->EntityToBCompatRef(pEnt);
kyle@4297
   469
		int other = gamehelpers->EntityToBCompatRef(pOther);
kyle@4297
   470
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
   471
		{
kyle@4297
   472
			if (entity != pawnlist[entry].entity)
kyle@4297
   473
			{
kyle@4297
   474
				continue;
kyle@4297
   475
			}
kyle@4297
   476
kyle@4297
   477
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
   478
			callback->PushCell(entity);
kyle@4297
   479
			callback->PushCell(other);
kyle@4297
   480
kyle@4297
   481
			cell_t res;
kyle@4297
   482
			callback->Execute(&res);
kyle@4297
   483
			if(res > ret)
kyle@4297
   484
			{
kyle@4297
   485
				ret = res;
kyle@4297
   486
			}
kyle@4297
   487
		}
kyle@4297
   488
kyle@4297
   489
		break;
kyle@4297
   490
	}
kyle@4297
   491
kyle@4297
   492
	return ret;
skamonkey@3767
   493
}
skamonkey@3767
   494
skamonkey@3767
   495
void SDKHooks::SetupHooks()
skamonkey@3767
   496
{
skamonkey@3767
   497
	int offset;
skamonkey@3767
   498
skamonkey@3767
   499
	//			gamedata          pre    post
skamonkey@3767
   500
	// (pre is not necessarily a prehook, just named without "Post" appeneded)
skamonkey@3767
   501
skamonkey@3767
   502
	CHECKOFFSET(EndTouch,         true,  true);
skamonkey@3767
   503
	CHECKOFFSET(FireBullets,      false, true);
skamonkey@3767
   504
	CHECKOFFSET(GroundEntChanged, false, true);
skamonkey@3767
   505
	CHECKOFFSET(OnTakeDamage,     true,  true);
skamonkey@3767
   506
	CHECKOFFSET(PreThink,         true,  true);
skamonkey@3767
   507
	CHECKOFFSET(PostThink,        true,  true);
skamonkey@3767
   508
	CHECKOFFSET(Reload,           true,  true);
skamonkey@3767
   509
	CHECKOFFSET(SetTransmit,      true,  false);
skamonkey@3767
   510
	CHECKOFFSET(ShouldCollide,    true,  false);
skamonkey@3767
   511
	CHECKOFFSET(Spawn,            true,  true);
skamonkey@3767
   512
	CHECKOFFSET(StartTouch,       true,  true);
skamonkey@3767
   513
	CHECKOFFSET(Think,            true,  true);
skamonkey@3767
   514
	CHECKOFFSET(Touch,            true,  true);
skamonkey@3767
   515
	CHECKOFFSET(TraceAttack,      true,  true);
skamonkey@3767
   516
	CHECKOFFSET(Use,              true,  true);
skamonkey@3767
   517
	CHECKOFFSET_W(CanSwitchTo,    true,  true);
skamonkey@3767
   518
	CHECKOFFSET_W(CanUse,         true,  true);
skamonkey@3767
   519
	CHECKOFFSET_W(Drop,           true,  true);
skamonkey@3767
   520
	CHECKOFFSET_W(Equip,          true,  true);
skamonkey@3767
   521
	CHECKOFFSET_W(Switch,         true,  true);
skamonkey@3767
   522
	CHECKOFFSET(VPhysicsUpdate,   true,  true);
skamonkey@3767
   523
skamonkey@3767
   524
	// this one is in a class all its own -_-
skamonkey@3767
   525
	offset = 0;
skamonkey@3767
   526
	g_pGameConf->GetOffset("GroundEntChanged", &offset);
skamonkey@3767
   527
	if (offset > 0)
skamonkey@3767
   528
	{
skamonkey@3767
   529
		SH_MANUALHOOK_RECONFIGURE(GroundEntChanged, offset, 0, 0);
skamonkey@3767
   530
		g_HookTypes[SDKHook_GroundEntChangedPost].supported = true;
skamonkey@3767
   531
	}
skamonkey@3767
   532
skamonkey@3767
   533
#ifdef GETMAXHEALTH_IS_VIRTUAL
skamonkey@3767
   534
	CHECKOFFSET(GetMaxHealth,	true,	false);
skamonkey@3767
   535
#endif
skamonkey@3767
   536
}
skamonkey@3767
   537
skamonkey@3767
   538
HookReturn SDKHooks::Hook(int entity, SDKHookType type, IPluginFunction *callback)
skamonkey@3767
   539
{
skamonkey@3767
   540
	if(!g_HookTypes[type].supported)
skamonkey@3767
   541
		return HookRet_NotSupported;
skamonkey@3767
   542
skamonkey@4294
   543
	CBaseEntity *pEnt = gamehelpers->ReferenceToEntity(entity);
skamonkey@3767
   544
	if(!pEnt)
skamonkey@3767
   545
		return HookRet_InvalidEntity;
skamonkey@3767
   546
	if(type < 0 || type >= SDKHook_MAXHOOKS)
skamonkey@3767
   547
		return HookRet_InvalidHookType;
skamonkey@3767
   548
skamonkey@3767
   549
	if (!!strcmp(g_HookTypes[type].dtReq, ""))
skamonkey@3767
   550
	{
kyle@4297
   551
		IServerUnknown *pUnk = (IServerUnknown *)pEnt;
kyle@4297
   552
kyle@4297
   553
		IServerNetworkable *pNet = pUnk->GetNetworkable();
skamonkey@4054
   554
		if (pNet && !UTIL_ContainsDataTable(pNet->GetServerClass()->m_pTable, g_HookTypes[type].dtReq))
skamonkey@3767
   555
			return HookRet_BadEntForHookType;
skamonkey@3767
   556
	}
skamonkey@3767
   557
kyle@4297
   558
	size_t entry;
kyle@4297
   559
	CVTableHook vhook(pEnt);
kyle@4297
   560
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
kyle@4297
   561
	for (entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
   562
	{
kyle@4297
   563
		if (vhook == vtablehooklist[entry]->vtablehook)
skamonkey@3767
   564
		{
skamonkey@3767
   565
			break;
skamonkey@3767
   566
		}
skamonkey@3767
   567
	}
kyle@4297
   568
kyle@4297
   569
	if (entry == vtablehooklist.length())
skamonkey@3767
   570
	{
kyle@4297
   571
		int hookid = 0;
skamonkey@3767
   572
		switch(type)
skamonkey@3767
   573
		{
skamonkey@3767
   574
			case SDKHook_EndTouch:
kyle@4297
   575
				hookid = SH_ADD_MANUALVPHOOK(EndTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_EndTouch), false);
skamonkey@3767
   576
				break;
skamonkey@3767
   577
			case SDKHook_EndTouchPost:
kyle@4297
   578
				hookid = SH_ADD_MANUALVPHOOK(EndTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_EndTouchPost), true);
skamonkey@3767
   579
				break;
skamonkey@3767
   580
			case SDKHook_FireBulletsPost:
kyle@4297
   581
				hookid = SH_ADD_MANUALVPHOOK(FireBullets, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_FireBulletsPost), true);
skamonkey@3767
   582
				break;
skamonkey@3767
   583
#ifdef GETMAXHEALTH_IS_VIRTUAL
skamonkey@3767
   584
			case SDKHook_GetMaxHealth:
kyle@4297
   585
				hookid = SH_ADD_MANUALVPHOOK(GetMaxHealth, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GetMaxHealth), false);
skamonkey@3767
   586
				break;
skamonkey@3767
   587
#endif
skamonkey@3767
   588
			case SDKHook_GroundEntChangedPost:
kyle@4297
   589
				hookid = SH_ADD_MANUALVPHOOK(GroundEntChanged, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_GroundEntChangedPost), true);
skamonkey@3767
   590
				break;
skamonkey@3767
   591
			case SDKHook_OnTakeDamage:
kyle@4297
   592
				hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamage), false);
skamonkey@3767
   593
				break;
skamonkey@3767
   594
			case SDKHook_OnTakeDamagePost:
kyle@4297
   595
				hookid = SH_ADD_MANUALVPHOOK(OnTakeDamage, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_OnTakeDamagePost), true);
skamonkey@3767
   596
				break;
skamonkey@3767
   597
			case SDKHook_PreThink:
kyle@4297
   598
				hookid = SH_ADD_MANUALVPHOOK(PreThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PreThink), false);
skamonkey@3767
   599
				break;
skamonkey@3767
   600
			case SDKHook_PreThinkPost:
kyle@4297
   601
				hookid = SH_ADD_MANUALVPHOOK(PreThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PreThinkPost), true);
skamonkey@3767
   602
				break;
skamonkey@3767
   603
			case SDKHook_PostThink:
kyle@4297
   604
				hookid = SH_ADD_MANUALVPHOOK(PostThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PostThink), false);
skamonkey@3767
   605
				break;
skamonkey@3767
   606
			case SDKHook_PostThinkPost:
kyle@4297
   607
				hookid = SH_ADD_MANUALVPHOOK(PostThink, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_PostThinkPost), true);
skamonkey@3767
   608
				break;
skamonkey@3767
   609
			case SDKHook_Reload:
kyle@4297
   610
				hookid = SH_ADD_MANUALVPHOOK(Reload, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Reload), false);
skamonkey@3767
   611
				break;
skamonkey@3767
   612
			case SDKHook_ReloadPost:
kyle@4297
   613
				hookid = SH_ADD_MANUALVPHOOK(Reload, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ReloadPost), true);
skamonkey@3767
   614
				break;
skamonkey@3767
   615
			case SDKHook_SetTransmit:
kyle@4297
   616
				hookid = SH_ADD_MANUALVPHOOK(SetTransmit, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_SetTransmit), false);
skamonkey@3767
   617
				break;
skamonkey@3767
   618
			case SDKHook_Spawn:
kyle@4297
   619
				hookid = SH_ADD_MANUALVPHOOK(Spawn, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Spawn), false);
skamonkey@3767
   620
				break;
skamonkey@3767
   621
			case SDKHook_SpawnPost:
kyle@4297
   622
				hookid = SH_ADD_MANUALVPHOOK(Spawn, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_SpawnPost), true);
skamonkey@3767
   623
				break;
skamonkey@3767
   624
			case SDKHook_StartTouch:
kyle@4297
   625
				hookid = SH_ADD_MANUALVPHOOK(StartTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_StartTouch), false);
skamonkey@3767
   626
				break;
skamonkey@3767
   627
			case SDKHook_StartTouchPost:
kyle@4297
   628
				hookid = SH_ADD_MANUALVPHOOK(StartTouch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_StartTouchPost), true);
skamonkey@3767
   629
				break;
skamonkey@3767
   630
			case SDKHook_Think:
kyle@4297
   631
				hookid = SH_ADD_MANUALVPHOOK(Think, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Think), false);
skamonkey@3767
   632
				break;
skamonkey@3767
   633
			case SDKHook_ThinkPost:
kyle@4297
   634
				hookid = SH_ADD_MANUALVPHOOK(Think, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ThinkPost), true);
skamonkey@3767
   635
				break;
skamonkey@3767
   636
			case SDKHook_Touch:
kyle@4297
   637
				hookid = SH_ADD_MANUALVPHOOK(Touch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Touch), false);
skamonkey@3767
   638
				break;
skamonkey@3767
   639
			case SDKHook_TouchPost:
kyle@4297
   640
				hookid = SH_ADD_MANUALVPHOOK(Touch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TouchPost), true);
skamonkey@3767
   641
				break;
skamonkey@3767
   642
			case SDKHook_TraceAttack:
kyle@4297
   643
				hookid = SH_ADD_MANUALVPHOOK(TraceAttack, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TraceAttack), false);
skamonkey@3767
   644
				break;
skamonkey@3767
   645
			case SDKHook_TraceAttackPost:
kyle@4297
   646
				hookid = SH_ADD_MANUALVPHOOK(TraceAttack, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_TraceAttackPost), true);
skamonkey@3767
   647
				break;
skamonkey@3767
   648
			case SDKHook_Use:
kyle@4297
   649
				hookid = SH_ADD_MANUALVPHOOK(Use, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_Use), false);
skamonkey@3767
   650
				break;
skamonkey@3767
   651
			case SDKHook_UsePost:
kyle@4297
   652
				hookid = SH_ADD_MANUALVPHOOK(Use, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_UsePost), true);
skamonkey@3767
   653
				break;
skamonkey@3767
   654
			case SDKHook_VPhysicsUpdate:
kyle@4297
   655
				hookid = SH_ADD_MANUALVPHOOK(VPhysicsUpdate, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_VPhysicsUpdate), false);
skamonkey@3767
   656
				break;
skamonkey@3767
   657
			case SDKHook_VPhysicsUpdatePost:
kyle@4297
   658
				hookid = SH_ADD_MANUALVPHOOK(VPhysicsUpdate, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_VPhysicsUpdatePost), true);
skamonkey@3767
   659
				break;
skamonkey@3767
   660
			case SDKHook_WeaponCanSwitchTo:
kyle@4297
   661
				hookid = SH_ADD_MANUALVPHOOK(Weapon_CanSwitchTo, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanSwitchTo), false);
skamonkey@3767
   662
				break;
skamonkey@3767
   663
			case SDKHook_WeaponCanSwitchToPost:
kyle@4297
   664
				hookid = SH_ADD_MANUALVPHOOK(Weapon_CanSwitchTo, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanSwitchToPost), true);
skamonkey@3767
   665
				break;
skamonkey@3767
   666
			case SDKHook_WeaponCanUse:
kyle@4297
   667
				hookid = SH_ADD_MANUALVPHOOK(Weapon_CanUse, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanUse), false);
skamonkey@3767
   668
				break;
skamonkey@3767
   669
			case SDKHook_WeaponCanUsePost:
kyle@4297
   670
				hookid = SH_ADD_MANUALVPHOOK(Weapon_CanUse, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponCanUsePost), true);
skamonkey@3767
   671
				break;
skamonkey@3767
   672
			case SDKHook_WeaponDrop:
kyle@4297
   673
				hookid = SH_ADD_MANUALVPHOOK(Weapon_Drop, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponDrop), false);
skamonkey@3767
   674
				break;
skamonkey@3767
   675
			case SDKHook_WeaponDropPost:
kyle@4297
   676
				hookid = SH_ADD_MANUALVPHOOK(Weapon_Drop, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponDropPost), true);
skamonkey@3767
   677
				break;
skamonkey@3767
   678
			case SDKHook_WeaponEquip:
kyle@4297
   679
				hookid = SH_ADD_MANUALVPHOOK(Weapon_Equip, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponEquip), false);
skamonkey@3767
   680
				break;
skamonkey@3767
   681
			case SDKHook_WeaponEquipPost:
kyle@4297
   682
				hookid = SH_ADD_MANUALVPHOOK(Weapon_Equip, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponEquipPost), true);
skamonkey@3767
   683
				break;
skamonkey@3767
   684
			case SDKHook_WeaponSwitch:
kyle@4297
   685
				hookid = SH_ADD_MANUALVPHOOK(Weapon_Switch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponSwitch), false);
skamonkey@3767
   686
				break;
skamonkey@3767
   687
			case SDKHook_WeaponSwitchPost:
kyle@4297
   688
				hookid = SH_ADD_MANUALVPHOOK(Weapon_Switch, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_WeaponSwitchPost), true);
skamonkey@3767
   689
				break;
skamonkey@3767
   690
			case SDKHook_ShouldCollide:
kyle@4297
   691
				hookid = SH_ADD_MANUALVPHOOK(ShouldCollide, pEnt, SH_MEMBER(&g_Interface, &SDKHooks::Hook_ShouldCollide), false);
skamonkey@3767
   692
				break;
skamonkey@3767
   693
		}
kyle@4297
   694
kyle@4297
   695
		vhook.SetHookID(hookid);
kyle@4297
   696
kyle@4297
   697
		CVTableList *vtablelist = new CVTableList;
kyle@4297
   698
		vtablelist->vtablehook = new CVTableHook(vhook);
kyle@4297
   699
		vtablehooklist.append(vtablelist);
skamonkey@3767
   700
	}
kyle@4297
   701
	
skamonkey@3767
   702
	// Add hook to hook list
skamonkey@3767
   703
	HookList hook;
kyle@4297
   704
	hook.entity = gamehelpers->EntityToBCompatRef(pEnt);
skamonkey@3767
   705
	hook.callback = callback;
kyle@4297
   706
	vtablehooklist[entry]->hooks.append(hook);
kyle@4297
   707
skamonkey@3767
   708
	return HookRet_Successful;
skamonkey@3767
   709
}
skamonkey@3767
   710
kyle@4297
   711
void SDKHooks::Unhook(CBaseEntity *pEntity)
skamonkey@3767
   712
{
kyle@4297
   713
	if (pEntity == NULL)
kyle@4297
   714
	{
skamonkey@3767
   715
		return;
kyle@4297
   716
	}
skamonkey@3767
   717
kyle@4297
   718
	int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
   719
	for (size_t type = 0; type < SDKHook_MAXHOOKS; ++type)
skamonkey@3767
   720
	{
kyle@4297
   721
		ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
kyle@4297
   722
		for (size_t listentry = 0; listentry < vtablehooklist.length(); ++listentry)
skamonkey@3767
   723
		{
kyle@4297
   724
			ke::Vector<HookList> &pawnhooks = vtablehooklist[listentry]->hooks;
kyle@4297
   725
			for (size_t entry = 0; entry < pawnhooks.length(); ++entry)
kyle@4297
   726
			{
kyle@4297
   727
				if (entity != pawnhooks[entry].entity)
kyle@4297
   728
				{
kyle@4297
   729
					continue;
kyle@4297
   730
				}
kyle@4297
   731
kyle@4297
   732
				pawnhooks.remove(entry--);
kyle@4297
   733
			}
kyle@4297
   734
kyle@4297
   735
			if (pawnhooks.length() == 0)
kyle@4297
   736
			{
kyle@4297
   737
				delete vtablehooklist[listentry];
kyle@4297
   738
				vtablehooklist.remove(listentry--);
kyle@4297
   739
			}
skamonkey@3767
   740
		}
skamonkey@3767
   741
	}
kyle@4297
   742
}
kyle@4297
   743
kyle@4297
   744
void SDKHooks::Unhook(IPluginContext *pContext)
kyle@4297
   745
{
kyle@4297
   746
	for (size_t type = 0; type < SDKHook_MAXHOOKS; ++type)
skamonkey@3767
   747
	{
kyle@4297
   748
		ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
kyle@4297
   749
		for (size_t listentry = 0; listentry < vtablehooklist.length(); ++listentry)
skamonkey@3767
   750
		{
kyle@4297
   751
			ke::Vector<HookList> &pawnhooks = vtablehooklist[listentry]->hooks;
kyle@4297
   752
			for (size_t entry = 0; entry < pawnhooks.length(); ++entry)
kyle@4297
   753
			{
kyle@4297
   754
				if (pContext != NULL && pContext != pawnhooks[entry].callback->GetParentRuntime()->GetDefaultContext())
kyle@4297
   755
				{
kyle@4297
   756
					continue;
kyle@4297
   757
				}
kyle@4297
   758
kyle@4297
   759
				pawnhooks.remove(entry--);
kyle@4297
   760
			}
kyle@4297
   761
kyle@4297
   762
			if (pawnhooks.length() == 0)
kyle@4297
   763
			{
kyle@4297
   764
				delete vtablehooklist[listentry];
kyle@4297
   765
				vtablehooklist.remove(listentry--);
kyle@4297
   766
			}
skamonkey@3767
   767
		}
skamonkey@3767
   768
	}
skamonkey@3767
   769
}
skamonkey@3767
   770
kyle@4297
   771
void SDKHooks::Unhook(int entity, SDKHookType type, IPluginFunction *pCallback)
kyle@4297
   772
{
kyle@4297
   773
	CBaseEntity *pEntity = gamehelpers->ReferenceToEntity(entity);
kyle@4297
   774
	if (pEntity == NULL)
kyle@4297
   775
	{
kyle@4297
   776
		return;
kyle@4297
   777
	}
kyle@4297
   778
kyle@4297
   779
	CVTableHook vhook(pEntity);
kyle@4297
   780
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[type];
kyle@4297
   781
	for (size_t listentry = 0; listentry < vtablehooklist.length(); ++listentry)
kyle@4297
   782
	{
kyle@4297
   783
		if (vhook != vtablehooklist[listentry]->vtablehook)
kyle@4297
   784
		{
kyle@4297
   785
			continue;
kyle@4297
   786
		}
kyle@4297
   787
kyle@4297
   788
		entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
   789
kyle@4297
   790
		ke::Vector<HookList> &pawnhooks = vtablehooklist[listentry]->hooks;
kyle@4297
   791
		for (size_t entry = 0; entry < pawnhooks.length(); ++entry)
kyle@4297
   792
		{
kyle@4297
   793
			HookList &hookentry = pawnhooks[entry];
kyle@4297
   794
			if (entity != hookentry.entity || pCallback != hookentry.callback)
kyle@4297
   795
			{
kyle@4297
   796
				continue;
kyle@4297
   797
			}
kyle@4297
   798
kyle@4297
   799
			pawnhooks.remove(entry--);
kyle@4297
   800
		}
kyle@4297
   801
kyle@4297
   802
		if (pawnhooks.length() == 0)
kyle@4297
   803
		{
kyle@4297
   804
			delete vtablehooklist[listentry];
kyle@4297
   805
			vtablehooklist.remove(listentry);
kyle@4297
   806
		}
kyle@4297
   807
kyle@4297
   808
		break;
kyle@4297
   809
	}
kyle@4297
   810
}
skamonkey@3767
   811
skamonkey@3767
   812
/**
skamonkey@3767
   813
 * IEntityFactoryDictionary, IServerGameDLL & IVEngineServer Hook Handlers
skamonkey@3767
   814
 */
skamonkey@3767
   815
void SDKHooks::OnEntityCreated(CBaseEntity *pEntity)
skamonkey@3767
   816
{
skamonkey@3767
   817
	// Call OnEntityCreated forward
skamonkey@3767
   818
	int entity = gamehelpers->ReferenceToIndex(gamehelpers->EntityToBCompatRef(pEntity));
skamonkey@3767
   819
	if (m_EntityExists.IsBitSet(entity) || (entity > 0 && entity <= playerhelpers->GetMaxClients()))
skamonkey@3767
   820
	{
skamonkey@3767
   821
		return;
skamonkey@3767
   822
	}
skamonkey@3767
   823
aangione@3971
   824
	const char *pName = gamehelpers->GetEntityClassname(pEntity);
skamonkey@3767
   825
aangione@3971
   826
	// Send OnEntityCreated to SM listeners
aangione@3971
   827
	SourceHook::List<ISMEntityListener *>::iterator iter;
aangione@3971
   828
	ISMEntityListener *pListener = NULL;
aangione@3971
   829
	for (iter=m_EntListeners.begin(); iter!=m_EntListeners.end(); iter++)
aangione@3971
   830
	{
aangione@3971
   831
		pListener = (*iter);
aangione@3971
   832
		pListener->OnEntityCreated(pEntity, pName ? pName : "");
aangione@3971
   833
	}
aangione@3971
   834
aangione@3971
   835
	g_pOnEntityCreated->PushCell(gamehelpers->EntityToBCompatRef(pEntity));
skamonkey@3767
   836
	g_pOnEntityCreated->PushString(pName ? pName : "");
skamonkey@3767
   837
	g_pOnEntityCreated->Execute(NULL);
skamonkey@3767
   838
skamonkey@3767
   839
	m_EntityExists.Set(entity);
skamonkey@3767
   840
}
skamonkey@3767
   841
skamonkey@3767
   842
#ifdef GAMEDESC_CAN_CHANGE
skamonkey@3767
   843
const char *SDKHooks::Hook_GetGameDescription()
skamonkey@3767
   844
{
skamonkey@3767
   845
	static char szGameDesc[64];
skamonkey@3767
   846
	cell_t result = Pl_Continue;
skamonkey@3767
   847
skamonkey@3767
   848
	g_pSM->Format(szGameDesc, sizeof(szGameDesc), "%s",
skamonkey@3767
   849
		SH_CALL(gamedll, &IServerGameDLL::GetGameDescription)());
skamonkey@3767
   850
skamonkey@3767
   851
	// Call OnGetGameDescription forward
skamonkey@3767
   852
	g_pOnGetGameNameDescription->PushStringEx(szGameDesc, sizeof(szGameDesc), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
skamonkey@3767
   853
	g_pOnGetGameNameDescription->Execute(&result);
skamonkey@3767
   854
skamonkey@3767
   855
	if(result == Pl_Changed)
skamonkey@3767
   856
		RETURN_META_VALUE(MRES_SUPERCEDE, szGameDesc);
skamonkey@3767
   857
skamonkey@3767
   858
	RETURN_META_VALUE(MRES_IGNORED, NULL);
skamonkey@3767
   859
}
skamonkey@3767
   860
#endif
skamonkey@3767
   861
skamonkey@3767
   862
const char *SDKHooks::Hook_GetMapEntitiesString()
skamonkey@3767
   863
{
skamonkey@3767
   864
	if(g_szMapEntities[0])
skamonkey@3767
   865
		RETURN_META_VALUE(MRES_SUPERCEDE, g_szMapEntities);
skamonkey@3767
   866
skamonkey@3767
   867
	RETURN_META_VALUE(MRES_IGNORED, NULL);
skamonkey@3767
   868
}
skamonkey@3767
   869
skamonkey@3767
   870
bool SDKHooks::Hook_LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
skamonkey@3767
   871
{
skamonkey@3767
   872
	strcpy(g_szMapEntities, pMapEntities);
skamonkey@3767
   873
	cell_t result = Pl_Continue;
skamonkey@3767
   874
skamonkey@3767
   875
	// Call OnLevelInit forward
skamonkey@3767
   876
	g_pOnLevelInit->PushString(pMapName);
skamonkey@3767
   877
	g_pOnLevelInit->PushStringEx(g_szMapEntities, sizeof(g_szMapEntities), SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
skamonkey@3767
   878
	g_pOnLevelInit->Execute(&result);
skamonkey@3767
   879
skamonkey@3767
   880
	if(result >= Pl_Handled)
skamonkey@3767
   881
		RETURN_META_VALUE(MRES_SUPERCEDE, false);
skamonkey@3767
   882
skamonkey@3767
   883
	if(result == Pl_Changed)
skamonkey@3767
   884
		RETURN_META_VALUE_NEWPARAMS(MRES_HANDLED, true, &IServerGameDLL::LevelInit, (pMapName, g_szMapEntities, pOldLevel, pLandmarkName, loadGame, background));
skamonkey@3767
   885
skamonkey@3767
   886
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
   887
}
skamonkey@3767
   888
skamonkey@3767
   889
skamonkey@3767
   890
/**
skamonkey@3767
   891
 * CBaseEntity Hook Handlers
skamonkey@3767
   892
 */
skamonkey@3767
   893
void SDKHooks::Hook_EndTouch(CBaseEntity *pOther)
skamonkey@3767
   894
{
skamonkey@3767
   895
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_EndTouch, pOther);
skamonkey@3767
   896
	if(result >= Pl_Handled)
skamonkey@3767
   897
		RETURN_META(MRES_SUPERCEDE);
skamonkey@3767
   898
skamonkey@3767
   899
	RETURN_META(MRES_IGNORED);
skamonkey@3767
   900
}
skamonkey@3767
   901
skamonkey@3767
   902
void SDKHooks::Hook_EndTouchPost(CBaseEntity *pOther)
skamonkey@3767
   903
{
skamonkey@3767
   904
	Call(META_IFACEPTR(CBaseEntity), SDKHook_EndTouchPost, pOther);
skamonkey@3767
   905
	RETURN_META(MRES_IGNORED);
skamonkey@3767
   906
}
skamonkey@3767
   907
skamonkey@3767
   908
void SDKHooks::Hook_FireBulletsPost(const FireBulletsInfo_t &info)
skamonkey@3767
   909
{
kyle@4297
   910
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
kyle@4297
   911
	int entity = gamehelpers->EntityToBCompatRef(pEntity);
skamonkey@3767
   912
skamonkey@3767
   913
	IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(entity);
skamonkey@3767
   914
	if(!pPlayer)
skamonkey@3767
   915
		RETURN_META(MRES_IGNORED);
skamonkey@3767
   916
skamonkey@3767
   917
	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
skamonkey@3767
   918
	if(!pInfo)
skamonkey@3767
   919
		RETURN_META(MRES_IGNORED);
skamonkey@3767
   920
kyle@4297
   921
	CVTableHook vhook(pEntity);
kyle@4297
   922
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_FireBulletsPost];
kyle@4297
   923
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
   924
	{
kyle@4297
   925
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
   926
		{
skamonkey@3767
   927
			continue;
kyle@4297
   928
		}
skamonkey@3767
   929
kyle@4297
   930
		const char *weapon = pInfo->GetWeaponName();
kyle@4297
   931
kyle@4297
   932
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
   933
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
   934
		{
kyle@4297
   935
			if (entity != pawnlist[entry].entity)
kyle@4297
   936
			{
kyle@4297
   937
				continue;
kyle@4297
   938
			}
kyle@4297
   939
kyle@4297
   940
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
   941
			callback->PushCell(entity);
kyle@4297
   942
			callback->PushCell(info.m_iShots);
kyle@4297
   943
			callback->PushString(weapon?weapon:"");
kyle@4297
   944
			callback->Execute(NULL);
kyle@4297
   945
		}
kyle@4297
   946
kyle@4297
   947
		break;
skamonkey@3767
   948
	}
skamonkey@3767
   949
skamonkey@3767
   950
	RETURN_META(MRES_IGNORED);
skamonkey@3767
   951
}
skamonkey@3767
   952
skamonkey@3767
   953
#ifdef GETMAXHEALTH_IS_VIRTUAL
skamonkey@3767
   954
int SDKHooks::Hook_GetMaxHealth()
skamonkey@3767
   955
{
skamonkey@3767
   956
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
   957
	int original_max = SH_MCALL(pEntity, GetMaxHealth)();
skamonkey@3767
   958
kyle@4297
   959
	CVTableHook vhook(pEntity);
kyle@4297
   960
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_GetMaxHealth];
kyle@4297
   961
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
   962
	{
kyle@4297
   963
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
   964
		{
skamonkey@3767
   965
			continue;
kyle@4297
   966
		}
kyle@4297
   967
kyle@4297
   968
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
   969
kyle@4297
   970
		int new_max = original_max;
kyle@4297
   971
kyle@4297
   972
		cell_t res = Pl_Continue;
skamonkey@3767
   973
kyle@4297
   974
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
   975
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
   976
		{
kyle@4297
   977
			if (entity != pawnlist[entry].entity)
kyle@4297
   978
			{
kyle@4297
   979
				continue;
kyle@4297
   980
			}
kyle@4297
   981
kyle@4297
   982
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
   983
			callback->PushCell(entity);
kyle@4297
   984
			callback->PushCellByRef(&new_max);
kyle@4297
   985
			callback->Execute(&res);
kyle@4297
   986
		}
kyle@4297
   987
kyle@4297
   988
		if (res >= Pl_Changed)
kyle@4297
   989
			RETURN_META_VALUE(MRES_SUPERCEDE, new_max);
kyle@4297
   990
kyle@4297
   991
		break;
skamonkey@3767
   992
	}
skamonkey@3767
   993
skamonkey@3767
   994
	RETURN_META_VALUE(MRES_IGNORED, original_max);
skamonkey@3767
   995
}
skamonkey@3767
   996
#endif
skamonkey@3767
   997
skamonkey@3767
   998
void SDKHooks::Hook_GroundEntChangedPost()
skamonkey@3767
   999
{
skamonkey@3767
  1000
	Call(META_IFACEPTR(CBaseEntity), SDKHook_GroundEntChangedPost);
skamonkey@3767
  1001
}
skamonkey@3767
  1002
skamonkey@3767
  1003
int SDKHooks::Hook_OnTakeDamage(CTakeDamageInfoHack &info)
skamonkey@3767
  1004
{
kyle@4297
  1005
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1006
kyle@4297
  1007
	CVTableHook vhook(pEntity);
kyle@4297
  1008
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_OnTakeDamage];
kyle@4297
  1009
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1010
	{
kyle@4297
  1011
		if (vhook != vtablehooklist[entry]->vtablehook)
skamonkey@3767
  1012
		{
kyle@4297
  1013
			continue;
skamonkey@3767
  1014
		}
skamonkey@3767
  1015
kyle@4297
  1016
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1017
		int attacker = info.GetAttacker();
kyle@4297
  1018
		int inflictor = info.GetInflictor();
kyle@4297
  1019
		float damage = info.GetDamage();
kyle@4297
  1020
		int damagetype = info.GetDamageType();
kyle@4297
  1021
		int weapon = info.GetWeapon();
kyle@4297
  1022
kyle@4297
  1023
		Vector force = info.GetDamageForce();
kyle@4297
  1024
		cell_t damageForce[3] = {sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z)};
kyle@4297
  1025
kyle@4297
  1026
		Vector pos = info.GetDamagePosition();
kyle@4297
  1027
		cell_t damagePosition[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
kyle@4297
  1028
kyle@4297
  1029
		cell_t res, ret = Pl_Continue;
kyle@4297
  1030
kyle@4297
  1031
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1032
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1033
		{
kyle@4297
  1034
			if (entity != pawnlist[entry].entity)
kyle@4297
  1035
			{
kyle@4297
  1036
				continue;
kyle@4297
  1037
			}
kyle@4297
  1038
kyle@4297
  1039
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1040
			callback->PushCell(entity);
kyle@4297
  1041
			callback->PushCellByRef(&attacker);
kyle@4297
  1042
			callback->PushCellByRef(&inflictor);
kyle@4297
  1043
			callback->PushFloatByRef(&damage);
kyle@4297
  1044
			callback->PushCellByRef(&damagetype);
kyle@4297
  1045
			callback->PushCellByRef(&weapon);
kyle@4297
  1046
			callback->PushArray(damageForce, 3, SM_PARAM_COPYBACK);
kyle@4297
  1047
			callback->PushArray(damagePosition, 3, SM_PARAM_COPYBACK);	
kyle@4297
  1048
			callback->PushCell(info.GetDamageCustom());
kyle@4297
  1049
			callback->Execute(&res);
skamonkey@3767
  1050
kyle@4297
  1051
			if(res >= ret)
kyle@4297
  1052
			{
kyle@4297
  1053
				ret = res;
kyle@4297
  1054
				if(ret == Pl_Changed)
kyle@4297
  1055
				{
kyle@4297
  1056
					CBaseEntity *pEntAttacker = gamehelpers->ReferenceToEntity(attacker);
kyle@4297
  1057
					if(!pEntAttacker)
kyle@4297
  1058
					{
kyle@4297
  1059
						callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Entity %d for attacker is invalid", attacker);
kyle@4297
  1060
						RETURN_META_VALUE(MRES_IGNORED, 0);
kyle@4297
  1061
					}
kyle@4297
  1062
					CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor);
kyle@4297
  1063
					if(!pEntInflictor)
kyle@4297
  1064
					{
kyle@4297
  1065
						callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Entity %d for inflictor is invalid", inflictor);
kyle@4297
  1066
						RETURN_META_VALUE(MRES_IGNORED, 0);
kyle@4297
  1067
					}
kyle@4297
  1068
kyle@4297
  1069
					info.SetAttacker(pEntAttacker);
kyle@4297
  1070
					info.SetInflictor(pEntInflictor);
kyle@4297
  1071
					info.SetDamage(damage);
kyle@4297
  1072
					info.SetDamageType(damagetype);
kyle@4297
  1073
					info.SetWeapon(gamehelpers->ReferenceToEntity(weapon));
kyle@4297
  1074
					info.SetDamageForce(
kyle@4297
  1075
						sp_ctof(damageForce[0]),
kyle@4297
  1076
						sp_ctof(damageForce[1]),
kyle@4297
  1077
						sp_ctof(damageForce[2]));
kyle@4297
  1078
					info.SetDamagePosition(
kyle@4297
  1079
						sp_ctof(damagePosition[0]),
kyle@4297
  1080
						sp_ctof(damagePosition[1]),
kyle@4297
  1081
						sp_ctof(damagePosition[2]));
kyle@4297
  1082
				}
kyle@4297
  1083
			}
kyle@4297
  1084
		}
kyle@4297
  1085
		
kyle@4297
  1086
		if(ret >= Pl_Handled)
kyle@4297
  1087
			RETURN_META_VALUE(MRES_SUPERCEDE, 1);
kyle@4297
  1088
kyle@4297
  1089
		if(ret == Pl_Changed)
kyle@4297
  1090
			RETURN_META_VALUE(MRES_HANDLED, 1); 
kyle@4297
  1091
kyle@4297
  1092
		break;
skamonkey@3767
  1093
	}
skamonkey@3767
  1094
skamonkey@3767
  1095
	RETURN_META_VALUE(MRES_IGNORED, 0);
skamonkey@3767
  1096
}
skamonkey@3767
  1097
skamonkey@3767
  1098
int SDKHooks::Hook_OnTakeDamagePost(CTakeDamageInfoHack &info)
skamonkey@3767
  1099
{
kyle@4297
  1100
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1101
kyle@4297
  1102
	CVTableHook vhook(pEntity);
kyle@4297
  1103
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_OnTakeDamagePost];
kyle@4297
  1104
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1105
	{
kyle@4297
  1106
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1107
		{
skamonkey@3767
  1108
			continue;
kyle@4297
  1109
		}
kyle@4297
  1110
kyle@4297
  1111
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1112
kyle@4297
  1113
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1114
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1115
		{
kyle@4297
  1116
			if (entity != pawnlist[entry].entity)
kyle@4297
  1117
			{
kyle@4297
  1118
				continue;
kyle@4297
  1119
			}
skamonkey@3767
  1120
kyle@4297
  1121
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1122
			callback->PushCell(entity);
kyle@4297
  1123
			callback->PushCell(info.GetAttacker());
kyle@4297
  1124
			callback->PushCell(info.GetInflictor());
kyle@4297
  1125
			callback->PushFloat(info.GetDamage());
kyle@4297
  1126
			callback->PushCell(info.GetDamageType());
kyle@4297
  1127
			callback->PushCell(info.GetWeapon());
skamonkey@3767
  1128
kyle@4297
  1129
			Vector force = info.GetDamageForce();
kyle@4297
  1130
			cell_t damageForce[3] = {sp_ftoc(force.x), sp_ftoc(force.y), sp_ftoc(force.z)};
kyle@4297
  1131
			callback->PushArray(damageForce, 3);
skamonkey@3767
  1132
kyle@4297
  1133
			Vector pos = info.GetDamagePosition();
kyle@4297
  1134
			cell_t damagePosition[3] = {sp_ftoc(pos.x), sp_ftoc(pos.y), sp_ftoc(pos.z)};
kyle@4297
  1135
			callback->PushArray(damagePosition, 3);
skamonkey@3767
  1136
kyle@4297
  1137
			callback->PushCell(info.GetDamageCustom());
skamonkey@3767
  1138
kyle@4297
  1139
			callback->Execute(NULL);
kyle@4297
  1140
		}
kyle@4297
  1141
kyle@4297
  1142
		break;
skamonkey@3767
  1143
	}
skamonkey@3767
  1144
skamonkey@3767
  1145
	RETURN_META_VALUE(MRES_IGNORED, 0);
skamonkey@3767
  1146
}
skamonkey@3767
  1147
skamonkey@3767
  1148
void SDKHooks::Hook_PreThink()
skamonkey@3767
  1149
{
skamonkey@3767
  1150
	Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThink);
skamonkey@4214
  1151
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1152
}
skamonkey@3767
  1153
skamonkey@3767
  1154
void SDKHooks::Hook_PreThinkPost()
skamonkey@3767
  1155
{
skamonkey@3767
  1156
	Call(META_IFACEPTR(CBaseEntity), SDKHook_PreThinkPost);
skamonkey@3767
  1157
}
skamonkey@3767
  1158
skamonkey@3767
  1159
void SDKHooks::Hook_PostThink()
skamonkey@3767
  1160
{
skamonkey@3767
  1161
	Call(META_IFACEPTR(CBaseEntity), SDKHook_PostThink);
skamonkey@4214
  1162
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1163
}
skamonkey@3767
  1164
skamonkey@3767
  1165
void SDKHooks::Hook_PostThinkPost()
skamonkey@3767
  1166
{
skamonkey@3767
  1167
	Call(META_IFACEPTR(CBaseEntity), SDKHook_PostThinkPost);
skamonkey@3767
  1168
}
skamonkey@3767
  1169
skamonkey@3767
  1170
bool SDKHooks::Hook_Reload()
skamonkey@3767
  1171
{
kyle@4297
  1172
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1173
kyle@4297
  1174
	CVTableHook vhook(pEntity);
kyle@4297
  1175
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_Reload];
kyle@4297
  1176
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1177
	{
kyle@4297
  1178
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1179
		{
skamonkey@3767
  1180
			continue;
kyle@4297
  1181
		}
skamonkey@3767
  1182
kyle@4297
  1183
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1184
		cell_t res = Pl_Continue;
kyle@4297
  1185
kyle@4297
  1186
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1187
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1188
		{
kyle@4297
  1189
			if (entity != pawnlist[entry].entity)
kyle@4297
  1190
			{
kyle@4297
  1191
				continue;
kyle@4297
  1192
			}
kyle@4297
  1193
kyle@4297
  1194
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1195
			callback->PushCell(entity);
kyle@4297
  1196
			callback->Execute(&res);
kyle@4297
  1197
		}
kyle@4297
  1198
kyle@4297
  1199
		if (res >= Pl_Handled)
kyle@4297
  1200
			RETURN_META_VALUE(MRES_SUPERCEDE, false);
kyle@4297
  1201
kyle@4297
  1202
		break;
skamonkey@3767
  1203
	}
skamonkey@3767
  1204
skamonkey@3767
  1205
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
  1206
}
skamonkey@3767
  1207
skamonkey@3767
  1208
bool SDKHooks::Hook_ReloadPost()
skamonkey@3767
  1209
{
kyle@4297
  1210
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1211
kyle@4297
  1212
	CVTableHook vhook(pEntity);
kyle@4297
  1213
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_Reload];
kyle@4297
  1214
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1215
	{
kyle@4297
  1216
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1217
		{
skamonkey@3767
  1218
			continue;
kyle@4297
  1219
		}
kyle@4297
  1220
kyle@4297
  1221
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1222
		cell_t origreturn = META_RESULT_ORIG_RET(bool) ? 1 : 0;
skamonkey@3767
  1223
kyle@4297
  1224
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1225
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1226
		{
kyle@4297
  1227
			if (entity != pawnlist[entry].entity)
kyle@4297
  1228
			{
kyle@4297
  1229
				continue;
kyle@4297
  1230
			}
kyle@4297
  1231
kyle@4297
  1232
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1233
			callback->PushCell(entity);
kyle@4297
  1234
			callback->PushCell(origreturn);
kyle@4297
  1235
			callback->Execute(NULL);
kyle@4297
  1236
		}
kyle@4297
  1237
kyle@4297
  1238
		break;
skamonkey@3767
  1239
	}
skamonkey@3767
  1240
skamonkey@3767
  1241
	return true;
skamonkey@3767
  1242
}
skamonkey@3767
  1243
skamonkey@3767
  1244
void SDKHooks::Hook_SetTransmit(CCheckTransmitInfo *pInfo, bool bAlways)
skamonkey@3767
  1245
{
skamonkey@3767
  1246
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_SetTransmit, gamehelpers->IndexOfEdict(pInfo->m_pClientEnt));
skamonkey@3767
  1247
skamonkey@3767
  1248
	if(result >= Pl_Handled)
skamonkey@3767
  1249
		RETURN_META(MRES_SUPERCEDE);
skamonkey@3767
  1250
skamonkey@3767
  1251
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1252
}
skamonkey@3767
  1253
skamonkey@3767
  1254
bool SDKHooks::Hook_ShouldCollide(int collisionGroup, int contentsMask)
skamonkey@3767
  1255
{
kyle@4297
  1256
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1257
kyle@4297
  1258
	CVTableHook vhook(pEntity);
kyle@4297
  1259
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_ShouldCollide];
kyle@4297
  1260
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1261
	{
kyle@4297
  1262
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1263
		{
skamonkey@3767
  1264
			continue;
kyle@4297
  1265
		}
kyle@4297
  1266
kyle@4297
  1267
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1268
		cell_t origRet = ((META_RESULT_STATUS >= MRES_OVERRIDE)?(META_RESULT_OVERRIDE_RET(bool)):(META_RESULT_ORIG_RET(bool))) ? 1 : 0;
kyle@4297
  1269
		cell_t res = 0;
skamonkey@3767
  1270
kyle@4297
  1271
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1272
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1273
		{
kyle@4297
  1274
			if (entity != pawnlist[entry].entity)
kyle@4297
  1275
			{
kyle@4297
  1276
				continue;
kyle@4297
  1277
			}
kyle@4297
  1278
kyle@4297
  1279
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1280
			callback->PushCell(entity);
kyle@4297
  1281
			callback->PushCell(collisionGroup);
kyle@4297
  1282
			callback->PushCell(contentsMask);
kyle@4297
  1283
			callback->PushCell(origRet);
kyle@4297
  1284
			callback->Execute(&res);
kyle@4297
  1285
		}
kyle@4297
  1286
kyle@4297
  1287
		bool ret = false;
kyle@4297
  1288
		if (res != 0)
kyle@4297
  1289
		{
kyle@4297
  1290
			ret = true;
kyle@4297
  1291
		}
kyle@4297
  1292
kyle@4297
  1293
		RETURN_META_VALUE(MRES_SUPERCEDE, ret);
skamonkey@3767
  1294
	}
skamonkey@3767
  1295
kyle@4297
  1296
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
  1297
}
skamonkey@3767
  1298
skamonkey@4180
  1299
#if SOURCE_ENGINE == SE_DOTA
skamonkey@4180
  1300
void SDKHooks::Hook_Spawn(CEntityKeyValues *kv)
skamonkey@4180
  1301
#else
skamonkey@3767
  1302
void SDKHooks::Hook_Spawn()
skamonkey@4180
  1303
#endif
skamonkey@3767
  1304
{
kyle@4297
  1305
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1306
kyle@4297
  1307
	CVTableHook vhook(pEntity);
kyle@4297
  1308
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_Spawn];
kyle@4297
  1309
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1310
	{
kyle@4297
  1311
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1312
		{
skamonkey@3767
  1313
			continue;
kyle@4297
  1314
		}
skamonkey@3767
  1315
kyle@4297
  1316
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1317
		cell_t res = Pl_Continue;
kyle@4297
  1318
kyle@4297
  1319
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1320
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1321
		{
kyle@4297
  1322
			if (entity != pawnlist[entry].entity)
kyle@4297
  1323
			{
kyle@4297
  1324
				continue;
kyle@4297
  1325
			}
kyle@4297
  1326
kyle@4297
  1327
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1328
			callback->PushCell(entity);
kyle@4297
  1329
			callback->Execute(&res);
kyle@4297
  1330
		}
kyle@4297
  1331
kyle@4297
  1332
		if (res >= Pl_Handled)
kyle@4297
  1333
			RETURN_META(MRES_SUPERCEDE);
kyle@4297
  1334
kyle@4297
  1335
		break;
skamonkey@3767
  1336
	}
skamonkey@3767
  1337
skamonkey@3767
  1338
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1339
}
skamonkey@3767
  1340
skamonkey@4180
  1341
#if SOURCE_ENGINE == SE_DOTA
skamonkey@4180
  1342
void SDKHooks::Hook_SpawnPost(CEntityKeyValues *kv)
skamonkey@4180
  1343
#else
skamonkey@3767
  1344
void SDKHooks::Hook_SpawnPost()
skamonkey@4180
  1345
#endif
skamonkey@3767
  1346
{
skamonkey@3767
  1347
	Call(META_IFACEPTR(CBaseEntity), SDKHook_SpawnPost);
skamonkey@3767
  1348
}
skamonkey@3767
  1349
skamonkey@3767
  1350
void SDKHooks::Hook_StartTouch(CBaseEntity *pOther)
skamonkey@3767
  1351
{
skamonkey@3767
  1352
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_StartTouch, pOther);
skamonkey@3767
  1353
	if(result >= Pl_Handled)
skamonkey@3767
  1354
		RETURN_META(MRES_SUPERCEDE);
skamonkey@3767
  1355
skamonkey@3767
  1356
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1357
}
skamonkey@3767
  1358
skamonkey@3767
  1359
void SDKHooks::Hook_StartTouchPost(CBaseEntity *pOther)
skamonkey@3767
  1360
{
skamonkey@3767
  1361
	Call(META_IFACEPTR(CBaseEntity), SDKHook_StartTouchPost, pOther);
skamonkey@3767
  1362
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1363
}
skamonkey@3767
  1364
skamonkey@3767
  1365
void SDKHooks::Hook_Think()
skamonkey@3767
  1366
{
skamonkey@3767
  1367
	Call(META_IFACEPTR(CBaseEntity), SDKHook_Think);
skamonkey@4214
  1368
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1369
}
skamonkey@3767
  1370
skamonkey@3767
  1371
void SDKHooks::Hook_ThinkPost()
skamonkey@3767
  1372
{
skamonkey@3767
  1373
	Call(META_IFACEPTR(CBaseEntity), SDKHook_ThinkPost);
skamonkey@3767
  1374
}
skamonkey@3767
  1375
skamonkey@3767
  1376
void SDKHooks::Hook_Touch(CBaseEntity *pOther)
skamonkey@3767
  1377
{
skamonkey@3767
  1378
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_Touch, pOther);
skamonkey@3767
  1379
skamonkey@3767
  1380
	if(result >= Pl_Handled)
skamonkey@3767
  1381
		RETURN_META(MRES_SUPERCEDE);
skamonkey@3767
  1382
skamonkey@3767
  1383
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1384
}
skamonkey@3767
  1385
skamonkey@3767
  1386
void SDKHooks::Hook_TouchPost(CBaseEntity *pOther)
skamonkey@3767
  1387
{
skamonkey@3767
  1388
	Call(META_IFACEPTR(CBaseEntity), SDKHook_TouchPost, pOther);
skamonkey@3767
  1389
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1390
}
skamonkey@3767
  1391
skamonkey@4281
  1392
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_SDK2013
skamonkey@4281
  1393
void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator)
skamonkey@3767
  1394
#else
skamonkey@3767
  1395
void SDKHooks::Hook_TraceAttack(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr)
skamonkey@3767
  1396
#endif
skamonkey@3767
  1397
{
kyle@4297
  1398
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1399
kyle@4297
  1400
	CVTableHook vhook(pEntity);
kyle@4297
  1401
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_TraceAttack];
kyle@4297
  1402
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1403
	{
kyle@4297
  1404
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1405
		{
skamonkey@3767
  1406
			continue;
kyle@4297
  1407
		}
skamonkey@3767
  1408
kyle@4297
  1409
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1410
		int attacker = info.GetAttacker();
kyle@4297
  1411
		int inflictor = info.GetInflictor();
kyle@4297
  1412
		float damage = info.GetDamage();
kyle@4297
  1413
		int damagetype = info.GetDamageType();
kyle@4297
  1414
		int ammotype = info.GetAmmoType();
kyle@4297
  1415
		cell_t res, ret = Pl_Continue;
kyle@4297
  1416
kyle@4297
  1417
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1418
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1419
		{
kyle@4297
  1420
			if (entity != pawnlist[entry].entity)
kyle@4297
  1421
			{
kyle@4297
  1422
				continue;
kyle@4297
  1423
			}
skamonkey@3767
  1424
kyle@4297
  1425
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1426
			callback->PushCell(entity);
kyle@4297
  1427
			callback->PushCellByRef(&attacker);
kyle@4297
  1428
			callback->PushCellByRef(&inflictor);
kyle@4297
  1429
			callback->PushFloatByRef(&damage);
kyle@4297
  1430
			callback->PushCellByRef(&damagetype);
kyle@4297
  1431
			callback->PushCellByRef(&ammotype);
kyle@4297
  1432
			callback->PushCell(ptr->hitbox);
kyle@4297
  1433
			callback->PushCell(ptr->hitgroup);
kyle@4297
  1434
			callback->Execute(&res);
skamonkey@3767
  1435
kyle@4297
  1436
			if(res > ret)
kyle@4297
  1437
			{
kyle@4297
  1438
				ret = res;
skamonkey@3767
  1439
kyle@4297
  1440
				if(ret == Pl_Changed)
kyle@4297
  1441
				{
kyle@4297
  1442
					CBaseEntity *pEntAttacker = gamehelpers->ReferenceToEntity(attacker);
kyle@4297
  1443
					if(!pEntAttacker)
kyle@4297
  1444
					{
kyle@4297
  1445
						callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Entity %d for attacker is invalid", attacker);
kyle@4297
  1446
						RETURN_META(MRES_IGNORED);
kyle@4297
  1447
					}
kyle@4297
  1448
					CBaseEntity *pEntInflictor = gamehelpers->ReferenceToEntity(inflictor);
kyle@4297
  1449
					if(!pEntInflictor)
kyle@4297
  1450
					{
kyle@4297
  1451
						callback->GetParentRuntime()->GetDefaultContext()->ThrowNativeError("Entity %d for inflictor is invalid", inflictor);
kyle@4297
  1452
						RETURN_META(MRES_IGNORED);
kyle@4297
  1453
					}
kyle@4297
  1454
					
kyle@4297
  1455
					info.SetAttacker(pEntAttacker);
kyle@4297
  1456
					info.SetInflictor(pEntInflictor);
kyle@4297
  1457
					info.SetDamage(damage);
kyle@4297
  1458
					info.SetDamageType(damagetype);
kyle@4297
  1459
					info.SetAmmoType(ammotype);
kyle@4297
  1460
				}
kyle@4297
  1461
			}
skamonkey@3767
  1462
		}
kyle@4297
  1463
kyle@4297
  1464
		if(ret >= Pl_Handled)
kyle@4297
  1465
			RETURN_META(MRES_SUPERCEDE);
skamonkey@3767
  1466
kyle@4297
  1467
		if(ret == Pl_Changed)
kyle@4297
  1468
			RETURN_META(MRES_HANDLED);
kyle@4297
  1469
kyle@4297
  1470
		break;
skamonkey@3767
  1471
	}
skamonkey@3767
  1472
skamonkey@3767
  1473
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1474
}
skamonkey@3767
  1475
skamonkey@4281
  1476
#if SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_SDK2013
skamonkey@4281
  1477
void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator)
skamonkey@3767
  1478
#else
skamonkey@3767
  1479
void SDKHooks::Hook_TraceAttackPost(CTakeDamageInfoHack &info, const Vector &vecDir, trace_t *ptr)
skamonkey@3767
  1480
#endif
skamonkey@3767
  1481
{
kyle@4297
  1482
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1483
kyle@4297
  1484
	CVTableHook vhook(pEntity);
kyle@4297
  1485
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_TraceAttackPost];
kyle@4297
  1486
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1487
	{
kyle@4297
  1488
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1489
		{
skamonkey@3767
  1490
			continue;
kyle@4297
  1491
		}
kyle@4297
  1492
kyle@4297
  1493
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
skamonkey@3767
  1494
kyle@4297
  1495
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1496
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1497
		{
kyle@4297
  1498
			if (entity != pawnlist[entry].entity)
kyle@4297
  1499
			{
kyle@4297
  1500
				continue;
kyle@4297
  1501
			}
kyle@4297
  1502
kyle@4297
  1503
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1504
			callback->PushCell(entity);
kyle@4297
  1505
			callback->PushCell(info.GetAttacker());
kyle@4297
  1506
			callback->PushCell(info.GetInflictor());
kyle@4297
  1507
			callback->PushFloat(info.GetDamage());
kyle@4297
  1508
			callback->PushCell(info.GetDamageType());
kyle@4297
  1509
			callback->PushCell(info.GetAmmoType());
kyle@4297
  1510
			callback->PushCell(ptr->hitbox);
kyle@4297
  1511
			callback->PushCell(ptr->hitgroup);
kyle@4297
  1512
			callback->Execute(NULL);
kyle@4297
  1513
		}
kyle@4297
  1514
kyle@4297
  1515
		break;
skamonkey@3767
  1516
	}
skamonkey@3767
  1517
skamonkey@3767
  1518
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1519
}
skamonkey@3767
  1520
skamonkey@3767
  1521
void SDKHooks::Hook_Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
skamonkey@3767
  1522
{
kyle@4297
  1523
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1524
kyle@4297
  1525
	CVTableHook vhook(pEntity);
kyle@4297
  1526
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_Use];
kyle@4297
  1527
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
kyle@4297
  1528
	{
kyle@4297
  1529
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1530
		{
kyle@4297
  1531
			continue;
kyle@4297
  1532
		}
skamonkey@3767
  1533
kyle@4297
  1534
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1535
		int activator = gamehelpers->EntityToBCompatRef(pActivator);
kyle@4297
  1536
		int caller = gamehelpers->EntityToBCompatRef(pCaller);
kyle@4297
  1537
		cell_t ret = Pl_Continue;
skamonkey@3767
  1538
kyle@4297
  1539
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1540
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1541
		{
kyle@4297
  1542
			if (entity != pawnlist[entry].entity)
kyle@4297
  1543
			{
kyle@4297
  1544
				continue;
kyle@4297
  1545
			}
kyle@4297
  1546
kyle@4297
  1547
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1548
			callback->PushCell(entity);
kyle@4297
  1549
			callback->PushCell(activator);
kyle@4297
  1550
			callback->PushCell(caller);
kyle@4297
  1551
			callback->PushCell(useType);
kyle@4297
  1552
			callback->PushFloat(value);
kyle@4297
  1553
			callback->Execute(&ret);
kyle@4297
  1554
		}
kyle@4297
  1555
kyle@4297
  1556
		if (ret >= Pl_Handled)
kyle@4297
  1557
			RETURN_META(MRES_SUPERCEDE);
kyle@4297
  1558
kyle@4297
  1559
		break;
skamonkey@3767
  1560
	}
skamonkey@3767
  1561
skamonkey@3767
  1562
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1563
}
skamonkey@3767
  1564
skamonkey@3767
  1565
void SDKHooks::Hook_UsePost(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value)
skamonkey@3767
  1566
{
kyle@4297
  1567
	CBaseEntity *pEntity = META_IFACEPTR(CBaseEntity);
skamonkey@3767
  1568
kyle@4297
  1569
	CVTableHook vhook(pEntity);
kyle@4297
  1570
	ke::Vector<CVTableList *> &vtablehooklist = g_HookList[SDKHook_UsePost];
kyle@4297
  1571
	for (size_t entry = 0; entry < vtablehooklist.length(); ++entry)
skamonkey@3767
  1572
	{
kyle@4297
  1573
		if (vhook != vtablehooklist[entry]->vtablehook)
kyle@4297
  1574
		{
skamonkey@3767
  1575
			continue;
kyle@4297
  1576
		}
kyle@4297
  1577
kyle@4297
  1578
		int entity = gamehelpers->EntityToBCompatRef(pEntity);
kyle@4297
  1579
		int activator = gamehelpers->EntityToBCompatRef(pActivator);
kyle@4297
  1580
		int caller = gamehelpers->EntityToBCompatRef(pCaller);
skamonkey@3767
  1581
kyle@4297
  1582
		ke::Vector<HookList> &pawnlist = vtablehooklist[entry]->hooks;
kyle@4297
  1583
		for (entry = 0; entry < pawnlist.length(); ++entry)
kyle@4297
  1584
		{
kyle@4297
  1585
			if (entity != pawnlist[entry].entity)
kyle@4297
  1586
			{
kyle@4297
  1587
				continue;
kyle@4297
  1588
			}
kyle@4297
  1589
kyle@4297
  1590
			IPluginFunction *callback = pawnlist[entry].callback;
kyle@4297
  1591
			callback->PushCell(entity);
kyle@4297
  1592
			callback->PushCell(activator);
kyle@4297
  1593
			callback->PushCell(caller);
kyle@4297
  1594
			callback->PushCell(useType);
kyle@4297
  1595
			callback->PushFloat(value);
kyle@4297
  1596
			callback->Execute(NULL);
kyle@4297
  1597
		}
kyle@4297
  1598
kyle@4297
  1599
		break;
skamonkey@3767
  1600
	}
skamonkey@3767
  1601
skamonkey@3767
  1602
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1603
}
skamonkey@3767
  1604
skamonkey@3767
  1605
void SDKHooks::OnEntityDeleted(CBaseEntity *pEntity)
skamonkey@3767
  1606
{
aangione@3971
  1607
	// Send OnEntityDestroyed to SM listeners
aangione@3971
  1608
	SourceHook::List<ISMEntityListener *>::iterator iter;
aangione@3971
  1609
	ISMEntityListener *pListener = NULL;
aangione@3971
  1610
	for (iter=m_EntListeners.begin(); iter!=m_EntListeners.end(); iter++)
aangione@3971
  1611
	{
aangione@3971
  1612
		pListener = (*iter);
aangione@3971
  1613
		pListener->OnEntityDestroyed(pEntity);
aangione@3971
  1614
	}
aangione@3971
  1615
skamonkey@3767
  1616
	int entity = gamehelpers->EntityToBCompatRef(pEntity);
skamonkey@3767
  1617
skamonkey@3767
  1618
	// Call OnEntityDestroyed forward
skamonkey@3767
  1619
	g_pOnEntityDestroyed->PushCell(entity);
skamonkey@3767
  1620
	g_pOnEntityDestroyed->Execute(NULL);
skamonkey@3767
  1621
	
kyle@4297
  1622
	Unhook(pEntity);
skamonkey@3767
  1623
skamonkey@3767
  1624
	m_EntityExists.Set(gamehelpers->ReferenceToIndex(entity), false);
skamonkey@3767
  1625
}
skamonkey@3767
  1626
skamonkey@3767
  1627
void SDKHooks::Hook_VPhysicsUpdate(IPhysicsObject *pPhysics)
skamonkey@3767
  1628
{
skamonkey@3767
  1629
	Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdate);
skamonkey@4214
  1630
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1631
}
skamonkey@3767
  1632
skamonkey@3767
  1633
void SDKHooks::Hook_VPhysicsUpdatePost(IPhysicsObject *pPhysics)
skamonkey@3767
  1634
{
skamonkey@3767
  1635
	Call(META_IFACEPTR(CBaseEntity), SDKHook_VPhysicsUpdatePost);
skamonkey@3767
  1636
}
skamonkey@3767
  1637
skamonkey@3767
  1638
bool SDKHooks::Hook_WeaponCanSwitchTo(CBaseCombatWeapon *pWeapon)
skamonkey@3767
  1639
{
skamonkey@3767
  1640
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchTo, pWeapon);
skamonkey@3767
  1641
skamonkey@3767
  1642
	if(result >= Pl_Handled)
skamonkey@3767
  1643
		RETURN_META_VALUE(MRES_SUPERCEDE, false);
skamonkey@3767
  1644
skamonkey@3767
  1645
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
  1646
}
skamonkey@3767
  1647
skamonkey@3767
  1648
bool SDKHooks::Hook_WeaponCanSwitchToPost(CBaseCombatWeapon *pWeapon)
skamonkey@3767
  1649
{
skamonkey@3767
  1650
	Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanSwitchToPost, pWeapon);
skamonkey@3767
  1651
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
  1652
}
skamonkey@3767
  1653
skamonkey@3767
  1654
bool SDKHooks::Hook_WeaponCanUse(CBaseCombatWeapon *pWeapon)
skamonkey@3767
  1655
{
skamonkey@3767
  1656
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanUse, pWeapon);
skamonkey@3767
  1657
skamonkey@3767
  1658
	if(result >= Pl_Handled)
skamonkey@3767
  1659
		RETURN_META_VALUE(MRES_SUPERCEDE, false);
skamonkey@3767
  1660
skamonkey@3767
  1661
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
  1662
}
skamonkey@3767
  1663
skamonkey@3767
  1664
bool SDKHooks::Hook_WeaponCanUsePost(CBaseCombatWeapon *pWeapon)
skamonkey@3767
  1665
{
skamonkey@3767
  1666
	Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponCanUsePost, pWeapon);
skamonkey@3767
  1667
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
  1668
}
skamonkey@3767
  1669
skamonkey@3767
  1670
void SDKHooks::Hook_WeaponDrop(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity)
skamonkey@3767
  1671
{
skamonkey@3767
  1672
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponDrop, pWeapon);
skamonkey@3767
  1673
skamonkey@3767
  1674
	if(result >= Pl_Handled)
skamonkey@3767
  1675
		RETURN_META(MRES_SUPERCEDE);
skamonkey@3767
  1676
skamonkey@3767
  1677
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1678
}
skamonkey@3767
  1679
skamonkey@3767
  1680
void SDKHooks::Hook_WeaponDropPost(CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity)
skamonkey@3767
  1681
{
skamonkey@3767
  1682
	Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponDropPost, pWeapon);
skamonkey@3767
  1683
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1684
}
skamonkey@3767
  1685
skamonkey@3767
  1686
void SDKHooks::Hook_WeaponEquip(CBaseCombatWeapon *pWeapon)
skamonkey@3767
  1687
{
skamonkey@3767
  1688
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponEquip, pWeapon);
skamonkey@3767
  1689
skamonkey@3767
  1690
	if(result >= Pl_Handled)
skamonkey@3767
  1691
		RETURN_META(MRES_SUPERCEDE);
skamonkey@3767
  1692
skamonkey@3767
  1693
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1694
}
skamonkey@3767
  1695
skamonkey@3767
  1696
void SDKHooks::Hook_WeaponEquipPost(CBaseCombatWeapon *pWeapon)
skamonkey@3767
  1697
{
skamonkey@3767
  1698
	Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponEquipPost, pWeapon);
skamonkey@3767
  1699
	RETURN_META(MRES_IGNORED);
skamonkey@3767
  1700
}
skamonkey@3767
  1701
skamonkey@3767
  1702
bool SDKHooks::Hook_WeaponSwitch(CBaseCombatWeapon *pWeapon, int viewmodelindex)
skamonkey@3767
  1703
{
skamonkey@3767
  1704
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponSwitch, pWeapon);
skamonkey@3767
  1705
skamonkey@3767
  1706
	if(result >= Pl_Handled)
skamonkey@3767
  1707
		RETURN_META_VALUE(MRES_SUPERCEDE, false);
skamonkey@3767
  1708
skamonkey@3767
  1709
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
  1710
}
skamonkey@3767
  1711
skamonkey@3767
  1712
bool SDKHooks::Hook_WeaponSwitchPost(CBaseCombatWeapon *pWeapon, int viewmodelindex)
skamonkey@3767
  1713
{
skamonkey@3767
  1714
	cell_t result = Call(META_IFACEPTR(CBaseEntity), SDKHook_WeaponSwitchPost, pWeapon);
skamonkey@3767
  1715
	RETURN_META_VALUE(MRES_IGNORED, true);
skamonkey@3767
  1716
}