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