diff --git a/extensions/sdktools/extension.cpp b/extensions/sdktools/extension.cpp
index 9a3a26b2..7afefba0 100644
--- a/extensions/sdktools/extension.cpp
+++ b/extensions/sdktools/extension.cpp
@@ -48,6 +48,7 @@
*/
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
+SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int);
SDKTools g_SdkTools; /**< Global singleton for extension's main interface */
IServerGameEnts *gameents = NULL;
@@ -73,6 +74,7 @@ extern sp_nativeinfo_t g_TRNatives[];
extern sp_nativeinfo_t g_StringTableNatives[];
extern sp_nativeinfo_t g_VoiceNatives[];
extern sp_nativeinfo_t g_EntInputNatives[];
+extern sp_nativeinfo_t g_TeamNatives[];
bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
{
@@ -85,6 +87,7 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
sharesys->AddNatives(myself, g_StringTableNatives);
sharesys->AddNatives(myself, g_VoiceNatives);
sharesys->AddNatives(myself, g_EntInputNatives);
+ sharesys->AddNatives(myself, g_TeamNatives);
SM_GET_IFACE(GAMEHELPERS, g_pGameHelpers);
@@ -103,6 +106,7 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
CONVAR_REGISTER(this);
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
+ SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &SDKTools::OnServerActivate, false);
MathLib_Init(2.2f, 2.2f, 0.0f, 2);
@@ -146,6 +150,7 @@ void SDKTools::SDK_OnUnload()
playerhelpers->RemoveClientListener(&g_SdkTools);
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SDKTools::LevelInit, true);
+ SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, gamedll, this, &SDKTools::OnServerActivate, false);
}
bool SDKTools::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
diff --git a/extensions/sdktools/extension.h b/extensions/sdktools/extension.h
index 81060576..2556a01f 100644
--- a/extensions/sdktools/extension.h
+++ b/extensions/sdktools/extension.h
@@ -82,6 +82,7 @@ public: // IVoiceServer
bool OnSetClientListening(int iReceiver, int iSender, bool bListen);
public:
bool LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
+ void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
};
extern SDKTools g_SdkTools;
diff --git a/extensions/sdktools/msvc8/sdktools.vcproj b/extensions/sdktools/msvc8/sdktools.vcproj
index 04c5ee9f..4eeee64a 100644
--- a/extensions/sdktools/msvc8/sdktools.vcproj
+++ b/extensions/sdktools/msvc8/sdktools.vcproj
@@ -680,6 +680,10 @@
RelativePath="..\inputnatives.cpp"
>
+
+
diff --git a/extensions/sdktools/teamnatives.cpp b/extensions/sdktools/teamnatives.cpp
new file mode 100644
index 00000000..a3de00f5
--- /dev/null
+++ b/extensions/sdktools/teamnatives.cpp
@@ -0,0 +1,171 @@
+/**
+ * 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 .
+ *
+ * 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 .
+ *
+ * Version: $Id$
+ */
+
+#include "extension.h"
+#include
+
+struct TeamInfo
+{
+ const char *ClassName;
+ CBaseEntity *pEnt;
+};
+
+SourceHook::CVector g_Teams;
+
+bool FindTeamEntities(SendTable *pTable, const char *name)
+{
+ int props = pTable->GetNumProps();
+ SendProp *prop;
+
+ for (int i=0; iGetProp(i);
+ if (prop->GetDataTable())
+ {
+ if (strcmp(prop->GetDataTable()->GetName(), name) == 0)
+ {
+ return true;
+ }
+ if (FindTeamEntities(prop->GetDataTable(), name))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void SDKTools::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
+{
+ g_Teams.clear();
+ g_Teams.resize(1);
+
+ for (int i=0; iPEntityOfEntIndex(i);
+ if (!pEdict || pEdict->IsFree())
+ {
+ continue;
+ }
+ if (!pEdict->GetNetworkable())
+ {
+ continue;
+ }
+
+ ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
+ if (FindTeamEntities(pClass->m_pTable, "DT_Team"))
+ {
+ static int offset = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum")->GetOffset();
+ CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
+ int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
+
+ if (TeamIndex >= (int)g_Teams.size())
+ {
+ g_Teams.resize(TeamIndex+1);
+ }
+ g_Teams[TeamIndex].ClassName = pClass->GetName();
+ g_Teams[TeamIndex].pEnt = pEnt;
+ }
+ }
+}
+
+static cell_t GetTeamCount(IPluginContext *pContext, const cell_t *params)
+{
+ return g_Teams.size();
+}
+
+static cell_t GetTeamName(IPluginContext *pContext, const cell_t *params)
+{
+ int teamindex = params[1];
+ if (teamindex > (int)g_Teams.size())
+ {
+ pContext->ThrowNativeError("Team index %d is invalid", teamindex);
+ }
+
+ static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_szTeamname")->GetOffset();
+ char *name = (char *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
+
+ pContext->StringToLocalUTF8(params[2], params[3], name, NULL);
+
+ return 1;
+}
+
+static cell_t GetTeamScore(IPluginContext *pContext, const cell_t *params)
+{
+ int teamindex = params[1];
+ if (teamindex > (int)g_Teams.size())
+ {
+ pContext->ThrowNativeError("Team index %d is invalid", teamindex);
+ }
+
+ static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
+
+ return *(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
+}
+
+static cell_t SetTeamScore(IPluginContext *pContext, const cell_t *params)
+{
+ int teamindex = params[1];
+ if (teamindex > (int)g_Teams.size())
+ {
+ pContext->ThrowNativeError("Team index %d is invalid", teamindex);
+ }
+
+ static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
+ *(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset) = params[2];
+
+ return 1;
+}
+
+static cell_t GetTeamClientCount(IPluginContext *pContext, const cell_t *params)
+{
+ int teamindex = params[1];
+ if (teamindex > (int)g_Teams.size())
+ {
+ pContext->ThrowNativeError("Team index %d is invalid", teamindex);
+ }
+
+ SendProp *pProp = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "\"player_array\"");
+ ArrayLengthSendProxyFn fn = pProp->GetArrayLengthProxy();
+
+ return fn(g_Teams[teamindex].pEnt, 0);
+}
+
+sp_nativeinfo_t g_TeamNatives[] =
+{
+ {"GetTeamCount", GetTeamCount},
+ {"GetTeamName", GetTeamName},
+ {"GetTeamScore", GetTeamScore},
+ {"SetTeamScore", SetTeamScore},
+ {"GetTeamClientCount", GetTeamClientCount},
+ {NULL, NULL}
+};
diff --git a/plugins/include/sdktools_functions.inc b/plugins/include/sdktools_functions.inc
index e126611c..3718bcae 100644
--- a/plugins/include/sdktools_functions.inc
+++ b/plugins/include/sdktools_functions.inc
@@ -217,6 +217,51 @@ native bool:DispatchKeyValueVector(entity, const String:keyName[], const Float:v
*/
native GetClientAimTarget(client, bool:only_clients=true);
+/**
+ * Returns the total number of teams in a game.
+ *
+ * @return Total number of teams.
+ */
+native GetTeamCount();
+
+/**
+ * Retrieves the team name based on a team index.
+ *
+ * @param index Team index.
+ * @param name Buffer to store string in.
+ * @param maxlength Maximum length of string buffer.
+ * @noreturn
+ * @error Invalid team index.
+ */
+native GetTeamName(index, String:name[], maxlength);
+
+/**
+ * Returns the score of a team based on a team index.
+ *
+ * @param index Team index.
+ * @return Score.
+ * @error Invalid team index.
+ */
+native GetTeamScore(index);
+
+/**
+ * Sets the score of a team based on a team index.
+ *
+ * @param index Team index.
+ * @return Score.
+ * @error Invalid team index.
+ */
+native SetTeamScore(index);
+
+/**
+ * Retrieves the number of players in a certain team.
+ *
+ * @param index Team index.
+ * @return Number of players in the team.
+ * @error Invalid team index.
+ */
+native GetTeamClientCount(index);
+
/**
* @deprecated
*/