3 * =============================================================================
4 * SourceMod SDKTools Extension
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "extension.h"
33 #include <sh_vector.h>
37 const char *ClassName;
41 SourceHook::CVector<TeamInfo> g_Teams;
43 bool FindTeamEntities(SendTable *pTable, const char *name)
45 if (strcmp(pTable->GetName(), name) == 0)
50 int props = pTable->GetNumProps();
53 for (int i=0; i<props; i++)
55 prop = pTable->GetProp(i);
56 if (prop->GetDataTable())
58 if (FindTeamEntities(prop->GetDataTable(), name))
68 void SDKTools::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
73 for (int i=0; i<edictCount; i++)
75 edict_t *pEdict = PEntityOfEntIndex(i);
76 if (!pEdict || pEdict->IsFree())
80 if (!pEdict->GetNetworkable())
85 ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
86 if (FindTeamEntities(pClass->m_pTable, "DT_Team"))
88 SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
90 if (pTeamNumProp != NULL)
92 int offset = pTeamNumProp->GetOffset();
93 CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
94 int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
96 if (TeamIndex >= (int)g_Teams.size())
98 g_Teams.resize(TeamIndex+1);
100 g_Teams[TeamIndex].ClassName = pClass->GetName();
101 g_Teams[TeamIndex].pEnt = pEnt;
107 static cell_t GetTeamCount(IPluginContext *pContext, const cell_t *params)
109 return g_Teams.size();
112 static int g_teamname_offset = -1;
114 const char *tools_GetTeamName(int team)
116 if (size_t(team) >= g_Teams.size())
118 if (g_teamname_offset == 0)
120 if (g_teamname_offset == -1)
122 SendProp *prop = g_pGameHelpers->FindInSendTable(g_Teams[team].ClassName, "m_szTeamname");
125 g_teamname_offset = 0;
128 g_teamname_offset = prop->GetOffset();
131 return (const char *)((unsigned char *)g_Teams[team].pEnt + g_teamname_offset);
134 static cell_t GetTeamName(IPluginContext *pContext, const cell_t *params)
136 int teamindex = params[1];
137 if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
138 return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
140 if (g_teamname_offset == 0)
141 return pContext->ThrowNativeError("Team names are not available on this game.");
143 const char *name = tools_GetTeamName(teamindex);
145 return pContext->ThrowNativeError("Team names are not available on this game.");
147 pContext->StringToLocalUTF8(params[2], params[3], name, NULL);
152 static cell_t GetTeamScore(IPluginContext *pContext, const cell_t *params)
154 int teamindex = params[1];
155 if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
157 return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
160 static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
162 return *(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
165 static cell_t SetTeamScore(IPluginContext *pContext, const cell_t *params)
167 int teamindex = params[1];
168 if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
170 return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
173 static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
175 CBaseEntity *pTeam = g_Teams[teamindex].pEnt;
176 *(int *)((unsigned char *)pTeam + offset) = params[2];
177 gamehelpers->SetEdictStateChanged(pTeam, offset);
182 static cell_t GetTeamClientCount(IPluginContext *pContext, const cell_t *params)
184 int teamindex = params[1];
185 if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
187 return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
190 SendProp *pProp = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "\"player_array\"");
191 ArrayLengthSendProxyFn fn = pProp->GetArrayLengthProxy();
193 return fn(g_Teams[teamindex].pEnt, 0);
196 sp_nativeinfo_t g_TeamNatives[] =
198 {"GetTeamCount", GetTeamCount},
199 {"GetTeamName", GetTeamName},
200 {"GetTeamScore", GetTeamScore},
201 {"SetTeamScore", SetTeamScore},
202 {"GetTeamClientCount", GetTeamClientCount},