1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/smn_halflife.cpp Sun Jul 06 04:49:55 2008 +0000
1.3 @@ -0,0 +1,501 @@
1.4 +/**
1.5 + * vim: set ts=4 :
1.6 + * =============================================================================
1.7 + * SourceMod
1.8 + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 + * =============================================================================
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify it under
1.12 + * the terms of the GNU General Public License, version 3.0, as published by the
1.13 + * Free Software Foundation.
1.14 + *
1.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 + * details.
1.19 + *
1.20 + * You should have received a copy of the GNU General Public License along with
1.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 + *
1.23 + * As a special exception, AlliedModders LLC gives you permission to link the
1.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 + * by the Valve Corporation. You must obey the GNU General Public License in
1.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 + * this exception to all derivative works. AlliedModders LLC defines further
1.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 + * or <http://www.sourcemod.net/license.php>.
1.31 + *
1.32 + * Version: $Id$
1.33 + */
1.34 +
1.35 +#include "sm_globals.h"
1.36 +#include "sourcemod.h"
1.37 +#include "sourcemm_api.h"
1.38 +#include "HandleSys.h"
1.39 +#include "PlayerManager.h"
1.40 +#include "HalfLife2.h"
1.41 +
1.42 +static cell_t SetRandomSeed(IPluginContext *pContext, const cell_t *params)
1.43 +{
1.44 + engrandom->SetSeed(params[1]);
1.45 +
1.46 + return 1;
1.47 +}
1.48 +
1.49 +static cell_t GetRandomFloat(IPluginContext *pContext, const cell_t *params)
1.50 +{
1.51 + float fMin = sp_ctof(params[1]);
1.52 + float fMax = sp_ctof(params[2]);
1.53 +
1.54 + float fRandom = engrandom->RandomFloat(fMin, fMax);
1.55 +
1.56 + return sp_ftoc(fRandom);
1.57 +}
1.58 +
1.59 +static cell_t GetRandomInt(IPluginContext *pContext, const cell_t *params)
1.60 +{
1.61 + return engrandom->RandomInt(params[1], params[2]);
1.62 +}
1.63 +
1.64 +static cell_t IsMapValid(IPluginContext *pContext, const cell_t *params)
1.65 +{
1.66 + char *map;
1.67 + pContext->LocalToString(params[1], &map);
1.68 +
1.69 + return engine->IsMapValid(map);
1.70 +}
1.71 +
1.72 +static cell_t IsDedicatedServer(IPluginContext *pContext, const cell_t *params)
1.73 +{
1.74 + return engine->IsDedicatedServer();
1.75 +}
1.76 +
1.77 +static cell_t GetEngineTime(IPluginContext *pContext, const cell_t *params)
1.78 +{
1.79 + float fTime = engine->Time();
1.80 + return sp_ftoc(fTime);
1.81 +}
1.82 +
1.83 +static cell_t GetGameTime(IPluginContext *pContext, const cell_t *params)
1.84 +{
1.85 + return sp_ftoc(gpGlobals->curtime);
1.86 +}
1.87 +
1.88 +static cell_t CreateFakeClient(IPluginContext *pContext, const cell_t *params)
1.89 +{
1.90 + char *netname;
1.91 +
1.92 + pContext->LocalToString(params[1], &netname);
1.93 +
1.94 + edict_t *pEdict = engine->CreateFakeClient(netname);
1.95 +
1.96 + /* :TODO: does the engine fire forwards for us and whatnot? no idea... */
1.97 +
1.98 + if (!pEdict)
1.99 + {
1.100 + return 0;
1.101 + }
1.102 +
1.103 + return engine->IndexOfEdict(pEdict);
1.104 +}
1.105 +
1.106 +static cell_t SetFakeClientConVar(IPluginContext *pContext, const cell_t *params)
1.107 +{
1.108 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1.109 +
1.110 + if (!pPlayer)
1.111 + {
1.112 + return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1.113 + }
1.114 +
1.115 + if (!pPlayer->IsConnected())
1.116 + {
1.117 + return pContext->ThrowNativeError("Client %d is not connected", params[1]);
1.118 + }
1.119 +
1.120 + if (!pPlayer->IsFakeClient())
1.121 + {
1.122 + return pContext->ThrowNativeError("Client %d is not a fake client", params[1]);
1.123 + }
1.124 +
1.125 + char *cvar, *value;
1.126 +
1.127 + pContext->LocalToString(params[2], &cvar);
1.128 + pContext->LocalToString(params[3], &value);
1.129 +
1.130 + engine->SetFakeClientConVarValue(pPlayer->GetEdict(), cvar, value);
1.131 +
1.132 + return 1;
1.133 +}
1.134 +
1.135 +static cell_t GetGameDescription(IPluginContext *pContext, const cell_t *params)
1.136 +{
1.137 + const char *description;
1.138 +
1.139 + if (params[3])
1.140 + {
1.141 + description = gamedll->GetGameDescription();
1.142 + } else {
1.143 + description = SERVER_CALL(GetGameDescription)();
1.144 + }
1.145 +
1.146 + size_t numBytes;
1.147 +
1.148 + pContext->StringToLocalUTF8(params[1], params[2], description, &numBytes);
1.149 +
1.150 + return numBytes;
1.151 +}
1.152 +
1.153 +static cell_t GetGameFolderName(IPluginContext *pContext, const cell_t *params)
1.154 +{
1.155 + const char *name = g_SourceMod.GetGameFolderName();
1.156 + size_t numBytes;
1.157 +
1.158 + pContext->StringToLocalUTF8(params[1], params[2], name, &numBytes);
1.159 +
1.160 + return numBytes;
1.161 +}
1.162 +
1.163 +/* Useless comment to bump the build */
1.164 +static cell_t GetCurrentMap(IPluginContext *pContext, const cell_t *params)
1.165 +{
1.166 + size_t bytes;
1.167 + pContext->StringToLocalUTF8(params[1], params[2], STRING(gpGlobals->mapname), &bytes);
1.168 + return bytes;
1.169 +}
1.170 +
1.171 +static cell_t PrecacheModel(IPluginContext *pContext, const cell_t *params)
1.172 +{
1.173 + char *model;
1.174 + pContext->LocalToString(params[1], &model);
1.175 +
1.176 + return engine->PrecacheModel(model, params[2] ? true : false);
1.177 +}
1.178 +
1.179 +static cell_t PrecacheSentenceFile(IPluginContext *pContext, const cell_t *params)
1.180 +{
1.181 + char *sentencefile;
1.182 + pContext->LocalToString(params[1], &sentencefile);
1.183 +
1.184 + return engine->PrecacheSentenceFile(sentencefile, params[2] ? true : false);
1.185 +}
1.186 +
1.187 +static cell_t PrecacheDecal(IPluginContext *pContext, const cell_t *params)
1.188 +{
1.189 + char *decal;
1.190 + pContext->LocalToString(params[1], &decal);
1.191 +
1.192 + return engine->PrecacheDecal(decal, params[2] ? true : false);
1.193 +}
1.194 +
1.195 +static cell_t PrecacheGeneric(IPluginContext *pContext, const cell_t *params)
1.196 +{
1.197 + char *generic;
1.198 + pContext->LocalToString(params[1], &generic);
1.199 +
1.200 + return engine->PrecacheGeneric(generic, params[2] ? true : false);
1.201 +}
1.202 +
1.203 +static cell_t IsModelPrecached(IPluginContext *pContext, const cell_t *params)
1.204 +{
1.205 + char *model;
1.206 + pContext->LocalToString(params[1], &model);
1.207 +
1.208 + return engine->IsModelPrecached(model) ? 1 : 0;
1.209 +}
1.210 +
1.211 +static cell_t IsDecalPrecached(IPluginContext *pContext, const cell_t *params)
1.212 +{
1.213 + char *decal;
1.214 + pContext->LocalToString(params[1], &decal);
1.215 +
1.216 + return engine->IsDecalPrecached(decal) ? 1 : 0;
1.217 +}
1.218 +
1.219 +static cell_t IsGenericPrecached(IPluginContext *pContext, const cell_t *params)
1.220 +{
1.221 + char *generic;
1.222 + pContext->LocalToString(params[1], &generic);
1.223 +
1.224 + return engine->IsGenericPrecached(generic) ? 1 : 0;
1.225 +}
1.226 +
1.227 +static cell_t PrecacheSound(IPluginContext *pContext, const cell_t *params)
1.228 +{
1.229 + char *sample;
1.230 + pContext->LocalToString(params[1], &sample);
1.231 +
1.232 + return enginesound->PrecacheSound(sample, params[2] ? true : false) ? 1 : 0;
1.233 +}
1.234 +
1.235 +static cell_t IsSoundPrecached(IPluginContext *pContext, const cell_t *params)
1.236 +{
1.237 + char *sample;
1.238 + pContext->LocalToString(params[1], &sample);
1.239 +
1.240 + return enginesound->IsSoundPrecached(sample) ? 1 : 0;
1.241 +}
1.242 +
1.243 +static cell_t smn_CreateDialog(IPluginContext *pContext, const cell_t *params)
1.244 +{
1.245 + KeyValues *pKV;
1.246 + HandleError herr;
1.247 + Handle_t hndl = static_cast<Handle_t>(params[2]);
1.248 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
1.249 +
1.250 + if (!pPlayer)
1.251 + {
1.252 + return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
1.253 + }
1.254 +
1.255 + if (!pPlayer->IsInGame())
1.256 + {
1.257 + return pContext->ThrowNativeError("Client %d is not in game", params[1]);
1.258 + }
1.259 +
1.260 + pKV = g_SourceMod.ReadKeyValuesHandle(hndl, &herr, true);
1.261 + if (herr != HandleError_None)
1.262 + {
1.263 + return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
1.264 + }
1.265 +
1.266 + serverpluginhelpers->CreateMessage(pPlayer->GetEdict(),
1.267 + static_cast<DIALOG_TYPE>(params[3]),
1.268 + pKV,
1.269 + vsp_interface);
1.270 +
1.271 + return 1;
1.272 +}
1.273 +
1.274 +static cell_t PrintToChat(IPluginContext *pContext, const cell_t *params)
1.275 +{
1.276 + int client = params[1];
1.277 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1.278 +
1.279 + if (!pPlayer)
1.280 + {
1.281 + return pContext->ThrowNativeError("Client index %d is invalid", client);
1.282 + }
1.283 +
1.284 + if (!pPlayer->IsInGame())
1.285 + {
1.286 + return pContext->ThrowNativeError("Client %d is not in game", client);
1.287 + }
1.288 +
1.289 + g_SourceMod.SetGlobalTarget(client);
1.290 +
1.291 + char buffer[192];
1.292 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.293 +
1.294 + /* Check for an error before printing to the client */
1.295 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.296 + {
1.297 + return 0;
1.298 + }
1.299 +
1.300 + if (!g_HL2.TextMsg(client, HUD_PRINTTALK, buffer))
1.301 + {
1.302 + return pContext->ThrowNativeError("Could not send a usermessage");
1.303 + }
1.304 +
1.305 + return 1;
1.306 +}
1.307 +
1.308 +static cell_t PrintCenterText(IPluginContext *pContext, const cell_t *params)
1.309 +{
1.310 + int client = params[1];
1.311 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1.312 +
1.313 + if (!pPlayer)
1.314 + {
1.315 + return pContext->ThrowNativeError("Client index %d is invalid", client);
1.316 + }
1.317 +
1.318 + if (!pPlayer->IsInGame())
1.319 + {
1.320 + return pContext->ThrowNativeError("Client %d is not in game", client);
1.321 + }
1.322 +
1.323 + g_SourceMod.SetGlobalTarget(client);
1.324 +
1.325 + char buffer[192];
1.326 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.327 +
1.328 + /* Check for an error before printing to the client */
1.329 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.330 + {
1.331 + return 0;
1.332 + }
1.333 +
1.334 + if (!g_HL2.TextMsg(client, HUD_PRINTCENTER, buffer))
1.335 + {
1.336 + return pContext->ThrowNativeError("Could not send a usermessage");
1.337 + }
1.338 +
1.339 + return 1;
1.340 +}
1.341 +
1.342 +static cell_t PrintHintText(IPluginContext *pContext, const cell_t *params)
1.343 +{
1.344 + int client = params[1];
1.345 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1.346 +
1.347 + if (!pPlayer)
1.348 + {
1.349 + return pContext->ThrowNativeError("Client index %d is invalid", client);
1.350 + }
1.351 +
1.352 + if (!pPlayer->IsInGame())
1.353 + {
1.354 + return pContext->ThrowNativeError("Client %d is not in game", client);
1.355 + }
1.356 +
1.357 + g_SourceMod.SetGlobalTarget(client);
1.358 +
1.359 + char buffer[192];
1.360 + g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1.361 +
1.362 + /* Check for an error before printing to the client */
1.363 + if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1.364 + {
1.365 + return 0;
1.366 + }
1.367 +
1.368 + if (!g_HL2.HintTextMsg(client, buffer))
1.369 + {
1.370 + return pContext->ThrowNativeError("Could not send a usermessage");
1.371 + }
1.372 +
1.373 + return 1;
1.374 +}
1.375 +
1.376 +static cell_t ShowVGUIPanel(IPluginContext *pContext, const cell_t *params)
1.377 +{
1.378 + HandleError herr;
1.379 + char *name;
1.380 + KeyValues *pKV = NULL;
1.381 + int client = params[1];
1.382 + Handle_t hndl = static_cast<Handle_t>(params[3]);
1.383 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1.384 +
1.385 + if (!pPlayer)
1.386 + {
1.387 + return pContext->ThrowNativeError("Client index %d is invalid", client);
1.388 + }
1.389 +
1.390 + if (!pPlayer->IsInGame())
1.391 + {
1.392 + return pContext->ThrowNativeError("Client %d is not in game", client);
1.393 + }
1.394 +
1.395 + if (hndl != BAD_HANDLE)
1.396 + {
1.397 + pKV = g_SourceMod.ReadKeyValuesHandle(hndl, &herr, true);
1.398 + if (herr != HandleError_None)
1.399 + {
1.400 + return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
1.401 + }
1.402 + }
1.403 +
1.404 + pContext->LocalToString(params[2], &name);
1.405 +
1.406 + if (!g_HL2.ShowVGUIMenu(client, name, pKV, (params[4]) ? true : false))
1.407 + {
1.408 + return pContext->ThrowNativeError("Could not send a usermessage");
1.409 + }
1.410 +
1.411 + return 1;
1.412 +}
1.413 +
1.414 +static cell_t smn_IsPlayerAlive(IPluginContext *pContext, const cell_t *params)
1.415 +{
1.416 + CPlayer *player = g_Players.GetPlayerByIndex(params[1]);
1.417 + if (player == NULL)
1.418 + {
1.419 + return pContext->ThrowNativeError("Invalid client index %d", params[1]);
1.420 + }
1.421 + else if (!player->IsInGame())
1.422 + {
1.423 + return pContext->ThrowNativeError("Client %d is not in game", params[1]);
1.424 + }
1.425 +
1.426 + unsigned int state = player->GetLifeState();
1.427 +
1.428 + if (state == PLAYER_LIFE_UNKNOWN)
1.429 + {
1.430 + return pContext->ThrowNativeError("\"IsPlayerAlive\" not supported by this mod");
1.431 + }
1.432 + else if (state == PLAYER_LIFE_ALIVE)
1.433 + {
1.434 + return 1;
1.435 + }
1.436 + else
1.437 + {
1.438 + return 0;
1.439 + }
1.440 +}
1.441 +
1.442 +static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params)
1.443 +{
1.444 +#if defined METAMOD_PLAPI_VERSION
1.445 + int version = g_SMAPI->GetSourceEngineBuild();
1.446 +
1.447 + if (version == SOURCE_ENGINE_ORIGINAL)
1.448 + {
1.449 + return 10;
1.450 + }
1.451 + else if (version == SOURCE_ENGINE_EPISODEONE)
1.452 + {
1.453 + return 20;
1.454 + }
1.455 + else if (version == SOURCE_ENGINE_ORANGEBOX)
1.456 + {
1.457 + return 30;
1.458 + }
1.459 +#else
1.460 + if (g_HL2.IsOriginalEngine())
1.461 + {
1.462 + return 10;
1.463 + }
1.464 + else
1.465 + {
1.466 + return 20;
1.467 + }
1.468 +#endif
1.469 +
1.470 + return 0;
1.471 +}
1.472 +
1.473 +REGISTER_NATIVES(halflifeNatives)
1.474 +{
1.475 + {"CreateFakeClient", CreateFakeClient},
1.476 + {"GetCurrentMap", GetCurrentMap},
1.477 + {"GetEngineTime", GetEngineTime},
1.478 + {"GetGameDescription", GetGameDescription},
1.479 + {"GetGameFolderName", GetGameFolderName},
1.480 + {"GetGameTime", GetGameTime},
1.481 + {"GetRandomFloat", GetRandomFloat},
1.482 + {"GetRandomInt", GetRandomInt},
1.483 + {"IsDedicatedServer", IsDedicatedServer},
1.484 + {"IsMapValid", IsMapValid},
1.485 + {"SetFakeClientConVar", SetFakeClientConVar},
1.486 + {"SetRandomSeed", SetRandomSeed},
1.487 + {"PrecacheModel", PrecacheModel},
1.488 + {"PrecacheSentenceFile", PrecacheSentenceFile},
1.489 + {"PrecacheDecal", PrecacheDecal},
1.490 + {"PrecacheGeneric", PrecacheGeneric},
1.491 + {"IsModelPrecached", IsModelPrecached},
1.492 + {"IsDecalPrecached", IsDecalPrecached},
1.493 + {"IsGenericPrecached", IsGenericPrecached},
1.494 + {"PrecacheSound", PrecacheSound},
1.495 + {"IsSoundPrecached", IsSoundPrecached},
1.496 + {"CreateDialog", smn_CreateDialog},
1.497 + {"PrintToChat", PrintToChat},
1.498 + {"PrintCenterText", PrintCenterText},
1.499 + {"PrintHintText", PrintHintText},
1.500 + {"ShowVGUIPanel", ShowVGUIPanel},
1.501 + {"IsPlayerAlive", smn_IsPlayerAlive},
1.502 + {"GuessSDKVersion", GuessSDKVersion},
1.503 + {NULL, NULL},
1.504 +};