core/smn_halflife.cpp
author Matt Woodrow <pred@alliedmods.net>
Mon Jun 09 07:12:32 2008 +0000 (2008-06-09)
changeset 2107 5e6c815d7ed9
parent 1952 b7aa2b626807
child 2175 54a8411faaac
permissions -rw-r--r--
Added SetUserInfo command to sdktools.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "sm_globals.h"
    33 #include "sourcemod.h"
    34 #include "sourcemm_api.h"
    35 #include "HandleSys.h"
    36 #include "PlayerManager.h"
    37 #include "HalfLife2.h"
    38 
    39 static cell_t SetRandomSeed(IPluginContext *pContext, const cell_t *params)
    40 {
    41 	engrandom->SetSeed(params[1]);
    42 
    43 	return 1;
    44 }
    45 
    46 static cell_t GetRandomFloat(IPluginContext *pContext, const cell_t *params)
    47 {
    48 	float fMin = sp_ctof(params[1]);
    49 	float fMax = sp_ctof(params[2]);
    50 
    51 	float fRandom = engrandom->RandomFloat(fMin, fMax);
    52 
    53 	return sp_ftoc(fRandom);
    54 }
    55 
    56 static cell_t GetRandomInt(IPluginContext *pContext, const cell_t *params)
    57 {
    58 	return engrandom->RandomInt(params[1], params[2]);
    59 }
    60 
    61 static cell_t IsMapValid(IPluginContext *pContext, const cell_t *params)
    62 {
    63 	char *map;
    64 	pContext->LocalToString(params[1], &map);
    65 
    66 	return engine->IsMapValid(map);
    67 }
    68 
    69 static cell_t IsDedicatedServer(IPluginContext *pContext, const cell_t *params)
    70 {
    71 	return engine->IsDedicatedServer();
    72 }
    73 
    74 static cell_t GetEngineTime(IPluginContext *pContext, const cell_t *params)
    75 {
    76 	float fTime = engine->Time();
    77 	return sp_ftoc(fTime);
    78 }
    79 
    80 static cell_t GetGameTime(IPluginContext *pContext, const cell_t *params)
    81 {
    82 	return sp_ftoc(gpGlobals->curtime);
    83 }
    84 
    85 static cell_t CreateFakeClient(IPluginContext *pContext, const cell_t *params)
    86 {
    87 	char *netname;
    88 
    89 	pContext->LocalToString(params[1], &netname);
    90 
    91 	edict_t *pEdict = engine->CreateFakeClient(netname);
    92 
    93 	/* :TODO: does the engine fire forwards for us and whatnot? no idea... */
    94 
    95 	if (!pEdict)
    96 	{
    97 		return 0;
    98 	}
    99 
   100 	return engine->IndexOfEdict(pEdict);
   101 }
   102 
   103 static cell_t SetFakeClientConVar(IPluginContext *pContext, const cell_t *params)
   104 {
   105 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   106 
   107 	if (!pPlayer)
   108 	{
   109 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
   110 	}
   111 
   112 	if (!pPlayer->IsConnected())
   113 	{
   114 		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
   115 	}
   116 
   117 	if (!pPlayer->IsFakeClient())
   118 	{
   119 		return pContext->ThrowNativeError("Client %d is not a fake client", params[1]);
   120 	}
   121 
   122 	char *cvar, *value;
   123 
   124 	pContext->LocalToString(params[2], &cvar);
   125 	pContext->LocalToString(params[3], &value);
   126 
   127 	engine->SetFakeClientConVarValue(pPlayer->GetEdict(), cvar, value);
   128 
   129 	return 1;
   130 }
   131 
   132 static cell_t GetGameDescription(IPluginContext *pContext, const cell_t *params)
   133 {
   134 	const char *description;
   135 
   136 	if (params[3])
   137 	{
   138 		description = gamedll->GetGameDescription();
   139 	} else {
   140 		description = SERVER_CALL(GetGameDescription)();
   141 	}
   142 
   143 	size_t numBytes;
   144 	
   145 	pContext->StringToLocalUTF8(params[1], params[2], description, &numBytes);
   146 
   147 	return numBytes;
   148 }
   149 
   150 static cell_t GetGameFolderName(IPluginContext *pContext, const cell_t *params)
   151 {
   152 	const char *name = g_SourceMod.GetGameFolderName();
   153 	size_t numBytes;
   154 
   155 	pContext->StringToLocalUTF8(params[1], params[2], name, &numBytes);
   156 
   157 	return numBytes;
   158 }
   159 
   160 /* Useless comment to bump the build */
   161 static cell_t GetCurrentMap(IPluginContext *pContext, const cell_t *params)
   162 {
   163 	size_t bytes;
   164 	pContext->StringToLocalUTF8(params[1], params[2], STRING(gpGlobals->mapname), &bytes);
   165 	return bytes;
   166 }
   167 
   168 static cell_t PrecacheModel(IPluginContext *pContext, const cell_t *params)
   169 {
   170 	char *model;
   171 	pContext->LocalToString(params[1], &model);
   172 
   173 	return engine->PrecacheModel(model, params[2] ? true : false);
   174 }
   175 
   176 static cell_t PrecacheSentenceFile(IPluginContext *pContext, const cell_t *params)
   177 {
   178 	char *sentencefile;
   179 	pContext->LocalToString(params[1], &sentencefile);
   180 
   181 	return engine->PrecacheSentenceFile(sentencefile, params[2] ? true : false);
   182 }
   183 
   184 static cell_t PrecacheDecal(IPluginContext *pContext, const cell_t *params)
   185 {
   186 	char *decal;
   187 	pContext->LocalToString(params[1], &decal);
   188 
   189 	return engine->PrecacheDecal(decal, params[2] ? true : false);
   190 }
   191 
   192 static cell_t PrecacheGeneric(IPluginContext *pContext, const cell_t *params)
   193 {
   194 	char *generic;
   195 	pContext->LocalToString(params[1], &generic);
   196 
   197 	return engine->PrecacheGeneric(generic, params[2] ? true : false);
   198 }
   199 
   200 static cell_t IsModelPrecached(IPluginContext *pContext, const cell_t *params)
   201 {
   202 	char *model;
   203 	pContext->LocalToString(params[1], &model);
   204 
   205 	return engine->IsModelPrecached(model) ? 1 : 0;
   206 }
   207 
   208 static cell_t IsDecalPrecached(IPluginContext *pContext, const cell_t *params)
   209 {
   210 	char *decal;
   211 	pContext->LocalToString(params[1], &decal);
   212 
   213 	return engine->IsDecalPrecached(decal) ? 1 : 0;
   214 }
   215 
   216 static cell_t IsGenericPrecached(IPluginContext *pContext, const cell_t *params)
   217 {
   218 	char *generic;
   219 	pContext->LocalToString(params[1], &generic);
   220 
   221 	return engine->IsGenericPrecached(generic) ? 1 : 0;
   222 }
   223 
   224 static cell_t PrecacheSound(IPluginContext *pContext, const cell_t *params)
   225 {
   226 	char *sample;
   227 	pContext->LocalToString(params[1], &sample);
   228 
   229 	return enginesound->PrecacheSound(sample, params[2] ? true : false) ? 1 : 0;
   230 }
   231 
   232 static cell_t IsSoundPrecached(IPluginContext *pContext, const cell_t *params)
   233 {
   234 	char *sample;
   235 	pContext->LocalToString(params[1], &sample);
   236 
   237 	return enginesound->IsSoundPrecached(sample) ? 1 : 0;
   238 }
   239 
   240 static cell_t smn_CreateDialog(IPluginContext *pContext, const cell_t *params)
   241 {
   242 	KeyValues *pKV;
   243 	HandleError herr;
   244 	Handle_t hndl = static_cast<Handle_t>(params[2]);
   245 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   246 
   247 	if (!pPlayer)
   248 	{
   249 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
   250 	}
   251 
   252 	if (!pPlayer->IsInGame())
   253 	{
   254 		return pContext->ThrowNativeError("Client %d is not in game", params[1]);
   255 	}
   256 
   257 	pKV = g_SourceMod.ReadKeyValuesHandle(hndl, &herr, true);
   258 	if (herr != HandleError_None)
   259 	{
   260 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   261 	}
   262 
   263 	serverpluginhelpers->CreateMessage(pPlayer->GetEdict(), 
   264 		static_cast<DIALOG_TYPE>(params[3]), 
   265 		pKV, 
   266 		vsp_interface);
   267 
   268 	return 1;
   269 }
   270 
   271 static cell_t PrintToChat(IPluginContext *pContext, const cell_t *params)
   272 {
   273 	int client = params[1];
   274 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   275 
   276 	if (!pPlayer)
   277 	{
   278 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   279 	}
   280 
   281 	if (!pPlayer->IsInGame())
   282 	{
   283 		return pContext->ThrowNativeError("Client %d is not in game", client);
   284 	}
   285 
   286 	g_SourceMod.SetGlobalTarget(client);
   287 
   288 	char buffer[192];
   289 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   290 
   291 	/* Check for an error before printing to the client */
   292 	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
   293 	{
   294 		return 0;
   295 	}
   296 
   297 	if (!g_HL2.TextMsg(client, HUD_PRINTTALK, buffer))
   298 	{
   299 		return pContext->ThrowNativeError("Could not send a usermessage");
   300 	}
   301 
   302 	return 1;
   303 }
   304 
   305 static cell_t PrintCenterText(IPluginContext *pContext, const cell_t *params)
   306 {
   307 	int client = params[1];
   308 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   309 
   310 	if (!pPlayer)
   311 	{
   312 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   313 	}
   314 
   315 	if (!pPlayer->IsInGame())
   316 	{
   317 		return pContext->ThrowNativeError("Client %d is not in game", client);
   318 	}
   319 
   320 	g_SourceMod.SetGlobalTarget(client);
   321 
   322 	char buffer[192];
   323 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   324 
   325 	/* Check for an error before printing to the client */
   326 	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
   327 	{
   328 		return 0;
   329 	}
   330 
   331 	if (!g_HL2.TextMsg(client, HUD_PRINTCENTER, buffer))
   332 	{
   333 		return pContext->ThrowNativeError("Could not send a usermessage");
   334 	}
   335 
   336 	return 1;
   337 }
   338 
   339 static cell_t PrintHintText(IPluginContext *pContext, const cell_t *params)
   340 {
   341 	int client = params[1];
   342 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   343 
   344 	if (!pPlayer)
   345 	{
   346 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   347 	}
   348 
   349 	if (!pPlayer->IsInGame())
   350 	{
   351 		return pContext->ThrowNativeError("Client %d is not in game", client);
   352 	}
   353 
   354 	g_SourceMod.SetGlobalTarget(client);
   355 
   356 	char buffer[192];
   357 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   358 
   359 	/* Check for an error before printing to the client */
   360 	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
   361 	{
   362 		return 0;
   363 	}
   364 
   365 	if (!g_HL2.HintTextMsg(client, buffer))
   366 	{
   367 		return pContext->ThrowNativeError("Could not send a usermessage");
   368 	}
   369 
   370 	return 1;
   371 }
   372 
   373 static cell_t ShowVGUIPanel(IPluginContext *pContext, const cell_t *params)
   374 {
   375 	HandleError herr;
   376 	char *name;
   377 	KeyValues *pKV = NULL;
   378 	int client = params[1];
   379 	Handle_t hndl = static_cast<Handle_t>(params[3]);
   380 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   381 
   382 	if (!pPlayer)
   383 	{
   384 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   385 	}
   386 
   387 	if (!pPlayer->IsInGame())
   388 	{
   389 		return pContext->ThrowNativeError("Client %d is not in game", client);
   390 	}
   391 
   392 	if (hndl != BAD_HANDLE)
   393 	{
   394 		pKV = g_SourceMod.ReadKeyValuesHandle(hndl, &herr, true);
   395 		if (herr != HandleError_None)
   396 		{
   397 			return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   398 		}
   399 	}
   400 
   401 	pContext->LocalToString(params[2], &name);
   402 
   403 	if (!g_HL2.ShowVGUIMenu(client, name, pKV, (params[4]) ? true : false))
   404 	{
   405 		return pContext->ThrowNativeError("Could not send a usermessage");
   406 	}
   407 
   408 	return 1;
   409 }
   410 
   411 static cell_t smn_IsPlayerAlive(IPluginContext *pContext, const cell_t *params)
   412 {
   413 	CPlayer *player = g_Players.GetPlayerByIndex(params[1]);
   414 	if (player == NULL)
   415 	{
   416 		return pContext->ThrowNativeError("Invalid client index %d", params[1]);
   417 	}
   418 	else if (!player->IsInGame())
   419 	{
   420 		return pContext->ThrowNativeError("Client %d is not in game", params[1]);
   421 	}
   422 
   423 	unsigned int state = player->GetLifeState();
   424 
   425 	if (state == PLAYER_LIFE_UNKNOWN)
   426 	{
   427 		return pContext->ThrowNativeError("\"IsPlayerAlive\" not supported by this mod");
   428 	}
   429 	else if (state == PLAYER_LIFE_ALIVE)
   430 	{
   431 		return 1;
   432 	}
   433 	else
   434 	{
   435 		return 0;
   436 	}
   437 }
   438 
   439 static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params)
   440 {
   441 #if defined METAMOD_PLAPI_VERSION
   442 	int version = g_SMAPI->GetSourceEngineBuild();
   443 
   444 	if (version == SOURCE_ENGINE_ORIGINAL)
   445 	{
   446 		return 10;
   447 	}
   448 	else if (version == SOURCE_ENGINE_EPISODEONE)
   449 	{
   450 		return 20;
   451 	}
   452 	else if (version == SOURCE_ENGINE_ORANGEBOX)
   453 	{
   454 		return 30;
   455 	}
   456 #else
   457 	if (g_HL2.IsOriginalEngine())
   458 	{
   459 		return 10;
   460 	}
   461 	else
   462 	{
   463 		return 20;
   464 	}
   465 #endif
   466 
   467 	return 0;
   468 }
   469 
   470 REGISTER_NATIVES(halflifeNatives)
   471 {
   472 	{"CreateFakeClient",		CreateFakeClient},
   473 	{"GetCurrentMap",			GetCurrentMap},
   474 	{"GetEngineTime",			GetEngineTime},
   475 	{"GetGameDescription",		GetGameDescription},
   476 	{"GetGameFolderName",		GetGameFolderName},
   477 	{"GetGameTime",				GetGameTime},
   478 	{"GetRandomFloat",			GetRandomFloat},
   479 	{"GetRandomInt",			GetRandomInt},
   480 	{"IsDedicatedServer",		IsDedicatedServer},
   481 	{"IsMapValid",				IsMapValid},
   482 	{"SetFakeClientConVar",		SetFakeClientConVar},
   483 	{"SetRandomSeed",			SetRandomSeed},
   484 	{"PrecacheModel",			PrecacheModel},
   485 	{"PrecacheSentenceFile",	PrecacheSentenceFile},
   486 	{"PrecacheDecal",			PrecacheDecal},
   487 	{"PrecacheGeneric",			PrecacheGeneric},
   488 	{"IsModelPrecached",		IsModelPrecached},
   489 	{"IsDecalPrecached",		IsDecalPrecached},
   490 	{"IsGenericPrecached",		IsGenericPrecached},
   491 	{"PrecacheSound",			PrecacheSound},
   492 	{"IsSoundPrecached",		IsSoundPrecached},
   493 	{"CreateDialog",			smn_CreateDialog},
   494 	{"PrintToChat",				PrintToChat},
   495 	{"PrintCenterText",			PrintCenterText},
   496 	{"PrintHintText",			PrintHintText},
   497 	{"ShowVGUIPanel",			ShowVGUIPanel},
   498 	{"IsPlayerAlive",			smn_IsPlayerAlive},
   499 	{"GuessSDKVersion",			GuessSDKVersion},
   500 	{NULL,						NULL},
   501 };