Added ability in SDKTools to get/set prop values on gamerules class (bug 4983, r=fyren).
authorNicholas Hastings <skamonkey@gmail.com>
Wed Jul 06 17:37:35 2011 -0400 (2011-07-06)
changeset 3333e247490894a1
parent 3332 e0af1cba759f
child 3334 7d8a28e7e38b
Added ability in SDKTools to get/set prop values on gamerules class (bug 4983, r=fyren).
extensions/sdktools/AMBuilder
extensions/sdktools/Makefile
extensions/sdktools/extension.cpp
extensions/sdktools/gamerulesnatives.cpp
extensions/sdktools/gamerulesnatives.h
extensions/sdktools/msvc10/sdktools.vcxproj
extensions/sdktools/msvc10/sdktools.vcxproj.filters
extensions/sdktools/vglobals.cpp
extensions/sdktools/vglobals.h
extensions/sdktools/vhelpers.cpp
gamedata/sdktools.games/engine.l4d.txt
gamedata/sdktools.games/engine.l4d2.txt
gamedata/sdktools.games/game.alienswarm.txt
gamedata/sdktools.games/game.cstrike.txt
gamedata/sdktools.games/game.dinodday.txt
gamedata/sdktools.games/game.dod.txt
gamedata/sdktools.games/game.tf.txt
plugins/include/sdktools.inc
plugins/include/sdktools_gamerules.inc
plugins/testsuite/gamerules-props.sp
     1.1 --- a/extensions/sdktools/AMBuilder	Wed Jul 06 17:37:35 2011 -0400
     1.2 +++ b/extensions/sdktools/AMBuilder	Wed Jul 06 17:37:35 2011 -0400
     1.3 @@ -39,6 +39,7 @@
     1.4  		'voice.cpp',
     1.5  		'vsound.cpp',
     1.6  		'hooks.cpp',
     1.7 +		'gamerulesnatives.cpp',
     1.8  		'vstringtable.cpp',
     1.9  		'CDetour/detours.cpp',
    1.10  		'sdk/smsdk_ext.cpp',
     2.1 --- a/extensions/sdktools/Makefile	Wed Jul 06 17:37:35 2011 -0400
     2.2 +++ b/extensions/sdktools/Makefile	Wed Jul 06 17:37:35 2011 -0400
     2.3 @@ -22,7 +22,7 @@
     2.4  OBJECTS = sdk/smsdk_ext.cpp extension.cpp vdecoder.cpp vcallbuilder.cpp vcaller.cpp \
     2.5  	vnatives.cpp vsound.cpp tenatives.cpp trnatives.cpp tempents.cpp vstringtable.cpp \
     2.6  	vhelpers.cpp vglobals.cpp voice.cpp inputnatives.cpp teamnatives.cpp output.cpp \
     2.7 -	outputnatives.cpp hooks.cpp CDetour/detours.cpp asm/asm.c
     2.8 +	outputnatives.cpp hooks.cpp gamerulesnatives.cpp CDetour/detours.cpp asm/asm.c
     2.9  
    2.10  ##############################################
    2.11  ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
     3.1 --- a/extensions/sdktools/extension.cpp	Wed Jul 06 17:37:35 2011 -0400
     3.2 +++ b/extensions/sdktools/extension.cpp	Wed Jul 06 17:37:35 2011 -0400
     3.3 @@ -40,6 +40,7 @@
     3.4  #include "vsound.h"
     3.5  #include "output.h"
     3.6  #include "hooks.h"
     3.7 +#include "gamerulesnatives.h"
     3.8  #include <ISDKTools.h>
     3.9  
    3.10  /**
    3.11 @@ -84,6 +85,7 @@
    3.12  extern sp_nativeinfo_t g_VoiceNatives[];
    3.13  extern sp_nativeinfo_t g_EntInputNatives[];
    3.14  extern sp_nativeinfo_t g_TeamNatives[];
    3.15 +extern sp_nativeinfo_t g_GameRulesNatives[];
    3.16  
    3.17  static void InitSDKToolsAPI();
    3.18  
    3.19 @@ -107,6 +109,7 @@
    3.20  	sharesys->AddNatives(myself, g_EntInputNatives);
    3.21  	sharesys->AddNatives(myself, g_TeamNatives);
    3.22  	sharesys->AddNatives(myself, g_EntOutputNatives);
    3.23 +	sharesys->AddNatives(myself, g_GameRulesNatives);
    3.24  
    3.25  	SM_GET_IFACE(GAMEHELPERS, g_pGameHelpers);
    3.26  
    3.27 @@ -154,6 +157,8 @@
    3.28  
    3.29  	GetIServer();
    3.30  
    3.31 +	GameRulesNativesInit();
    3.32 +
    3.33  	InitSDKToolsAPI();
    3.34  
    3.35  	return true;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/extensions/sdktools/gamerulesnatives.cpp	Wed Jul 06 17:37:35 2011 -0400
     4.3 @@ -0,0 +1,609 @@
     4.4 +/**
     4.5 + * vim: set ts=4 :
     4.6 + * =============================================================================
     4.7 + * SourceMod SDKTools Extension
     4.8 + * Copyright (C) 2004-2011 AlliedModders LLC.  All rights reserved.
     4.9 + * =============================================================================
    4.10 + *
    4.11 + * This program is free software; you can redistribute it and/or modify it under
    4.12 + * the terms of the GNU General Public License, version 3.0, as published by the
    4.13 + * Free Software Foundation.
    4.14 + * 
    4.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
    4.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    4.18 + * details.
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License along with
    4.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
    4.22 + *
    4.23 + * As a special exception, AlliedModders LLC gives you permission to link the
    4.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
    4.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    4.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
    4.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
    4.28 + * this exception to all derivative works.  AlliedModders LLC defines further
    4.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    4.30 + * or <http://www.sourcemod.net/license.php>.
    4.31 + *
    4.32 + * Version: $Id$
    4.33 + */
    4.34 +
    4.35 +#include "extension.h"
    4.36 +#include "gamerulesnatives.h"
    4.37 +#include "vglobals.h"
    4.38 +
    4.39 +const char *g_szGameRulesProxy;
    4.40 +
    4.41 +void GameRulesNativesInit()
    4.42 +{
    4.43 +	g_szGameRulesProxy = g_pGameConf->GetKeyValue("GameRulesProxy");
    4.44 +}
    4.45 +
    4.46 +static CBaseEntity *FindEntityByNetClass(int start, const char *classname)
    4.47 +{
    4.48 +	int maxEntities = gpGlobals->maxEntities;
    4.49 +	for (int i = start; i < maxEntities; i++)
    4.50 +	{
    4.51 +		edict_t *current = gamehelpers->EdictOfIndex(i);
    4.52 +		if (current == NULL)
    4.53 +			continue;
    4.54 +
    4.55 +		IServerNetworkable *network = current->GetNetworkable();
    4.56 +		if (network == NULL)
    4.57 +			continue;
    4.58 +
    4.59 +		ServerClass *sClass = network->GetServerClass();
    4.60 +		const char *name = sClass->GetName();
    4.61 +
    4.62 +		if (!strcmp(name, classname))
    4.63 +			return gamehelpers->ReferenceToEntity(gamehelpers->IndexOfEdict(current));		
    4.64 +	}
    4.65 +
    4.66 +	return NULL;
    4.67 +}
    4.68 +
    4.69 +static CBaseEntity* GetGameRulesProxyEnt()
    4.70 +{
    4.71 +	static cell_t proxyEntRef = -1;
    4.72 +	CBaseEntity *pProxy;
    4.73 +	if (proxyEntRef == -1 || (pProxy = gamehelpers->ReferenceToEntity(proxyEntRef)) == NULL)
    4.74 +	{
    4.75 +		pProxy = FindEntityByNetClass(playerhelpers->GetMaxClients(), g_szGameRulesProxy);
    4.76 +		proxyEntRef = gamehelpers->EntityToReference(pProxy);
    4.77 +	}
    4.78 +	
    4.79 +	return pProxy;
    4.80 +}
    4.81 +
    4.82 +enum PropFieldType
    4.83 +{
    4.84 +	PropField_Unsupported,		/**< The type is unsupported. */
    4.85 +	PropField_Integer,			/**< Valid for SendProp and Data fields */
    4.86 +	PropField_Float,			/**< Valid for SendProp and Data fields */
    4.87 +	PropField_Entity,			/**< Valid for Data fields only (SendProp shows as int) */
    4.88 +	PropField_Vector,			/**< Valid for SendProp and Data fields */
    4.89 +	PropField_String,			/**< Valid for SendProp and Data fields */
    4.90 +	PropField_String_T,			/**< Valid for Data fields.  Read only! */
    4.91 +};
    4.92 +
    4.93 +#define FIND_PROP_SEND(type, type_name) \
    4.94 +	sm_sendprop_info_t info;\
    4.95 +	if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info)) \
    4.96 +	{ \
    4.97 +		return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop); \
    4.98 +	} \
    4.99 +	\
   4.100 +	offset = info.actual_offset; \
   4.101 +	bit_count = info.prop->m_nBits; \
   4.102 +	\
   4.103 +	switch (info.prop->GetType()) \
   4.104 +	{ \
   4.105 +	case type: \
   4.106 +		{ \
   4.107 +			if (element > 0) \
   4.108 +			{ \
   4.109 +				return pContext->ThrowNativeError("SendProp %s is not an array. Element %d is invalid.", \
   4.110 +					prop, \
   4.111 +					element); \
   4.112 +			} \
   4.113 +			break; \
   4.114 +		} \
   4.115 +	case DPT_DataTable: \
   4.116 +		{ \
   4.117 +			SendProp *pProp; \
   4.118 +			FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name); \
   4.119 +			\
   4.120 +			offset += pProp->GetOffset(); \
   4.121 +			bit_count = pProp->m_nBits; \
   4.122 +			break; \
   4.123 +		} \
   4.124 +	default: \
   4.125 +		{ \
   4.126 +			return pContext->ThrowNativeError("SendProp %s type is not " type_name " (%d != %d)", \
   4.127 +				prop, \
   4.128 +				info.prop->GetType(), \
   4.129 +				type); \
   4.130 +		} \
   4.131 +	} \
   4.132 +
   4.133 +#define FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name) \
   4.134 +	SendTable *pTable = info.prop->GetDataTable(); \
   4.135 +	if (!pTable) \
   4.136 +	{ \
   4.137 +		return pContext->ThrowNativeError("Error looking up DataTable for prop %s", \
   4.138 +			prop); \
   4.139 +	} \
   4.140 +	\
   4.141 +	int elementCount = pTable->GetNumProps(); \
   4.142 +	if (element >= elementCount) \
   4.143 +	{ \
   4.144 +		return pContext->ThrowNativeError("Element %d is out of bounds (Prop %s has %d elements).", \
   4.145 +			element, \
   4.146 +			prop, \
   4.147 +			elementCount); \
   4.148 +	} \
   4.149 +	\
   4.150 +	pProp = pTable->GetProp(element); \
   4.151 +	if (pProp->GetType() != type) \
   4.152 +	{ \
   4.153 +		return pContext->ThrowNativeError("SendProp %s type is not " type_name " ([%d,%d] != %d)", \
   4.154 +			prop, \
   4.155 +			info.prop->GetType(), \
   4.156 +			info.prop->m_nBits, \
   4.157 +			type); \
   4.158 +	}
   4.159 +
   4.160 +static cell_t GameRules_GetProp(IPluginContext *pContext, const cell_t *params)
   4.161 +{
   4.162 +	char *prop;
   4.163 +	int element = params[3];
   4.164 +	int offset;
   4.165 +	int bit_count;
   4.166 +
   4.167 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.168 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.169 +
   4.170 +	pContext->LocalToString(params[1], &prop);
   4.171 +
   4.172 +	int elementCount = 1;
   4.173 +
   4.174 +	FIND_PROP_SEND(DPT_Int, "integer");
   4.175 +
	if (bit_count < 1)
   4.176 +	{
   4.177 +		bit_count = params[2] * 8;
   4.178 +	}
   4.179 +
   4.180 +	void *pGameRules = *g_pGameRules;
   4.181 +
   4.182 +	if (bit_count >= 17)
   4.183 +	{
   4.184 +		return *(int32_t *)((intptr_t)pGameRules + offset);
   4.185 +	}
   4.186 +	else if (bit_count >= 9)
   4.187 +	{
   4.188 +		return *(int16_t *)((intptr_t)pGameRules + offset);
   4.189 +	}
   4.190 +	else if (bit_count >= 2)
   4.191 +	{
   4.192 +		return *(int8_t *)((intptr_t)pGameRules + offset);
   4.193 +	}
   4.194 +	else
   4.195 +	{
   4.196 +		return *(bool *)((intptr_t)pGameRules + offset) ? 1 : 0;
   4.197 +	}
   4.198 +
   4.199 +	return -1;
   4.200 +}
   4.201 +
   4.202 +static cell_t GameRules_SetProp(IPluginContext *pContext, const cell_t *params)
   4.203 +{
   4.204 +	char *prop;
   4.205 +	int element = params[4];
   4.206 +	int offset;
   4.207 +	int bit_count;
   4.208 +
   4.209 +	bool sendChange = true;
   4.210 +	if (params[5] == 0)
   4.211 +		sendChange = false;
   4.212 +
   4.213 +	CBaseEntity *pProxy = NULL;
   4.214 +	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
   4.215 +		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity");
   4.216 +	
   4.217 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.218 +		return pContext->ThrowNativeError("Gamerules lookup failed");
   4.219 +
   4.220 +	pContext->LocalToString(params[1], &prop);
   4.221 +
   4.222 +	FIND_PROP_SEND(DPT_Int, "integer");
   4.223 +
   4.224 +	void *pGameRules = *g_pGameRules;
   4.225 +
   4.226 +	if (bit_count < 1)
   4.227 +	{
   4.228 +		bit_count = params[3] * 8;
   4.229 +	}
   4.230 +
   4.231 +	if (bit_count >= 17)
   4.232 +	{
   4.233 +		*(int32_t *)((intptr_t)pGameRules + offset) = params[2];
   4.234 +		if (sendChange)
   4.235 +		{
   4.236 +			*(int32_t *)((intptr_t)pProxy + offset) = params[2];
   4.237 +			gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
   4.238 +		}
   4.239 +	}
   4.240 +	else if (bit_count >= 9)
   4.241 +	{
   4.242 +		*(int16_t *)((intptr_t)pGameRules + offset) = (int16_t)params[2];
   4.243 +		if (sendChange)
   4.244 +		{
   4.245 +			*(int16_t *)((intptr_t)pProxy + offset) = (int16_t)params[2];
   4.246 +			gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
   4.247 +		}
   4.248 +	}
   4.249 +	else if (bit_count >= 2)
   4.250 +	{
   4.251 +		*(int8_t *)((intptr_t)pGameRules + offset) = (int8_t)params[2];
   4.252 +		if (sendChange)
   4.253 +		{
   4.254 +			*(int8_t *)((intptr_t)pProxy + offset) = (int8_t)params[2];
   4.255 +			gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
   4.256 +		}
   4.257 +	}
   4.258 +	else
   4.259 +	{
   4.260 +		*(bool *)((intptr_t)pGameRules + offset) = (params[2] == 0) ? false : true;
   4.261 +		if (sendChange)
   4.262 +		{
   4.263 +			*(bool *)((intptr_t)pProxy + offset) = (params[2] == 0) ? false : true;
   4.264 +			gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
   4.265 +		}
   4.266 +	}
   4.267 +
   4.268 +	return 0;
   4.269 +}
   4.270 +
   4.271 +static cell_t GameRules_GetPropFloat(IPluginContext *pContext, const cell_t *params)
   4.272 +{
   4.273 +	char *prop;
   4.274 +	int element = params[2];
   4.275 +	int offset;
   4.276 +	int bit_count;
   4.277 +
   4.278 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.279 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.280 +
   4.281 +	pContext->LocalToString(params[1], &prop);
   4.282 +
   4.283 +	FIND_PROP_SEND(DPT_Float, "float");
   4.284 +
   4.285 +	void *pGameRules = *g_pGameRules;
   4.286 +
   4.287 +	float val = *(float *)((intptr_t)pGameRules + offset);
   4.288 +
   4.289 +	return sp_ftoc(val);
   4.290 +}
   4.291 +
   4.292 +static cell_t GameRules_SetPropFloat(IPluginContext *pContext, const cell_t *params)
   4.293 +{
   4.294 +	char *prop;
   4.295 +	int element = params[3];
   4.296 +	int offset;
   4.297 +	int bit_count;
   4.298 +
   4.299 +	bool sendChange = true;
   4.300 +	if (params[4] == 0)
   4.301 +		sendChange = false;
   4.302 +
   4.303 +	CBaseEntity *pProxy = NULL;
   4.304 +	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
   4.305 +		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
   4.306 +	
   4.307 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.308 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.309 +
   4.310 +	pContext->LocalToString(params[1], &prop);
   4.311 +
   4.312 +	FIND_PROP_SEND(DPT_Float, "float");
   4.313 +
   4.314 +	void *pGameRules = *g_pGameRules;
   4.315 +	float newVal = sp_ctof(params[2]);
   4.316 +
   4.317 +	*(float *)((intptr_t)pGameRules + offset) = newVal;
   4.318 +
   4.319 +	if (sendChange)
   4.320 +	{
   4.321 +		*(float *)((intptr_t)pProxy + offset) = newVal;
   4.322 +		gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
   4.323 +	}
   4.324 +
   4.325 +	return 0;
   4.326 +}
   4.327 +
   4.328 +static cell_t GameRules_GetPropEnt(IPluginContext *pContext, const cell_t *params)
   4.329 +{
   4.330 +	char *prop;
   4.331 +	int element = params[2];
   4.332 +	int offset;
   4.333 +	int bit_count;
   4.334 +
   4.335 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.336 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.337 +
   4.338 +	pContext->LocalToString(params[1], &prop);
   4.339 +
   4.340 +	FIND_PROP_SEND(DPT_Int, "Integer");
   4.341 +
   4.342 +	void *pGameRules = *g_pGameRules;
   4.343 +
   4.344 +	CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pGameRules + offset);
   4.345 +
   4.346 +	int ref = gamehelpers->IndexToReference(hndl.GetEntryIndex());
   4.347 +	return gamehelpers->ReferenceToBCompatRef(ref);
   4.348 +}
   4.349 +
   4.350 +static cell_t GameRules_SetPropEnt(IPluginContext *pContext, const cell_t *params)
   4.351 +{
   4.352 +	char *prop;
   4.353 +	int element = params[3];
   4.354 +	int offset;
   4.355 +	int bit_count;
   4.356 +
   4.357 +	bool sendChange = true;
   4.358 +	if (params[4] == 0)
   4.359 +		sendChange = false;
   4.360 +
   4.361 +	CBaseEntity *pProxy = NULL;
   4.362 +	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
   4.363 +		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
   4.364 +	
   4.365 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.366 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.367 +
   4.368 +	pContext->LocalToString(params[1], &prop);
   4.369 +
   4.370 +	FIND_PROP_SEND(DPT_Int, "integer");
   4.371 +
   4.372 +	void *pGameRules = *g_pGameRules;
   4.373 +
   4.374 +	CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pGameRules + offset);
   4.375 +	CBaseEntity *pOther;
   4.376 +
   4.377 +	if (params[2] == -1)
   4.378 +	{
   4.379 +		hndl.Set(NULL);
   4.380 +	}
   4.381 +	else
   4.382 +	{
   4.383 +		pOther = gamehelpers->ReferenceToEntity(params[2]);
   4.384 +
   4.385 +		if (!pOther)
   4.386 +		{
   4.387 +			return pContext->ThrowNativeError("Entity %d (%d) is invalid", gamehelpers->ReferenceToIndex(params[4]), params[4]);
   4.388 +		}
   4.389 +
   4.390 +		IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
   4.391 +		hndl.Set(pHandleEnt);
   4.392 +	}
   4.393 +
   4.394 +	if (sendChange)
   4.395 +	{
   4.396 +		CBaseHandle &hndl = *(CBaseHandle *)((intptr_t)pProxy + offset);
   4.397 +		if (params[2] == -1)
   4.398 +		{
   4.399 +			hndl.Set(NULL);
   4.400 +		}
   4.401 +		else
   4.402 +		{
   4.403 +			IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
   4.404 +			hndl.Set(pHandleEnt);
   4.405 +		}
   4.406 +
   4.407 +		gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
   4.408 +	}
   4.409 +
   4.410 +	return 0;
   4.411 +}
   4.412 +
   4.413 +static cell_t GameRules_GetPropVector(IPluginContext *pContext, const cell_t *params)
   4.414 +{
   4.415 +	char *prop;
   4.416 +	int element = params[3];
   4.417 +	int offset;
   4.418 +	int bit_count;
   4.419 +
   4.420 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.421 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.422 +
   4.423 +	pContext->LocalToString(params[1], &prop);
   4.424 +
   4.425 +	FIND_PROP_SEND(DPT_Vector, "vector");
   4.426 +
   4.427 +	void *pGameRules = *g_pGameRules;
   4.428 +
   4.429 +	Vector *v = (Vector *)((intptr_t)pGameRules + offset);
   4.430 +
   4.431 +	cell_t *vec;
   4.432 +	pContext->LocalToPhysAddr(params[2], &vec);
   4.433 +
   4.434 +	vec[0] = sp_ftoc(v->x);
   4.435 +	vec[1] = sp_ftoc(v->y);
   4.436 +	vec[2] = sp_ftoc(v->z);
   4.437 +
   4.438 +	return 1;
   4.439 +}
   4.440 +
   4.441 +static cell_t GameRules_SetPropVector(IPluginContext *pContext, const cell_t *params)
   4.442 +{
   4.443 +	char *prop;
   4.444 +	int element = params[3];
   4.445 +	int offset;
   4.446 +	int bit_count;
   4.447 +
   4.448 +	bool sendChange = true;
   4.449 +	if (params[4] == 0)
   4.450 +		sendChange = false;
   4.451 +
   4.452 +	CBaseEntity *pProxy = NULL;
   4.453 +	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
   4.454 +		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
   4.455 +	
   4.456 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.457 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.458 +
   4.459 +	pContext->LocalToString(params[1], &prop);
   4.460 +
   4.461 +	FIND_PROP_SEND(DPT_Vector, "vector");
   4.462 +
   4.463 +	void *pGameRules = *g_pGameRules;
   4.464 +
   4.465 +	Vector *v = (Vector *)((intptr_t)pGameRules + offset);
   4.466 +
   4.467 +	cell_t *vec;
   4.468 +	pContext->LocalToPhysAddr(params[2], &vec);
   4.469 +
   4.470 +	v->x = sp_ctof(vec[0]);
   4.471 +	v->y = sp_ctof(vec[1]);
   4.472 +	v->z = sp_ctof(vec[2]);
   4.473 +
   4.474 +	if (sendChange)
   4.475 +	{
   4.476 +		v = (Vector *)((intptr_t)g_pGameRules + offset);
   4.477 +		v->x = sp_ctof(vec[0]);
   4.478 +		v->y = sp_ctof(vec[1]);
   4.479 +		v->z = sp_ctof(vec[2]);
   4.480 +
   4.481 +		gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
   4.482 +	}
   4.483 +
   4.484 +	return 1;
   4.485 +}
   4.486 +
   4.487 +static cell_t GameRules_GetPropString(IPluginContext *pContext, const cell_t *params)
   4.488 +{
   4.489 +	char *prop;
   4.490 +	int offset;
   4.491 +
   4.492 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.493 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.494 +
   4.495 +	pContext->LocalToString(params[1], &prop);
   4.496 +
   4.497 +	sm_sendprop_info_t info;
   4.498 +	if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info))
   4.499 +	{
   4.500 +		return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop);
   4.501 +	}
   4.502 +	
   4.503 +	offset = info.actual_offset;
   4.504 +	
   4.505 +	if (info.prop->GetType() != DPT_String)
   4.506 +	{
   4.507 +		return pContext->ThrowNativeError("SendProp %s type is not a string (%d != %d)",
   4.508 +				prop,
   4.509 +				info.prop->GetType(),
   4.510 +				DPT_String);
   4.511 +	}
   4.512 +
   4.513 +	void *pGameRules = *g_pGameRules;
   4.514 +
   4.515 +	size_t len;
   4.516 +	const char *src;
   4.517 +
   4.518 +	src = (char *)((intptr_t)pGameRules + offset);
   4.519 +
   4.520 +	pContext->StringToLocalUTF8(params[2], params[3], src, &len);
   4.521 +
   4.522 +	return len;
   4.523 +}
   4.524 +
   4.525 +// From sm_stringutil
   4.526 +inline int strncopy(char *dest, const char *src, size_t count)
   4.527 +{
   4.528 +	if (!count)
   4.529 +	{
   4.530 +		return 0;
   4.531 +	}
   4.532 +
   4.533 +	char *start = dest;
   4.534 +	while ((*src) && (--count))
   4.535 +	{
   4.536 +		*dest++ = *src++;
   4.537 +	}
   4.538 +	*dest = '\0';
   4.539 +
   4.540 +	return (dest - start);
   4.541 +}
   4.542 +//
   4.543 +
   4.544 +static cell_t GameRules_SetPropString(IPluginContext *pContext, const cell_t *params)
   4.545 +{
   4.546 +	char *prop;
   4.547 +	int offset;
   4.548 +	int maxlen;
   4.549 +
   4.550 +	bool sendChange = true;
   4.551 +	if (params[3] == 0)
   4.552 +		sendChange = false;
   4.553 +
   4.554 +	CBaseEntity *pProxy = NULL;
   4.555 +	if (sendChange && ((pProxy = GetGameRulesProxyEnt()) == NULL))
   4.556 +		return pContext->ThrowNativeError("Couldn't find gamerules proxy entity.");
   4.557 +	
   4.558 +	if (!g_pGameRules || !g_szGameRulesProxy || !strcmp(g_szGameRulesProxy, ""))
   4.559 +		return pContext->ThrowNativeError("Gamerules lookup failed.");
   4.560 +
   4.561 +	pContext->LocalToString(params[1], &prop);
   4.562 +
   4.563 +	sm_sendprop_info_t info;
   4.564 +	if (!gamehelpers->FindSendPropInfo(g_szGameRulesProxy, prop, &info))
   4.565 +	{
   4.566 +		return pContext->ThrowNativeError("Property \"%s\" not found on the gamerules proxy", prop);
   4.567 +	}
   4.568 +	
   4.569 +	offset = info.actual_offset;
   4.570 +	
   4.571 +	if (info.prop->GetType() != DPT_String)
   4.572 +	{
   4.573 +		return pContext->ThrowNativeError("SendProp %s type is not a string (%d != %d)",
   4.574 +				prop,
   4.575 +				info.prop->GetType(),
   4.576 +				DPT_String);
   4.577 +	}
   4.578 +
   4.579 +	void *pGameRules = *g_pGameRules;
   4.580 +	maxlen = DT_MAX_STRING_BUFFERSIZE;
   4.581 +
   4.582 +	char *src;
   4.583 +	char *dest = (char *)((intptr_t)pGameRules + offset);
   4.584 +
   4.585 +	pContext->LocalToString(params[2], &src);
   4.586 +	size_t len = strncopy(dest, src, maxlen);
   4.587 +
   4.588 +	if (sendChange)
   4.589 +	{
   4.590 +		dest = (char *)((intptr_t)pProxy + offset);
   4.591 +		strncopy(dest, src, maxlen);
   4.592 +		gamehelpers->SetEdictStateChanged(gamehelpers->EdictOfIndex(gamehelpers->EntityToBCompatRef(pProxy)), offset);
   4.593 +	}
   4.594 +
   4.595 +	return len;
   4.596 +}
   4.597 +
   4.598 +sp_nativeinfo_t g_GameRulesNatives[] = 
   4.599 +{
   4.600 +	{"GameRules_GetProp",			GameRules_GetProp},
   4.601 +	{"GameRules_SetProp",			GameRules_SetProp},
   4.602 +	{"GameRules_GetPropFloat",		GameRules_GetPropFloat},
   4.603 +	{"GameRules_SetPropFloat",		GameRules_SetPropFloat},
   4.604 +	{"GameRules_GetPropEnt",		GameRules_GetPropEnt},
   4.605 +	{"GameRules_SetPropEnt",		GameRules_SetPropEnt},
   4.606 +	{"GameRules_GetPropVector",		GameRules_GetPropVector},
   4.607 +	{"GameRules_SetPropVector",		GameRules_SetPropVector},
   4.608 +	{"GameRules_GetPropString",		GameRules_GetPropString},
   4.609 +	{"GameRules_SetPropString",		GameRules_SetPropString},
   4.610 +	{NULL,							NULL},
   4.611 +};
   4.612 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/extensions/sdktools/gamerulesnatives.h	Wed Jul 06 17:37:35 2011 -0400
     5.3 @@ -0,0 +1,44 @@
     5.4 +/**
     5.5 + * vim: set ts=4 :
     5.6 + * =============================================================================
     5.7 + * SourceMod SDKTools Extension
     5.8 + * Copyright (C) 2004-2011 AlliedModders LLC.  All rights reserved.
     5.9 + * =============================================================================
    5.10 + *
    5.11 + * This program is free software; you can redistribute it and/or modify it under
    5.12 + * the terms of the GNU General Public License, version 3.0, as published by the
    5.13 + * Free Software Foundation.
    5.14 + * 
    5.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
    5.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    5.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    5.18 + * details.
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License along with
    5.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
    5.22 + *
    5.23 + * As a special exception, AlliedModders LLC gives you permission to link the
    5.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
    5.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    5.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
    5.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
    5.28 + * this exception to all derivative works.  AlliedModders LLC defines further
    5.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    5.30 + * or <http://www.sourcemod.net/license.php>.
    5.31 + *
    5.32 + * Version: $Id$
    5.33 + */
    5.34 +
    5.35 +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_GRNATIVES_H_
    5.36 +#define _INCLUDE_SOURCEMOD_EXTENSION_GRNATIVES_H_
    5.37 +
    5.38 +/**
    5.39 + * @file gamerulesnatives.h
    5.40 + * @brief SDK Tools extension gamerules natives header.
    5.41 + */
    5.42 +
    5.43 +void GameRulesNativesInit();
    5.44 +
    5.45 +extern sp_nativeinfo_t g_GameRulesNatives[];
    5.46 +
    5.47 +#endif //_INCLUDE_SOURCEMOD_EXTENSION_GRNATIVES_H_
     6.1 --- a/extensions/sdktools/msvc10/sdktools.vcxproj	Wed Jul 06 17:37:35 2011 -0400
     6.2 +++ b/extensions/sdktools/msvc10/sdktools.vcxproj	Wed Jul 06 17:37:35 2011 -0400
     6.3 @@ -841,6 +841,7 @@
     6.4      <ClCompile Include="..\asm\asm.c" />
     6.5      <ClCompile Include="..\CDetour\detours.cpp" />
     6.6      <ClCompile Include="..\extension.cpp" />
     6.7 +    <ClCompile Include="..\gamerulesnatives.cpp" />
     6.8      <ClCompile Include="..\hooks.cpp" />
     6.9      <ClCompile Include="..\inputnatives.cpp" />
    6.10      <ClCompile Include="..\output.cpp" />
    6.11 @@ -863,6 +864,7 @@
    6.12    <ItemGroup>
    6.13      <ClInclude Include="..\CellRecipientFilter.h" />
    6.14      <ClInclude Include="..\extension.h" />
    6.15 +    <ClInclude Include="..\gamerulesnatives.h" />
    6.16      <ClInclude Include="..\hooks.h" />
    6.17      <ClInclude Include="..\..\..\public\extensions\ISDKTools.h" />
    6.18      <ClInclude Include="..\output.h" />
     7.1 --- a/extensions/sdktools/msvc10/sdktools.vcxproj.filters	Wed Jul 06 17:37:35 2011 -0400
     7.2 +++ b/extensions/sdktools/msvc10/sdktools.vcxproj.filters	Wed Jul 06 17:37:35 2011 -0400
     7.3 @@ -81,6 +81,9 @@
     7.4      <ClCompile Include="..\sdk\smsdk_ext.cpp">
     7.5        <Filter>SourceMod SDK</Filter>
     7.6      </ClCompile>
     7.7 +    <ClCompile Include="..\gamerulesnatives.cpp">
     7.8 +      <Filter>Source Files</Filter>
     7.9 +    </ClCompile>
    7.10    </ItemGroup>
    7.11    <ItemGroup>
    7.12      <ClInclude Include="..\CellRecipientFilter.h">
    7.13 @@ -125,5 +128,8 @@
    7.14      <ClInclude Include="..\sdk\smsdk_ext.h">
    7.15        <Filter>SourceMod SDK</Filter>
    7.16      </ClInclude>
    7.17 +    <ClInclude Include="..\gamerulesnatives.h">
    7.18 +      <Filter>Header Files</Filter>
    7.19 +    </ClInclude>
    7.20    </ItemGroup>
    7.21  </Project>
    7.22 \ No newline at end of file
     8.1 --- a/extensions/sdktools/vglobals.cpp	Wed Jul 06 17:37:35 2011 -0400
     8.2 +++ b/extensions/sdktools/vglobals.cpp	Wed Jul 06 17:37:35 2011 -0400
     8.3 @@ -182,3 +182,40 @@
     8.4  	iserver = reinterpret_cast<IServer *>(addr);
     8.5  }
     8.6  #endif
     8.7 +
     8.8 +const char *GetDTTypeName(int type)
     8.9 +{
    8.10 +	switch (type)
    8.11 +	{
    8.12 +	case DPT_Int:
    8.13 +		{
    8.14 +			return "integer";
    8.15 +		}
    8.16 +	case DPT_Float:
    8.17 +		{
    8.18 +			return "float";
    8.19 +		}
    8.20 +	case DPT_Vector:
    8.21 +		{
    8.22 +			return "vector";
    8.23 +		}
    8.24 +	case DPT_String:
    8.25 +		{
    8.26 +			return "string";
    8.27 +		}
    8.28 +	case DPT_Array:
    8.29 +		{
    8.30 +			return "array";
    8.31 +		}
    8.32 +	case DPT_DataTable:
    8.33 +		{
    8.34 +			return "datatable";
    8.35 +		}
    8.36 +	default:
    8.37 +		{
    8.38 +			return NULL;
    8.39 +		}
    8.40 +	}
    8.41 +
    8.42 +	return NULL;
    8.43 +}
     9.1 --- a/extensions/sdktools/vglobals.h	Wed Jul 06 17:37:35 2011 -0400
     9.2 +++ b/extensions/sdktools/vglobals.h	Wed Jul 06 17:37:35 2011 -0400
     9.3 @@ -38,4 +38,6 @@
     9.4  void InitializeValveGlobals();
     9.5  void GetIServer();
     9.6  
     9.7 +const char *GetDTTypeName(int type);
     9.8 +
     9.9  #endif // _INCLUDE_SDKTOOLS_VGLOBALS_H_
    10.1 --- a/extensions/sdktools/vhelpers.cpp	Wed Jul 06 17:37:35 2011 -0400
    10.2 +++ b/extensions/sdktools/vhelpers.cpp	Wed Jul 06 17:37:35 2011 -0400
    10.3 @@ -32,6 +32,7 @@
    10.4  #include "extension.h"
    10.5  #include "util.h"
    10.6  #include "vhelpers.h"
    10.7 +#include "vglobals.h"
    10.8  
    10.9  CallHelper s_Teleport;
   10.10  CallHelper s_GetVelocity;
   10.11 @@ -278,43 +279,6 @@
   10.12  	s_EyeAngles.Shutdown();
   10.13  }
   10.14  
   10.15 -const char *GetDTTypeName(int type)
   10.16 -{
   10.17 -	switch (type)
   10.18 -	{
   10.19 -	case DPT_Int:
   10.20 -		{
   10.21 -			return "integer";
   10.22 -		}
   10.23 -	case DPT_Float:
   10.24 -		{
   10.25 -			return "float";
   10.26 -		}
   10.27 -	case DPT_Vector:
   10.28 -		{
   10.29 -			return "vector";
   10.30 -		}
   10.31 -	case DPT_String:
   10.32 -		{
   10.33 -			return "string";
   10.34 -		}
   10.35 -	case DPT_Array:
   10.36 -		{
   10.37 -			return "array";
   10.38 -		}
   10.39 -	case DPT_DataTable:
   10.40 -		{
   10.41 -			return "datatable";
   10.42 -		}
   10.43 -	default:
   10.44 -		{
   10.45 -			return NULL;
   10.46 -		}
   10.47 -	}
   10.48 -
   10.49 -	return NULL;
   10.50 -}
   10.51 -
   10.52  void UTIL_DrawSendTable_XML(FILE *fp, SendTable *pTable, int space_count)
   10.53  {
   10.54  	char spaces[255];
    11.1 --- a/gamedata/sdktools.games/engine.l4d.txt	Wed Jul 06 17:37:35 2011 -0400
    11.2 +++ b/gamedata/sdktools.games/engine.l4d.txt	Wed Jul 06 17:37:35 2011 -0400
    11.3 @@ -19,6 +19,8 @@
    11.4  			"SlapSoundCount"	"2"
    11.5  			"SlapSound1"		"player/damage1.wav"
    11.6  			"SlapSound2"		"player/damage2.wav"
    11.7 +			
    11.8 +			"GameRulesProxy"	"CTerrorGameRulesProxy"
    11.9  		}
   11.10  	}
   11.11  	
    12.1 --- a/gamedata/sdktools.games/engine.l4d2.txt	Wed Jul 06 17:37:35 2011 -0400
    12.2 +++ b/gamedata/sdktools.games/engine.l4d2.txt	Wed Jul 06 17:37:35 2011 -0400
    12.3 @@ -19,6 +19,8 @@
    12.4  			"SlapSoundCount"	"2"
    12.5  			"SlapSound1"		"player/damage1.wav"
    12.6  			"SlapSound2"		"player/damage2.wav"
    12.7 +			
    12.8 +			"GameRulesProxy"	"CTerrorGameRulesProxy"
    12.9  		}
   12.10  	}
   12.11  	
    13.1 --- a/gamedata/sdktools.games/game.alienswarm.txt	Wed Jul 06 17:37:35 2011 -0400
    13.2 +++ b/gamedata/sdktools.games/game.alienswarm.txt	Wed Jul 06 17:37:35 2011 -0400
    13.3 @@ -42,5 +42,10 @@
    13.4  				"windows"	"442"
    13.5  			}
    13.6  		}
    13.7 +		
    13.8 +		"Keys"
    13.9 +		{
   13.10 +			"GameRulesProxy"	"CAlienSwarmProxy"
   13.11 +		}
   13.12  	}
   13.13  }
   13.14 \ No newline at end of file
    14.1 --- a/gamedata/sdktools.games/game.cstrike.txt	Wed Jul 06 17:37:35 2011 -0400
    14.2 +++ b/gamedata/sdktools.games/game.cstrike.txt	Wed Jul 06 17:37:35 2011 -0400
    14.3 @@ -20,6 +20,8 @@
    14.4  			"SlapSound1"		"player/damage1.wav"
    14.5  			"SlapSound2"		"player/damage2.wav"
    14.6  			"SlapSound3"		"player/damage3.wav"
    14.7 +			
    14.8 +			"GameRulesProxy"	"CCSGameRulesProxy"
    14.9  		}
   14.10  
   14.11  		"Offsets"
    15.1 --- a/gamedata/sdktools.games/game.dinodday.txt	Wed Jul 06 17:37:35 2011 -0400
    15.2 +++ b/gamedata/sdktools.games/game.dinodday.txt	Wed Jul 06 17:37:35 2011 -0400
    15.3 @@ -62,5 +62,10 @@
    15.4  				"windows"	"442"
    15.5  			}
    15.6  		}
    15.7 +		
    15.8 +		"Keys"
    15.9 +		{
   15.10 +			"GameRulesProxy"	"CDDDGameRulesProxy"
   15.11 +		}
   15.12  	}
   15.13  }
   15.14 \ No newline at end of file
    16.1 --- a/gamedata/sdktools.games/game.dod.txt	Wed Jul 06 17:37:35 2011 -0400
    16.2 +++ b/gamedata/sdktools.games/game.dod.txt	Wed Jul 06 17:37:35 2011 -0400
    16.3 @@ -101,5 +101,10 @@
    16.4  				"mac"		"408"
    16.5  			}
    16.6  		}
    16.7 +		
    16.8 +		"Keys"
    16.9 +		{
   16.10 +			"GameRulesProxy"	"CDODGameRulesProxy"
   16.11 +		}
   16.12  	}
   16.13  }
    17.1 --- a/gamedata/sdktools.games/game.tf.txt	Wed Jul 06 17:37:35 2011 -0400
    17.2 +++ b/gamedata/sdktools.games/game.tf.txt	Wed Jul 06 17:37:35 2011 -0400
    17.3 @@ -101,5 +101,10 @@
    17.4  				"mac"		"408"
    17.5  			}
    17.6  		}
    17.7 +		
    17.8 +		"Keys"
    17.9 +		{
   17.10 +			"GameRulesProxy"	"CTFGameRulesProxy"
   17.11 +		}
   17.12  	}
   17.13  }
    18.1 --- a/plugins/include/sdktools.inc	Wed Jul 06 17:37:35 2011 -0400
    18.2 +++ b/plugins/include/sdktools.inc	Wed Jul 06 17:37:35 2011 -0400
    18.3 @@ -49,6 +49,7 @@
    18.4  #include <sdktools_entinput>
    18.5  #include <sdktools_entoutput>
    18.6  #include <sdktools_hooks>
    18.7 +#include <sdktools_gamerules>
    18.8  
    18.9  enum SDKCallType
   18.10  {
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/plugins/include/sdktools_gamerules.inc	Wed Jul 06 17:37:35 2011 -0400
    19.3 @@ -0,0 +1,194 @@
    19.4 +/**
    19.5 + * vim: set ts=4 :
    19.6 + * =============================================================================
    19.7 + * SourceMod (C)2004-2011 AlliedModders LLC.  All rights reserved.
    19.8 + * =============================================================================
    19.9 + *
   19.10 + * This file is part of the SourceMod/SourcePawn SDK.
   19.11 + *
   19.12 + * This program is free software; you can redistribute it and/or modify it under
   19.13 + * the terms of the GNU General Public License, version 3.0, as published by the
   19.14 + * Free Software Foundation.
   19.15 + * 
   19.16 + * This program is distributed in the hope that it will be useful, but WITHOUT
   19.17 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   19.18 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
   19.19 + * details.
   19.20 + *
   19.21 + * You should have received a copy of the GNU General Public License along with
   19.22 + * this program.  If not, see <http://www.gnu.org/licenses/>.
   19.23 + *
   19.24 + * As a special exception, AlliedModders LLC gives you permission to link the
   19.25 + * code of this program (as well as its derivative works) to "Half-Life 2," the
   19.26 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
   19.27 + * by the Valve Corporation.  You must obey the GNU General Public License in
   19.28 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
   19.29 + * this exception to all derivative works.  AlliedModders LLC defines further
   19.30 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
   19.31 + * or <http://www.sourcemod.net/license.php>.
   19.32 + *
   19.33 + * Version: $Id$
   19.34 + */
   19.35 +
   19.36 +#if defined _sdktools_gamerules_included
   19.37 +  #endinput
   19.38 +#endif
   19.39 +#define _sdktools_gamerules_included
   19.40 +
   19.41 +enum RoundState {
   19.42 +	// initialize the game, create teams
   19.43 +	RoundState_Init,
   19.44 +	
   19.45 +	//Before players have joined the game. Periodically checks to see if enough players are ready
   19.46 +	//to start a game. Also reverts to this when there are no active players
   19.47 +	RoundState_Pregame,
   19.48 +	
   19.49 +	//The game is about to start, wait a bit and spawn everyone
   19.50 +	RoundState_StartGame,
   19.51 +	
   19.52 +	//All players are respawned, frozen in place
   19.53 +	RoundState_Preround,
   19.54 +	
   19.55 +	//Round is on, playing normally
   19.56 +	RoundState_RoundRunning,
   19.57 +	
   19.58 +	//Someone has won the round
   19.59 +	RoundState_TeamWin,
   19.60 +	
   19.61 +	//Noone has won, manually restart the game, reset scores
   19.62 +	RoundState_Restart,
   19.63 +	
   19.64 +	//Noone has won, restart the game
   19.65 +	RoundState_Stalemate,
   19.66 +	
   19.67 +	//Game is over, showing the scoreboard etc
   19.68 +	RoundState_GameOver,
   19.69 +	
   19.70 +	//Game is over, doing bonus round stuff
   19.71 +	RoundState_Bonus,
   19.72 +};
   19.73 +
   19.74 +/**
   19.75 + * Retrieves an integer value from a property of the gamerules entity.
   19.76 + * 
   19.77 + * @param prop			Property name.
   19.78 + * @param size			Number of bytes to read (valid values are 1, 2, or 4).
   19.79 + *						This value is auto-detected, and the size parameter is 
   19.80 + *						only used as a fallback in case detection fails.
   19.81 + * @param element		Element # (starting from 0) if property is an array.
   19.82 + * @return				Value at the given property offset.
   19.83 + * @error				Not supported.
   19.84 + */
   19.85 +native GameRules_GetProp(const String:prop[], size=4, element=0);
   19.86 +
   19.87 +/**
   19.88 + * Sets an integer value for a property of the gamerules entity.
   19.89 + *
   19.90 + * @param prop			Property name.
   19.91 + * @param value			Value to set.
   19.92 + * @param size			Number of bytes to write (valid values are 1, 2, or 4).
   19.93 + *						This value is auto-detected, and the size parameter is 
   19.94 + *						only used as a fallback in case detection fails.
   19.95 + * @param element		Element # (starting from 0) if property is an array.
   19.96 + * @error				Not supported.
   19.97 + * @noreturn
   19.98 + */
   19.99 +native GameRules_SetProp(const String:prop[], any:value, size=4, element=0, bool:changeState=false);
  19.100 +
  19.101 +/**
  19.102 + * Retrieves a float value from a property of the gamerules entity.
  19.103 + * 
  19.104 + * @param prop			Property name.
  19.105 + * @param element		Element # (starting from 0) if property is an array.
  19.106 + * @return				Value at the given property offset.
  19.107 + * @error				Not supported.
  19.108 + */
  19.109 +native Float:GameRules_GetPropFloat(const String:prop[], element=0);
  19.110 +
  19.111 +/**
  19.112 + * Sets a float value for a property of the gamerules entity.
  19.113 + * 
  19.114 + * @param prop			Property name.
  19.115 + * @param value			Value to set.
  19.116 + * @param element		Element # (starting from 0) if property is an array.
  19.117 + * @noreturn
  19.118 + * @error				Not supported.
  19.119 + */
  19.120 +native GameRules_SetPropFloat(const String:prop[], Float:value, element=0, bool:changeState=false);
  19.121 +
  19.122 +/**
  19.123 + * Retrieves a entity index from a property of the gamerules entity.
  19.124 + * 
  19.125 + * @param prop			Property name.
  19.126 + * @param element		Element # (starting from 0) if property is an array.
  19.127 + * @return				Entity index at the given property.
  19.128 + *						If there is no entity, or the entity is not valid, 
  19.129 + *						then -1 is returned.
  19.130 + * @error				Not supported.
  19.131 + */
  19.132 +native GameRules_GetPropEnt(const String:prop[], element=0);
  19.133 +
  19.134 +/**
  19.135 + * Sets an entity index for a property of the gamerules entity.
  19.136 + * 
  19.137 + * @param prop			Property name.
  19.138 + * @param other			Entity index to set, or -1 to unset.
  19.139 + * @param element		Element # (starting from 0) if property is an array.
  19.140 + * @noreturn
  19.141 + * @error				Not supported.
  19.142 + */
  19.143 +native GameRules_SetPropEnt(const String:prop[], other, element=0, bool:changeState=false);
  19.144 +
  19.145 +/**
  19.146 + * Retrieves a vector of floats from the gamerules entity, given a named network property.
  19.147 + * 
  19.148 + * @param prop			Property name.
  19.149 + * @param vec			Vector buffer to store data in.
  19.150 + * @param element		Element # (starting from 0) if property is an array.
  19.151 + * @noreturn
  19.152 + * @error				Not supported.
  19.153 + */
  19.154 +native GameRules_GetPropVector(const String:prop[], Float:vec[3], element=0);
  19.155 +
  19.156 +/**
  19.157 + * Sets a vector of floats in the gamerules entity, given a named network property.
  19.158 + *
  19.159 + * @param prop			Property name.
  19.160 + * @param vec			Vector to set.
  19.161 + * @param element		Element # (starting from 0) if property is an array.
  19.162 + * @noreturn
  19.163 + * @error				Not supported.
  19.164 + */
  19.165 +native GameRules_SetPropVector(const String:prop[], const Float:vec[3], element=0, bool:changeState=false);
  19.166 +
  19.167 +/**
  19.168 + * Gets a gamerules property as a string.
  19.169 + * 
  19.170 + * @param prop			Property to use.
  19.171 + * @param buffer		Destination string buffer.
  19.172 + * @param maxlen		Maximum length of output string buffer.
  19.173 + * @return				Number of non-null bytes written.
  19.174 + * @error				Not supported.
  19.175 + */
  19.176 +native GameRules_GetPropString(const String:prop[], String:buffer[], maxlen);
  19.177 +
  19.178 +/**
  19.179 + * Sets a gamerules property as a string.
  19.180 + *
  19.181 + * @param prop			Property to use.
  19.182 + * @param buffer		String to set.		
  19.183 + * @return				Number of non-null bytes written.
  19.184 + * @error				Not supported.
  19.185 + */
  19.186 +native GameRules_SetPropString(const String:prop[], const String:buffer[], bool:changeState=false);
  19.187 +
  19.188 +/**
  19.189 + * Gets the current round state.
  19.190 + *
  19.191 + * @return				Round state.
  19.192 + * @error				Game doesn't support round state.
  19.193 + */
  19.194 +stock RoundState:GameRules_GetRoundState()
  19.195 +{
  19.196 +	return RoundState:GameRules_GetProp("m_iRoundState");
  19.197 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/plugins/testsuite/gamerules-props.sp	Wed Jul 06 17:37:35 2011 -0400
    20.3 @@ -0,0 +1,129 @@
    20.4 +#include <sourcemod>
    20.5 +#include <sdktools>
    20.6 +
    20.7 +enum Game { Game_TF, Game_SWARM }
    20.8 +new Game:g_Game;
    20.9 +
   20.10 +public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
   20.11 +{
   20.12 +	decl String:gamedir[64];
   20.13 +	GetGameFolderName(gamedir, sizeof(gamedir));
   20.14 +	if (!strcmp(gamedir, "tf"))
   20.15 +	{
   20.16 +		g_Game = Game_TF;
   20.17 +		return APLRes_Success;
   20.18 +	}
   20.19 +	
   20.20 +	if (!strcmp(gamedir, "swarm"))
   20.21 +	{
   20.22 +		g_Game = Game_SWARM;
   20.23 +		return APLRes_Success;
   20.24 +	}
   20.25 +	
   20.26 +	strcopy(error, err_max, "These tests are only supported on TF2 and Alien Swarm");
   20.27 +	return APLRes_Failure;
   20.28 +}
   20.29 +
   20.30 +public OnPluginStart()
   20.31 +{	
   20.32 +	if (g_Game == Game_TF)
   20.33 +	{
   20.34 +		RegConsoleCmd("gr_getstate", gr_getstate);
   20.35 +		RegConsoleCmd("gr_ttr", gr_ttr);
   20.36 +		RegConsoleCmd("gr_tbs", gr_tbs);
   20.37 +		RegConsoleCmd("gr_nextspawn", gr_nextspawn);
   20.38 +		RegConsoleCmd("gr_settime", gr_settime);
   20.39 +		RegConsoleCmd("gr_getgoal", gr_getgoal);
   20.40 +		RegConsoleCmd("gr_setgoal", gr_setgoal);
   20.41 +	}
   20.42 +	else if (g_Game == Game_SWARM)
   20.43 +	{
   20.44 +		HookEvent("entity_killed", entity_killed);
   20.45 +		RegConsoleCmd("gr_getstimmer", gr_getstimmer);
   20.46 +	}
   20.47 +}
   20.48 +
   20.49 +public Action:gr_getstate(client, argc)
   20.50 +{
   20.51 +	ReplyToCommand(client, "Round state is %d", GameRules_GetRoundState());
   20.52 +	return Plugin_Handled;
   20.53 +}
   20.54 +
   20.55 +stock Float:GameRules_GetTimeUntilRndReset()
   20.56 +{
   20.57 +	new Float:flRestartTime = GameRules_GetPropFloat("m_flRestartRoundTime");
   20.58 +	if (flRestartTime == -1.0)
   20.59 +		return flRestartTime;
   20.60 +	
   20.61 +	return flRestartTime - GetGameTime();
   20.62 +}
   20.63 +
   20.64 +public Action:gr_ttr(client, argc)
   20.65 +{
   20.66 +	ReplyToCommand(client, "Time til restart is %.2f", GameRules_GetTimeUntilRndReset());
   20.67 +	return Plugin_Handled;
   20.68 +}
   20.69 +
   20.70 +public Action:gr_tbs(client, argc)
   20.71 +{
   20.72 +	ReplyToCommand(client, "Time between spawns for team2 is %.2f", GameRules_GetPropFloat("m_TeamRespawnWaveTimes", 2));
   20.73 +	return Plugin_Handled;
   20.74 +}
   20.75 +
   20.76 +public Action:gr_nextspawn(client, argc)
   20.77 +{
   20.78 +	ReplyToCommand(client, "Next spawn for team2 is %.2f", GameRules_GetPropFloat("m_flNextRespawnWave", 2));
   20.79 +	return Plugin_Handled;
   20.80 +}
   20.81 +
   20.82 +public Action:gr_settime(client, argc)
   20.83 +{
   20.84 +	GameRules_SetPropFloat("m_TeamRespawnWaveTimes", 2.0, 2, true);
   20.85 +	return Plugin_Handled;
   20.86 +}
   20.87 +
   20.88 +public Action:gr_getgoal(client, argc)
   20.89 +{
   20.90 +	decl String:goal[64];
   20.91 +	GameRules_GetPropString("m_pszTeamGoalStringRed", goal, sizeof(goal));
   20.92 +	ReplyToCommand(client, "Red goal string is \"%s\"", goal);
   20.93 +	return Plugin_Handled;
   20.94 +}
   20.95 +
   20.96 +public Action:gr_setgoal(client, argc)
   20.97 +{
   20.98 +	GameRules_SetPropString("m_pszTeamGoalStringRed", "urururur", true);
   20.99 +	
  20.100 +	decl String:goal[64];
  20.101 +	GameRules_GetPropString("m_pszTeamGoalStringRed", goal, sizeof(goal));
  20.102 +	ReplyToCommand(client, "Red goal string is \"%s\"", goal);
  20.103 +	return Plugin_Handled;
  20.104 +}
  20.105 +
  20.106 +//.. DIE
  20.107 +public entity_killed(Handle:event, const String:name[], bool:dontBroadcast)
  20.108 +{
  20.109 +	new ent = GetEventInt(event, "entindex_killed");
  20.110 +	if (!IsValidEdict(ent))
  20.111 +		return;
  20.112 +	
  20.113 +	decl String:classname[64];
  20.114 +	GetEdictClassname(ent, classname, sizeof(classname));
  20.115 +	
  20.116 +	if (!!strcmp(classname, "asw_marine"))
  20.117 +		return;
  20.118 +	
  20.119 +	decl Float:deathvec[3];
  20.120 +	GameRules_GetPropVector("m_vMarineDeathPos", deathvec);
  20.121 +	PrintToChatAll("Death vec is %.3f %.3f %.3f", deathvec[0], deathvec[1], deathvec[2]);
  20.122 +}
  20.123 +
  20.124 +// you can manually induce this with asw_PermaStim (needs sv_cheats)
  20.125 +public Action:gr_getstimmer(client, argc)
  20.126 +{
  20.127 +	ReplyToCommand(client, "%N (%.2f/%.2f)",
  20.128 +		GameRules_GetPropEnt("m_hStartStimPlayer"),
  20.129 +		GameRules_GetPropFloat("m_flStimStartTime"),
  20.130 +		GameRules_GetPropFloat("m_flStimEndTime"));
  20.131 +	return Plugin_Handled;
  20.132 +}