core/smn_player.cpp
author David Anderson <dvander@alliedmods.net>
Mon Jun 18 03:39:15 2007 +0000 (2007-06-18)
changeset 977 1dd1a7659ad4
parent 924 330f478a2d1d
child 992 77133031b0d2
permissions -rw-r--r--
fixed a bug where menu handler used wrong variable for param2 bitmask in MenuVoteEnd
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include "PlayerManager.h"
    16 #include "AdminCache.h"
    17 #include "sm_stringutil.h"
    18 #include "HalfLife2.h"
    19 #include "sourcemod.h"
    20 #include <inetchannelinfo.h>
    21 #include "ChatTriggers.h"
    22 
    23 ConVar sm_show_activity("sm_show_activity", "13", FCVAR_SPONLY|FCVAR_PROTECTED, "Activity display setting (see sourcemod.cfg)");
    24 
    25 static cell_t sm_GetClientCount(IPluginContext *pCtx, const cell_t *params)
    26 {
    27 	if (params[1])
    28 	{
    29 		return g_Players.NumPlayers();
    30 	}
    31 
    32 	int maxplayers = g_Players.MaxClients();
    33 	int count = 0;
    34 	for (int i=1; i<=maxplayers; ++i)
    35 	{
    36 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
    37 		if ((pPlayer->IsConnected()) && !(pPlayer->IsInGame()))
    38 		{
    39 			count++;
    40 		}
    41 	}
    42 
    43 	return (g_Players.NumPlayers() + count);
    44 }
    45 
    46 static cell_t sm_GetMaxClients(IPluginContext *pCtx, const cell_t *params)
    47 {
    48 	return g_Players.MaxClients();
    49 }
    50 
    51 static cell_t sm_GetClientName(IPluginContext *pCtx, const cell_t *params)
    52 {
    53 	int index = params[1];
    54 	if ((index < 1) || (index > g_Players.GetMaxClients()))
    55 	{
    56 		return pCtx->ThrowNativeError("Invalid client index %d", index);
    57 	}
    58 
    59 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
    60 	if (!pPlayer->IsConnected())
    61 	{
    62 		return pCtx->ThrowNativeError("Client %d is not connected", index);
    63 	}
    64 
    65 	pCtx->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pPlayer->GetName(), NULL);
    66 	return 1;
    67 }
    68 
    69 static cell_t sm_GetClientIP(IPluginContext *pCtx, const cell_t *params)
    70 {
    71 	int index = params[1];
    72 	if ((index < 1) || (index > g_Players.GetMaxClients()))
    73 	{
    74 		return pCtx->ThrowNativeError("Invalid client index %d", index);
    75 	}
    76 
    77 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
    78 	if (!pPlayer->IsConnected())
    79 	{
    80 		return pCtx->ThrowNativeError("Client %d is not connected", index);
    81 	}
    82 
    83 	char buf[64], *ptr;
    84 	strcpy(buf, pPlayer->GetIPAddress());
    85 
    86 	if (params[4] && (ptr = strchr(buf, ':')))
    87 	{
    88 		*ptr = '\0';
    89 	}
    90 
    91 	pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), buf);
    92 	return 1;
    93 }
    94 
    95 static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params)
    96 {
    97 	int index = params[1];
    98 	if ((index < 1) || (index > g_Players.GetMaxClients()))
    99 	{
   100 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   101 	}
   102 
   103 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
   104 	if (!pPlayer->IsConnected())
   105 	{
   106 		return pCtx->ThrowNativeError("Client %d is not connected", index);
   107 	}
   108 
   109 	if (!pPlayer->IsAuthorized())
   110 	{
   111 		return 0;
   112 	}
   113 
   114 	pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), pPlayer->GetAuthString());
   115 
   116 	return 1;
   117 }
   118 
   119 static cell_t sm_IsClientConnected(IPluginContext *pCtx, const cell_t *params)
   120 {
   121 	int index = params[1];
   122 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   123 	{
   124 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   125 	}
   126 
   127 	return (g_Players.GetPlayerByIndex(index)->IsConnected()) ? 1 : 0;
   128 }
   129 
   130 static cell_t sm_IsClientInGame(IPluginContext *pCtx, const cell_t *params)
   131 {
   132 	int index = params[1];
   133 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   134 	{
   135 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   136 	}
   137 
   138 	return (g_Players.GetPlayerByIndex(index)->IsInGame()) ? 1 : 0;
   139 }
   140 
   141 static cell_t sm_IsClientAuthorized(IPluginContext *pCtx, const cell_t *params)
   142 {
   143 	int index = params[1];
   144 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   145 	{
   146 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   147 	}
   148 
   149 	return (g_Players.GetPlayerByIndex(index)->IsAuthorized()) ? 1 : 0;
   150 }
   151 
   152 static cell_t sm_IsClientFakeClient(IPluginContext *pCtx, const cell_t *params)
   153 {
   154 	int index = params[1];
   155 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   156 	{
   157 		return pCtx->ThrowNativeError("Invalid client index %d", index);
   158 	}
   159 
   160 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
   161 	if (!pPlayer->IsConnected())
   162 	{
   163 		return pCtx->ThrowNativeError("Client %d is not connected", index);
   164 	}
   165 
   166 	return (pPlayer->IsFakeClient()) ? 1 : 0;
   167 }
   168 
   169 static cell_t sm_GetClientInfo(IPluginContext *pContext, const cell_t *params)
   170 {
   171 	int client = params[1];
   172 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   173 	if (!pPlayer)
   174 	{
   175 		return pContext->ThrowNativeError("Invalid client index %d", client);
   176 	}
   177 	if (!pPlayer->IsConnected())
   178 	{
   179 		return pContext->ThrowNativeError("Client %d is not connected", client);
   180 	}
   181 
   182 	char *key;
   183 	pContext->LocalToString(params[2], &key);
   184 
   185 	const char *val = engine->GetClientConVarValue(client, key);
   186 	if (!val)
   187 	{
   188 		return false;
   189 	}
   190 
   191 	pContext->StringToLocalUTF8(params[3], params[4], val, NULL);
   192 	return 1;
   193 }
   194 
   195 static cell_t SetUserAdmin(IPluginContext *pContext, const cell_t *params)
   196 {
   197 	int client = params[1];
   198 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   199 	if (!pPlayer)
   200 	{
   201 		return pContext->ThrowNativeError("Invalid client index %d", client);
   202 	}
   203 	if (!pPlayer->IsConnected())
   204 	{
   205 		return pContext->ThrowNativeError("Client %d is not connected", client);
   206 	}
   207 	if (!g_Admins.IsValidAdmin(params[2]))
   208 	{
   209 		return pContext->ThrowNativeError("AdminId %x is not valid", params[2]);
   210 	}
   211 
   212 	pPlayer->SetAdminId(params[2], params[3] ? true : false);
   213 
   214 	return 1;
   215 }
   216 
   217 static cell_t GetUserAdmin(IPluginContext *pContext, const cell_t *params)
   218 {
   219 	int client = params[1];
   220 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   221 	if (!pPlayer)
   222 	{
   223 		return pContext->ThrowNativeError("Invalid client index %d", client);
   224 	}
   225 	if (!pPlayer->IsConnected())
   226 	{
   227 		return pContext->ThrowNativeError("Client %d is not connected", client);
   228 	}
   229 
   230 	return pPlayer->GetAdminId();
   231 }
   232 
   233 static cell_t AddUserFlags(IPluginContext *pContext, const cell_t *params)
   234 {
   235 	int client = params[1];
   236 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   237 	if (!pPlayer)
   238 	{
   239 		return pContext->ThrowNativeError("Invalid client index %d", client);
   240 	}
   241 	if (!pPlayer->IsConnected())
   242 	{
   243 		return pContext->ThrowNativeError("Client %d is not connected", client);
   244 	}
   245 
   246 	AdminId id;
   247 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   248 	{
   249 		id = g_Admins.CreateAdmin(NULL);
   250 		pPlayer->SetAdminId(id, true);
   251 	}
   252 
   253 	cell_t *addr;
   254 	for (int i=2; i<=params[0]; i++)
   255 	{
   256 		pContext->LocalToPhysAddr(params[i], &addr);
   257 		g_Admins.SetAdminFlag(id, (AdminFlag)*addr, true);
   258 	}
   259 
   260 	return 1;
   261 }
   262 
   263 static cell_t RemoveUserFlags(IPluginContext *pContext, const cell_t *params)
   264 {
   265 	int client = params[1];
   266 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   267 	if (!pPlayer)
   268 	{
   269 		return pContext->ThrowNativeError("Invalid client index %d", client);
   270 	}
   271 	if (!pPlayer->IsConnected())
   272 	{
   273 		return pContext->ThrowNativeError("Client %d is not connected", client);
   274 	}
   275 	
   276 	AdminId id;
   277 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   278 	{
   279 		return 0;
   280 	}
   281 
   282 	cell_t *addr;
   283 	for (int i=2; i<=params[0]; i++)
   284 	{
   285 		pContext->LocalToPhysAddr(params[i], &addr);
   286 		g_Admins.SetAdminFlag(id, (AdminFlag)*addr, false);
   287 	}
   288 
   289 	return 1;
   290 }
   291 
   292 static cell_t SetUserFlagBits(IPluginContext *pContext, const cell_t *params)
   293 {
   294 	int client = params[1];
   295 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   296 	if (!pPlayer)
   297 	{
   298 		return pContext->ThrowNativeError("Invalid client index %d", client);
   299 	}
   300 	if (!pPlayer->IsConnected())
   301 	{
   302 		return pContext->ThrowNativeError("Client %d is not connected", client);
   303 	}
   304 
   305 	AdminId id;
   306 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   307 	{
   308 		id = g_Admins.CreateAdmin(NULL);
   309 		pPlayer->SetAdminId(id, true);
   310 	}
   311 
   312 	g_Admins.SetAdminFlags(id, Access_Effective, params[2]);
   313 
   314 	return 1;
   315 }
   316 
   317 static cell_t GetUserFlagBits(IPluginContext *pContext, const cell_t *params)
   318 {
   319 	int client = params[1];
   320 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   321 	if (!pPlayer)
   322 	{
   323 		return pContext->ThrowNativeError("Invalid client index %d", client);
   324 	}
   325 	if (!pPlayer->IsConnected())
   326 	{
   327 		return pContext->ThrowNativeError("Client %d is not connected", client);
   328 	}
   329 
   330 	AdminId id;
   331 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   332 	{
   333 		return 0;
   334 	}
   335 
   336 	return g_Admins.GetAdminFlags(id, Access_Effective);
   337 }
   338 
   339 static cell_t GetClientUserId(IPluginContext *pContext, const cell_t *params)
   340 {
   341 	int client = params[1];
   342 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   343 	if (!pPlayer)
   344 	{
   345 		return pContext->ThrowNativeError("Invalid client index %d", client);
   346 	}
   347 	if (!pPlayer->IsConnected())
   348 	{
   349 		return pContext->ThrowNativeError("Client %d is not connected", client);
   350 	}
   351 
   352 	return engine->GetPlayerUserId(pPlayer->GetEdict());
   353 }
   354 
   355 static cell_t CanUserTarget(IPluginContext *pContext, const cell_t *params)
   356 {
   357 	int client = params[1];
   358 	int target = params[2];
   359 
   360 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   361 	if (!pPlayer)
   362 	{
   363 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   364 	} else if (!pPlayer->IsConnected()) {
   365 		return pContext->ThrowNativeError("Player %d is not connected", client);
   366 	}
   367 
   368 	CPlayer *pTarget = g_Players.GetPlayerByIndex(target);
   369 	if (!pTarget)
   370 	{
   371 		return pContext->ThrowNativeError("Player %d is not a valid client", target);
   372 	} else if (!pTarget->IsConnected()) {
   373 		return pContext->ThrowNativeError("Player %d is not connected", target);
   374 	}
   375 
   376 	return g_Admins.CanAdminTarget(pPlayer->GetAdminId(), pTarget->GetAdminId()) ? 1 : 0;
   377 }
   378 
   379 static cell_t GetClientTeam(IPluginContext *pContext, const cell_t *params)
   380 {
   381 	int client = params[1];
   382 
   383 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   384 	if (!pPlayer)
   385 	{
   386 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   387 	} else if (!pPlayer->IsInGame()) {
   388 		return pContext->ThrowNativeError("Player %d is not in game", client);
   389 	}
   390 
   391 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   392 	if (!pInfo)
   393 	{
   394 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   395 	}
   396 
   397 	return pInfo->GetTeamIndex();
   398 }
   399 
   400 static cell_t GetFragCount(IPluginContext *pContext, const cell_t *params)
   401 {
   402 	int client = params[1];
   403 
   404 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   405 	if (!pPlayer)
   406 	{
   407 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   408 	} else if (!pPlayer->IsInGame()) {
   409 		return pContext->ThrowNativeError("Player %d is not in game", client);
   410 	}
   411 
   412 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   413 	if (!pInfo)
   414 	{
   415 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   416 	}
   417 
   418 	return pInfo->GetFragCount();
   419 }
   420 
   421 static cell_t GetDeathCount(IPluginContext *pContext, const cell_t *params)
   422 {
   423 	int client = params[1];
   424 
   425 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   426 	if (!pPlayer)
   427 	{
   428 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   429 	} else if (!pPlayer->IsInGame()) {
   430 		return pContext->ThrowNativeError("Player %d is not in game", client);
   431 	}
   432 
   433 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   434 	if (!pInfo)
   435 	{
   436 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   437 	}
   438 
   439 	return pInfo->GetDeathCount();
   440 }
   441 
   442 static cell_t GetArmorValue(IPluginContext *pContext, const cell_t *params)
   443 {
   444 	int client = params[1];
   445 
   446 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   447 	if (!pPlayer)
   448 	{
   449 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   450 	} else if (!pPlayer->IsInGame()) {
   451 		return pContext->ThrowNativeError("Player %d is not in game", client);
   452 	}
   453 
   454 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   455 	if (!pInfo)
   456 	{
   457 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   458 	}
   459 
   460 	return pInfo->GetArmorValue();
   461 }
   462 
   463 static cell_t GetAbsOrigin(IPluginContext *pContext, const cell_t *params)
   464 {
   465 	int client = params[1];
   466 
   467 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   468 	if (!pPlayer)
   469 	{
   470 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   471 	} else if (!pPlayer->IsInGame()) {
   472 		return pContext->ThrowNativeError("Player %d is not in game", client);
   473 	}
   474 
   475 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   476 	if (!pInfo)
   477 	{
   478 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   479 	}
   480 
   481 	cell_t *pVec;
   482 	pContext->LocalToPhysAddr(params[2], &pVec);
   483 
   484 	Vector vec = pInfo->GetAbsOrigin();
   485 	pVec[0] = sp_ftoc(vec.x);
   486 	pVec[1] = sp_ftoc(vec.y);
   487 	pVec[2] = sp_ftoc(vec.z);
   488 
   489 	return 1;
   490 }
   491 
   492 static cell_t GetAbsAngles(IPluginContext *pContext, const cell_t *params)
   493 {
   494 	int client = params[1];
   495 
   496 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   497 	if (!pPlayer)
   498 	{
   499 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   500 	} else if (!pPlayer->IsInGame()) {
   501 		return pContext->ThrowNativeError("Player %d is not in game", client);
   502 	}
   503 
   504 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   505 	if (!pInfo)
   506 	{
   507 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   508 	}
   509 
   510 	cell_t *pAng;
   511 	pContext->LocalToPhysAddr(params[2], &pAng);
   512 
   513 	QAngle ang = pInfo->GetAbsAngles();
   514 	pAng[0] = sp_ftoc(ang.x);
   515 	pAng[1] = sp_ftoc(ang.y);
   516 	pAng[2] = sp_ftoc(ang.z);
   517 
   518 	return 1;
   519 }
   520 
   521 static cell_t GetPlayerMins(IPluginContext *pContext, const cell_t *params)
   522 {
   523 	int client = params[1];
   524 
   525 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   526 	if (!pPlayer)
   527 	{
   528 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   529 	} else if (!pPlayer->IsInGame()) {
   530 		return pContext->ThrowNativeError("Player %d is not in game", client);
   531 	}
   532 
   533 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   534 	if (!pInfo)
   535 	{
   536 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   537 	}
   538 
   539 	cell_t *pVec;
   540 	pContext->LocalToPhysAddr(params[2], &pVec);
   541 
   542 	Vector vec = pInfo->GetPlayerMins();
   543 	pVec[0] = sp_ftoc(vec.x);
   544 	pVec[1] = sp_ftoc(vec.y);
   545 	pVec[2] = sp_ftoc(vec.z);
   546 
   547 	return 1;
   548 }
   549 
   550 static cell_t GetPlayerMaxs(IPluginContext *pContext, const cell_t *params)
   551 {
   552 	int client = params[1];
   553 
   554 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   555 	if (!pPlayer)
   556 	{
   557 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   558 	} else if (!pPlayer->IsInGame()) {
   559 		return pContext->ThrowNativeError("Player %d is not in game", client);
   560 	}
   561 
   562 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   563 	if (!pInfo)
   564 	{
   565 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   566 	}
   567 
   568 	cell_t *pVec;
   569 	pContext->LocalToPhysAddr(params[2], &pVec);
   570 
   571 	Vector vec = pInfo->GetPlayerMaxs();
   572 	pVec[0] = sp_ftoc(vec.x);
   573 	pVec[1] = sp_ftoc(vec.y);
   574 	pVec[2] = sp_ftoc(vec.z);
   575 
   576 	return 1;
   577 }
   578 
   579 static cell_t GetWeaponName(IPluginContext *pContext, const cell_t *params)
   580 {
   581 	int client = params[1];
   582 
   583 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   584 	if (!pPlayer)
   585 	{
   586 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   587 	} else if (!pPlayer->IsInGame()) {
   588 		return pContext->ThrowNativeError("Player %d is not in game", client);
   589 	}
   590 
   591 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   592 	if (!pInfo)
   593 	{
   594 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   595 	}
   596 
   597 	const char *weapon = pInfo->GetWeaponName();
   598 	pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), weapon ? weapon : "", NULL);
   599 
   600 	return 1;
   601 }
   602 
   603 static cell_t GetModelName(IPluginContext *pContext, const cell_t *params)
   604 {
   605 	int client = params[1];
   606 
   607 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   608 	if (!pPlayer)
   609 	{
   610 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   611 	} else if (!pPlayer->IsInGame()) {
   612 		return pContext->ThrowNativeError("Player %d is not in game", client);
   613 	}
   614 
   615 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   616 	if (!pInfo)
   617 	{
   618 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   619 	}
   620 
   621 	const char *model = pInfo->GetModelName();
   622 	pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), model ? model : "", NULL);
   623 
   624 	return 1;
   625 }
   626 
   627 static cell_t GetHealth(IPluginContext *pContext, const cell_t *params)
   628 {
   629 	int client = params[1];
   630 
   631 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   632 	if (!pPlayer)
   633 	{
   634 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   635 	} else if (!pPlayer->IsInGame()) {
   636 		return pContext->ThrowNativeError("Player %d is not in game", client);
   637 	}
   638 
   639 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   640 	if (!pInfo)
   641 	{
   642 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   643 	}
   644 
   645 	return pInfo->GetHealth();
   646 }
   647 
   648 static cell_t GetTimeConnected(IPluginContext *pContext, const cell_t *params)
   649 {
   650 	int client = params[1];
   651 
   652 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   653 	if (!pPlayer)
   654 	{
   655 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   656 	} else if (!pPlayer->IsInGame()) {
   657 		return pContext->ThrowNativeError("Player %d is not in game", client);
   658 	} else if (pPlayer->IsFakeClient()) {
   659 		return pContext->ThrowNativeError("Player %d is a bot", client);
   660 	}
   661 
   662 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   663 
   664 	return sp_ftoc(pInfo->GetTimeConnected());
   665 }
   666 
   667 static cell_t GetDataRate(IPluginContext *pContext, const cell_t *params)
   668 {
   669 	int client = params[1];
   670 
   671 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   672 	if (!pPlayer)
   673 	{
   674 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   675 	} else if (!pPlayer->IsInGame()) {
   676 		return pContext->ThrowNativeError("Player %d is not in game", client);
   677 	} else if (pPlayer->IsFakeClient()) {
   678 		return pContext->ThrowNativeError("Player %d is a bot", client);
   679 	}
   680 
   681 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   682 
   683 	return pInfo->GetDataRate();
   684 }
   685 
   686 static cell_t IsTimingOut(IPluginContext *pContext, const cell_t *params)
   687 {
   688 	int client = params[1];
   689 
   690 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   691 	if (!pPlayer)
   692 	{
   693 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   694 	} else if (!pPlayer->IsInGame()) {
   695 		return pContext->ThrowNativeError("Player %d is not in game", client);
   696 	} else if (pPlayer->IsFakeClient()) {
   697 		return pContext->ThrowNativeError("Player %d is a bot", client);
   698 	}
   699 
   700 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   701 
   702 	return pInfo->IsTimingOut() ? 1 : 0;
   703 }
   704 
   705 static cell_t GetLatency(IPluginContext *pContext, const cell_t *params)
   706 {
   707 	int client = params[1];
   708 
   709 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   710 	if (!pPlayer)
   711 	{
   712 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   713 	} else if (!pPlayer->IsInGame()) {
   714 		return pContext->ThrowNativeError("Player %d is not in game", client);
   715 	} else if (pPlayer->IsFakeClient()) {
   716 		return pContext->ThrowNativeError("Player %d is a bot", client);
   717 	}
   718 
   719 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   720 
   721 	return sp_ftoc(pInfo->GetLatency(params[2]));
   722 }
   723 
   724 static cell_t GetAvgLatency(IPluginContext *pContext, const cell_t *params)
   725 {
   726 	int client = params[1];
   727 
   728 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   729 	if (!pPlayer)
   730 	{
   731 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   732 	} else if (!pPlayer->IsInGame()) {
   733 		return pContext->ThrowNativeError("Player %d is not in game", client);
   734 	} else if (pPlayer->IsFakeClient()) {
   735 		return pContext->ThrowNativeError("Player %d is a bot", client);
   736 	}
   737 
   738 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   739 
   740 	return sp_ftoc(pInfo->GetAvgLatency(params[2]));
   741 }
   742 
   743 static cell_t GetAvgLoss(IPluginContext *pContext, const cell_t *params)
   744 {
   745 	int client = params[1];
   746 
   747 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   748 	if (!pPlayer)
   749 	{
   750 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   751 	} else if (!pPlayer->IsInGame()) {
   752 		return pContext->ThrowNativeError("Player %d is not in game", client);
   753 	} else if (pPlayer->IsFakeClient()) {
   754 		return pContext->ThrowNativeError("Player %d is a bot", client);
   755 	}
   756 
   757 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   758 
   759 	return sp_ftoc(pInfo->GetAvgLoss(params[2]));
   760 }
   761 
   762 static cell_t GetAvgChoke(IPluginContext *pContext, const cell_t *params)
   763 {
   764 	int client = params[1];
   765 
   766 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   767 	if (!pPlayer)
   768 	{
   769 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   770 	} else if (!pPlayer->IsInGame()) {
   771 		return pContext->ThrowNativeError("Player %d is not in game", client);
   772 	} else if (pPlayer->IsFakeClient()) {
   773 		return pContext->ThrowNativeError("Player %d is a bot", client);
   774 	}
   775 
   776 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   777 
   778 	return sp_ftoc(pInfo->GetAvgChoke(params[2]));
   779 }
   780 
   781 static cell_t GetAvgData(IPluginContext *pContext, const cell_t *params)
   782 {
   783 	int client = params[1];
   784 
   785 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   786 	if (!pPlayer)
   787 	{
   788 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   789 	} else if (!pPlayer->IsInGame()) {
   790 		return pContext->ThrowNativeError("Player %d is not in game", client);
   791 	} else if (pPlayer->IsFakeClient()) {
   792 		return pContext->ThrowNativeError("Player %d is a bot", client);
   793 	}
   794 
   795 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   796 
   797 	return sp_ftoc(pInfo->GetAvgData(params[2]));
   798 }
   799 
   800 static cell_t GetAvgPackets(IPluginContext *pContext, const cell_t *params)
   801 {
   802 	int client = params[1];
   803 
   804 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   805 	if (!pPlayer)
   806 	{
   807 		return pContext->ThrowNativeError("Player %d is not a valid client", client);
   808 	} else if (!pPlayer->IsInGame()) {
   809 		return pContext->ThrowNativeError("Player %d is not in game", client);
   810 	} else if (pPlayer->IsFakeClient()) {
   811 		return pContext->ThrowNativeError("Player %d is a bot", client);
   812 	}
   813 
   814 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   815 
   816 	return sp_ftoc(pInfo->GetAvgPackets(params[2]));
   817 }
   818 
   819 static cell_t GetClientOfUserId(IPluginContext *pContext, const cell_t *params)
   820 {
   821 	return g_Players.GetClientOfUserId(params[1]);
   822 }
   823 
   824 static cell_t ShowActivity(IPluginContext *pContext, const cell_t *params)
   825 {
   826 	char message[255];
   827 	char buffer[255];
   828 	int value = sm_show_activity.GetInt();
   829 	unsigned int replyto = g_ChatTriggers.GetReplyTo();
   830 	int client = params[1];
   831 
   832 	const char *name = "Console";
   833 	const char *sign = "ADMIN";
   834 	bool display_in_chat = false;
   835 	if (client != 0)
   836 	{
   837 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   838 		if (!pPlayer || !pPlayer->IsConnected())
   839 		{
   840 			return pContext->ThrowNativeError("Client index %d is invalid", client);
   841 		}
   842 		name = pPlayer->GetName();
   843 		AdminId id = pPlayer->GetAdminId();
   844 		if (id == INVALID_ADMIN_ID
   845 			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
   846 		{
   847 			sign = "PLAYER";
   848 		}
   849 
   850 		/* Display the message to the client? */
   851 		if (replyto == SM_REPLY_CONSOLE)
   852 		{
   853 			g_SourceMod.SetGlobalTarget(client);
   854 			g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   855 			UTIL_Format(message, sizeof(message), "[SM] %s\n", buffer);
   856 			engine->ClientPrintf(pPlayer->GetEdict(), message);
   857 			display_in_chat = true;
   858 		}
   859 	} else {
   860 		g_SourceMod.SetGlobalTarget(LANG_SERVER);
   861 		g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   862 		UTIL_Format(message, sizeof(message), "[SM] %s\n", buffer);
   863 		META_CONPRINT(message);
   864 	}
   865 
   866 	if (!value)
   867 	{
   868 		return 1;
   869 	}
   870 
   871 	int maxClients = g_Players.GetMaxClients();
   872 	for (int i=1; i<=maxClients; i++)
   873 	{
   874 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
   875 		if (!pPlayer->IsInGame() 
   876 			|| pPlayer->IsFakeClient()
   877 			|| (display_in_chat && i == client))
   878 		{
   879 			continue;
   880 		}
   881 		AdminId id = pPlayer->GetAdminId();
   882 		g_SourceMod.SetGlobalTarget(i);
   883 		if (id == INVALID_ADMIN_ID
   884 			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
   885 		{
   886 			/* Treat this as a normal user */
   887 			if ((value & 1) || (value & 2))
   888 			{
   889 				const char *newsign = sign;
   890 				if (value & 2)
   891 				{
   892 					newsign = name;
   893 				}
   894 				g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   895 				UTIL_Format(message, sizeof(message), "[SM] %s: %s", newsign, buffer);
   896 				g_HL2.TextMsg(i, HUD_PRINTTALK, message);
   897 			}
   898 		} else {
   899 			/* Treat this as an admin user */
   900 			bool is_root = g_Admins.GetAdminFlag(id, Admin_Root, Access_Effective);
   901 			if ((value & 4) 
   902 				|| (value & 8)
   903 				|| ((value & 16) && is_root))
   904 			{
   905 				const char *newsign = sign;
   906 				if ((value & 8) || ((value & 16) && is_root))
   907 				{
   908 					newsign = name;
   909 				}
   910 				g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   911 				UTIL_Format(message, sizeof(message), "[SM] %s: %s", newsign, buffer);
   912 				g_HL2.TextMsg(i, HUD_PRINTTALK, message);
   913 			}
   914 		}
   915 	}
   916 
   917 	return 1;
   918 }
   919 
   920 REGISTER_NATIVES(playernatives)
   921 {
   922 	{"AddUserFlags",			AddUserFlags},
   923 	{"CanUserTarget",			CanUserTarget},
   924 	{"GetClientAuthString",		sm_GetClientAuthStr},
   925 	{"GetClientCount",			sm_GetClientCount},
   926 	{"GetClientInfo",			sm_GetClientInfo},
   927 	{"GetClientIP",				sm_GetClientIP},
   928 	{"GetClientName",			sm_GetClientName},
   929 	{"GetClientTeam",			GetClientTeam},
   930 	{"GetClientUserId",			GetClientUserId},
   931 	{"GetMaxClients",			sm_GetMaxClients},
   932 	{"GetUserAdmin",			GetUserAdmin},
   933 	{"GetUserFlagBits",			GetUserFlagBits},
   934 	{"IsClientAuthorized",		sm_IsClientAuthorized},
   935 	{"IsClientConnected",		sm_IsClientConnected},
   936 	{"IsFakeClient",			sm_IsClientFakeClient},
   937 	{"IsPlayerInGame",			sm_IsClientInGame},			/* Backwards compat shim */
   938 	{"IsClientInGame",			sm_IsClientInGame},
   939 	{"RemoveUserFlags",			RemoveUserFlags},
   940 	{"SetUserAdmin",			SetUserAdmin},
   941 	{"SetUserFlagBits",			SetUserFlagBits},
   942 	{"GetClientDeaths",			GetDeathCount},
   943 	{"GetClientFrags",			GetFragCount},
   944 	{"GetClientArmor",			GetArmorValue},
   945 	{"GetClientAbsOrigin",		GetAbsOrigin},
   946 	{"GetClientAbsAngles",		GetAbsAngles},
   947 	{"GetClientMins",			GetPlayerMins},
   948 	{"GetClientMaxs",			GetPlayerMaxs},
   949 	{"GetClientWeapon",			GetWeaponName},
   950 	{"GetClientModel",			GetModelName},
   951 	{"GetClientHealth",			GetHealth},
   952 	{"GetClientTime",			GetTimeConnected},
   953 	{"GetClientDataRate",		GetDataRate},
   954 	{"IsClentTimingOut",		IsTimingOut},
   955 	{"GetClientLatency",		GetLatency},
   956 	{"GetClientAvgLatency",		GetAvgLatency},
   957 	{"GetClientAvgLoss",		GetAvgLoss},
   958 	{"GetClientAvgChoke",		GetAvgChoke},
   959 	{"GetClientAvgData",		GetAvgData},
   960 	{"GetClientAvgPackets",		GetAvgPackets},
   961 	{"GetClientOfUserId",		GetClientOfUserId},
   962 	{"ShowActivity",			ShowActivity},
   963 	{NULL,						NULL}
   964 };