Added ability in SDKTools to get/set prop values on gamerules class (bug 4983, r=fyren).
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 +}