3 * =============================================================================
5 * Copyright (C) 2004-2008 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, "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);
728 return sp_ftoc(pInfo->GetTimeConnected());
731 static cell_t GetDataRate(IPluginContext *pContext, const cell_t *params)
733 int client = params[1];
735 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
738 return pContext->ThrowNativeError("Client index %d is invalid", client);
739 } else if (!pPlayer->IsInGame()) {
740 return pContext->ThrowNativeError("Client %d is not in game", client);
741 } else if (pPlayer->IsFakeClient()) {
742 return pContext->ThrowNativeError("Client %d is a bot", client);
745 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
751 return pInfo->GetDataRate();
754 static cell_t IsTimingOut(IPluginContext *pContext, const cell_t *params)
756 int client = params[1];
758 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
761 return pContext->ThrowNativeError("Client index %d is invalid", client);
762 } else if (!pPlayer->IsInGame()) {
763 return pContext->ThrowNativeError("Client %d is not in game", client);
764 } else if (pPlayer->IsFakeClient()) {
765 return pContext->ThrowNativeError("Client %d is a bot", client);
768 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
774 return pInfo->IsTimingOut() ? 1 : 0;
777 static cell_t GetLatency(IPluginContext *pContext, const cell_t *params)
779 int client = params[1];
782 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
785 return pContext->ThrowNativeError("Client index %d is invalid", client);
787 else if (!pPlayer->IsInGame())
789 return pContext->ThrowNativeError("Client %d is not in game", client);
791 else if (pPlayer->IsFakeClient())
793 return pContext->ThrowNativeError("Client %d is a bot", client);
796 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
802 if (params[2] == MAX_FLOWS)
804 value = pInfo->GetLatency(FLOW_INCOMING) + pInfo->GetLatency(FLOW_OUTGOING);
808 value = pInfo->GetLatency(params[2]);
811 return sp_ftoc(value);
814 static cell_t GetAvgLatency(IPluginContext *pContext, const cell_t *params)
816 int client = params[1];
819 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
822 return pContext->ThrowNativeError("Client index %d is invalid", client);
824 else if (!pPlayer->IsInGame())
826 return pContext->ThrowNativeError("Client %d is not in game", client);
828 else if (pPlayer->IsFakeClient())
830 return pContext->ThrowNativeError("Client %d is a bot", client);
833 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
839 if (params[2] == MAX_FLOWS)
841 value = pInfo->GetAvgLatency(FLOW_INCOMING) + pInfo->GetAvgLatency(FLOW_OUTGOING);
845 value = pInfo->GetAvgLatency(params[2]);
848 return sp_ftoc(value);
851 static cell_t GetAvgLoss(IPluginContext *pContext, const cell_t *params)
853 int client = params[1];
856 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
859 return pContext->ThrowNativeError("Client index %d is invalid", client);
861 else if (!pPlayer->IsInGame())
863 return pContext->ThrowNativeError("Client %d is not in game", client);
865 else if (pPlayer->IsFakeClient())
867 return pContext->ThrowNativeError("Client %d is a bot", client);
870 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
876 if (params[2] == MAX_FLOWS)
878 value = pInfo->GetAvgLoss(FLOW_INCOMING) + pInfo->GetAvgLoss(FLOW_OUTGOING);
882 value = pInfo->GetAvgLoss(params[2]);
885 return sp_ftoc(value);
888 static cell_t GetAvgChoke(IPluginContext *pContext, const cell_t *params)
890 int client = params[1];
893 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
896 return pContext->ThrowNativeError("Client index %d is invalid", client);
898 else if (!pPlayer->IsInGame())
900 return pContext->ThrowNativeError("Client %d is not in game", client);
902 else if (pPlayer->IsFakeClient())
904 return pContext->ThrowNativeError("Client %d is a bot", client);
907 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
913 if (params[2] == MAX_FLOWS)
915 value = pInfo->GetAvgChoke(FLOW_INCOMING) + pInfo->GetAvgChoke(FLOW_OUTGOING);
919 value = pInfo->GetAvgChoke(params[2]);
922 return sp_ftoc(value);
925 static cell_t GetAvgData(IPluginContext *pContext, const cell_t *params)
927 int client = params[1];
930 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
933 return pContext->ThrowNativeError("Client index %d is invalid", client);
935 else if (!pPlayer->IsInGame())
937 return pContext->ThrowNativeError("Client %d is not in game", client);
939 else if (pPlayer->IsFakeClient())
941 return pContext->ThrowNativeError("Client %d is a bot", client);
944 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
950 if (params[2] == MAX_FLOWS)
952 value = pInfo->GetAvgData(FLOW_INCOMING) + pInfo->GetAvgData(FLOW_OUTGOING);
956 value = pInfo->GetAvgData(params[2]);
959 return sp_ftoc(value);
962 static cell_t GetAvgPackets(IPluginContext *pContext, const cell_t *params)
964 int client = params[1];
967 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
970 return pContext->ThrowNativeError("Client index %d is invalid", client);
972 else if (!pPlayer->IsInGame())
974 return pContext->ThrowNativeError("Client %d is not in game", client);
976 else if (pPlayer->IsFakeClient())
978 return pContext->ThrowNativeError("Client %d is a bot", client);
981 INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client);
988 if (params[2] == MAX_FLOWS)
990 value = pInfo->GetAvgPackets(FLOW_INCOMING) + pInfo->GetAvgPackets(FLOW_OUTGOING);
994 value = pInfo->GetAvgPackets(params[2]);
997 return sp_ftoc(value);
1000 static cell_t GetClientOfUserId(IPluginContext *pContext, const cell_t *params)
1002 return g_Players.GetClientOfUserId(params[1]);
1005 static cell_t _ShowActivity(IPluginContext *pContext,
1006 const cell_t *params,
1012 int value = sm_show_activity.GetInt();
1013 unsigned int replyto = g_ChatTriggers.GetReplyTo();
1014 int client = params[1];
1016 const char *name = "Console";
1017 const char *sign = "ADMIN";
1018 bool display_in_chat = false;
1021 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1022 if (!pPlayer || !pPlayer->IsConnected())
1024 return pContext->ThrowNativeError("Client index %d is invalid", client);
1026 name = pPlayer->GetName();
1027 AdminId id = pPlayer->GetAdminId();
1028 if (id == INVALID_ADMIN_ID
1029 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
1034 /* Display the message to the client? */
1035 if (replyto == SM_REPLY_CONSOLE)
1037 g_SourceMod.SetGlobalTarget(client);
1038 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1040 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1045 UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
1046 engine->ClientPrintf(pPlayer->GetEdict(), message);
1047 display_in_chat = true;
1052 g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
1053 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1055 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1060 UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
1061 META_CONPRINT(message);
1069 int maxClients = g_Players.GetMaxClients();
1070 for (int i=1; i<=maxClients; i++)
1072 CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
1073 if (!pPlayer->IsInGame()
1074 || pPlayer->IsFakeClient()
1075 || (display_in_chat && i == client))
1079 AdminId id = pPlayer->GetAdminId();
1080 g_SourceMod.SetGlobalTarget(i);
1081 if (id == INVALID_ADMIN_ID
1082 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
1084 /* Treat this as a normal user */
1085 if ((value & 1) || (value & 2))
1087 const char *newsign = sign;
1088 if ((value & 2) || (i == client))
1092 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1094 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1099 UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
1100 g_HL2.TextMsg(i, HUD_PRINTTALK, message);
1105 /* Treat this as an admin user */
1106 bool is_root = g_Admins.GetAdminFlag(id, Admin_Root, Access_Effective);
1109 || ((value & 16) && is_root))
1111 const char *newsign = sign;
1112 if ((value & 8) || ((value & 16) && is_root) || (i == client))
1116 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1118 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1123 UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
1124 g_HL2.TextMsg(i, HUD_PRINTTALK, message);
1132 static cell_t _ShowActivity2(IPluginContext *pContext,
1133 const cell_t *params,
1139 int value = sm_show_activity.GetInt();
1140 unsigned int replyto = g_ChatTriggers.GetReplyTo();
1141 int client = params[1];
1143 const char *name = "Console";
1144 const char *sign = "ADMIN";
1147 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1148 if (!pPlayer || !pPlayer->IsConnected())
1150 return pContext->ThrowNativeError("Client index %d is invalid", client);
1152 name = pPlayer->GetName();
1153 AdminId id = pPlayer->GetAdminId();
1154 if (id == INVALID_ADMIN_ID
1155 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
1160 g_SourceMod.SetGlobalTarget(client);
1161 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1163 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1168 /* We don't display directly to the console because the chat text
1169 * simply gets added to the console, so we don't want it to print
1172 if (replyto == SM_REPLY_CONSOLE)
1175 UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
1176 engine->ClientPrintf(pPlayer->GetEdict(), message);
1178 UTIL_Format(message, sizeof(message), "%s%s", tag, buffer);
1179 g_HL2.TextMsg(client, HUD_PRINTTALK, message);
1183 UTIL_Format(message, sizeof(message), "%s%s", tag, buffer);
1184 g_HL2.TextMsg(client, HUD_PRINTTALK, message);
1189 g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
1190 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1192 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1197 UTIL_Format(message, sizeof(message), "%s%s\n", tag, buffer);
1198 META_CONPRINT(message);
1206 int maxClients = g_Players.GetMaxClients();
1207 for (int i=1; i<=maxClients; i++)
1209 CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
1210 if (!pPlayer->IsInGame()
1211 || pPlayer->IsFakeClient()
1216 AdminId id = pPlayer->GetAdminId();
1217 g_SourceMod.SetGlobalTarget(i);
1218 if (id == INVALID_ADMIN_ID
1219 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
1221 /* Treat this as a normal user */
1222 if ((value & 1) || (value & 2))
1224 const char *newsign = sign;
1229 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1231 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1236 UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
1237 g_HL2.TextMsg(i, HUD_PRINTTALK, message);
1242 /* Treat this as an admin user */
1243 bool is_root = g_Admins.GetAdminFlag(id, Admin_Root, Access_Effective);
1246 || ((value & 16) && is_root))
1248 const char *newsign = sign;
1249 if ((value & 8) || ((value & 16) && is_root))
1253 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
1255 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1260 UTIL_Format(message, sizeof(message), "%s%s: %s", tag, newsign, buffer);
1261 g_HL2.TextMsg(i, HUD_PRINTTALK, message);
1269 static cell_t ShowActivity(IPluginContext *pContext, const cell_t *params)
1271 return _ShowActivity(pContext, params, "[SM] ", 2);
1274 static cell_t ShowActivityEx(IPluginContext *pContext, const cell_t *params)
1277 pContext->LocalToString(params[2], &str);
1279 return _ShowActivity(pContext, params, str, 3);
1282 static cell_t ShowActivity2(IPluginContext *pContext, const cell_t *params)
1285 pContext->LocalToString(params[2], &str);
1287 return _ShowActivity2(pContext, params, str, 3);
1290 static cell_t KickClient(IPluginContext *pContext, const cell_t *params)
1292 int client = params[1];
1294 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1297 return pContext->ThrowNativeError("Client index %d is invalid", client);
1299 else if (!pPlayer->IsConnected())
1301 return pContext->ThrowNativeError("Client %d is not connected", client);
1304 /* Ignore duplicate kicks */
1305 if (pPlayer->IsInKickQueue())
1310 pPlayer->MarkAsBeingKicked();
1312 if (pPlayer->IsFakeClient())
1315 UTIL_Format(kickcmd, sizeof(kickcmd), "kick %s\n", pPlayer->GetName());
1317 engine->ServerCommand(kickcmd);
1321 g_SourceMod.SetGlobalTarget(client);
1324 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1326 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1331 g_HL2.AddDelayedKick(client, pPlayer->GetUserId(), buffer);
1336 static cell_t KickClientEx(IPluginContext *pContext, const cell_t *params)
1338 int client = params[1];
1340 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1343 return pContext->ThrowNativeError("Client index %d is invalid", client);
1345 else if (!pPlayer->IsConnected())
1347 return pContext->ThrowNativeError("Client %d is not connected", client);
1350 /* Ignore duplicate kicks */
1351 if (pPlayer->IsInKickQueue())
1356 pPlayer->MarkAsBeingKicked();
1358 if (pPlayer->IsFakeClient())
1361 UTIL_Format(kickcmd, sizeof(kickcmd), "kick %s\n", pPlayer->GetName());
1363 engine->ServerCommand(kickcmd);
1367 g_SourceMod.SetGlobalTarget(client);
1370 g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
1372 if (pContext->GetLastNativeError() != SP_ERROR_NONE)
1377 pPlayer->Kick(buffer);
1382 static cell_t ChangeClientTeam(IPluginContext *pContext, const cell_t *params)
1384 int client = params[1];
1386 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1389 return pContext->ThrowNativeError("Client index %d is invalid", client);
1391 else if (!pPlayer->IsInGame())
1393 return pContext->ThrowNativeError("Client %d is not in game", client);
1396 IPlayerInfo *pInfo = pPlayer->GetPlayerInfo();
1399 return pContext->ThrowNativeError("IPlayerInfo not supported by game");
1402 pInfo->ChangeTeam(params[2]);
1407 static cell_t RunAdminCacheChecks(IPluginContext *pContext, const cell_t *params)
1409 int client = params[1];
1411 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1414 return pContext->ThrowNativeError("Client index %d is invalid", client);
1416 else if (!pPlayer->IsInGame())
1418 return pContext->ThrowNativeError("Client %d is not in game", client);
1420 else if (!pPlayer->IsAuthorized())
1422 return pContext->ThrowNativeError("Client %d is not authorized", client);
1425 AdminId id = pPlayer->GetAdminId();
1426 pPlayer->DoBasicAdminChecks();
1428 return (id != pPlayer->GetAdminId()) ? 1 : 0;
1431 static cell_t NotifyPostAdminCheck(IPluginContext *pContext, const cell_t *params)
1433 int client = params[1];
1435 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1438 return pContext->ThrowNativeError("Client index %d is invalid", client);
1440 else if (!pPlayer->IsInGame()) {
1441 return pContext->ThrowNativeError("Client %d is not in game", client);
1443 else if (!pPlayer->IsAuthorized())
1445 return pContext->ThrowNativeError("Client %d is not authorized", client);
1448 pPlayer->NotifyPostAdminChecks();
1453 static cell_t IsClientInKickQueue(IPluginContext *pContext, const cell_t *params)
1455 int client = params[1];
1457 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1461 return pContext->ThrowNativeError("Client index %d is invalid", client);
1463 else if (!pPlayer->IsConnected())
1465 return pContext->ThrowNativeError("Client %d is not in game", client);
1468 return pPlayer->IsInKickQueue() ? 1 : 0;
1471 static cell_t ProcessTargetString(IPluginContext *pContext, const cell_t *params)
1473 cmd_target_info_t info;
1475 pContext->LocalToString(params[1], (char **)&info.pattern);
1476 info.admin = params[2];
1477 pContext->LocalToPhysAddr(params[3], &info.targets);
1478 info.max_targets = params[4];
1479 info.flags = params[5];
1480 pContext->LocalToString(params[6], &info.target_name);
1481 info.target_name_maxlength = params[7];
1484 pContext->LocalToPhysAddr(params[8], &tn_is_ml);
1486 g_Players.ProcessCommandTarget(&info);
1488 if (info.target_name_style == COMMAND_TARGETNAME_ML)
1497 if (info.num_targets == 0)
1503 return info.num_targets;
1507 static cell_t FormatActivitySource(IPluginContext *pContext, const cell_t *params)
1514 const char *identity[2] = {"Console", "ADMIN"};
1519 if ((pTarget = g_Players.GetPlayerByIndex(target)) == NULL)
1521 return pContext->ThrowNativeError("Invalid client index %d", target);
1523 if (!pTarget->IsConnected())
1525 return pContext->ThrowNativeError("Client %d not connected", target);
1528 value = sm_show_activity.GetInt();
1534 if ((pPlayer = g_Players.GetPlayerByIndex(client)) == NULL)
1536 return pContext->ThrowNativeError("Invalid client index %d", client);
1538 if (!pPlayer->IsConnected())
1540 return pContext->ThrowNativeError("Client %d not connected", client);
1543 identity[0] = pPlayer->GetName();
1545 AdminId id = pPlayer->GetAdminId();
1546 if (id == INVALID_ADMIN_ID
1547 || !g_Admins.GetAdminFlag(id, Admin_Generic, Access_Effective))
1549 identity[1] = "PLAYER";
1554 bool bShowActivity = false;
1556 if ((aidTarget = pTarget->GetAdminId()) == INVALID_ADMIN_ID
1557 || !g_Admins.GetAdminFlag(aidTarget, Admin_Generic, Access_Effective))
1559 /* Treat this as a normal user */
1560 if ((value & 1) || (value & 2))
1562 if ((value & 2) || (target == client))
1566 bShowActivity = true;
1571 /* Treat this as an admin user */
1572 bool is_root = g_Admins.GetAdminFlag(aidTarget, Admin_Root, Access_Effective);
1575 || ((value & 16) && is_root))
1577 if ((value & 8) || ((value & 16) && is_root) || (target == client))
1581 bShowActivity = true;
1585 /* Otherwise, send it back to the script. */
1586 pContext->StringToLocalUTF8(params[3], params[4], identity[mode], NULL);
1588 return bShowActivity ? 1 : 0;
1591 static cell_t sm_GetClientSerial(IPluginContext *pContext, const cell_t *params)
1593 int client = params[1];
1595 CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
1598 return pContext->ThrowNativeError("Client index %d is invalid", client);
1601 return pPlayer->GetSerial();
1604 static cell_t sm_GetClientFromSerial(IPluginContext *pContext, const cell_t *params)
1606 return g_Players.GetClientFromSerial(params[1]);
1609 REGISTER_NATIVES(playernatives)
1611 {"AddUserFlags", AddUserFlags},
1612 {"CanUserTarget", CanUserTarget},
1613 {"ChangeClientTeam", ChangeClientTeam},
1614 {"GetClientAuthString", sm_GetClientAuthStr},
1615 {"GetClientCount", sm_GetClientCount},
1616 {"GetClientInfo", sm_GetClientInfo},
1617 {"GetClientIP", sm_GetClientIP},
1618 {"GetClientName", sm_GetClientName},
1619 {"GetClientTeam", GetClientTeam},
1620 {"GetClientUserId", GetClientUserId},
1621 {"GetMaxClients", sm_GetMaxClients},
1622 {"GetUserAdmin", GetUserAdmin},
1623 {"GetUserFlagBits", GetUserFlagBits},
1624 {"IsClientAuthorized", sm_IsClientAuthorized},
1625 {"IsClientConnected", sm_IsClientConnected},
1626 {"IsFakeClient", sm_IsClientFakeClient},
1627 {"IsClientInGame", sm_IsClientInGame},
1628 {"IsClientObserver", IsClientObserver},
1629 {"RemoveUserFlags", RemoveUserFlags},
1630 {"SetUserAdmin", SetUserAdmin},
1631 {"SetUserFlagBits", SetUserFlagBits},
1632 {"GetClientDeaths", GetDeathCount},
1633 {"GetClientFrags", GetFragCount},
1634 {"GetClientArmor", GetArmorValue},
1635 {"GetClientAbsOrigin", GetAbsOrigin},
1636 {"GetClientAbsAngles", GetAbsAngles},
1637 {"GetClientMins", GetPlayerMins},
1638 {"GetClientMaxs", GetPlayerMaxs},
1639 {"GetClientWeapon", GetWeaponName},
1640 {"GetClientModel", GetModelName},
1641 {"GetClientHealth", GetHealth},
1642 {"GetClientTime", GetTimeConnected},
1643 {"GetClientDataRate", GetDataRate},
1644 {"IsClientTimingOut", IsTimingOut},
1645 {"GetClientLatency", GetLatency},
1646 {"GetClientAvgLatency", GetAvgLatency},
1647 {"GetClientAvgLoss", GetAvgLoss},
1648 {"GetClientAvgChoke", GetAvgChoke},
1649 {"GetClientAvgData", GetAvgData},
1650 {"GetClientAvgPackets", GetAvgPackets},
1651 {"GetClientOfUserId", GetClientOfUserId},
1652 {"ShowActivity", ShowActivity},
1653 {"ShowActivityEx", ShowActivityEx},
1654 {"ShowActivity2", ShowActivity2},
1655 {"KickClient", KickClient},
1656 {"KickClientEx", KickClientEx},
1657 {"RunAdminCacheChecks", RunAdminCacheChecks},
1658 {"NotifyPostAdminCheck", NotifyPostAdminCheck},
1659 {"IsClientInKickQueue", IsClientInKickQueue},
1660 {"ProcessTargetString", ProcessTargetString},
1661 {"FormatActivitySource", FormatActivitySource},
1662 {"GetClientSerial", sm_GetClientSerial},
1663 {"GetClientFromSerial", sm_GetClientFromSerial},