core/smn_player.cpp
author David Anderson <dvander@alliedmods.net>
Fri Oct 02 03:47:42 2009 -0700 (2009-10-02)
changeset 2815 2c7137f077fe
parent 2591 15213de19689
child 2961 c3bb13e8760b
permissions -rw-r--r--
Re-enabled PDB files.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "PlayerManager.h"
    33 #include "AdminCache.h"
    34 #include "sm_stringutil.h"
    35 #include "HalfLife2.h"
    36 #include "sourcemod.h"
    37 #include "ChatTriggers.h"
    38 #include <inetchannel.h>
    39 #include <iclient.h>
    40 
    41 ConVar sm_show_activity("sm_show_activity", "13", FCVAR_SPONLY, "Activity display setting (see sourcemod.cfg)");
    42 
    43 static cell_t sm_GetClientCount(IPluginContext *pCtx, const cell_t *params)
    44 {
    45 	if (params[1])
    46 	{
    47 		return g_Players.NumPlayers();
    48 	}
    49 
    50 	int maxplayers = g_Players.MaxClients();
    51 	int count = 0;
    52 	for (int i=1; i<=maxplayers; ++i)
    53 	{
    54 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
    55 		if ((pPlayer->IsConnected()) && !(pPlayer->IsInGame()))
    56 		{
    57 			count++;
    58 		}
    59 	}
    60 
    61 	return (g_Players.NumPlayers() + count);
    62 }
    63 
    64 static cell_t sm_GetMaxClients(IPluginContext *pCtx, const cell_t *params)
    65 {
    66 	return g_Players.MaxClients();
    67 }
    68 
    69 static cell_t sm_GetClientName(IPluginContext *pCtx, const cell_t *params)
    70 {
    71 	int index = params[1];
    72 
    73 	if (index == 0)
    74 	{
    75 		static ConVar *hostname = NULL;
    76 		if (!hostname)
    77 		{
    78 			hostname = icvar->FindVar("hostname");
    79 			if (!hostname)
    80 			{
    81 				return pCtx->ThrowNativeError("Could not find \"hostname\" cvar");
    82 			}
    83 		}
    84 		pCtx->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), hostname->GetString(), NULL);
    85 		return 1;
    86 	}
    87 
    88 	if ((index < 1) || (index > g_Players.GetMaxClients()))
    89 	{
    90 		return pCtx->ThrowNativeError("Client index %d is invalid", index);
    91 	}
    92 
    93 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
    94 	if (!pPlayer->IsConnected())
    95 	{
    96 		return pCtx->ThrowNativeError("Client %d is not connected", index);
    97 	}
    98 
    99 	pCtx->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pPlayer->GetName(), NULL);
   100 	return 1;
   101 }
   102 
   103 static cell_t sm_GetClientIP(IPluginContext *pCtx, const cell_t *params)
   104 {
   105 	int index = params[1];
   106 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   107 	{
   108 		return pCtx->ThrowNativeError("Client index %d is invalid", index);
   109 	}
   110 
   111 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
   112 	if (!pPlayer->IsConnected())
   113 	{
   114 		return pCtx->ThrowNativeError("Client %d is not connected", index);
   115 	}
   116 
   117 	char buf[64], *ptr;
   118 	strcpy(buf, pPlayer->GetIPAddress());
   119 
   120 	if (params[4] && (ptr = strchr(buf, ':')))
   121 	{
   122 		*ptr = '\0';
   123 	}
   124 
   125 	pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), buf);
   126 	return 1;
   127 }
   128 
   129 static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params)
   130 {
   131 	int index = params[1];
   132 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   133 	{
   134 		return pCtx->ThrowNativeError("Client index %d is invalid", index);
   135 	}
   136 
   137 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
   138 	if (!pPlayer->IsConnected())
   139 	{
   140 		return pCtx->ThrowNativeError("Client %d is not connected", index);
   141 	}
   142 
   143 	if (!pPlayer->IsAuthorized())
   144 	{
   145 		return 0;
   146 	}
   147 
   148 	pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), pPlayer->GetAuthString());
   149 
   150 	return 1;
   151 }
   152 
   153 static cell_t sm_IsClientConnected(IPluginContext *pCtx, const cell_t *params)
   154 {
   155 	int index = params[1];
   156 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   157 	{
   158 		return pCtx->ThrowNativeError("Client index %d is invalid", index);
   159 	}
   160 
   161 	return (g_Players.GetPlayerByIndex(index)->IsConnected()) ? 1 : 0;
   162 }
   163 
   164 static cell_t sm_IsClientInGame(IPluginContext *pCtx, const cell_t *params)
   165 {
   166 	int index = params[1];
   167 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   168 	{
   169 		return pCtx->ThrowNativeError("Client index %d is invalid", index);
   170 	}
   171 
   172 	return (g_Players.GetPlayerByIndex(index)->IsInGame()) ? 1 : 0;
   173 }
   174 
   175 static cell_t sm_IsClientAuthorized(IPluginContext *pCtx, const cell_t *params)
   176 {
   177 	int index = params[1];
   178 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   179 	{
   180 		return pCtx->ThrowNativeError("Client index %d is invalid", index);
   181 	}
   182 
   183 	return (g_Players.GetPlayerByIndex(index)->IsAuthorized()) ? 1 : 0;
   184 }
   185 
   186 static cell_t sm_IsClientFakeClient(IPluginContext *pCtx, const cell_t *params)
   187 {
   188 	int index = params[1];
   189 	if ((index < 1) || (index > g_Players.GetMaxClients()))
   190 	{
   191 		return pCtx->ThrowNativeError("Client index %d is invalid", index);
   192 	}
   193 
   194 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
   195 	if (!pPlayer->IsConnected())
   196 	{
   197 		return pCtx->ThrowNativeError("Client %d is not connected", index);
   198 	}
   199 
   200 	return (pPlayer->IsFakeClient()) ? 1 : 0;
   201 }
   202 
   203 static cell_t IsClientObserver(IPluginContext *pContext, const cell_t *params)
   204 {
   205 	int client = params[1];
   206 
   207 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   208 	if (!pPlayer)
   209 	{
   210 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   211 	} else if (!pPlayer->IsInGame()) {
   212 		return pContext->ThrowNativeError("Client %d is not in game", client);
   213 	}
   214 
   215 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   216 	if (!pInfo)
   217 	{
   218 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   219 	}
   220 
   221 	return pInfo->IsObserver() ? 1 : 0;
   222 }
   223 
   224 static cell_t sm_GetClientInfo(IPluginContext *pContext, const cell_t *params)
   225 {
   226 	int client = params[1];
   227 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   228 	if (!pPlayer)
   229 	{
   230 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   231 	}
   232 	if (!pPlayer->IsConnected())
   233 	{
   234 		return pContext->ThrowNativeError("Client %d is not connected", client);
   235 	}
   236 
   237 	char *key;
   238 	pContext->LocalToString(params[2], &key);
   239 
   240 	const char *val = engine->GetClientConVarValue(client, key);
   241 	if (!val)
   242 	{
   243 		return false;
   244 	}
   245 
   246 	pContext->StringToLocalUTF8(params[3], params[4], val, NULL);
   247 	return 1;
   248 }
   249 
   250 static cell_t SetUserAdmin(IPluginContext *pContext, const cell_t *params)
   251 {
   252 	int client = params[1];
   253 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   254 	if (!pPlayer)
   255 	{
   256 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   257 	}
   258 	if (!pPlayer->IsConnected())
   259 	{
   260 		return pContext->ThrowNativeError("Client %d is not connected", client);
   261 	}
   262 	if (!g_Admins.IsValidAdmin(params[2]) && params[2] != INVALID_ADMIN_ID)
   263 	{
   264 		return pContext->ThrowNativeError("AdminId %x is invalid", params[2]);
   265 	}
   266 
   267 	pPlayer->SetAdminId(params[2], params[3] ? true : false);
   268 
   269 	return 1;
   270 }
   271 
   272 static cell_t GetUserAdmin(IPluginContext *pContext, const cell_t *params)
   273 {
   274 	int client = params[1];
   275 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   276 	if (!pPlayer)
   277 	{
   278 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   279 	}
   280 	if (!pPlayer->IsConnected())
   281 	{
   282 		return pContext->ThrowNativeError("Client %d is not connected", client);
   283 	}
   284 
   285 	return pPlayer->GetAdminId();
   286 }
   287 
   288 static cell_t AddUserFlags(IPluginContext *pContext, const cell_t *params)
   289 {
   290 	int client = params[1];
   291 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   292 	if (!pPlayer)
   293 	{
   294 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   295 	}
   296 	if (!pPlayer->IsConnected())
   297 	{
   298 		return pContext->ThrowNativeError("Client %d is not connected", client);
   299 	}
   300 
   301 	AdminId id;
   302 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   303 	{
   304 		id = g_Admins.CreateAdmin(NULL);
   305 		pPlayer->SetAdminId(id, true);
   306 	}
   307 
   308 	cell_t *addr;
   309 	for (int i=2; i<=params[0]; i++)
   310 	{
   311 		pContext->LocalToPhysAddr(params[i], &addr);
   312 		g_Admins.SetAdminFlag(id, (AdminFlag)*addr, true);
   313 	}
   314 
   315 	return 1;
   316 }
   317 
   318 static cell_t RemoveUserFlags(IPluginContext *pContext, const cell_t *params)
   319 {
   320 	int client = params[1];
   321 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   322 	if (!pPlayer)
   323 	{
   324 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   325 	}
   326 	if (!pPlayer->IsConnected())
   327 	{
   328 		return pContext->ThrowNativeError("Client %d is not connected", client);
   329 	}
   330 	
   331 	AdminId id;
   332 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   333 	{
   334 		return 0;
   335 	}
   336 
   337 	cell_t *addr;
   338 	for (int i=2; i<=params[0]; i++)
   339 	{
   340 		pContext->LocalToPhysAddr(params[i], &addr);
   341 		g_Admins.SetAdminFlag(id, (AdminFlag)*addr, false);
   342 	}
   343 
   344 	return 1;
   345 }
   346 
   347 static cell_t SetUserFlagBits(IPluginContext *pContext, const cell_t *params)
   348 {
   349 	int client = params[1];
   350 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   351 	if (!pPlayer)
   352 	{
   353 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   354 	}
   355 	if (!pPlayer->IsConnected())
   356 	{
   357 		return pContext->ThrowNativeError("Client %d is not connected", client);
   358 	}
   359 
   360 	AdminId id;
   361 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   362 	{
   363 		id = g_Admins.CreateAdmin(NULL);
   364 		pPlayer->SetAdminId(id, true);
   365 	}
   366 
   367 	g_Admins.SetAdminFlags(id, Access_Effective, params[2]);
   368 
   369 	return 1;
   370 }
   371 
   372 static cell_t GetUserFlagBits(IPluginContext *pContext, const cell_t *params)
   373 {
   374 	int client = params[1];
   375 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   376 	if (!pPlayer)
   377 	{
   378 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   379 	}
   380 	if (!pPlayer->IsConnected())
   381 	{
   382 		return pContext->ThrowNativeError("Client %d is not connected", client);
   383 	}
   384 
   385 	AdminId id;
   386 	if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
   387 	{
   388 		return 0;
   389 	}
   390 
   391 	return g_Admins.GetAdminFlags(id, Access_Effective);
   392 }
   393 
   394 static cell_t GetClientUserId(IPluginContext *pContext, const cell_t *params)
   395 {
   396 	int client = params[1];
   397 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   398 	if (!pPlayer)
   399 	{
   400 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   401 	}
   402 	if (!pPlayer->IsConnected())
   403 	{
   404 		return pContext->ThrowNativeError("Client %d is not connected", client);
   405 	}
   406 
   407 	return engine->GetPlayerUserId(pPlayer->GetEdict());
   408 }
   409 
   410 static cell_t CanUserTarget(IPluginContext *pContext, const cell_t *params)
   411 {
   412 	int client = params[1];
   413 	int target = params[2];
   414 
   415 	if (client == 0)
   416 	{
   417 		return 1;
   418 	}
   419 
   420 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   421 	if (!pPlayer)
   422 	{
   423 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   424 	} else if (!pPlayer->IsConnected()) {
   425 		return pContext->ThrowNativeError("Client %d is not connected", client);
   426 	}
   427 
   428 	CPlayer *pTarget = g_Players.GetPlayerByIndex(target);
   429 	if (!pTarget)
   430 	{
   431 		return pContext->ThrowNativeError("Client index %d is invalid", target);
   432 	} else if (!pTarget->IsConnected()) {
   433 		return pContext->ThrowNativeError("Client %d is not connected", target);
   434 	}
   435 
   436 	return g_Admins.CanAdminTarget(pPlayer->GetAdminId(), pTarget->GetAdminId()) ? 1 : 0;
   437 }
   438 
   439 static cell_t GetClientTeam(IPluginContext *pContext, const cell_t *params)
   440 {
   441 	int client = params[1];
   442 
   443 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   444 	if (!pPlayer)
   445 	{
   446 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   447 	} else if (!pPlayer->IsInGame()) {
   448 		return pContext->ThrowNativeError("Client %d is not in game", client);
   449 	}
   450 
   451 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   452 	if (!pInfo)
   453 	{
   454 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   455 	}
   456 
   457 	return pInfo->GetTeamIndex();
   458 }
   459 
   460 static cell_t GetFragCount(IPluginContext *pContext, const cell_t *params)
   461 {
   462 	int client = params[1];
   463 
   464 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   465 	if (!pPlayer)
   466 	{
   467 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   468 	} else if (!pPlayer->IsInGame()) {
   469 		return pContext->ThrowNativeError("Client %d is not in game", client);
   470 	}
   471 
   472 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   473 	if (!pInfo)
   474 	{
   475 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   476 	}
   477 
   478 	return pInfo->GetFragCount();
   479 }
   480 
   481 static cell_t GetDeathCount(IPluginContext *pContext, const cell_t *params)
   482 {
   483 	int client = params[1];
   484 
   485 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   486 	if (!pPlayer)
   487 	{
   488 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   489 	} else if (!pPlayer->IsInGame()) {
   490 		return pContext->ThrowNativeError("Client %d is not in game", client);
   491 	}
   492 
   493 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   494 	if (!pInfo)
   495 	{
   496 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   497 	}
   498 
   499 	return pInfo->GetDeathCount();
   500 }
   501 
   502 static cell_t GetArmorValue(IPluginContext *pContext, const cell_t *params)
   503 {
   504 	int client = params[1];
   505 
   506 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   507 	if (!pPlayer)
   508 	{
   509 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   510 	} else if (!pPlayer->IsInGame()) {
   511 		return pContext->ThrowNativeError("Client %d is not in game", client);
   512 	}
   513 
   514 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   515 	if (!pInfo)
   516 	{
   517 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   518 	}
   519 
   520 	return pInfo->GetArmorValue();
   521 }
   522 
   523 static cell_t GetAbsOrigin(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->GetAbsOrigin();
   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 GetAbsAngles(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 *pAng;
   571 	pContext->LocalToPhysAddr(params[2], &pAng);
   572 
   573 	QAngle ang = pInfo->GetAbsAngles();
   574 	pAng[0] = sp_ftoc(ang.x);
   575 	pAng[1] = sp_ftoc(ang.y);
   576 	pAng[2] = sp_ftoc(ang.z);
   577 
   578 	return 1;
   579 }
   580 
   581 static cell_t GetPlayerMins(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 	cell_t *pVec;
   600 	pContext->LocalToPhysAddr(params[2], &pVec);
   601 
   602 	Vector vec = pInfo->GetPlayerMins();
   603 	pVec[0] = sp_ftoc(vec.x);
   604 	pVec[1] = sp_ftoc(vec.y);
   605 	pVec[2] = sp_ftoc(vec.z);
   606 
   607 	return 1;
   608 }
   609 
   610 static cell_t GetPlayerMaxs(IPluginContext *pContext, const cell_t *params)
   611 {
   612 	int client = params[1];
   613 
   614 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   615 	if (!pPlayer)
   616 	{
   617 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   618 	} else if (!pPlayer->IsInGame()) {
   619 		return pContext->ThrowNativeError("Client %d is not in game", client);
   620 	}
   621 
   622 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   623 	if (!pInfo)
   624 	{
   625 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   626 	}
   627 
   628 	cell_t *pVec;
   629 	pContext->LocalToPhysAddr(params[2], &pVec);
   630 
   631 	Vector vec = pInfo->GetPlayerMaxs();
   632 	pVec[0] = sp_ftoc(vec.x);
   633 	pVec[1] = sp_ftoc(vec.y);
   634 	pVec[2] = sp_ftoc(vec.z);
   635 
   636 	return 1;
   637 }
   638 
   639 static cell_t GetWeaponName(IPluginContext *pContext, const cell_t *params)
   640 {
   641 	int client = params[1];
   642 
   643 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   644 	if (!pPlayer)
   645 	{
   646 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   647 	} else if (!pPlayer->IsInGame()) {
   648 		return pContext->ThrowNativeError("Client %d is not in game", client);
   649 	}
   650 
   651 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   652 	if (!pInfo)
   653 	{
   654 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   655 	}
   656 
   657 	const char *weapon = pInfo->GetWeaponName();
   658 	pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), weapon ? weapon : "", NULL);
   659 
   660 	return 1;
   661 }
   662 
   663 static cell_t GetModelName(IPluginContext *pContext, const cell_t *params)
   664 {
   665 	int client = params[1];
   666 
   667 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   668 	if (!pPlayer)
   669 	{
   670 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   671 	} else if (!pPlayer->IsInGame()) {
   672 		return pContext->ThrowNativeError("Client %d is not in game", client);
   673 	}
   674 
   675 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   676 	if (!pInfo)
   677 	{
   678 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   679 	}
   680 
   681 	const char *model = pInfo->GetModelName();
   682 	pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), model ? model : "", NULL);
   683 
   684 	return 1;
   685 }
   686 
   687 static cell_t GetHealth(IPluginContext *pContext, const cell_t *params)
   688 {
   689 	int client = params[1];
   690 
   691 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   692 	if (!pPlayer)
   693 	{
   694 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   695 	} else if (!pPlayer->IsInGame()) {
   696 		return pContext->ThrowNativeError("Client %d is not in game", client);
   697 	}
   698 
   699 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
   700 	if (!pInfo)
   701 	{
   702 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
   703 	}
   704 
   705 	return pInfo->GetHealth();
   706 }
   707 
   708 static cell_t GetTimeConnected(IPluginContext *pContext, const cell_t *params)
   709 {
   710 	int client = params[1];
   711 
   712 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   713 	if (!pPlayer)
   714 	{
   715 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   716 	} else if (!pPlayer->IsInGame()) {
   717 		return pContext->ThrowNativeError("Client %d is not in game", client);
   718 	} else if (pPlayer->IsFakeClient()) {
   719 		return pContext->ThrowNativeError("Client %d is a bot", client);
   720 	}
   721 
   722 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   723 
   724 	return sp_ftoc(pInfo->GetTimeConnected());
   725 }
   726 
   727 static cell_t GetDataRate(IPluginContext *pContext, const cell_t *params)
   728 {
   729 	int client = params[1];
   730 
   731 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   732 	if (!pPlayer)
   733 	{
   734 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   735 	} else if (!pPlayer->IsInGame()) {
   736 		return pContext->ThrowNativeError("Client %d is not in game", client);
   737 	} else if (pPlayer->IsFakeClient()) {
   738 		return pContext->ThrowNativeError("Client %d is a bot", client);
   739 	}
   740 
   741 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   742 
   743 	return pInfo->GetDataRate();
   744 }
   745 
   746 static cell_t IsTimingOut(IPluginContext *pContext, const cell_t *params)
   747 {
   748 	int client = params[1];
   749 
   750 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   751 	if (!pPlayer)
   752 	{
   753 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   754 	} else if (!pPlayer->IsInGame()) {
   755 		return pContext->ThrowNativeError("Client %d is not in game", client);
   756 	} else if (pPlayer->IsFakeClient()) {
   757 		return pContext->ThrowNativeError("Client %d is a bot", client);
   758 	}
   759 
   760 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   761 
   762 	return pInfo->IsTimingOut() ? 1 : 0;
   763 }
   764 
   765 static cell_t GetLatency(IPluginContext *pContext, const cell_t *params)
   766 {
   767 	int client = params[1];
   768 	float value;
   769 
   770 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   771 	if (!pPlayer)
   772 	{
   773 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   774 	}
   775 	else if (!pPlayer->IsInGame())
   776 	{
   777 		return pContext->ThrowNativeError("Client %d is not in game", client);
   778 	}
   779 	else if (pPlayer->IsFakeClient())
   780 	{
   781 		return pContext->ThrowNativeError("Client %d is a bot", client);
   782 	}
   783 
   784 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   785 
   786 	if (params[2] == MAX_FLOWS)
   787 	{
   788 		value = pInfo->GetLatency(FLOW_INCOMING) + pInfo->GetLatency(FLOW_OUTGOING);
   789 	}
   790 	else
   791 	{
   792 		value = pInfo->GetLatency(params[2]);
   793 	}
   794 
   795 	return sp_ftoc(value);
   796 }
   797 
   798 static cell_t GetAvgLatency(IPluginContext *pContext, const cell_t *params)
   799 {
   800 	int client = params[1];
   801 	float value;
   802 
   803 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   804 	if (!pPlayer)
   805 	{
   806 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   807 	}
   808 	else if (!pPlayer->IsInGame())
   809 	{
   810 		return pContext->ThrowNativeError("Client %d is not in game", client);
   811 	}
   812 	else if (pPlayer->IsFakeClient())
   813 	{
   814 		return pContext->ThrowNativeError("Client %d is a bot", client);
   815 	}
   816 
   817 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   818 
   819 	if (params[2] == MAX_FLOWS)
   820 	{
   821 		value = pInfo->GetAvgLatency(FLOW_INCOMING) + pInfo->GetAvgLatency(FLOW_OUTGOING);
   822 	}
   823 	else
   824 	{
   825 		value = pInfo->GetAvgLatency(params[2]);
   826 	}
   827 
   828 	return sp_ftoc(value);
   829 }
   830 
   831 static cell_t GetAvgLoss(IPluginContext *pContext, const cell_t *params)
   832 {
   833 	int client = params[1];
   834 	float value;
   835 
   836 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   837 	if (!pPlayer)
   838 	{
   839 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   840 	}
   841 	else if (!pPlayer->IsInGame())
   842 	{
   843 		return pContext->ThrowNativeError("Client %d is not in game", client);
   844 	}
   845 	else if (pPlayer->IsFakeClient())
   846 	{
   847 		return pContext->ThrowNativeError("Client %d is a bot", client);
   848 	}
   849 
   850 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   851 
   852 	if (params[2] == MAX_FLOWS)
   853 	{
   854 		value = pInfo->GetAvgLoss(FLOW_INCOMING) + pInfo->GetAvgLoss(FLOW_OUTGOING);
   855 	}
   856 	else
   857 	{
   858 		value = pInfo->GetAvgLoss(params[2]);
   859 	}
   860 
   861 	return sp_ftoc(value);
   862 }
   863 
   864 static cell_t GetAvgChoke(IPluginContext *pContext, const cell_t *params)
   865 {
   866 	int client = params[1];
   867 	float value;
   868 
   869 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   870 	if (!pPlayer)
   871 	{
   872 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   873 	}
   874 	else if (!pPlayer->IsInGame())
   875 	{
   876 		return pContext->ThrowNativeError("Client %d is not in game", client);
   877 	}
   878 	else if (pPlayer->IsFakeClient())
   879 	{
   880 		return pContext->ThrowNativeError("Client %d is a bot", client);
   881 	}
   882 
   883 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   884 
   885 	if (params[2] == MAX_FLOWS)
   886 	{
   887 		value = pInfo->GetAvgChoke(FLOW_INCOMING) + pInfo->GetAvgChoke(FLOW_OUTGOING);
   888 	}
   889 	else
   890 	{
   891 		value = pInfo->GetAvgChoke(params[2]);
   892 	}
   893 
   894 	return sp_ftoc(value);
   895 }
   896 
   897 static cell_t GetAvgData(IPluginContext *pContext, const cell_t *params)
   898 {
   899 	int client = params[1];
   900 	float value;
   901 
   902 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   903 	if (!pPlayer)
   904 	{
   905 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   906 	}
   907 	else if (!pPlayer->IsInGame())
   908 	{
   909 		return pContext->ThrowNativeError("Client %d is not in game", client);
   910 	}
   911 	else if (pPlayer->IsFakeClient())
   912 	{
   913 		return pContext->ThrowNativeError("Client %d is a bot", client);
   914 	}
   915 
   916 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   917 
   918 	if (params[2] == MAX_FLOWS)
   919 	{
   920 		value = pInfo->GetAvgData(FLOW_INCOMING) + pInfo->GetAvgData(FLOW_OUTGOING);
   921 	}
   922 	else
   923 	{
   924 		value = pInfo->GetAvgData(params[2]);
   925 	}
   926 
   927 	return sp_ftoc(value);
   928 }
   929 
   930 static cell_t GetAvgPackets(IPluginContext *pContext, const cell_t *params)
   931 {
   932 	int client = params[1];
   933 	float value;
   934 
   935 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   936 	if (!pPlayer)
   937 	{
   938 		return pContext->ThrowNativeError("Client index %d is invalid", client);
   939 	}
   940 	else if (!pPlayer->IsInGame())
   941 	{
   942 		return pContext->ThrowNativeError("Client %d is not in game", client);
   943 	}
   944 	else if (pPlayer->IsFakeClient())
   945 	{
   946 		return pContext->ThrowNativeError("Client %d is a bot", client);
   947 	}
   948 
   949 	INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
   950 
   951 	if (params[2] == MAX_FLOWS)
   952 	{
   953 		value = pInfo->GetAvgPackets(FLOW_INCOMING) + pInfo->GetAvgPackets(FLOW_OUTGOING);
   954 	}
   955 	else
   956 	{
   957 		value = pInfo->GetAvgPackets(params[2]);
   958 	}
   959 
   960 	return sp_ftoc(value);
   961 }
   962 
   963 static cell_t GetClientOfUserId(IPluginContext *pContext, const cell_t *params)
   964 {
   965 	return g_Players.GetClientOfUserId(params[1]);
   966 }
   967 
   968 static cell_t _ShowActivity(IPluginContext *pContext,
   969 							const cell_t *params,
   970 							const char *tag,
   971 							cell_t fmt_param)
   972 {
   973 	char message[255];
   974 	char buffer[255];
   975 	int value = sm_show_activity.GetInt();
   976 	unsigned int replyto = g_ChatTriggers.GetReplyTo();
   977 	int client = params[1];
   978 
   979 	const char *name = "Console";
   980 	const char *sign = "ADMIN";
   981 	bool display_in_chat = false;
   982 	if (client != 0)
   983 	{
   984 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
   985 		if (!pPlayer || !pPlayer->IsConnected())
   986 		{
   987 			return pContext->ThrowNativeError("Client index %d is invalid", client);
   988 		}
   989 		name = pPlayer->GetName();
   990 		AdminId id = pPlayer->GetAdminId();
   991 		if (id == INVALID_ADMIN_ID
   992 			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
   993 		{
   994 			sign = "PLAYER";
   995 		}
   996 
   997 		/* Display the message to the client? */
   998 		if (replyto == SM_REPLY_CONSOLE)
   999 		{
  1000 			g_SourceMod.SetGlobalTarget(client);
  1001 			g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
  1002 
  1003 			if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1004 			{
  1005 				return 0;
  1006 			}
  1007 
  1008 			UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
  1009 			engine->ClientPrintf(pPlayer->GetEdict(), message);
  1010 			display_in_chat = true;
  1011 		}
  1012 	}
  1013 	else
  1014 	{
  1015 		g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
  1016 		g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
  1017 
  1018 		if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1019 		{
  1020 			return 0;
  1021 		}
  1022 
  1023 		UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
  1024 		META_CONPRINT(message);
  1025 	}
  1026 
  1027 	if (!value)
  1028 	{
  1029 		return 1;
  1030 	}
  1031 
  1032 	int maxClients = g_Players.GetMaxClients();
  1033 	for (int i=1; i<=maxClients; i++)
  1034 	{
  1035 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
  1036 		if (!pPlayer->IsInGame() 
  1037 			|| pPlayer->IsFakeClient()
  1038 			|| (display_in_chat && i == client))
  1039 		{
  1040 			continue;
  1041 		}
  1042 		AdminId id = pPlayer->GetAdminId();
  1043 		g_SourceMod.SetGlobalTarget(i);
  1044 		if (id == INVALID_ADMIN_ID
  1045 			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
  1046 		{
  1047 			/* Treat this as a normal user */
  1048 			if ((value & 1) || (value & 2))
  1049 			{
  1050 				const char *newsign = sign;
  1051 				if ((value & 2) || (i == client))
  1052 				{
  1053 					newsign = name;
  1054 				}
  1055 				g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
  1056 
  1057 				if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1058 				{
  1059 					return 0;
  1060 				}
  1061 
  1062 				UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
  1063 				g_HL2.TextMsg(i, HUD_PRINTTALK, message);
  1064 			}
  1065 		}
  1066 		else
  1067 		{
  1068 			/* Treat this as an admin user */
  1069 			bool is_root = g_Admins.GetAdminFlag(id, Admin_Root, Access_Effective);
  1070 			if ((value & 4) 
  1071 				|| (value & 8)
  1072 				|| ((value & 16) && is_root))
  1073 			{
  1074 				const char *newsign = sign;
  1075 				if ((value & 8) || ((value & 16) && is_root) || (i == client))
  1076 				{
  1077 					newsign = name;
  1078 				}
  1079 				g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
  1080 
  1081 				if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1082 				{
  1083 					return 0;
  1084 				}
  1085 
  1086 				UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
  1087 				g_HL2.TextMsg(i, HUD_PRINTTALK, message);
  1088 			}
  1089 		}
  1090 	}
  1091 
  1092 	return 1;
  1093 }
  1094 
  1095 static cell_t _ShowActivity2(IPluginContext *pContext,
  1096 							 const cell_t *params,
  1097 							 const char *tag,
  1098 							 cell_t fmt_param)
  1099 {
  1100 	char message[255];
  1101 	char buffer[255];
  1102 	int value = sm_show_activity.GetInt();
  1103 	unsigned int replyto = g_ChatTriggers.GetReplyTo();
  1104 	int client = params[1];
  1105 
  1106 	const char *name = "Console";
  1107 	const char *sign = "ADMIN";
  1108 	if (client != 0)
  1109 	{
  1110 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
  1111 		if (!pPlayer || !pPlayer->IsConnected())
  1112 		{
  1113 			return pContext->ThrowNativeError("Client index %d is invalid", client);
  1114 		}
  1115 		name = pPlayer->GetName();
  1116 		AdminId id = pPlayer->GetAdminId();
  1117 		if (id == INVALID_ADMIN_ID
  1118 			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
  1119 		{
  1120 			sign = "PLAYER";
  1121 		}
  1122 
  1123 		g_SourceMod.SetGlobalTarget(client);
  1124 		g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
  1125 
  1126 		if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1127 		{
  1128 			return 0;
  1129 		}
  1130 
  1131 		/* We don't display directly to the console because the chat text 
  1132 		 * simply gets added to the console, so we don't want it to print 
  1133 		 * twice.
  1134 		 */
  1135 		if (replyto == SM_REPLY_CONSOLE)
  1136 		{
  1137 #if 0
  1138 			UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
  1139 			engine->ClientPrintf(pPlayer->GetEdict(), message);
  1140 #endif
  1141 			UTIL_Format(message, sizeof(message), "%s%s", tag, buffer);
  1142 			g_HL2.TextMsg(client, HUD_PRINTTALK, message);
  1143 		}
  1144 		else
  1145 		{
  1146 			UTIL_Format(message, sizeof(message), "%s%s", tag, buffer);
  1147 			g_HL2.TextMsg(client, HUD_PRINTTALK, message);
  1148 		}
  1149 	}
  1150 	else
  1151 	{
  1152 		g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
  1153 		g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
  1154 
  1155 		if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1156 		{
  1157 			return 0;
  1158 		}
  1159 
  1160 		UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
  1161 		META_CONPRINT(message);
  1162 	}
  1163 
  1164 	if (!value)
  1165 	{
  1166 		return 1;
  1167 	}
  1168 
  1169 	int maxClients = g_Players.GetMaxClients();
  1170 	for (int i=1; i<=maxClients; i++)
  1171 	{
  1172 		CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
  1173 		if (!pPlayer->IsInGame() 
  1174 			|| pPlayer->IsFakeClient()
  1175 			|| i == client)
  1176 		{
  1177 			continue;
  1178 		}
  1179 		AdminId id = pPlayer->GetAdminId();
  1180 		g_SourceMod.SetGlobalTarget(i);
  1181 		if (id == INVALID_ADMIN_ID
  1182 			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
  1183 		{
  1184 			/* Treat this as a normal user */
  1185 			if ((value & 1) || (value & 2))
  1186 			{
  1187 				const char *newsign = sign;
  1188 				if ((value & 2))
  1189 				{
  1190 					newsign = name;
  1191 				}
  1192 				g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
  1193 
  1194 				if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1195 				{
  1196 					return 0;
  1197 				}
  1198 
  1199 				UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
  1200 				g_HL2.TextMsg(i, HUD_PRINTTALK, message);
  1201 			}
  1202 		}
  1203 		else
  1204 		{
  1205 			/* Treat this as an admin user */
  1206 			bool is_root = g_Admins.GetAdminFlag(id, Admin_Root, Access_Effective);
  1207 			if ((value & 4) 
  1208 				|| (value & 8)
  1209 				|| ((value & 16) && is_root))
  1210 			{
  1211 				const char *newsign = sign;
  1212 				if ((value & 8) || ((value & 16) && is_root))
  1213 				{
  1214 					newsign = name;
  1215 				}
  1216 				g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
  1217 
  1218 				if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1219 				{
  1220 					return 0;
  1221 				}
  1222 
  1223 				UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
  1224 				g_HL2.TextMsg(i, HUD_PRINTTALK, message);
  1225 			}
  1226 		}
  1227 	}
  1228 
  1229 	return 1;
  1230 }
  1231 
  1232 static cell_t ShowActivity(IPluginContext *pContext, const cell_t *params)
  1233 {
  1234 	return _ShowActivity(pContext, params, "[SM] ", 2);
  1235 }
  1236 
  1237 static cell_t ShowActivityEx(IPluginContext *pContext, const cell_t *params)
  1238 {
  1239 	char *str;
  1240 	pContext->LocalToString(params[2], &str);
  1241 
  1242 	return _ShowActivity(pContext, params, str, 3);
  1243 }
  1244 
  1245 static cell_t ShowActivity2(IPluginContext *pContext, const cell_t *params)
  1246 {
  1247 	char *str;
  1248 	pContext->LocalToString(params[2], &str);
  1249 
  1250 	return _ShowActivity2(pContext, params, str, 3);
  1251 }
  1252 
  1253 static cell_t KickClient(IPluginContext *pContext, const cell_t *params)
  1254 {
  1255 	int client = params[1];
  1256 
  1257 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
  1258 	if (!pPlayer)
  1259 	{
  1260 		return pContext->ThrowNativeError("Client index %d is invalid", client);
  1261 	}
  1262 	else if (!pPlayer->IsConnected())
  1263 	{
  1264 		return pContext->ThrowNativeError("Client %d is not connected", client);
  1265 	}
  1266 
  1267 	/* Ignore duplicate kicks */
  1268 	if (pPlayer->IsInKickQueue())
  1269 	{
  1270 		return 1;
  1271 	}
  1272 
  1273 	pPlayer->MarkAsBeingKicked();
  1274 
  1275 	if (pPlayer->IsFakeClient())
  1276 	{
  1277 		char kickcmd[40];
  1278 		UTIL_Format(kickcmd, sizeof(kickcmd), "kick %s\n", pPlayer->GetName());
  1279 
  1280 		engine->ServerCommand(kickcmd);
  1281 		return 1;
  1282 	}
  1283 
  1284 	g_SourceMod.SetGlobalTarget(client);
  1285 
  1286 	char buffer[256];
  1287 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
  1288 
  1289 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1290 	{
  1291 		return 0;
  1292 	}
  1293 
  1294 	g_HL2.AddDelayedKick(client, pPlayer->GetUserId(), buffer);
  1295 
  1296 	return 1;
  1297 }
  1298 
  1299 static cell_t KickClientEx(IPluginContext *pContext, const cell_t *params)
  1300 {
  1301 	int client = params[1];
  1302 
  1303 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
  1304 	if (!pPlayer)
  1305 	{
  1306 		return pContext->ThrowNativeError("Client index %d is invalid", client);
  1307 	}
  1308 	else if (!pPlayer->IsConnected())
  1309 	{
  1310 		return pContext->ThrowNativeError("Client %d is not connected", client);
  1311 	}
  1312 
  1313 	/* Ignore duplicate kicks */
  1314 	if (pPlayer->IsInKickQueue())
  1315 	{
  1316 		return 1;
  1317 	}
  1318 
  1319 	pPlayer->MarkAsBeingKicked();
  1320 
  1321 	if (pPlayer->IsFakeClient())
  1322 	{
  1323 		char kickcmd[40];
  1324 		UTIL_Format(kickcmd, sizeof(kickcmd), "kick %s\n", pPlayer->GetName());
  1325 
  1326 		engine->ServerCommand(kickcmd);
  1327 		return 1;
  1328 	}
  1329 
  1330 	g_SourceMod.SetGlobalTarget(client);
  1331 
  1332 	char buffer[256];
  1333 	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
  1334 
  1335 	if (pContext->GetLastNativeError() != SP_ERROR_NONE)
  1336 	{
  1337 		return 0;
  1338 	}
  1339 
  1340 	pPlayer->Kick(buffer);
  1341 
  1342 	return 1;
  1343 }
  1344 
  1345 static cell_t ChangeClientTeam(IPluginContext *pContext, const cell_t *params)
  1346 {
  1347 	int client = params[1];
  1348 
  1349 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
  1350 	if (!pPlayer)
  1351 	{
  1352 		return pContext->ThrowNativeError("Client index %d is invalid", client);
  1353 	}
  1354 	else if (!pPlayer->IsInGame())
  1355 	{
  1356 		return pContext->ThrowNativeError("Client %d is not in game", client);
  1357 	}
  1358 
  1359 	IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
  1360 	if (!pInfo)
  1361 	{
  1362 		return pContext->ThrowNativeError("IPlayerInfo not supported by game");
  1363 	}
  1364 
  1365 	pInfo->ChangeTeam(params[2]);
  1366 
  1367 	return 1;
  1368 }
  1369 
  1370 static cell_t RunAdminCacheChecks(IPluginContext *pContext, const cell_t *params)
  1371 {
  1372 	int client = params[1];
  1373 
  1374 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
  1375 	if (!pPlayer)
  1376 	{
  1377 		return pContext->ThrowNativeError("Client index %d is invalid", client);
  1378 	}
  1379 	else if (!pPlayer->IsInGame())
  1380 	{
  1381 		return pContext->ThrowNativeError("Client %d is not in game", client);
  1382 	}
  1383 	else if (!pPlayer->IsAuthorized())
  1384 	{
  1385 		return pContext->ThrowNativeError("Client %d is not authorized", client);
  1386 	}
  1387 
  1388 	AdminId id = pPlayer->GetAdminId();
  1389 	pPlayer->DoBasicAdminChecks();
  1390 
  1391 	return (id != pPlayer->GetAdminId()) ? 1 : 0;
  1392 }
  1393 
  1394 static cell_t NotifyPostAdminCheck(IPluginContext *pContext, const cell_t *params)
  1395 {
  1396 	int client = params[1];
  1397 
  1398 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
  1399 	if (!pPlayer)
  1400 	{
  1401 		return pContext->ThrowNativeError("Client index %d is invalid", client);
  1402 	}
  1403 	else if (!pPlayer->IsInGame()) {
  1404 		return pContext->ThrowNativeError("Client %d is not in game", client);
  1405 	}
  1406 	else if (!pPlayer->IsAuthorized())
  1407 	{
  1408 		return pContext->ThrowNativeError("Client %d is not authorized", client);
  1409 	}
  1410 
  1411 	pPlayer->NotifyPostAdminChecks();
  1412 
  1413 	return 1;
  1414 }
  1415 
  1416 static cell_t IsClientInKickQueue(IPluginContext *pContext, const cell_t *params)
  1417 {
  1418 	int client = params[1];
  1419 
  1420 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
  1421 
  1422 	if (!pPlayer)
  1423 	{
  1424 		return pContext->ThrowNativeError("Client index %d is invalid", client);
  1425 	}
  1426 	else if (!pPlayer->IsConnected())
  1427 	{
  1428 		return pContext->ThrowNativeError("Client %d is not in game", client);
  1429 	}
  1430 
  1431 	return pPlayer->IsInKickQueue() ? 1 : 0;
  1432 }
  1433 
  1434 static cell_t ProcessTargetString(IPluginContext *pContext, const cell_t *params)
  1435 {
  1436 	cmd_target_info_t info;
  1437 
  1438 	pContext->LocalToString(params[1], (char **)&info.pattern);
  1439 	info.admin = params[2];
  1440 	pContext->LocalToPhysAddr(params[3], &info.targets);
  1441 	info.max_targets = params[4];
  1442 	info.flags = params[5];
  1443 	pContext->LocalToString(params[6], &info.target_name);
  1444 	info.target_name_maxlength = params[7];
  1445 
  1446 	cell_t *tn_is_ml;
  1447 	pContext->LocalToPhysAddr(params[8], &tn_is_ml);
  1448 
  1449 	g_Players.ProcessCommandTarget(&info);
  1450 
  1451 	if (info.target_name_style == COMMAND_TARGETNAME_ML)
  1452 	{
  1453 		*tn_is_ml = 1;
  1454 	}
  1455 	else
  1456 	{
  1457 		*tn_is_ml = 0;
  1458 	}
  1459 
  1460 	if (info.num_targets == 0)
  1461 	{
  1462 		return info.reason;
  1463 	}
  1464 	else
  1465 	{
  1466 		return info.num_targets;
  1467 	}
  1468 }
  1469 
  1470 static cell_t FormatActivitySource(IPluginContext *pContext, const cell_t *params)
  1471 {
  1472 	int value;
  1473 	int client;
  1474 	int target;
  1475 	CPlayer *pTarget;
  1476 	AdminId aidTarget;
  1477 	const char *identity[2] = {"Console", "ADMIN"};
  1478 
  1479 	client = params[1];
  1480 	target = params[2];
  1481 
  1482 	if ((pTarget = g_Players.GetPlayerByIndex(target)) == NULL)
  1483 	{
  1484 		return pContext->ThrowNativeError("Invalid client index %d", target);
  1485 	}
  1486 	if (!pTarget->IsConnected())
  1487 	{
  1488 		return pContext->ThrowNativeError("Client %d not connected", target);
  1489 	}
  1490 
  1491 	value = sm_show_activity.GetInt();
  1492 
  1493 	if (client != 0)
  1494 	{
  1495 		CPlayer *pPlayer;
  1496 
  1497 		if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
  1498 		{
  1499 			return pContext->ThrowNativeError("Invalid client index %d", client);
  1500 		}
  1501 		if (!pPlayer->IsConnected())
  1502 		{
  1503 			return pContext->ThrowNativeError("Client %d not connected", client);
  1504 		}
  1505 
  1506 		identity[0] = pPlayer->GetName();
  1507 
  1508 		AdminId id = pPlayer->GetAdminId();
  1509 		if (id == INVALID_ADMIN_ID
  1510 			|| !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
  1511 		{
  1512 			identity[1] = "PLAYER";
  1513 		}
  1514 	}
  1515 
  1516 	int mode = 1;
  1517 	bool bShowActivity = false;
  1518 
  1519 	if ((aidTarget = pTarget->GetAdminId()) == INVALID_ADMIN_ID
  1520 		|| !g_Admins.GetAdminFlag(aidTarget, Admin_Generic, Access_Effective))
  1521 	{
  1522 		/* Treat this as a normal user */
  1523 		if ((value & 1) || (value & 2))
  1524 		{
  1525 			if ((value & 2) || (target == client))
  1526 			{
  1527 				mode = 0;
  1528 			}
  1529 			bShowActivity = true;
  1530 		}
  1531 	}
  1532 	else
  1533 	{
  1534 		/* Treat this as an admin user */
  1535 		bool is_root = g_Admins.GetAdminFlag(aidTarget, Admin_Root, Access_Effective);
  1536 		if ((value & 4) 
  1537 			|| (value & 8)
  1538 			|| ((value & 16) && is_root))
  1539 		{
  1540 			if ((value & 8) || ((value & 16) && is_root) || (target == client))
  1541 			{
  1542 				mode = 0;
  1543 			}
  1544 			bShowActivity = true;
  1545 		}
  1546 	}
  1547 
  1548 	/* Otherwise, send it back to the script. */
  1549 	pContext->StringToLocalUTF8(params[3], params[4], identity[mode], NULL);
  1550 
  1551 	return bShowActivity ? 1 : 0;
  1552 }
  1553 
  1554 static cell_t sm_GetClientSerial(IPluginContext *pContext, const cell_t *params)
  1555 {
  1556 	int client = params[1];
  1557 
  1558 	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
  1559 	if (!pPlayer)
  1560 	{
  1561 		return pContext->ThrowNativeError("Client index %d is invalid", client);
  1562 	}
  1563 
  1564 	return pPlayer->GetSerial();
  1565 }
  1566 
  1567 static cell_t sm_GetClientFromSerial(IPluginContext *pContext, const cell_t *params)
  1568 {
  1569 	return g_Players.GetClientFromSerial(params[1]);
  1570 }
  1571 
  1572 REGISTER_NATIVES(playernatives)
  1573 {
  1574 	{"AddUserFlags",			AddUserFlags},
  1575 	{"CanUserTarget",			CanUserTarget},
  1576 	{"ChangeClientTeam",		ChangeClientTeam},
  1577 	{"GetClientAuthString",		sm_GetClientAuthStr},
  1578 	{"GetClientCount",			sm_GetClientCount},
  1579 	{"GetClientInfo",			sm_GetClientInfo},
  1580 	{"GetClientIP",				sm_GetClientIP},
  1581 	{"GetClientName",			sm_GetClientName},
  1582 	{"GetClientTeam",			GetClientTeam},
  1583 	{"GetClientUserId",			GetClientUserId},
  1584 	{"GetMaxClients",			sm_GetMaxClients},
  1585 	{"GetUserAdmin",			GetUserAdmin},
  1586 	{"GetUserFlagBits",			GetUserFlagBits},
  1587 	{"IsClientAuthorized",		sm_IsClientAuthorized},
  1588 	{"IsClientConnected",		sm_IsClientConnected},
  1589 	{"IsFakeClient",			sm_IsClientFakeClient},
  1590 	{"IsClientInGame",			sm_IsClientInGame},
  1591 	{"IsClientObserver",		IsClientObserver},
  1592 	{"RemoveUserFlags",			RemoveUserFlags},
  1593 	{"SetUserAdmin",			SetUserAdmin},
  1594 	{"SetUserFlagBits",			SetUserFlagBits},
  1595 	{"GetClientDeaths",			GetDeathCount},
  1596 	{"GetClientFrags",			GetFragCount},
  1597 	{"GetClientArmor",			GetArmorValue},
  1598 	{"GetClientAbsOrigin",		GetAbsOrigin},
  1599 	{"GetClientAbsAngles",		GetAbsAngles},
  1600 	{"GetClientMins",			GetPlayerMins},
  1601 	{"GetClientMaxs",			GetPlayerMaxs},
  1602 	{"GetClientWeapon",			GetWeaponName},
  1603 	{"GetClientModel",			GetModelName},
  1604 	{"GetClientHealth",			GetHealth},
  1605 	{"GetClientTime",			GetTimeConnected},
  1606 	{"GetClientDataRate",		GetDataRate},
  1607 	{"IsClientTimingOut",		IsTimingOut},
  1608 	{"GetClientLatency",		GetLatency},
  1609 	{"GetClientAvgLatency",		GetAvgLatency},
  1610 	{"GetClientAvgLoss",		GetAvgLoss},
  1611 	{"GetClientAvgChoke",		GetAvgChoke},
  1612 	{"GetClientAvgData",		GetAvgData},
  1613 	{"GetClientAvgPackets",		GetAvgPackets},
  1614 	{"GetClientOfUserId",		GetClientOfUserId},
  1615 	{"ShowActivity",			ShowActivity},
  1616 	{"ShowActivityEx",			ShowActivityEx},
  1617 	{"ShowActivity2",			ShowActivity2},
  1618 	{"KickClient",				KickClient},
  1619 	{"KickClientEx",			KickClientEx},
  1620 	{"RunAdminCacheChecks",		RunAdminCacheChecks},
  1621 	{"NotifyPostAdminCheck",	NotifyPostAdminCheck},
  1622 	{"IsClientInKickQueue",		IsClientInKickQueue},
  1623 	{"ProcessTargetString",		ProcessTargetString},
  1624 	{"FormatActivitySource",	FormatActivitySource},
  1625 	{"GetClientSerial",			sm_GetClientSerial},
  1626 	{"GetClientFromSerial",		sm_GetClientFromSerial},
  1627 	{NULL,						NULL}
  1628 };
  1629