core/smn_halflife.cpp
author Matt Woodrow <pred@alliedmods.net>
Fri Oct 30 14:29:45 2009 +1300 (2009-10-30)
changeset 2850 1242bcb70fa9
parent 2846 5e176efe7927
child 2851 87b5dcbedcab
permissions -rw-r--r--
SourceMod MSVC project files updated, windows tested and loading, gamedata fix.
     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 = Plat_FloatTime();
    77 	
    78 	return sp_ftoc(fTime);
    79 }
    80 
    81 static cell_t GetGameTime(IPluginContext *pContext, const cell_t *params)
    82 {
    83 	return sp_ftoc(gpGlobals->curtime);
    84 }
    85 
    86 static cell_t CreateFakeClient(IPluginContext *pContext, const cell_t *params)
    87 {
    88 	char *netname;
    89 
    90 	pContext->LocalToString(params[1], &netname);
    91 
    92 	edict_t *pEdict = engine->CreateFakeClient(netname);
    93 
    94 	/* :TODO: does the engine fire forwards for us and whatnot? no idea... */
    95 
    96 	if (!pEdict)
    97 	{
    98 		return 0;
    99 	}
   100 
   101 	return IndexOfEdict(pEdict);
   102 }
   103 
   104 static cell_t SetFakeClientConVar(IPluginContext *pContext, const cell_t *params)
   105 {
   106 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   107 
   108 	if (!pPlayer)
   109 	{
   110 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
   111 	}
   112 
   113 	if (!pPlayer->IsConnected())
   114 	{
   115 		return pContext->ThrowNativeError("Client %d is not connected", params[1]);
   116 	}
   117 
   118 	if (!pPlayer->IsFakeClient())
   119 	{
   120 		return pContext->ThrowNativeError("Client %d is not a fake client", params[1]);
   121 	}
   122 
   123 	char *cvar, *value;
   124 
   125 	pContext->LocalToString(params[2], &cvar);
   126 	pContext->LocalToString(params[3], &value);
   127 
   128 	engine->SetFakeClientConVarValue(pPlayer->GetEdict(), cvar, value);
   129 
   130 	return 1;
   131 }
   132 
   133 static cell_t GetGameDescription(IPluginContext *pContext, const cell_t *params)
   134 {
   135 	const char *description;
   136 
   137 	if (params[3])
   138 	{
   139 		description = gamedll->GetGameDescription();
   140 	} else {
   141 		description = SERVER_CALL(GetGameDescription)();
   142 	}
   143 
   144 	size_t numBytes;
   145 	
   146 	pContext->StringToLocalUTF8(params[1], params[2], description, &numBytes);
   147 
   148 	return numBytes;
   149 }
   150 
   151 static cell_t GetGameFolderName(IPluginContext *pContext, const cell_t *params)
   152 {
   153 	const char *name = g_SourceMod.GetGameFolderName();
   154 	size_t numBytes;
   155 
   156 	pContext->StringToLocalUTF8(params[1], params[2], name, &numBytes);
   157 
   158 	return numBytes;
   159 }
   160 
   161 /* Useless comment to bump the build */
   162 static cell_t GetCurrentMap(IPluginContext *pContext, const cell_t *params)
   163 {
   164 	size_t bytes;
   165 	pContext->StringToLocalUTF8(params[1], params[2], STRING(gpGlobals->mapname), &bytes);
   166 	return bytes;
   167 }
   168 
   169 static cell_t PrecacheModel(IPluginContext *pContext, const cell_t *params)
   170 {
   171 	char *model;
   172 	pContext->LocalToString(params[1], &model);
   173 
   174 	return engine->PrecacheModel(model, params[2] ? true : false);
   175 }
   176 
   177 static cell_t PrecacheSentenceFile(IPluginContext *pContext, const cell_t *params)
   178 {
   179 	char *sentencefile;
   180 	pContext->LocalToString(params[1], &sentencefile);
   181 
   182 	return engine->PrecacheSentenceFile(sentencefile, params[2] ? true : false);
   183 }
   184 
   185 static cell_t PrecacheDecal(IPluginContext *pContext, const cell_t *params)
   186 {
   187 	char *decal;
   188 	pContext->LocalToString(params[1], &decal);
   189 
   190 	return engine->PrecacheDecal(decal, params[2] ? true : false);
   191 }
   192 
   193 static cell_t PrecacheGeneric(IPluginContext *pContext, const cell_t *params)
   194 {
   195 	char *generic;
   196 	pContext->LocalToString(params[1], &generic);
   197 
   198 	return engine->PrecacheGeneric(generic, params[2] ? true : false);
   199 }
   200 
   201 static cell_t IsModelPrecached(IPluginContext *pContext, const cell_t *params)
   202 {
   203 	char *model;
   204 	pContext->LocalToString(params[1], &model);
   205 
   206 	return engine->IsModelPrecached(model) ? 1 : 0;
   207 }
   208 
   209 static cell_t IsDecalPrecached(IPluginContext *pContext, const cell_t *params)
   210 {
   211 	char *decal;
   212 	pContext->LocalToString(params[1], &decal);
   213 
   214 	return engine->IsDecalPrecached(decal) ? 1 : 0;
   215 }
   216 
   217 static cell_t IsGenericPrecached(IPluginContext *pContext, const cell_t *params)
   218 {
   219 	char *generic;
   220 	pContext->LocalToString(params[1], &generic);
   221 
   222 	return engine->IsGenericPrecached(generic) ? 1 : 0;
   223 }
   224 
   225 static cell_t PrecacheSound(IPluginContext *pContext, const cell_t *params)
   226 {
   227 	char *sample;
   228 	pContext->LocalToString(params[1], &sample);
   229 
   230 	return enginesound->PrecacheSound(sample, params[2] ? true : false) ? 1 : 0;
   231 }
   232 
   233 static cell_t IsSoundPrecached(IPluginContext *pContext, const cell_t *params)
   234 {
   235 	char *sample;
   236 	pContext->LocalToString(params[1], &sample);
   237 
   238 	return enginesound->IsSoundPrecached(sample) ? 1 : 0;
   239 }
   240 
   241 static cell_t smn_CreateDialog(IPluginContext *pContext, const cell_t *params)
   242 {
   243 	KeyValues *pKV;
   244 	HandleError herr;
   245 	Handle_t hndl = static_cast<Handle_t>(params[2]);
   246 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(params[1]);
   247 
   248 	if (!pPlayer)
   249 	{
   250 		return pContext->ThrowNativeError("Client index %d is invalid", params[1]);
   251 	}
   252 
   253 	if (!pPlayer->IsInGame())
   254 	{
   255 		return pContext->ThrowNativeError("Client %d is not in game", params[1]);
   256 	}
   257 
   258 	pKV = g_SourceMod.ReadKeyValuesHandle(hndl, &herr, true);
   259 	if (herr != HandleError_None)
   260 	{
   261 		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   262 	}
   263 
   264 	serverpluginhelpers->CreateMessage(pPlayer->GetEdict(), 
   265 		static_cast<DIALOG_TYPE>(params[3]), 
   266 		pKV, 
   267 		vsp_interface);
   268 
   269 	return 1;
   270 }
   271 
   272 static cell_t PrintToChat(IPluginContext *pContext, const cell_t *params)
   273 {
   274 	int client = params[1];
   275 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   276 
   277 	if (!pPlayer)
   278 	{
   279 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   280 	}
   281 
   282 	if (!pPlayer->IsInGame())
   283 	{
   284 		return pContext->ThrowNativeError("Client %d is not in game", client);
   285 	}
   286 
   287 	g_SourceMod.SetGlobalTarget(client);
   288 
   289 	char buffer[192];
   290 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   291 
   292 	/* Check for an error before printing to the client */
   293 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   294 	{
   295 		return 0;
   296 	}
   297 
   298 	if (!g_HL2.TextMsg(client, HUD_PRINTTALK, buffer))
   299 	{
   300 		return pContext->ThrowNativeError("Could not send a usermessage");
   301 	}
   302 
   303 	return 1;
   304 }
   305 
   306 static cell_t PrintCenterText(IPluginContext *pContext, const cell_t *params)
   307 {
   308 	int client = params[1];
   309 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   310 
   311 	if (!pPlayer)
   312 	{
   313 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   314 	}
   315 
   316 	if (!pPlayer->IsInGame())
   317 	{
   318 		return pContext->ThrowNativeError("Client %d is not in game", client);
   319 	}
   320 
   321 	g_SourceMod.SetGlobalTarget(client);
   322 
   323 	char buffer[192];
   324 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   325 
   326 	/* Check for an error before printing to the client */
   327 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   328 	{
   329 		return 0;
   330 	}
   331 
   332 	if (!g_HL2.TextMsg(client, HUD_PRINTCENTER, buffer))
   333 	{
   334 		return pContext->ThrowNativeError("Could not send a usermessage");
   335 	}
   336 
   337 	return 1;
   338 }
   339 
   340 static cell_t PrintHintText(IPluginContext *pContext, const cell_t *params)
   341 {
   342 	int client = params[1];
   343 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   344 
   345 	if (!pPlayer)
   346 	{
   347 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   348 	}
   349 
   350 	if (!pPlayer->IsInGame())
   351 	{
   352 		return pContext->ThrowNativeError("Client %d is not in game", client);
   353 	}
   354 
   355 	g_SourceMod.SetGlobalTarget(client);
   356 
   357 	char buffer[192];
   358 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   359 
   360 	/* Check for an error before printing to the client */
   361 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
   362 	{
   363 		return 0;
   364 	}
   365 
   366 	if (!g_HL2.HintTextMsg(client, buffer))
   367 	{
   368 		return pContext->ThrowNativeError("Could not send a usermessage");
   369 	}
   370 
   371 	return 1;
   372 }
   373 
   374 static cell_t ShowVGUIPanel(IPluginContext *pContext, const cell_t *params)
   375 {
   376 	HandleError herr;
   377 	char *name;
   378 	KeyValues *pKV = NULL;
   379 	int client = params[1];
   380 	Handle_t hndl = static_cast<Handle_t>(params[3]);
   381 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   382 
   383 	if (!pPlayer)
   384 	{
   385 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   386 	}
   387 
   388 	if (!pPlayer->IsInGame())
   389 	{
   390 		return pContext->ThrowNativeError("Client %d is not in game", client);
   391 	}
   392 
   393 	if (hndl != BAD_HANDLE)
   394 	{
   395 		pKV = g_SourceMod.ReadKeyValuesHandle(hndl, &herr, true);
   396 		if (herr != HandleError_None)
   397 		{
   398 			return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
   399 		}
   400 	}
   401 
   402 	pContext->LocalToString(params[2], &name);
   403 
   404 	if (!g_HL2.ShowVGUIMenu(client, name, pKV, (params[4]) ? true : false))
   405 	{
   406 		return pContext->ThrowNativeError("Could not send a usermessage");
   407 	}
   408 
   409 	return 1;
   410 }
   411 
   412 static cell_t smn_IsPlayerAlive(IPluginContext *pContext, const cell_t *params)
   413 {
   414 	CPlayer *player = g_Players.GetPlayerByIndex(params[1]);
   415 	if (player == NULL)
   416 	{
   417 		return pContext->ThrowNativeError("Invalid client index %d", params[1]);
   418 	}
   419 	else if (!player->IsInGame())
   420 	{
   421 		return pContext->ThrowNativeError("Client %d is not in game", params[1]);
   422 	}
   423 
   424 	unsigned int state = player->GetLifeState();
   425 
   426 	if (state == PLAYER_LIFE_UNKNOWN)
   427 	{
   428 		return pContext->ThrowNativeError("\"IsPlayerAlive\" not supported by this mod");
   429 	}
   430 	else if (state == PLAYER_LIFE_ALIVE)
   431 	{
   432 		return 1;
   433 	}
   434 	else
   435 	{
   436 		return 0;
   437 	}
   438 }
   439 
   440 static cell_t GuessSDKVersion(IPluginContext *pContext, const cell_t *params)
   441 {
   442 #if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
   443 	int version = g_SMAPI->GetSourceEngineBuild();
   444 
   445 	switch (version)
   446 	{
   447 	case SOURCE_ENGINE_ORIGINAL:
   448 		return 10;
   449 	case SOURCE_ENGINE_EPISODEONE:
   450 		return 20;
   451 
   452 # if defined METAMOD_PLAPI_VERISON
   453 	/* Newer games. */
   454 	case SOURCE_ENGINE_DARKMESSIAH:
   455 		return 15;
   456 	case SOURCE_ENGINE_ORANGEBOX:
   457 		return 30;
   458 	case SOURCE_ENGINE_LEFT4DEAD:
   459 		return 40;
   460 # endif
   461 	}
   462 #else
   463 	if (g_HL2.IsOriginalEngine())
   464 	{
   465 		return 10;
   466 	}
   467 	else
   468 	{
   469 		return 20;
   470 	}
   471 #endif
   472 
   473 	return 0;
   474 }
   475 
   476 static cell_t IndexToReference(IPluginContext *pContext, const cell_t *params)
   477 {
   478 	if (params[1] >= NUM_ENT_ENTRIES || params[1] < 0)
   479 	{
   480 		return pContext->ThrowNativeError("Invalid entity index %i", params[1]);
   481 	}
   482 
   483 	return g_HL2.IndexToReference(params[1]);
   484 }
   485 
   486 static cell_t ReferenceToIndex(IPluginContext *pContext, const cell_t *params)
   487 {
   488 	return g_HL2.ReferenceToIndex(params[1]);
   489 }
   490 
   491 static cell_t ReferenceToBCompatRef(IPluginContext *pContext, const cell_t *params)
   492 {
   493 	return g_HL2.ReferenceToBCompatRef(params[1]);
   494 }
   495 
   496 REGISTER_NATIVES(halflifeNatives)
   497 {
   498 	{"CreateFakeClient",		CreateFakeClient},
   499 	{"GetCurrentMap",			GetCurrentMap},
   500 	{"GetEngineTime",			GetEngineTime},
   501 	{"GetGameDescription",		GetGameDescription},
   502 	{"GetGameFolderName",		GetGameFolderName},
   503 	{"GetGameTime",				GetGameTime},
   504 	{"GetRandomFloat",			GetRandomFloat},
   505 	{"GetRandomInt",			GetRandomInt},
   506 	{"IsDedicatedServer",		IsDedicatedServer},
   507 	{"IsMapValid",				IsMapValid},
   508 	{"SetFakeClientConVar",		SetFakeClientConVar},
   509 	{"SetRandomSeed",			SetRandomSeed},
   510 	{"PrecacheModel",			PrecacheModel},
   511 	{"PrecacheSentenceFile",	PrecacheSentenceFile},
   512 	{"PrecacheDecal",			PrecacheDecal},
   513 	{"PrecacheGeneric",			PrecacheGeneric},
   514 	{"IsModelPrecached",		IsModelPrecached},
   515 	{"IsDecalPrecached",		IsDecalPrecached},
   516 	{"IsGenericPrecached",		IsGenericPrecached},
   517 	{"PrecacheSound",			PrecacheSound},
   518 	{"IsSoundPrecached",		IsSoundPrecached},
   519 	{"CreateDialog",			smn_CreateDialog},
   520 	{"PrintToChat",				PrintToChat},
   521 	{"PrintCenterText",			PrintCenterText},
   522 	{"PrintHintText",			PrintHintText},
   523 	{"ShowVGUIPanel",			ShowVGUIPanel},
   524 	{"IsPlayerAlive",			smn_IsPlayerAlive},
   525 	{"GuessSDKVersion",			GuessSDKVersion},
   526 	{"EntIndexToEntRef",		IndexToReference},
   527 	{"EntRefToEntIndex",		ReferenceToIndex},
   528 	{"MakeCompatEntRef",		ReferenceToBCompatRef},
   529 	{NULL,						NULL},
   530 };