core/smn_halflife.cpp
branchrefac-jit
changeset 2168 c24a6fa957db
child 2175 54a8411faaac
     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 +};