3 * =============================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * =============================================================================
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.
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
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/>.
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>.
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>
41 ConVar sm_show_activity("sm_show_activity", "13", FCVAR_SPONLY|FCVAR_PROTECTED, "Activity display setting (see sourcemod.cfg)");
43 static cell_t sm_GetClientCount(IPluginContext *pCtx, const cell_t *params)
47 return g_Players.NumPlayers();
50 int maxplayers = g_Players.MaxClients();
52 for (int i=1; i<=maxplayers; ++i)
54 CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
55 if ((pPlayer->IsConnected()) && !(pPlayer->IsInGame()))
61 return (g_Players.NumPlayers() + count);
64 static cell_t sm_GetMaxClients(IPluginContext *pCtx, const cell_t *params)
66 return g_Players.MaxClients();
69 static cell_t sm_GetClientName(IPluginContext *pCtx, const cell_t *params)
71 int index = params[1];
75 static ConVar *hostname = NULL;
78 hostname = icvar->FindVar("hostname");
81 return pCtx->ThrowNativeError("Could not find \"hostname\" cvar");
84 pCtx->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), hostname->GetString(), NULL);
88 if ((index < 1) || (index > g_Players.GetMaxClients()))
90 return pCtx->ThrowNativeError("Client index %d is invalid", index);
93 CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
94 if (!pPlayer->IsConnected())
96 return pCtx->ThrowNativeError("Client %d is not connected", index);
99 pCtx->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), pPlayer->GetName(), NULL);
103 static cell_t sm_GetClientIP(IPluginContext *pCtx, const cell_t *params)
105 int index = params[1];
106 if ((index < 1) || (index > g_Players.GetMaxClients()))
108 return pCtx->ThrowNativeError("Client index %d is invalid", index);
111 CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
112 if (!pPlayer->IsConnected())
114 return pCtx->ThrowNativeError("Client %d is not connected", index);
118 strcpy(buf, pPlayer->GetIPAddress());
120 if (params[4] && (ptr = strchr(buf, ':')))
125 pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), buf);
129 static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params)
131 int index = params[1];
132 if ((index < 1) || (index > g_Players.GetMaxClients()))
134 return pCtx->ThrowNativeError("Client index %d is invalid", index);
137 CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
138 if (!pPlayer->IsConnected())
140 return pCtx->ThrowNativeError("Client %d is not connected", index);
143 if (!pPlayer->IsAuthorized())
148 pCtx->StringToLocal(params[2], static_cast<size_t>(params[3]), pPlayer->GetAuthString());
153 static cell_t sm_IsClientConnected(IPluginContext *pCtx, const cell_t *params)
155 int index = params[1];
156 if ((index < 1) || (index > g_Players.GetMaxClients()))
158 return pCtx->ThrowNativeError("Client index %d is invalid", index);
161 return (g_Players.GetPlayerByIndex(index)->IsConnected()) ? 1 : 0;
164 static cell_t sm_IsClientInGame(IPluginContext *pCtx, const cell_t *params)
166 int index = params[1];
167 if ((index < 1) || (index > g_Players.GetMaxClients()))
169 return pCtx->ThrowNativeError("Client index %d is invalid", index);
172 return (g_Players.GetPlayerByIndex(index)->IsInGame()) ? 1 : 0;
175 static cell_t sm_IsClientAuthorized(IPluginContext *pCtx, const cell_t *params)
177 int index = params[1];
178 if ((index < 1) || (index > g_Players.GetMaxClients()))
180 return pCtx->ThrowNativeError("Client index %d is invalid", index);
183 return (g_Players.GetPlayerByIndex(index)->IsAuthorized()) ? 1 : 0;
186 static cell_t sm_IsClientFakeClient(IPluginContext *pCtx, const cell_t *params)
188 int index = params[1];
189 if ((index < 1) || (index > g_Players.GetMaxClients()))
191 return pCtx->ThrowNativeError("Client index %d is invalid", index);
194 CPlayer *pPlayer = g_Players.GetPlayerByIndex(index);
195 if (!pPlayer->IsConnected())
197 return pCtx->ThrowNativeError("Client %d is not connected", index);
200 return (pPlayer->IsFakeClient()) ? 1 : 0;
203 static cell_t IsClientObserver(IPluginContext *pContext, const cell_t *params)
205 int client = params[1];
207 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
215 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
218 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
221 return pInfo->IsObserver() ? 1 : 0;
224 static cell_t sm_GetClientInfo(IPluginContext *pContext, const cell_t *params)
226 int client = params[1];
227 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
230 return pContext->ThrowNativeError("Client index %d is invalid", client);
232 if (!pPlayer->IsConnected())
234 return pContext->ThrowNativeError("Client %d is not connected", client);
238 pContext->LocalToString(params[2], &key);
240 const char *val = engine->GetClientConVarValue(client, key);
246 pContext->StringToLocalUTF8(params[3], params[4], val, NULL);
250 static cell_t SetUserAdmin(IPluginContext *pContext, const cell_t *params)
252 int client = params[1];
253 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
256 return pContext->ThrowNativeError("Client index %d is invalid", client);
258 if (!pPlayer->IsConnected())
260 return pContext->ThrowNativeError("Client %d is not connected", client);
262 if (!g_Admins.IsValidAdmin(params[2]) && params[2] != INVALID_ADMIN_ID)
264 return pContext->ThrowNativeError("AdminId %x is invalid", params[2]);
267 pPlayer->SetAdminId(params[2], params[3] ? true : false);
272 static cell_t GetUserAdmin(IPluginContext *pContext, const cell_t *params)
274 int client = params[1];
275 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
278 return pContext->ThrowNativeError("Client index %d is invalid", client);
280 if (!pPlayer->IsConnected())
282 return pContext->ThrowNativeError("Client %d is not connected", client);
285 return pPlayer->GetAdminId();
288 static cell_t AddUserFlags(IPluginContext *pContext, const cell_t *params)
290 int client = params[1];
291 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
294 return pContext->ThrowNativeError("Client index %d is invalid", client);
296 if (!pPlayer->IsConnected())
298 return pContext->ThrowNativeError("Client %d is not connected", client);
302 if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
304 id = g_Admins.CreateAdmin(NULL);
305 pPlayer->SetAdminId(id, true);
309 for (int i=2; i<=params[0]; i++)
311 pContext->LocalToPhysAddr(params[i], &addr);
312 g_Admins.SetAdminFlag(id, (AdminFlag)*addr, true);
318 static cell_t RemoveUserFlags(IPluginContext *pContext, const cell_t *params)
320 int client = params[1];
321 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
324 return pContext->ThrowNativeError("Client index %d is invalid", client);
326 if (!pPlayer->IsConnected())
328 return pContext->ThrowNativeError("Client %d is not connected", client);
332 if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
338 for (int i=2; i<=params[0]; i++)
340 pContext->LocalToPhysAddr(params[i], &addr);
341 g_Admins.SetAdminFlag(id, (AdminFlag)*addr, false);
347 static cell_t SetUserFlagBits(IPluginContext *pContext, const cell_t *params)
349 int client = params[1];
350 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
353 return pContext->ThrowNativeError("Client index %d is invalid", client);
355 if (!pPlayer->IsConnected())
357 return pContext->ThrowNativeError("Client %d is not connected", client);
361 if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
363 id = g_Admins.CreateAdmin(NULL);
364 pPlayer->SetAdminId(id, true);
367 g_Admins.SetAdminFlags(id, Access_Effective, params[2]);
372 static cell_t GetUserFlagBits(IPluginContext *pContext, const cell_t *params)
374 int client = params[1];
375 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
378 return pContext->ThrowNativeError("Client index %d is invalid", client);
380 if (!pPlayer->IsConnected())
382 return pContext->ThrowNativeError("Client %d is not connected", client);
386 if ((id=pPlayer->GetAdminId()) == INVALID_ADMIN_ID)
391 return g_Admins.GetAdminFlags(id, Access_Effective);
394 static cell_t GetClientUserId(IPluginContext *pContext, const cell_t *params)
396 int client = params[1];
397 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
400 return pContext->ThrowNativeError("Client index %d is invalid", client);
402 if (!pPlayer->IsConnected())
404 return pContext->ThrowNativeError("Client %d is not connected", client);
407 return engine->GetPlayerUserId(pPlayer->GetEdict());
410 static cell_t CanUserTarget(IPluginContext *pContext, const cell_t *params)
412 int client = params[1];
413 int target = params[2];
420 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
428 CPlayer *pTarget = g_Players.GetPlayerByIndex(target);
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);
436 return g_Admins.CanAdminTarget(pPlayer->GetAdminId(), pTarget->GetAdminId()) ? 1 : 0;
439 static cell_t GetClientTeam(IPluginContext *pContext, const cell_t *params)
441 int client = params[1];
443 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
451 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
454 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
457 return pInfo->GetTeamIndex();
460 static cell_t GetFragCount(IPluginContext *pContext, const cell_t *params)
462 int client = params[1];
464 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
472 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
475 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
478 return pInfo->GetFragCount();
481 static cell_t GetDeathCount(IPluginContext *pContext, const cell_t *params)
483 int client = params[1];
485 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
493 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
496 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
499 return pInfo->GetDeathCount();
502 static cell_t GetArmorValue(IPluginContext *pContext, const cell_t *params)
504 int client = params[1];
506 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
514 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
517 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
520 return pInfo->GetArmorValue();
523 static cell_t GetAbsOrigin(IPluginContext *pContext, const cell_t *params)
525 int client = params[1];
527 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
535 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
538 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
542 pContext->LocalToPhysAddr(params[2], &pVec);
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);
552 static cell_t GetAbsAngles(IPluginContext *pContext, const cell_t *params)
554 int client = params[1];
556 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
564 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
567 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
571 pContext->LocalToPhysAddr(params[2], &pAng);
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);
581 static cell_t GetPlayerMins(IPluginContext *pContext, const cell_t *params)
583 int client = params[1];
585 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
593 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
596 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
600 pContext->LocalToPhysAddr(params[2], &pVec);
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);
610 static cell_t GetPlayerMaxs(IPluginContext *pContext, const cell_t *params)
612 int client = params[1];
614 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
622 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
625 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
629 pContext->LocalToPhysAddr(params[2], &pVec);
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);
639 static cell_t GetWeaponName(IPluginContext *pContext, const cell_t *params)
641 int client = params[1];
643 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
651 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
654 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
657 const char *weapon = pInfo->GetWeaponName();
658 pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), weapon ? weapon : "", NULL);
663 static cell_t GetModelName(IPluginContext *pContext, const cell_t *params)
665 int client = params[1];
667 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
675 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
678 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
681 const char *model = pInfo->GetModelName();
682 pContext->StringToLocalUTF8(params[2], static_cast<size_t>(params[3]), model ? model : "", NULL);
687 static cell_t GetHealth(IPluginContext *pContext, const cell_t *params)
689 int client = params[1];
691 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
699 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
702 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
705 return pInfo->GetHealth();
708 static cell_t GetTimeConnected(IPluginContext *pContext, const cell_t *params)
710 int client = params[1];
712 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
722 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
724 return sp_ftoc(pInfo->GetTimeConnected());
727 static cell_t GetDataRate(IPluginContext *pContext, const cell_t *params)
729 int client = params[1];
731 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
741 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
743 return pInfo->GetDataRate();
746 static cell_t IsTimingOut(IPluginContext *pContext, const cell_t *params)
748 int client = params[1];
750 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
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);
760 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
762 return pInfo->IsTimingOut() ? 1 : 0;
765 static cell_t GetLatency(IPluginContext *pContext, const cell_t *params)
767 int client = params[1];
769 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
772 return pContext->ThrowNativeError("Client index %d is invalid", client);
773 } else if (!pPlayer->IsInGame()) {
774 return pContext->ThrowNativeError("Client %d is not in game", client);
775 } else if (pPlayer->IsFakeClient()) {
776 return pContext->ThrowNativeError("Client %d is a bot", client);
779 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
781 return sp_ftoc(pInfo->GetLatency(params[2]));
784 static cell_t GetAvgLatency(IPluginContext *pContext, const cell_t *params)
786 int client = params[1];
788 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
791 return pContext->ThrowNativeError("Client index %d is invalid", client);
792 } else if (!pPlayer->IsInGame()) {
793 return pContext->ThrowNativeError("Client %d is not in game", client);
794 } else if (pPlayer->IsFakeClient()) {
795 return pContext->ThrowNativeError("Client %d is a bot", client);
798 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
800 return sp_ftoc(pInfo->GetAvgLatency(params[2]));
803 static cell_t GetAvgLoss(IPluginContext *pContext, const cell_t *params)
805 int client = params[1];
807 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
810 return pContext->ThrowNativeError("Client index %d is invalid", client);
811 } else if (!pPlayer->IsInGame()) {
812 return pContext->ThrowNativeError("Client %d is not in game", client);
813 } else if (pPlayer->IsFakeClient()) {
814 return pContext->ThrowNativeError("Client %d is a bot", client);
817 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
819 return sp_ftoc(pInfo->GetAvgLoss(params[2]));
822 static cell_t GetAvgChoke(IPluginContext *pContext, const cell_t *params)
824 int client = params[1];
826 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
829 return pContext->ThrowNativeError("Client index %d is invalid", client);
830 } else if (!pPlayer->IsInGame()) {
831 return pContext->ThrowNativeError("Client %d is not in game", client);
832 } else if (pPlayer->IsFakeClient()) {
833 return pContext->ThrowNativeError("Client %d is a bot", client);
836 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
838 return sp_ftoc(pInfo->GetAvgChoke(params[2]));
841 static cell_t GetAvgData(IPluginContext *pContext, const cell_t *params)
843 int client = params[1];
845 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
848 return pContext->ThrowNativeError("Client index %d is invalid", client);
849 } else if (!pPlayer->IsInGame()) {
850 return pContext->ThrowNativeError("Client %d is not in game", client);
851 } else if (pPlayer->IsFakeClient()) {
852 return pContext->ThrowNativeError("Client %d is a bot", client);
855 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
857 return sp_ftoc(pInfo->GetAvgData(params[2]));
860 static cell_t GetAvgPackets(IPluginContext *pContext, const cell_t *params)
862 int client = params[1];
864 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
867 return pContext->ThrowNativeError("Client index %d is invalid", client);
868 } else if (!pPlayer->IsInGame()) {
869 return pContext->ThrowNativeError("Client %d is not in game", client);
870 } else if (pPlayer->IsFakeClient()) {
871 return pContext->ThrowNativeError("Client %d is a bot", client);
874 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
876 return sp_ftoc(pInfo->GetAvgPackets(params[2]));
879 static cell_t GetClientOfUserId(IPluginContext *pContext, const cell_t *params)
881 return g_Players.GetClientOfUserId(params[1]);
884 static cell_t _ShowActivity(IPluginContext *pContext,
885 const cell_t *params,
891 int value = sm_show_activity.GetInt();
892 unsigned int replyto = g_ChatTriggers.GetReplyTo();
893 int client = params[1];
895 const char *name = "Console";
896 const char *sign = "ADMIN";
897 bool display_in_chat = false;
900 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
901 if (!pPlayer || !pPlayer->IsConnected())
903 return pContext->ThrowNativeError("Client index %d is invalid", client);
905 name = pPlayer->GetName();
906 AdminId id = pPlayer->GetAdminId();
907 if (id == INVALID_ADMIN_ID
908 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
913 /* Display the message to the client? */
914 if (replyto == SM_REPLY_CONSOLE)
916 g_SourceMod.SetGlobalTarget(client);
917 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
919 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
924 UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
925 engine->ClientPrintf(pPlayer->GetEdict(), message);
926 display_in_chat = true;
931 g_SourceMod.SetGlobalTarget(LANG_SERVER);
932 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
934 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
939 UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
940 META_CONPRINT(message);
948 int maxClients = g_Players.GetMaxClients();
949 for (int i=1; i<=maxClients; i++)
951 CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
952 if (!pPlayer->IsInGame()
953 || pPlayer->IsFakeClient()
954 || (display_in_chat && i == client))
958 AdminId id = pPlayer->GetAdminId();
959 g_SourceMod.SetGlobalTarget(i);
960 if (id == INVALID_ADMIN_ID
961 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
963 /* Treat this as a normal user */
964 if ((value & 1) || (value & 2))
966 const char *newsign = sign;
967 if ((value & 2) || (i == client))
971 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
973 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
978 UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
979 g_HL2.TextMsg(i, HUD_PRINTTALK, message);
984 /* Treat this as an admin user */
985 bool is_root = g_Admins.GetAdminFlag(id, Admin_Root, Access_Effective);
988 || ((value & 16) && is_root))
990 const char *newsign = sign;
991 if ((value & 8) || ((value & 16) && is_root) || (i == client))
995 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
997 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1002 UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
1003 g_HL2.TextMsg(i, HUD_PRINTTALK, message);
1011 static cell_t _ShowActivity2(IPluginContext *pContext,
1012 const cell_t *params,
1018 int value = sm_show_activity.GetInt();
1019 unsigned int replyto = g_ChatTriggers.GetReplyTo();
1020 int client = params[1];
1022 const char *name = "Console";
1023 const char *sign = "ADMIN";
1026 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1027 if (!pPlayer || !pPlayer->IsConnected())
1029 return pContext->ThrowNativeError("Client index %d is invalid", client);
1031 name = pPlayer->GetName();
1032 AdminId id = pPlayer->GetAdminId();
1033 if (id == INVALID_ADMIN_ID
1034 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
1039 g_SourceMod.SetGlobalTarget(client);
1040 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1042 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1047 /* We don't display directly to the console because the chat text
1048 * simply gets added to the console, so we don't want it to print
1051 if (replyto == SM_REPLY_CONSOLE)
1054 UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
1055 engine->ClientPrintf(pPlayer->GetEdict(), message);
1057 UTIL_Format(message, sizeof(message), "%s%s", tag, buffer);
1058 g_HL2.TextMsg(client, HUD_PRINTTALK, message);
1062 UTIL_Format(message, sizeof(message), "%s%s", tag, buffer);
1063 g_HL2.TextMsg(client, HUD_PRINTTALK, message);
1068 g_SourceMod.SetGlobalTarget(LANG_SERVER);
1069 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1071 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1076 UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
1077 META_CONPRINT(message);
1085 int maxClients = g_Players.GetMaxClients();
1086 for (int i=1; i<=maxClients; i++)
1088 CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
1089 if (!pPlayer->IsInGame()
1090 || pPlayer->IsFakeClient()
1095 AdminId id = pPlayer->GetAdminId();
1096 g_SourceMod.SetGlobalTarget(i);
1097 if (id == INVALID_ADMIN_ID
1098 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
1100 /* Treat this as a normal user */
1101 if ((value & 1) || (value & 2))
1103 const char *newsign = sign;
1108 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1110 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1115 UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
1116 g_HL2.TextMsg(i, HUD_PRINTTALK, message);
1121 /* Treat this as an admin user */
1122 bool is_root = g_Admins.GetAdminFlag(id, Admin_Root, Access_Effective);
1125 || ((value & 16) && is_root))
1127 const char *newsign = sign;
1128 if ((value & 8) || ((value & 16) && is_root))
1132 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1134 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1139 UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
1140 g_HL2.TextMsg(i, HUD_PRINTTALK, message);
1148 static cell_t ShowActivity(IPluginContext *pContext, const cell_t *params)
1150 return _ShowActivity(pContext, params, "[SM] ", 2);
1153 static cell_t ShowActivityEx(IPluginContext *pContext, const cell_t *params)
1156 pContext->LocalToString(params[2], &str);
1158 return _ShowActivity(pContext, params, str, 3);
1161 static cell_t ShowActivity2(IPluginContext *pContext, const cell_t *params)
1164 pContext->LocalToString(params[2], &str);
1166 return _ShowActivity2(pContext, params, str, 3);
1169 static cell_t KickClient(IPluginContext *pContext, const cell_t *params)
1171 int client = params[1];
1173 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1176 return pContext->ThrowNativeError("Client index %d is invalid", client);
1177 } else if (!pPlayer->IsConnected()) {
1178 return pContext->ThrowNativeError("Client %d is not connected", client);
1181 pPlayer->MarkAsBeingKicked();
1183 if (pPlayer->IsFakeClient())
1186 UTIL_Format(kickcmd, sizeof(kickcmd), "kick %s\n", pPlayer->GetName());
1188 engine->ServerCommand(kickcmd);
1192 g_SourceMod.SetGlobalTarget(client);
1195 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1197 if (pContext->GetContext()->n_err != SP_ERROR_NONE)
1202 pPlayer->Kick(buffer);
1207 static cell_t ChangeClientTeam(IPluginContext *pContext, const cell_t *params)
1209 int client = params[1];
1211 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1214 return pContext->ThrowNativeError("Client index %d is invalid", client);
1216 else if (!pPlayer->IsInGame())
1218 return pContext->ThrowNativeError("Client %d is not in game", client);
1221 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
1224 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
1227 pInfo->ChangeTeam(params[2]);
1232 static cell_t RunAdminCacheChecks(IPluginContext *pContext, const cell_t *params)
1234 int client = params[1];
1236 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1239 return pContext->ThrowNativeError("Client index %d is invalid", client);
1241 else if (!pPlayer->IsInGame())
1243 return pContext->ThrowNativeError("Client %d is not in game", client);
1245 else if (!pPlayer->IsAuthorized())
1247 return pContext->ThrowNativeError("Client %d is not authorized", client);
1250 AdminId id = pPlayer->GetAdminId();
1251 pPlayer->DoBasicAdminChecks();
1253 return (id != pPlayer->GetAdminId()) ? 1 : 0;
1256 static cell_t NotifyPostAdminCheck(IPluginContext *pContext, const cell_t *params)
1258 int client = params[1];
1260 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1263 return pContext->ThrowNativeError("Client index %d is invalid", client);
1265 else if (!pPlayer->IsInGame()) {
1266 return pContext->ThrowNativeError("Client %d is not in game", client);
1268 else if (!pPlayer->IsAuthorized())
1270 return pContext->ThrowNativeError("Client %d is not authorized", client);
1273 pPlayer->NotifyPostAdminChecks();
1278 static cell_t IsClientInKickQueue(IPluginContext *pContext, const cell_t *params)
1280 int client = params[1];
1282 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1286 return pContext->ThrowNativeError("Client index %d is invalid", client);
1288 else if (!pPlayer->IsConnected())
1290 return pContext->ThrowNativeError("Client %d is not in game", client);
1293 return pPlayer->IsInKickQueue() ? 1 : 0;
1296 static cell_t ProcessTargetString(IPluginContext *pContext, const cell_t *params)
1298 cmd_target_info_t info;
1300 pContext->LocalToString(params[1], (char **)&info.pattern);
1301 info.admin = params[2];
1302 pContext->LocalToPhysAddr(params[3], &info.targets);
1303 info.max_targets = params[4];
1304 info.flags = params[5];
1305 pContext->LocalToString(params[6], &info.target_name);
1306 info.target_name_maxlength = params[7];
1309 pContext->LocalToPhysAddr(params[8], &tn_is_ml);
1311 g_Players.ProcessCommandTarget(&info);
1313 if (info.target_name_style == COMMAND_TARGETNAME_ML)
1322 if (info.num_targets == 0)
1328 return info.num_targets;
1332 REGISTER_NATIVES(playernatives)
1334 {"AddUserFlags", AddUserFlags},
1335 {"CanUserTarget", CanUserTarget},
1336 {"ChangeClientTeam", ChangeClientTeam},
1337 {"GetClientAuthString", sm_GetClientAuthStr},
1338 {"GetClientCount", sm_GetClientCount},
1339 {"GetClientInfo", sm_GetClientInfo},
1340 {"GetClientIP", sm_GetClientIP},
1341 {"GetClientName", sm_GetClientName},
1342 {"GetClientTeam", GetClientTeam},
1343 {"GetClientUserId", GetClientUserId},
1344 {"GetMaxClients", sm_GetMaxClients},
1345 {"GetUserAdmin", GetUserAdmin},
1346 {"GetUserFlagBits", GetUserFlagBits},
1347 {"IsClientAuthorized", sm_IsClientAuthorized},
1348 {"IsClientConnected", sm_IsClientConnected},
1349 {"IsFakeClient", sm_IsClientFakeClient},
1350 {"IsPlayerInGame", sm_IsClientInGame}, /* Backwards compat shim */
1351 {"IsClientInGame", sm_IsClientInGame},
1352 {"IsClientObserver", IsClientObserver},
1353 {"RemoveUserFlags", RemoveUserFlags},
1354 {"SetUserAdmin", SetUserAdmin},
1355 {"SetUserFlagBits", SetUserFlagBits},
1356 {"GetClientDeaths", GetDeathCount},
1357 {"GetClientFrags", GetFragCount},
1358 {"GetClientArmor", GetArmorValue},
1359 {"GetClientAbsOrigin", GetAbsOrigin},
1360 {"GetClientAbsAngles", GetAbsAngles},
1361 {"GetClientMins", GetPlayerMins},
1362 {"GetClientMaxs", GetPlayerMaxs},
1363 {"GetClientWeapon", GetWeaponName},
1364 {"GetClientModel", GetModelName},
1365 {"GetClientHealth", GetHealth},
1366 {"GetClientTime", GetTimeConnected},
1367 {"GetClientDataRate", GetDataRate},
1368 {"IsClentTimingOut", IsTimingOut},
1369 {"GetClientLatency", GetLatency},
1370 {"GetClientAvgLatency", GetAvgLatency},
1371 {"GetClientAvgLoss", GetAvgLoss},
1372 {"GetClientAvgChoke", GetAvgChoke},
1373 {"GetClientAvgData", GetAvgData},
1374 {"GetClientAvgPackets", GetAvgPackets},
1375 {"GetClientOfUserId", GetClientOfUserId},
1376 {"ShowActivity", ShowActivity},
1377 {"ShowActivityEx", ShowActivityEx},
1378 {"ShowActivity2", ShowActivity2},
1379 {"KickClient", KickClient},
1380 {"RunAdminCacheChecks", RunAdminCacheChecks},
1381 {"NotifyPostAdminCheck", NotifyPostAdminCheck},
1382 {"IsClientInKickQueue", IsClientInKickQueue},
1383 {"ProcessTargetString", ProcessTargetString},