extensions/sdktools/teamnatives.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Wed Aug 14 14:20:57 2013 -0400 (2013-08-14)
changeset 4008 490b01aa0683
parent 3948 530b0c5c8a33
permissions -rw-r--r--
Updated some CS:GO gamedata.
     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 "vhelpers.h"
    34 #include <sh_vector.h>
    35 
    36 struct TeamInfo
    37 {
    38 	const char *ClassName;
    39 	CBaseEntity *pEnt;
    40 };
    41 
    42 const char *m_iScore;
    43 
    44 SourceHook::CVector<TeamInfo> g_Teams;
    45 
    46 void InitTeamNatives()
    47 {
    48 	g_Teams.clear();
    49 	g_Teams.resize(1);
    50 
    51 	int edictCount = gpGlobals->maxEntities;
    52 
    53 	for (int i=0; i<edictCount; i++)
    54 	{
    55 		edict_t *pEdict = PEntityOfEntIndex(i);
    56 		if (!pEdict || pEdict->IsFree())
    57 		{
    58 			continue;
    59 		}
    60 		if (!pEdict->GetNetworkable())
    61 		{
    62 			continue;
    63 		}
    64 
    65 		ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
    66 		if (FindNestedDataTable(pClass->m_pTable, "DT_Team"))
    67 		{
    68 			SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
    69 
    70 			if (pTeamNumProp != NULL)
    71 			{
    72 				int offset = pTeamNumProp->GetOffset();
    73 				CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
    74 				int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
    75 
    76 				if (TeamIndex >= (int)g_Teams.size())
    77 				{
    78 					g_Teams.resize(TeamIndex+1);
    79 				}
    80 				g_Teams[TeamIndex].ClassName = pClass->GetName();
    81 				g_Teams[TeamIndex].pEnt = pEnt;
    82 			}
    83 		}
    84 	}
    85 }
    86 
    87 static cell_t GetTeamCount(IPluginContext *pContext, const cell_t *params)
    88 {
    89 	return g_Teams.size();
    90 }
    91 
    92 static int g_teamname_offset = -1;
    93 
    94 const char *tools_GetTeamName(int team)
    95 {
    96 	if (size_t(team) >= g_Teams.size())
    97 		return NULL;
    98 	if (g_teamname_offset == 0)
    99 		return NULL;
   100 	if (g_teamname_offset == -1)
   101 	{
   102 		SendProp *prop = g_pGameHelpers->FindInSendTable(g_Teams[team].ClassName, "m_szTeamname");
   103 		if (prop == NULL)
   104 		{
   105 			g_teamname_offset = 0;
   106 			return NULL;
   107 		}
   108 		g_teamname_offset = prop->GetOffset();
   109 	}
   110 
   111 	return (const char *)((unsigned char *)g_Teams[team].pEnt + g_teamname_offset);
   112 }
   113 
   114 static cell_t GetTeamName(IPluginContext *pContext, const cell_t *params)
   115 {
   116 	int teamindex = params[1];
   117 	if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
   118 		return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   119 
   120 	if (g_teamname_offset == 0)
   121 		return pContext->ThrowNativeError("Team names are not available on this game.");
   122 
   123 	const char *name = tools_GetTeamName(teamindex);
   124 	if (name == NULL)
   125 		return pContext->ThrowNativeError("Team names are not available on this game.");
   126 
   127 	pContext->StringToLocalUTF8(params[2], params[3], name, NULL);
   128 
   129 	return 1;
   130 }
   131 
   132 static cell_t GetTeamScore(IPluginContext *pContext, const cell_t *params)
   133 {
   134 	int teamindex = params[1];
   135 	if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
   136 	{
   137 		return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   138 	}
   139 
   140 	if (!m_iScore)
   141 	{
   142 		m_iScore = g_pGameConf->GetKeyValue("m_iScore");
   143 		if (!m_iScore)
   144 		{
   145 			return pContext->ThrowNativeError("Failed to get m_iScore key");
   146 		}
   147 	}
   148 
   149 	static int offset = -1;
   150 
   151 	if (offset == -1)
   152 	{
   153 		SendProp *prop = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, m_iScore);
   154 		if (!prop)
   155 		{
   156 			return pContext->ThrowNativeError("Failed to get m_iScore prop");
   157 		}
   158 		offset = prop->GetOffset();
   159 	}
   160 
   161 
   162 	return *(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
   163 }
   164 
   165 static cell_t SetTeamScore(IPluginContext *pContext, const cell_t *params)
   166 {
   167 	if (!g_pSM->IsMapRunning())
   168 	{
   169 		return pContext->ThrowNativeError("Cannot set team score when no map is running");
   170 	}
   171 	
   172 	int teamindex = params[1];
   173 	if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
   174 	{
   175 		return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   176 	}
   177 
   178 	if (m_iScore == NULL)
   179 	{
   180 		m_iScore = g_pGameConf->GetKeyValue("m_iScore");
   181 		if (m_iScore == NULL)
   182 		{
   183 			return pContext->ThrowNativeError("Failed to get m_iScore key");
   184 		}
   185 	}
   186 
   187 	static int offset = -1;
   188 
   189 	if (offset == -1)
   190 	{
   191 		SendProp *prop = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, m_iScore);
   192 		if (!prop)
   193 		{
   194 			return pContext->ThrowNativeError("Failed to get m_iScore prop");
   195 		}
   196 		offset = prop->GetOffset();
   197 	}
   198 
   199 	CBaseEntity *pTeam = g_Teams[teamindex].pEnt;
   200 	*(int *)((unsigned char *)pTeam + offset) = params[2];
   201 
   202 	edict_t *pEdict = gameents->BaseEntityToEdict(pTeam);
   203 	gamehelpers->SetEdictStateChanged(pEdict, offset);
   204 
   205 	return 1;
   206 }
   207 
   208 static cell_t GetTeamClientCount(IPluginContext *pContext, const cell_t *params)
   209 {
   210 	int teamindex = params[1];
   211 	if (teamindex >= (int)g_Teams.size() || !g_Teams[teamindex].ClassName)
   212 	{
   213 		return pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   214 	}
   215 
   216 	SendProp *pProp = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "\"player_array\"");
   217 	ArrayLengthSendProxyFn fn = pProp->GetArrayLengthProxy();
   218 
   219 	return fn(g_Teams[teamindex].pEnt, 0);
   220 }
   221 
   222 sp_nativeinfo_t g_TeamNatives[] = 
   223 {
   224 	{"GetTeamCount",			GetTeamCount},
   225 	{"GetTeamName",				GetTeamName},
   226 	{"GetTeamScore",			GetTeamScore},
   227 	{"SetTeamScore",			SetTeamScore},
   228 	{"GetTeamClientCount",		GetTeamClientCount},
   229 	{NULL,						NULL}
   230 };