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