extensions/sdktools/teamnatives.cpp
author David Anderson <dvander@alliedmods.net>
Wed Feb 25 20:07:12 2009 -0500 (2009-02-25)
changeset 2607 f3b8bbe17f85
parent 2289 44045ead61cd
child 2400 76b7b4575e21
permissions -rw-r--r--
Backed out changeset fa286305bd3f
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SDKTools Extension
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     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.
    11  *
    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
    15  * details.
    16  *
    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/>.
    19  *
    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>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "extension.h"
    33 #include <sh_vector.h>
    34 
    35 struct TeamInfo
    36 {
    37 	const char *ClassName;
    38 	CBaseEntity *pEnt;
    39 };
    40 
    41 SourceHook::CVector<TeamInfo> g_Teams;
    42 
    43 bool FindTeamEntities(SendTable *pTable, const char *name)
    44 {
    45 	if (strcmp(pTable->GetName(), name) == 0)
    46 	{
    47 		return true;
    48 	}
    49 
    50 	int props = pTable->GetNumProps();
    51 	SendProp *prop;
    52 
    53 	for (int i=0; i<props; i++)
    54 	{
    55 		prop = pTable->GetProp(i);
    56 		if (prop->GetDataTable())
    57 		{
    58 			if (FindTeamEntities(prop->GetDataTable(), name))
    59 			{
    60 				return true;
    61 			}
    62 		}
    63 	}
    64 
    65 	return false;
    66 }
    67 
    68 void SDKTools::OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax)
    69 {
    70 	g_Teams.clear();
    71 	g_Teams.resize(1);
    72 
    73 	for (int i=0; i<edictCount; i++)
    74 	{
    75 		edict_t *pEdict = engine->PEntityOfEntIndex(i);
    76 		if (!pEdict || pEdict->IsFree())
    77 		{
    78 			continue;
    79 		}
    80 		if (!pEdict->GetNetworkable())
    81 		{
    82 			continue;
    83 		}
    84 
    85 		ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
    86 		if (FindTeamEntities(pClass->m_pTable, "DT_Team"))
    87 		{
    88 			SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
    89 
    90 			if (pTeamNumProp != NULL)
    91 			{
    92 				int offset = pTeamNumProp->GetOffset();
    93 				CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
    94 				int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
    95 
    96 				if (TeamIndex >= (int)g_Teams.size())
    97 				{
    98 					g_Teams.resize(TeamIndex+1);
    99 				}
   100 				g_Teams[TeamIndex].ClassName = pClass->GetName();
   101 				g_Teams[TeamIndex].pEnt = pEnt;
   102 			}
   103 		}
   104 	}
   105 }
   106 
   107 static cell_t GetTeamCount(IPluginContext *pContext, const cell_t *params)
   108 {
   109 	return g_Teams.size();
   110 }
   111 
   112 static int g_teamname_offset = -1;
   113 static cell_t GetTeamName(IPluginContext *pContext, const cell_t *params)
   114 {
   115 	int teamindex = params[1];
   116 	if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
   117 	{
   118 		return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   119 	}
   120 
   121 	if (g_teamname_offset == 0)
   122 	{
   123 		return pContext->ThrowNativeError("Team names are not available on this game.");
   124 	}
   125 
   126 	if (g_teamname_offset == -1)
   127 	{
   128 		SendProp *prop = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_szTeamname");
   129 
   130 		if (prop == NULL)
   131 		{
   132 			g_teamname_offset = 0;
   133 			return pContext->ThrowNativeError("Team names are not available on this game.");
   134 		}
   135 
   136 		g_teamname_offset = prop->GetOffset();
   137 	}
   138 
   139 	char *name = (char *)((unsigned char *)g_Teams[teamindex].pEnt + g_teamname_offset);
   140 
   141 	pContext->StringToLocalUTF8(params[2], params[3], name, NULL);
   142 
   143 	return 1;
   144 }
   145 
   146 static cell_t GetTeamScore(IPluginContext *pContext, const cell_t *params)
   147 {
   148 	int teamindex = params[1];
   149 	if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
   150 	{
   151 		return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   152 	}
   153 
   154 	static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
   155 
   156 	return *(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
   157 }
   158 
   159 static cell_t SetTeamScore(IPluginContext *pContext, const cell_t *params)
   160 {
   161 	int teamindex = params[1];
   162 	if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
   163 	{
   164 		return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   165 	}
   166 
   167 	static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
   168 	*(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset) = params[2];
   169 
   170 	return 1;
   171 }
   172 
   173 static cell_t GetTeamClientCount(IPluginContext *pContext, const cell_t *params)
   174 {
   175 	int teamindex = params[1];
   176 	if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
   177 	{
   178 		return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   179 	}
   180 
   181 	SendProp *pProp = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "\"player_array\"");
   182 	ArrayLengthSendProxyFn fn = pProp->GetArrayLengthProxy();
   183 
   184 	return fn(g_Teams[teamindex].pEnt, 0);
   185 }
   186 
   187 sp_nativeinfo_t g_TeamNatives[] = 
   188 {
   189 	{"GetTeamCount",			GetTeamCount},
   190 	{"GetTeamName",				GetTeamName},
   191 	{"GetTeamScore",			GetTeamScore},
   192 	{"SetTeamScore",			SetTeamScore},
   193 	{"GetTeamClientCount",		GetTeamClientCount},
   194 	{NULL,						NULL}
   195 };