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