From bcc798e165e5f3f2e06982e44d45c7fd51155849 Mon Sep 17 00:00:00 2001
From: Scott Ehlert <ds@alliedmods.net>
Date: Wed, 1 Aug 2007 07:18:58 +0000
Subject: [PATCH] Implemented amb584 - CGlobalEntityList support in SDKTools
 Also added FindEntityByClassname native to start this off

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401246
---
 extensions/sdktools/Makefile                  |  6 +-
 extensions/sdktools/extension.cpp             |  6 +-
 extensions/sdktools/gamerules.h               | 40 ---------
 extensions/sdktools/msvc8/sdktools.vcproj     | 16 ++--
 extensions/sdktools/vcallbuilder.cpp          |  5 +-
 extensions/sdktools/vcaller.cpp               | 13 ++-
 extensions/sdktools/vdecoder.h                |  1 +
 .../sdktools/{gamerules.cpp => vglobals.cpp}  | 90 +++++++++++--------
 extensions/sdktools/vglobals.h                | 32 +++++++
 extensions/sdktools/vnatives.cpp              | 58 ++++++++++--
 gamedata/sdktools.games.txt                   | 47 ++++++++++
 plugins/include/sdktools.inc                  |  1 +
 plugins/include/sdktools_functions.inc        | 11 +++
 13 files changed, 222 insertions(+), 104 deletions(-)
 delete mode 100644 extensions/sdktools/gamerules.h
 rename extensions/sdktools/{gamerules.cpp => vglobals.cpp} (51%)
 create mode 100644 extensions/sdktools/vglobals.h

diff --git a/extensions/sdktools/Makefile b/extensions/sdktools/Makefile
index 3023bc40..eb92d33c 100644
--- a/extensions/sdktools/Makefile
+++ b/extensions/sdktools/Makefile
@@ -14,9 +14,9 @@ PROJECT = sdktools
 #Uncomment for SourceMM-enabled extensions
 LINK_HL2 = $(HL2LIB)/tier1_i486.a $(HL2LIB)/mathlib_i486.a vstdlib_i486.so tier0_i486.so
 
-OBJECTS = sdk/smsdk_ext.cpp extension.cpp gamerules.cpp vdecoder.cpp vcallbuilder.cpp \
-	vcaller.cpp vnatives.cpp vsound.cpp tenatives.cpp trnatives.cpp tempents.cpp vstringtable.cpp \
-	vhelpers.cpp voice.cpp
+OBJECTS = sdk/smsdk_ext.cpp extension.cpp vdecoder.cpp vcallbuilder.cpp vcaller.cpp \
+	vnatives.cpp vsound.cpp tenatives.cpp trnatives.cpp tempents.cpp vstringtable.cpp \
+	vhelpers.cpp vglobals.cpp voice.cpp
 
 ##############################################
 ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
diff --git a/extensions/sdktools/extension.cpp b/extensions/sdktools/extension.cpp
index ea11b22c..eae9bd95 100644
--- a/extensions/sdktools/extension.cpp
+++ b/extensions/sdktools/extension.cpp
@@ -34,8 +34,8 @@
 #include "vcallbuilder.h"
 #include "vnatives.h"
 #include "vhelpers.h"
+#include "vglobals.h"
 #include "tempents.h"
-#include "gamerules.h"
 
 /**
  * @file extension.cpp
@@ -52,10 +52,10 @@ IBinTools *g_pBinTools = NULL;
 IGameConfig *g_pGameConf = NULL;
 IGameHelpers *g_pGameHelpers = NULL;
 IServerGameClients *serverClients = NULL;
+IVoiceServer *voiceserver = NULL;
 IPlayerInfoManager *playerinfomngr = NULL;
 HandleType_t g_CallHandle = 0;
 HandleType_t g_TraceHandle = 0;
-IVoiceServer *voiceserver = NULL;
 
 SMEXT_LINK(&g_SdkTools);
 
@@ -143,7 +143,7 @@ void SDKTools::SDK_OnAllLoaded()
 	SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
 
 	g_TEManager.Initialize();
-	InitializeGameRules();
+	InitializeValveGlobals();
 }
 
 bool SDKTools::QueryRunning(char *error, size_t maxlength)
diff --git a/extensions/sdktools/gamerules.h b/extensions/sdktools/gamerules.h
deleted file mode 100644
index e39801b2..00000000
--- a/extensions/sdktools/gamerules.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * vim: set ts=4 :
- * ================================================================
- * SourceMod SDKTools Extension
- * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
- * ================================================================
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of the GNU General Public License, 
- * version 3.0, as published by the Free Software Foundation.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, AlliedModders LLC gives you permission to 
- * link the code of this program (as well as its derivative works) to 
- * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
- * Game MODs that run on software by the Valve Corporation.  You must 
- * obey the GNU General Public License in all respects for all other 
- * code used. Additionally, AlliedModders LLC grants this exception 
- * to all derivative works. AlliedModders LLC defines further 
- * exceptions, found in LICENSE.txt (as of this writing, version 
- * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
- *
- * Version: $Id$
- */
-
-#ifndef _INCLUDE_SDKTOOLS_GAMERULES_H_
-#define _INCLUDE_SDKTOOLS_GAMERULES_H_
-
-extern void **g_pGameRules;
-
-void InitializeGameRules();
-
-#endif // _INCLUDE_SDKTOOLS_GAMERULES_H_
diff --git a/extensions/sdktools/msvc8/sdktools.vcproj b/extensions/sdktools/msvc8/sdktools.vcproj
index ba77f491..b218dd4f 100644
--- a/extensions/sdktools/msvc8/sdktools.vcproj
+++ b/extensions/sdktools/msvc8/sdktools.vcproj
@@ -187,10 +187,6 @@
 				RelativePath="..\extension.cpp"
 				>
 			</File>
-			<File
-				RelativePath="..\gamerules.cpp"
-				>
-			</File>
 			<File
 				RelativePath="..\tempents.cpp"
 				>
@@ -215,6 +211,10 @@
 				RelativePath="..\vdecoder.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\vglobals.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\vhelpers.cpp"
 				>
@@ -249,10 +249,6 @@
 				RelativePath="..\extension.h"
 				>
 			</File>
-			<File
-				RelativePath="..\gamerules.h"
-				>
-			</File>
 			<File
 				RelativePath="..\tempents.h"
 				>
@@ -265,6 +261,10 @@
 				RelativePath="..\vdecoder.h"
 				>
 			</File>
+			<File
+				RelativePath="..\vglobals.h"
+				>
+			</File>
 			<File
 				RelativePath="..\vhelpers.h"
 				>
diff --git a/extensions/sdktools/vcallbuilder.cpp b/extensions/sdktools/vcallbuilder.cpp
index 15ea6444..7288ba4e 100644
--- a/extensions/sdktools/vcallbuilder.cpp
+++ b/extensions/sdktools/vcallbuilder.cpp
@@ -156,10 +156,11 @@ ValveCall *CreateValveCall(void *addr,
 			thisinfo->flags = PASSFLAG_BYVAL;
 			thisinfo->decflags = 0;
 			break;
-		case ValveCall_GameRules:
+		default:
 			thisinfo->vtype = Valve_POD;
 			thisinfo->flags = PASSFLAG_ASPOINTER;
 			thisinfo->decflags = 0;
+			break;
 		}
 		thisinfo->encflags = 0;
 		thisinfo->offset = 0;
@@ -340,7 +341,7 @@ ValveCall *CreateValveVCall(unsigned int vtableIdx,
 		vc->thisinfo->flags = PASSFLAG_BYVAL;
 		vc->thisinfo->decflags = 0;
 		break;
-	case ValveCall_GameRules:
+	default:
 		vc->thisinfo->vtype = Valve_POD;
 		vc->thisinfo->flags = PASSFLAG_ASPOINTER;
 		vc->thisinfo->decflags = 0;
diff --git a/extensions/sdktools/vcaller.cpp b/extensions/sdktools/vcaller.cpp
index 5d0453dc..df7c38f6 100644
--- a/extensions/sdktools/vcaller.cpp
+++ b/extensions/sdktools/vcaller.cpp
@@ -32,7 +32,7 @@
 
 #include "extension.h"
 #include "vcallbuilder.h"
-#include "gamerules.h"
+#include "vglobals.h"
 
 enum SDKLibrary
 {
@@ -296,6 +296,17 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
 				*(void **)ptr = gamerules;
 			}
 			break;
+		case ValveCall_EntityList:
+			{
+				if (g_EntList == NULL)
+				{
+					vc->stk_put(ptr);
+					return pContext->ThrowNativeError("EntityList unsupported or not available; file a bug report");
+				}
+
+				*(void **)ptr = g_EntList;
+			}
+			break;
 		}
 	}
 
diff --git a/extensions/sdktools/vdecoder.h b/extensions/sdktools/vdecoder.h
index 4934f22b..34116d05 100644
--- a/extensions/sdktools/vdecoder.h
+++ b/extensions/sdktools/vdecoder.h
@@ -80,6 +80,7 @@ enum ValveCallType
 	ValveCall_Entity,		/**< Thiscall (CBaseEntity implicit first parameter) */
 	ValveCall_Player,		/**< Thiscall (CBasePlayer implicit first parameter) */
 	ValveCall_GameRules,	/**< Thiscall (CGameRules implicit first paramater) */
+	ValveCall_EntityList,	/**< Thiscall (CGlobalEntityList implicit first paramater) */
 };
 
 /**
diff --git a/extensions/sdktools/gamerules.cpp b/extensions/sdktools/vglobals.cpp
similarity index 51%
rename from extensions/sdktools/gamerules.cpp
rename to extensions/sdktools/vglobals.cpp
index 848754ec..35dcb58d 100644
--- a/extensions/sdktools/gamerules.cpp
+++ b/extensions/sdktools/vglobals.cpp
@@ -1,46 +1,38 @@
-/**
- * vim: set ts=4 :
- * ================================================================
- * SourceMod SDKTools Extension
- * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
- * ================================================================
- *
- * This program is free software; you can redistribute it and/or 
- * modify it under the terms of the GNU General Public License, 
- * version 3.0, as published by the Free Software Foundation.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * As a special exception, AlliedModders LLC gives you permission to 
- * link the code of this program (as well as its derivative works) to 
- * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
- * Game MODs that run on software by the Valve Corporation.  You must 
- * obey the GNU General Public License in all respects for all other 
- * code used. Additionally, AlliedModders LLC grants this exception 
- * to all derivative works. AlliedModders LLC defines further 
- * exceptions, found in LICENSE.txt (as of this writing, version 
- * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
- *
- * Version: $Id$
+/**
+ * vim: set ts=4 :
+ * ===============================================================
+ * SourceMod SDK Tools Extension
+ * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
+ * ===============================================================
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Version: $Id$
  */
 
 #include "extension.h"
 
 void **g_pGameRules = NULL;
-
-void InitializeGameRules()
-{
-	char *addr = NULL;
+void *g_EntList = NULL;
 
 #ifdef PLATFORM_WINDOWS
-	int offset = 0;
+void InitializeValveGlobals()
+{
+	char *addr = NULL;
+	int offset;
 
+	/* g_pGameRules */
 	if (!g_pGameConf->GetMemSig("CreateGameRulesObject", (void **)&addr) || !addr)
 	{
 		return;
@@ -49,14 +41,36 @@ void InitializeGameRules()
 	{
 		return;
 	}
-
 	g_pGameRules = *reinterpret_cast<void ***>(addr + offset);
+
+	/* gEntList and/or g_pEntityList */
+	if (!g_pGameConf->GetMemSig("LevelShutdown", (void **)&addr) || !addr)
+	{
+		return;
+	}
+	if (!g_pGameConf->GetOffset("gEntList", &offset) || !offset)
+	{
+		return;
+	}
+	g_EntList = *reinterpret_cast<void **>(addr + offset);
+}
 #elif defined PLATFORM_LINUX
+void InitializeValveGlobals()
+{
+	char *addr = NULL;
+
+	/* g_pGameRules */
 	if (!g_pGameConf->GetMemSig("g_pGameRules", (void **)&addr) || !addr)
 	{
 		return;
 	}
-
 	g_pGameRules = reinterpret_cast<void **>(addr);
-#endif
+
+	/* gEntList and/or g_pEntityList */
+	if (!g_pGameConf->GetMemSig("gEntList", (void **)&addr) || !addr)
+	{
+		return;
+	}
+	g_EntList = reinterpret_cast<void *>(addr);
 }
+#endif
diff --git a/extensions/sdktools/vglobals.h b/extensions/sdktools/vglobals.h
new file mode 100644
index 00000000..0b26c59a
--- /dev/null
+++ b/extensions/sdktools/vglobals.h
@@ -0,0 +1,32 @@
+/**
+ * vim: set ts=4 :
+ * ===============================================================
+ * SourceMod SDK Tools Extension
+ * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
+ * ===============================================================
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Version: $Id$
+ */
+
+#ifndef _INCLUDE_SDKTOOLS_VGLOBALS_H_
+#define _INCLUDE_SDKTOOLS_VGLOBALS_H_
+
+extern void **g_pGameRules;
+extern void *g_EntList;
+
+void InitializeValveGlobals();
+
+#endif // _INCLUDE_SDKTOOLS_VGLOBALS_H_
diff --git a/extensions/sdktools/vnatives.cpp b/extensions/sdktools/vnatives.cpp
index 13e3e277..ad9e8ed7 100644
--- a/extensions/sdktools/vnatives.cpp
+++ b/extensions/sdktools/vnatives.cpp
@@ -36,6 +36,7 @@
 #include "vcallbuilder.h"
 #include "vnatives.h"
 #include "vhelpers.h"
+#include "vglobals.h"
 #include "CellRecipientFilter.h"
 
 List<ValveCall *> g_RegCalls;
@@ -212,7 +213,7 @@ static cell_t GetPlayerWeaponSlot(IPluginContext *pContext, const cell_t *params
 	return engine->IndexOfEdict(pEdict);
 }
 
-static cell_t IgnitePlayer(IPluginContext *pContext, const cell_t *params)
+static cell_t IgniteEntity(IPluginContext *pContext, const cell_t *params)
 {
 	static ValveCall *pCall = NULL;
 	if (!pCall)
@@ -241,7 +242,7 @@ static cell_t IgnitePlayer(IPluginContext *pContext, const cell_t *params)
 	return 1;
 }
 
-static cell_t ExtinguishPlayer(IPluginContext *pContext, const cell_t *params)
+static cell_t ExtinguishEntity(IPluginContext *pContext, const cell_t *params)
 {
 	static ValveCall *pCall = NULL;
 	if (!pCall)
@@ -261,7 +262,7 @@ static cell_t ExtinguishPlayer(IPluginContext *pContext, const cell_t *params)
 	return 1;
 }
 
-static cell_t TeleportPlayer(IPluginContext *pContext, const cell_t *params)
+static cell_t TeleportEntity(IPluginContext *pContext, const cell_t *params)
 {
 	static ValveCall *pCall = NULL;
 	if (!pCall)
@@ -564,6 +565,44 @@ static cell_t GetClientEyeAngles(IPluginContext *pContext, const cell_t *params)
 	return 1;
 }
 
+static cell_t FindEntityByClassname(IPluginContext *pContext, const cell_t *params)
+{
+	static ValveCall *pCall = NULL;
+	if (!pCall)
+	{
+		ValvePassInfo pass[3];
+		InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL, VDECODE_FLAG_ALLOWNULL|VDECODE_FLAG_ALLOWWORLD);
+		InitPass(pass[1], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
+		InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
+		if (!CreateBaseCall("FindEntityByClassname", ValveCall_EntityList, &pass[2], pass, 2, &pCall))
+		{
+			return pContext->ThrowNativeError("\"FindEntityByClassname\" not supported by this mod");
+		} else if (!pCall) {
+			return pContext->ThrowNativeError("\"FindEntityByClassname\" wrapper failed to initialized");
+		}
+	}
+
+	CBaseEntity *pEntity;
+	START_CALL();
+	*(void **)vptr = g_EntList; 
+	DECODE_VALVE_PARAM(1, vparams, 0);
+	DECODE_VALVE_PARAM(2, vparams, 1);
+	FINISH_CALL_SIMPLE(&pEntity);
+
+	if (pEntity == NULL)
+	{
+		return -1;
+	}
+
+	edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
+	if (!pEdict)
+	{
+		return -1;
+	}
+
+	return engine->IndexOfEdict(pEdict);
+}
+
 static cell_t IsPlayerAlive(IPluginContext *pContext, const cell_t *params)
 {
 	IGamePlayer *player = playerhelpers->GetGamePlayer(params[1]);
@@ -600,21 +639,22 @@ static cell_t IsPlayerAlive(IPluginContext *pContext, const cell_t *params)
 
 sp_nativeinfo_t g_Natives[] = 
 {
-	{"ExtinguishPlayer",		ExtinguishPlayer},
-	{"ExtinguishEntity",		ExtinguishPlayer},
+	{"ExtinguishPlayer",		ExtinguishEntity},
+	{"ExtinguishEntity",		ExtinguishEntity},
 	{"ForcePlayerSuicide",		ForcePlayerSuicide},
 	{"GivePlayerItem",			GiveNamedItem},
 	{"GetPlayerWeaponSlot",		GetPlayerWeaponSlot},
-	{"IgnitePlayer",			IgnitePlayer},
-	{"IgniteEntity",			IgnitePlayer},
+	{"IgnitePlayer",			IgniteEntity},
+	{"IgniteEntity",			IgniteEntity},
 	{"RemovePlayerItem",		RemovePlayerItem},
-	{"TeleportPlayer",			TeleportPlayer},
-	{"TeleportEntity",			TeleportPlayer},
+	{"TeleportPlayer",			TeleportEntity},
+	{"TeleportEntity",			TeleportEntity},
 	{"SetClientViewEntity",		SetClientViewEntity},
 	{"SetLightStyle",			SetLightStyle},
 	{"SlapPlayer",				SlapPlayer},
 	{"GetClientEyePosition",	GetClientEyePosition},
 	{"GetClientEyeAngles",		GetClientEyeAngles},
+	{"FindEntityByClassname",	FindEntityByClassname},
 	{"IsPlayerAlive",			IsPlayerAlive},
 	{NULL,						NULL},
 };
diff --git a/gamedata/sdktools.games.txt b/gamedata/sdktools.games.txt
index 81cc68f9..d9e1910d 100644
--- a/gamedata/sdktools.games.txt
+++ b/gamedata/sdktools.games.txt
@@ -124,6 +124,53 @@
 			}
 		}
 	}
+	
+	/* CGlobalEntityList */
+	"#default"
+	{
+		"#supported"
+		{
+			"game"		"cstrike"
+			"game"		"dod"
+			"game"		"garrysmod"
+			"game"		"hl2mp"
+			"game"		"ship"
+			"game"		"!Insurgency"
+			"game"		"!Pirates, Vikings and Knights II"
+			"game"		"!SourceForts v1.9.2"
+		}
+		
+		"Offsets"
+		{
+			/* Offset into LevelShutdown */
+			"gEntList"
+			{
+				"windows"	"11"
+			}
+		}
+		
+		"Signatures"
+		{
+			"LevelShutdown"
+			{
+				"library"	"server"
+				"windows"	"\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xE8"
+			}
+			"gEntList"
+			{
+				"library"	"server"
+				"linux"		"@gEntList"
+			}
+			
+			/* Functions in CGlobalEntityList */
+			"FindEntityByClassname"
+			{
+				"library"	"server"
+				"windows"	"\x53\x55\x56\x8B\xF1\x8B\x4C\x24\x2A\x85\xC9\x57\x74\x2A\x8B\x01\xFF\x50\x2A\x8B\x08\x81\xE1\x2A\x2A\x2A\x2A\x83\xC1\x2A\xC1\xE1\x2A\x8B\x3C\x31\xEB\x2A\x8B\xBE\x2A\x2A\x2A\x2A\x85\xFF\x74\x2A\x8B\x5C\x24\x2A\x8B\x2D\x2A\x2A\x2A\x2A\x8D\x9B\x00\x00\x00\x00\x8B\x37\x85\xF6\x75\x2A\x68\x2A\x2A\x2A\x2A\xFF\x2A\x83\xC4\x2A\xEB\x2A\x39"
+				"linux"		"@_ZN17CGlobalEntityList21FindEntityByClassnameEP11CBaseEntityPKc"
+			}
+		}
+	}
 
 	/* Counter-Strike: Source */
 	"cstrike"
diff --git a/plugins/include/sdktools.inc b/plugins/include/sdktools.inc
index 272e5194..8664b91b 100644
--- a/plugins/include/sdktools.inc
+++ b/plugins/include/sdktools.inc
@@ -36,6 +36,7 @@ enum SDKCallType
 	SDKCall_Entity,		/**< CBaseEntity call */
 	SDKCall_Player,		/**< CBasePlayer call */
 	SDKCall_GameRules,	/**< CGameRules call */
+	SDKCall_EntityList,	/**< CGlobalEntityList call */ 
 };
 
 enum SDKLibrary
diff --git a/plugins/include/sdktools_functions.inc b/plugins/include/sdktools_functions.inc
index 6f2b8c55..f5687287 100644
--- a/plugins/include/sdktools_functions.inc
+++ b/plugins/include/sdktools_functions.inc
@@ -104,6 +104,17 @@ native ForcePlayerSuicide(client);
  */
 native SlapPlayer(client, health=5, bool:sound=true);
 
+/**
+ * Searches for an entity by classname.
+ *
+ * @param startEnt		The entity index to begin searching from.
+ *						Use -1 to start from the first entity.
+ * @param classname		Classname of the entity to find.
+ * @return				Entity index >= 0 if found, -1 otherwise.
+ * @error				Lack of mod support.
+ */
+native FindEntityByClassname(startEnt, const String:classname[]);
+
 /**
  * Returns the client's eye angles.
  *