sm-plugins/CallAdmin/scripting/CallAdmin.sp
2019-10-17 10:23:18 +02:00

1419 lines
30 KiB
SourcePawn

/**
* -----------------------------------------------------
* File calladmin.sp
* Authors Impact, dordnung
* License GPLv3
* Web http://gugyclan.eu, https://dordnung.de
* -----------------------------------------------------
*
* CallAdmin
* Copyright (C) 2013-2018 Impact, dordnung
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <sourcemod>
#include "include/autoexecconfig"
#include "include/calladmin"
#include "include/calladmin_stocks"
#undef REQUIRE_PLUGIN
#include <clientprefs>
#pragma semicolon 1
#pragma newdecls required
// Banreasons
ArrayList g_hReasonAdt;
char g_sReasonConfigFile[PLATFORM_MAX_PATH];
// Global Stuff
ConVar g_hServerName;
char g_sServerName[64];
ConVar g_hVersion;
ConVar g_hHostPort;
int g_iHostPort;
ConVar g_hHostIP;
char g_sHostIP[16];
Handle g_hAdvertTimer;
ConVar g_hAdvertInterval;
float g_fAdvertInterval;
ConVar g_hPublicMessage;
bool g_bPublicMessage;
ConVar g_hOwnReason;
bool g_bOwnReason;
ConVar g_hConfirmCall;
bool g_bConfirmCall;
ConVar g_hSpamTime;
int g_iSpamTime;
ConVar g_hReportTime;
int g_iReportTime;
ConVar g_hAdminAction;
int g_iAdminAction;
// Report id used for handling
int g_iCurrentReportID;
// List of not handled IDs
ArrayList g_hActiveReports;
// Log file
char g_sLogFile[PLATFORM_MAX_PATH];
#define ADMIN_ACTION_PASS 0
#define ADMIN_ACTION_BLOCK_MESSAGE 1
int g_iCurrentTrackers;
// Current target info
g_iTarget[MAXPLAYERS + 1];
char g_sTargetReason[MAXPLAYERS + 1][REASON_MAX_LENGTH];
// Is this player writing his own reason?
bool g_bAwaitingReason[MAXPLAYERS +1];
// When has this user reported the last time
g_iLastReport[MAXPLAYERS +1];
// When was this user reported the last time?
g_iLastReported[MAXPLAYERS +1];
// Whether or not a client saw the antispam message
bool g_bSawMessage[MAXPLAYERS +1];
// Cookies
Handle g_hLastReportCookie;
Handle g_hLastReportedCookie;
// Api
Handle g_hOnReportPreForward;
Handle g_hOnReportPostForward;
Handle g_hOnDrawMenuForward;
Handle g_hOnDrawOwnReasonForward;
Handle g_hOnTrackerCountChangedForward;
Handle g_hOnDrawTargetForward;
Handle g_hOnAddToAdminCountForward;
Handle g_hOnServerDataChangedForward;
Handle g_hOnLogMessageForward;
Handle g_hOnReportHandledForward;
public Plugin myinfo =
{
name = "CallAdmin",
author = "Impact, dordnung",
description = "Call an Admin for help",
version = CALLADMIN_VERSION,
url = "http://gugyclan.eu"
}
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
RegPluginLibrary("calladmin");
// Api
CreateNative("CallAdmin_GetTrackersCount", Native_GetCurrentTrackers);
CreateNative("CallAdmin_RequestTrackersCountRefresh", Native_RequestTrackersCountRefresh);
CreateNative("CallAdmin_GetHostName", Native_GetHostName);
CreateNative("CallAdmin_GetHostIP", Native_GetHostIP);
CreateNative("CallAdmin_GetHostPort", Native_GetHostPort);
CreateNative("CallAdmin_ReportClient", Native_ReportClient);
CreateNative("CallAdmin_LogMessage", Native_LogMessage);
CreateNative("CallAdmin_GetReportID", Native_GetReportID);
return APLRes_Success;
}
public int Native_GetCurrentTrackers(Handle plugin, int numParams)
{
return g_iCurrentTrackers;
}
public int Native_RequestTrackersCountRefresh(Handle plugin, int numParams)
{
Timer_UpdateTrackersCount(null);
}
public int Native_GetHostName(Handle plugin, int numParams)
{
int max_size = GetNativeCell(2);
SetNativeString(1, g_sServerName, max_size);
}
public int Native_GetHostIP(Handle plugin, int numParams)
{
int max_size = GetNativeCell(2);
SetNativeString(1, g_sHostIP, max_size);
}
public int Native_GetHostPort(Handle plugin, int numParams)
{
return g_iHostPort;
}
public int Native_ReportClient(Handle plugin, int numParams)
{
int client;
int target;
char sReason[REASON_MAX_LENGTH];
client = GetNativeCell(1);
target = GetNativeCell(2);
GetNativeString(3, sReason, sizeof(sReason));
// We check for the REPORTER_CONSOLE define here, if this is set we have no valid client and the report comes from server
if (!IsClientValid(client) && client != REPORTER_CONSOLE)
{
return false;
}
if (!IsClientValid(target))
{
return false;
}
if (!Forward_OnReportPre(client, target, sReason))
{
return false;
}
g_iCurrentReportID++;
g_hActiveReports.Push(g_iCurrentReportID);
Forward_OnReportPost(client, target, sReason);
return true;
}
public int Native_LogMessage(Handle plugin, int numParams)
{
char sPluginName[64];
char sMessage[256];
GetPluginInfo(plugin, PlInfo_Name, sPluginName, sizeof(sPluginName));
FormatNativeString(0, 1, 2, sizeof(sMessage), _, sMessage);
LogToFileEx(g_sLogFile, "[%s] %s", sPluginName, sMessage);
Forward_OnLogMessage(plugin, sMessage);
}
public int Native_GetReportID(Handle plugin, int numParams)
{
return g_iCurrentReportID;
}
public void OnConfigsExecuted()
{
g_iHostPort = g_hHostPort.IntValue;
UpdateHostIp();
g_hServerName.GetString(g_sServerName, sizeof(g_sServerName));
g_bPublicMessage = g_hPublicMessage.BoolValue;
g_bOwnReason = g_hOwnReason.BoolValue;
g_bConfirmCall = g_hConfirmCall.BoolValue;
g_iSpamTime = g_hSpamTime.IntValue;
g_iReportTime = g_hReportTime.IntValue;
g_iAdminAction = g_hAdminAction.IntValue;
g_fAdvertInterval = g_hAdvertInterval.FloatValue;
delete g_hAdvertTimer;
if (g_fAdvertInterval != 0.0)
{
g_hAdvertTimer = CreateTimer(g_fAdvertInterval, Timer_Advert, _, TIMER_REPEAT);
}
}
public void OnPluginStart()
{
BuildPath(Path_SM, g_sLogFile, sizeof(g_sLogFile), "logs/calladmin.log");
g_hHostPort = FindConVar("hostport");
g_hHostIP = FindConVar("hostip");
g_hServerName = FindConVar("hostname");
if (g_hHostPort == null)
{
CallAdmin_LogMessage("Couldn't find cvar 'hostport'");
SetFailState("Couldn't find cvar 'hostport'");
}
if (g_hHostIP == null)
{
CallAdmin_LogMessage("Couldn't find cvar 'hostip'");
SetFailState("Couldn't find cvar 'hostip'");
}
if (g_hServerName == null)
{
CallAdmin_LogMessage("Couldn't find cvar 'hostname'");
SetFailState("Couldn't find cvar 'hostname'");
}
RegConsoleCmd("sm_call", Command_Call);
RegConsoleCmd("sm_calladmin", Command_Call);
RegConsoleCmd("sm_call_handle", Command_HandleCall);
RegConsoleCmd("sm_calladmin_handle", Command_HandleCall);
RegConsoleCmd("sm_calladmin_reload", Command_Reload);
AutoExecConfig_SetFile("plugin.calladmin");
g_hVersion = AutoExecConfig_CreateConVar("sm_calladmin_version", CALLADMIN_VERSION, "Plugin version", FCVAR_NOTIFY|FCVAR_DONTRECORD);
g_hAdvertInterval = AutoExecConfig_CreateConVar("sm_calladmin_advert_interval", "60.0", "Interval to advert the use of calladmin, 0.0 deactivates the feature", FCVAR_NONE, true, 0.0, true, 1800.0);
g_hPublicMessage = AutoExecConfig_CreateConVar("sm_calladmin_public_message", "0", "Whether or not a report should be notified to all players or only the reporter.", FCVAR_NONE, true, 0.0, true, 1.0);
g_hOwnReason = AutoExecConfig_CreateConVar("sm_calladmin_own_reason", "1", "Whether or not a client can submit their own reason.", FCVAR_NONE, true, 0.0, true, 1.0);
g_hConfirmCall = AutoExecConfig_CreateConVar("sm_calladmin_confirm_call", "1", "Whether or not a call must be confirmed by the client", FCVAR_NONE, true, 0.0, true, 1.0);
g_hSpamTime = AutoExecConfig_CreateConVar("sm_calladmin_spamtime", "25", "An user must wait this many seconds after a report before he can issue a new one", FCVAR_NONE, true, 0.0);
g_hReportTime = AutoExecConfig_CreateConVar("sm_calladmin_reporttime", "300", "An user cannot be reported again for this many seconds", FCVAR_NONE, true, 0.0);
g_hAdminAction = AutoExecConfig_CreateConVar("sm_calladmin_admin_action", "0", "What happens when admins are in-game on report: 0 - Do nothing, let the report pass, 1 - Block the report and notify the caller and admins in-game about it", FCVAR_NONE, true, 0.0, true, 1.0);
AutoExecConfig(true, "plugin.CallAdmin");
AutoExecConfig_CleanFile();
LoadTranslations("calladmin.phrases");
// This is done so that when the plugin is updated its version stays up to date too
g_hVersion.SetString(CALLADMIN_VERSION, false, false);
g_hVersion.AddChangeHook(OnCvarChanged);
g_hServerName.AddChangeHook(OnCvarChanged);
g_hHostPort.AddChangeHook(OnCvarChanged);
g_hHostIP.AddChangeHook(OnCvarChanged);
g_hAdvertInterval.AddChangeHook(OnCvarChanged);
g_hPublicMessage.AddChangeHook(OnCvarChanged);
g_hOwnReason.AddChangeHook(OnCvarChanged);
g_hConfirmCall.AddChangeHook(OnCvarChanged);
g_hSpamTime.AddChangeHook(OnCvarChanged);
g_hReportTime.AddChangeHook(OnCvarChanged);
g_hAdminAction.AddChangeHook(OnCvarChanged);
// Modules must create their own updaters
CreateTimer(10.0, Timer_UpdateTrackersCount, _, TIMER_REPEAT);
// Used to allow a client to input their own reason
AddCommandListener(ChatListener, "say");
AddCommandListener(ChatListener, "say2");
AddCommandListener(ChatListener, "say_team");
// Api
g_hOnReportPreForward = CreateGlobalForward("CallAdmin_OnReportPre", ET_Event, Param_Cell, Param_Cell, Param_String);
g_hOnReportPostForward = CreateGlobalForward("CallAdmin_OnReportPost", ET_Ignore, Param_Cell, Param_Cell, Param_String);
g_hOnDrawMenuForward = CreateGlobalForward("CallAdmin_OnDrawMenu", ET_Event, Param_Cell);
g_hOnDrawOwnReasonForward = CreateGlobalForward("CallAdmin_OnDrawOwnReason", ET_Event, Param_Cell);
g_hOnTrackerCountChangedForward = CreateGlobalForward("CallAdmin_OnTrackerCountChanged", ET_Ignore, Param_Cell, Param_Cell);
g_hOnDrawTargetForward = CreateGlobalForward("CallAdmin_OnDrawTarget", ET_Event, Param_Cell, Param_Cell);
g_hOnAddToAdminCountForward = CreateGlobalForward("CallAdmin_OnAddToAdminCount", ET_Event, Param_Cell);
g_hOnServerDataChangedForward = CreateGlobalForward("CallAdmin_OnServerDataChanged", ET_Ignore, Param_Cell, Param_Cell, Param_String, Param_String);
g_hOnLogMessageForward = CreateGlobalForward("CallAdmin_OnLogMessage", ET_Ignore, Param_Cell, Param_String);
g_hOnReportHandledForward = CreateGlobalForward("CallAdmin_OnReportHandled", ET_Ignore, Param_Cell, Param_Cell);
// Cookies
if (LibraryExists("clientprefs"))
{
g_hLastReportCookie = RegClientCookie("CallAdmin_LastReport", "Contains a timestamp when this user has reported the last time", CookieAccess_Private);
g_hLastReportedCookie = RegClientCookie("CallAdmin_LastReported", "Contains a timestamp when this user was reported the last time", CookieAccess_Private);
FetchClientCookies();
}
// Report handling
g_hActiveReports = new ArrayList();
// Reason handling
g_hReasonAdt = new ArrayList(ByteCountToCells(REASON_MAX_LENGTH));
BuildPath(Path_SM, g_sReasonConfigFile, sizeof(g_sReasonConfigFile), "configs/calladmin_reasons.cfg");
if (!FileExists(g_sReasonConfigFile))
{
CreateReasonList();
}
ParseReasonList();
}
void CreateReasonList()
{
File hFile;
hFile = OpenFile(g_sReasonConfigFile, "w");
if (hFile == null)
{
CallAdmin_LogMessage("Failed to open configfile 'calladmin_reasons.cfg' for writing");
SetFailState("Failed to open configfile 'calladmin_reasons.cfg' for writing");
}
hFile.WriteLine("// List of reasons seperated by a new line, max %d in length", REASON_MAX_LENGTH);
hFile.WriteLine("Aimbot");
hFile.WriteLine("Wallhack");
hFile.WriteLine("Speedhack");
hFile.WriteLine("Spinhack");
hFile.WriteLine("Multihack");
hFile.WriteLine("No-Recoil Hack");
hFile.WriteLine("Other");
hFile.Close();
}
void ParseReasonList()
{
File hFile;
hFile = OpenFile(g_sReasonConfigFile, "r");
if (hFile == null)
{
CallAdmin_LogMessage("Failed to open configfile 'calladmin_reasons.cfg' for reading");
SetFailState("Failed to open configfile 'calladmin_reasons.cfg' for reading");
}
// Buffer must be a little bit bigger to have enough room for possible comments and being able to check for too long reasons
char sReadBuffer[PLATFORM_MAX_PATH];
int len;
while (!hFile.EndOfFile() && hFile.ReadLine(sReadBuffer, sizeof(sReadBuffer)))
{
if (sReadBuffer[0] == '/' || IsCharSpace(sReadBuffer[0]))
{
continue;
}
ReplaceString(sReadBuffer, sizeof(sReadBuffer), "\n", "");
ReplaceString(sReadBuffer, sizeof(sReadBuffer), "\r", "");
ReplaceString(sReadBuffer, sizeof(sReadBuffer), "\t", "");
len = strlen(sReadBuffer);
if (len < 3 || len > REASON_MAX_LENGTH)
{
continue;
}
// Add the reason to the list only if it doesn't already exist
if (g_hReasonAdt.FindString(sReadBuffer) == -1)
{
g_hReasonAdt.PushString(sReadBuffer);
}
}
hFile.Close();
}
public void OnClientCookiesCached(int client)
{
char sCookieBuf[24];
GetClientCookie(client, g_hLastReportCookie, sCookieBuf, sizeof(sCookieBuf));
if (strlen(sCookieBuf) > 0)
{
g_iLastReport[client] = StringToInt(sCookieBuf);
}
// Just to be safe
sCookieBuf[0] = '\0';
GetClientCookie(client, g_hLastReportedCookie, sCookieBuf, sizeof(sCookieBuf));
if (strlen(sCookieBuf) > 0)
{
g_iLastReported[client] = StringToInt(sCookieBuf);
}
}
void FetchClientCookies()
{
for (int i; i <= MaxClients; i++)
{
if (IsClientValid(i) && !IsFakeClient(i) && !IsClientSourceTV(i) && !IsClientReplay(i) && AreClientCookiesCached(i))
{
OnClientCookiesCached(i);
}
}
}
bool Forward_OnDrawMenu(int client)
{
Action result;
Call_StartForward(g_hOnDrawMenuForward);
Call_PushCell(client);
Call_Finish(result);
return (result == Plugin_Continue);
}
bool Forward_OnReportPre(int client, int target, const char[] reason)
{
Action result;
Call_StartForward(g_hOnReportPreForward);
Call_PushCell(client);
Call_PushCell(target);
Call_PushString(reason);
Call_Finish(result);
return (result == Plugin_Continue);
}
void Forward_OnReportPost(int client, int target, const char[] reason)
{
Call_StartForward(g_hOnReportPostForward);
Call_PushCell(client);
Call_PushCell(target);
Call_PushString(reason);
Call_Finish();
}
bool Forward_OnDrawOwnReason(int client)
{
Action result;
Call_StartForward(g_hOnDrawOwnReasonForward);
Call_PushCell(client);
Call_Finish(result);
return (result == Plugin_Continue);
}
bool Forward_OnAddToAdminCount(int client)
{
Action result;
Call_StartForward(g_hOnAddToAdminCountForward);
Call_PushCell(client);
Call_Finish(result);
return (result == Plugin_Continue);
}
void Forward_OnTrackerCountChanged(int oldVal, int newVal)
{
Call_StartForward(g_hOnTrackerCountChangedForward);
Call_PushCell(oldVal);
Call_PushCell(newVal);
Call_Finish();
}
bool Forward_OnDrawTarget(int client, int target)
{
Action result;
Call_StartForward(g_hOnDrawTargetForward);
Call_PushCell(client);
Call_PushCell(target);
Call_Finish(result);
return (result == Plugin_Continue);
}
void Forward_OnServerDataChanged(ConVar convar, ServerData type, const char[] oldVal, const char[] newVal)
{
Call_StartForward(g_hOnServerDataChangedForward);
Call_PushCell(convar);
Call_PushCell(type);
Call_PushString(oldVal);
Call_PushString(newVal);
Call_Finish();
}
void Forward_OnLogMessage(Handle plugin, const char[] message)
{
Call_StartForward(g_hOnLogMessageForward);
Call_PushCell(plugin);
Call_PushString(message);
Call_Finish();
}
void Forward_OnReportHandled(int client, int id)
{
Call_StartForward(g_hOnReportHandledForward);
Call_PushCell(client);
Call_PushCell(id);
Call_Finish();
}
public Action Timer_Advert(Handle timer)
{
if (g_iCurrentTrackers > 0)
{
// Spelling is different (0 admins, 1 admin, 2 admins, 3 admins...)
if (g_iCurrentTrackers == 1)
{
PrintToChatAll("\x04[CALLADMIN]\x03 %t", "CallAdmin_AdvertMessageSingular", g_iCurrentTrackers);
}
else
{
PrintToChatAll("\x04[CALLADMIN]\x03 %t", "CallAdmin_AdvertMessagePlural", g_iCurrentTrackers);
}
}
return Plugin_Handled;
}
public void OnCvarChanged(ConVar cvar, const char[] oldValue, const char[] newValue)
{
if (cvar == g_hHostPort)
{
g_iHostPort = g_hHostPort.IntValue;
Forward_OnServerDataChanged(cvar, ServerData_HostPort, oldValue, newValue);
}
else if (cvar == g_hHostIP)
{
UpdateHostIp();
Forward_OnServerDataChanged(cvar, ServerData_HostIP, g_sHostIP, g_sHostIP);
}
else if (cvar == g_hServerName)
{
g_hServerName.GetString(g_sServerName, sizeof(g_sServerName));
Forward_OnServerDataChanged(cvar, ServerData_HostName, oldValue, newValue);
}
else if (cvar == g_hVersion)
{
g_hVersion.SetString(CALLADMIN_VERSION, false, false);
}
else if (cvar == g_hAdvertInterval)
{
delete g_hAdvertTimer;
g_fAdvertInterval = g_hAdvertInterval.FloatValue;
if (g_fAdvertInterval != 0.0)
{
g_hAdvertTimer = CreateTimer(g_fAdvertInterval, Timer_Advert, _, TIMER_REPEAT);
}
}
else if (cvar == g_hPublicMessage)
{
g_bPublicMessage = g_hPublicMessage.BoolValue;
}
else if (cvar == g_hOwnReason)
{
g_bOwnReason = g_hOwnReason.BoolValue;
}
else if (cvar == g_hConfirmCall)
{
g_bConfirmCall = g_hConfirmCall.BoolValue;
}
else if (cvar == g_hSpamTime)
{
g_iSpamTime = g_hSpamTime.IntValue;
}
else if (cvar == g_hReportTime)
{
g_iReportTime = g_hReportTime.IntValue;
}
else if (cvar == g_hAdminAction)
{
g_iAdminAction = g_hAdminAction.IntValue;
}
}
public Action Command_Call(int client, int argc)
{
// Console cannot use this
if (client == 0)
{
ReplyToCommand(client, "This command can't be used from console");
return Plugin_Handled;
}
if (!Forward_OnDrawMenu(client))
{
return Plugin_Handled;
}
if (g_iLastReport[client] == 0 || LastReportTimeCheck(client))
{
g_bSawMessage[client] = false;
ShowClientSelectMenu(client);
}
else if (!g_bSawMessage[client])
{
ReplyToCommand(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_CommandNotAllowed", g_iSpamTime - ( GetTime() - g_iLastReport[client] ));
g_bSawMessage[client] = true;
}
return Plugin_Handled;
}
public Action Command_HandleCall(int client, int argc)
{
if (client == 0)
{
ReplyToCommand(client, "This command can't be used from console");
return Plugin_Handled;
}
if (!CheckCommandAccess(client, "sm_calladmin_admin", ADMFLAG_BAN, false))
{
ReplyToCommand(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_NoAdmin");
return Plugin_Handled;
}
if (argc != 1)
{
char cmdName[64];
GetCmdArg(0, cmdName, sizeof(cmdName));
ReplyToCommand(client, "\x04[CALLADMIN]\x03 %t: %s <id>", "CallAdmin_WrongNumberOfArguments", cmdName);
return Plugin_Handled;
}
char sArgID[10];
int reportID;
GetCmdArg(1, sArgID, sizeof(sArgID));
reportID = StringToInt(sArgID);
if (reportID > g_iCurrentReportID)
{
ReplyToCommand(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_WrongReportID");
return Plugin_Handled;
}
// Report was already handled
int reportIndex = g_hActiveReports.FindValue(reportID);
if (reportIndex == -1)
{
ReplyToCommand(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_ReportAlreadyHandled");
return Plugin_Handled;
}
g_hActiveReports.Erase(reportIndex);
Forward_OnReportHandled(client, reportID);
return Plugin_Handled;
}
public Action Command_Reload(int client, int argc)
{
if (!CheckCommandAccess(client, "sm_calladmin_admin", ADMFLAG_BAN, false))
{
ReplyToCommand(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_NoAdmin");
return Plugin_Handled;
}
g_hActiveReports.Clear();
g_hReasonAdt.Clear();
ParseReasonList();
return Plugin_Handled;
}
bool LastReportTimeCheck(int client)
{
if (g_iLastReport[client] <= ( GetTime() - g_iSpamTime ))
{
return true;
}
return false;
}
bool LastReportedTimeCheck(int client)
{
if (g_iLastReported[client] <= ( GetTime() - g_iReportTime ))
{
return true;
}
return false;
}
// Updates the timestamps of lastreport and lastreported
void SetStates(int client, int target)
{
int currentTime = GetTime();
g_iLastReport[client] = currentTime;
g_iLastReported[target] = currentTime;
// Cookies
if (LibraryExists("clientprefs"))
{
SetClientCookieEx(client, g_hLastReportCookie, "%d", currentTime);
SetClientCookieEx(target, g_hLastReportedCookie, "%d", currentTime);
}
}
void ConfirmCall(int client)
{
Menu menu = new Menu(MenuHandler_ConfirmCall);
menu.SetTitle("%T", "CallAdmin_ConfirmCall", client);
char sConfirm[24];
Format(sConfirm, sizeof(sConfirm), "%T", "CallAdmin_Yes", client);
menu.AddItem("Yes", sConfirm);
Format(sConfirm, sizeof(sConfirm), "%T", "CallAdmin_No", client);
menu.AddItem("No", sConfirm);
menu.Display(client, 30);
}
public int MenuHandler_ConfirmCall(Menu menu, MenuAction action, int client, int param2)
{
if (action == MenuAction_Select)
{
char sInfo[24];
menu.GetItem(param2, sInfo, sizeof(sInfo));
// Client has chosen to confirm the call
if (StrEqual("Yes", sInfo))
{
if (!ReportPlayer(client, g_iTarget[client], g_sTargetReason[client]))
{
return;
}
}
else
{
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_CallAborted");
}
}
else if (action == MenuAction_End)
{
menu.Close();
}
}
bool PreReportCheck(int client, int target)
{
// Selected target isn't valid anymore
if (!IsClientValid(target))
{
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_NotInGame");
return false;
}
// Already reported (race condition)
if (!LastReportedTimeCheck(target))
{
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_AlreadyReported");
return false;
}
return true;
}
bool ReportPlayer(int client, int target, char[] sReason)
{
if (!PreReportCheck(client, target))
{
return false;
}
// Admins available and we want to notify them instead of sending the report
if (GetAdminCount() > 0 && g_iAdminAction == ADMIN_ACTION_BLOCK_MESSAGE)
{
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_IngameAdminNotified");
PrintNotifyMessageToAdmins(client, g_iTarget[client]);
SetStates(client, g_iTarget[client]);
return false;
}
if (!Forward_OnReportPre(client, g_iTarget[client], g_sTargetReason[client]))
{
return false;
}
if (g_bPublicMessage)
{
PrintToChatAll("\x04[CALLADMIN]\x03 %t", "CallAdmin_HasReported", client, target, sReason);
}
else
{
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_YouHaveReported", target, sReason);
}
SetStates(client, target);
g_iCurrentReportID++;
g_hActiveReports.Push(g_iCurrentReportID);
Forward_OnReportPost(client, target, sReason);
return true;
}
public Action Timer_UpdateTrackersCount(Handle timer)
{
int temp = GetTotalTrackers();
if (temp != g_iCurrentTrackers)
{
Forward_OnTrackerCountChanged(g_iCurrentTrackers, temp);
}
g_iCurrentTrackers = temp;
return Plugin_Continue;
}
int GetTotalTrackers()
{
Handle hIter;
Handle hPlugin;
Function func;
int count;
int tempcount;
hIter = GetPluginIterator();
while (MorePlugins(hIter))
{
hPlugin = ReadPlugin(hIter);
if (GetPluginStatus(hPlugin) == Plugin_Running)
{
// We check if the plugin has the public CallAdmin_OnRequestTrackersCountRefresh function
if ( (func = GetFunctionByName(hPlugin, "CallAdmin_OnRequestTrackersCountRefresh") ) != INVALID_FUNCTION)
{
Call_StartFunction(hPlugin, func);
Call_PushCellRef(tempcount);
Call_Finish();
if (tempcount > 0)
{
count += tempcount;
}
}
}
}
delete hIter;
return count;
}
void ShowClientSelectMenu(int client)
{
char sName[MAX_NAME_LENGTH];
char sID[24];
Menu menu = new Menu(MenuHandler_ClientSelect);
menu.SetTitle("%T", "CallAdmin_SelectClient", client);
for (int i; i <= MaxClients; i++)
{
if (i != client && LastReportedTimeCheck(i) && IsClientValid(i) && !IsFakeClient(i) && !IsClientSourceTV(i) && !IsClientReplay(i) && Forward_OnDrawTarget(client, i))
{
GetClientName(i, sName, sizeof(sName));
Format(sID, sizeof(sID), "%d", GetClientSerial(i));
menu.AddItem(sID, sName);
}
}
// Menu has no items, no players to report
if (menu.ItemCount < 1)
{
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_NoPlayers");
}
else
{
menu.Display(client, 30);
}
}
public int MenuHandler_ClientSelect(Menu menu, MenuAction action, int client, int param2)
{
if (action == MenuAction_Select)
{
char sInfo[24];
int iSerial;
int iID;
menu.GetItem(param2, sInfo, sizeof(sInfo));
iSerial = StringToInt(sInfo);
iID = GetClientFromSerial(iSerial);
if (!PreReportCheck(client, iID))
{
return;
}
g_iTarget[client] = iID;
ShowBanReasonMenu(client);
}
else if (action == MenuAction_End)
{
menu.Close();
}
}
public void OnClientDisconnect_Post(int client)
{
g_iTarget[client] = 0;
g_sTargetReason[client][0] = '\0';
g_iLastReport[client] = 0;
g_iLastReported[client] = 0;
g_bSawMessage[client] = false;
g_bAwaitingReason[client] = false;
RemoveAsTarget(client);
}
void RemoveAsTarget(int client)
{
for (int i; i <= MaxClients; i++)
{
if (g_iTarget[i] == client)
{
g_iTarget[i] = 0;
}
}
}
void ShowBanReasonMenu(int client)
{
int count;
char sReasonBuffer[REASON_MAX_LENGTH];
count = g_hReasonAdt.Length;
Menu menu = new Menu(MenuHandler_BanReason);
menu.SetTitle("%T", "CallAdmin_SelectReason", client, g_iTarget[client]);
for (int i; i < count; i++)
{
g_hReasonAdt.GetString(i, sReasonBuffer, sizeof(sReasonBuffer));
if (strlen(sReasonBuffer) < 3)
{
continue;
}
menu.AddItem(sReasonBuffer, sReasonBuffer);
}
// Own reason, call the forward
if (g_bOwnReason && Forward_OnDrawOwnReason(client))
{
char sOwnReason[REASON_MAX_LENGTH];
Format(sOwnReason, sizeof(sOwnReason), "%T", "CallAdmin_OwnReason", client);
menu.AddItem("Own reason", sOwnReason);
}
menu.Display(client, 30);
}
public int MenuHandler_BanReason(Menu menu, MenuAction action, int client, int param2)
{
if (action == MenuAction_Select)
{
char sInfo[REASON_MAX_LENGTH];
menu.GetItem(param2, sInfo, sizeof(sInfo));
// User has chosen to use his own reason
if (StrEqual("Own reason", sInfo))
{
g_bAwaitingReason[client] = true;
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_TypeOwnReason");
return;
}
Format(g_sTargetReason[client], sizeof(g_sTargetReason[]), sInfo);
if (!PreReportCheck(client, g_iTarget[client]))
{
return;
}
if (g_bConfirmCall)
{
ConfirmCall(client);
}
else
{
if (!ReportPlayer(client, g_iTarget[client], g_sTargetReason[client]))
{
return;
}
}
}
else if (action == MenuAction_End)
{
menu.Close();
}
}
public Action ChatListener(int client, const char[] command, int argc)
{
// There were a few cases were the client index was invalid which caused an index out-of-bounds error
// Invalid clients shouldn't be able to trigger this callback so the reason why this happens has yet to be found out
// Until then we have this check here to prevent it
if (!IsClientValid(client))
{
return Plugin_Continue;
}
if (g_bAwaitingReason[client] && !IsChatTrigger())
{
// 2 more for quotes
char sReason[REASON_MAX_LENGTH + 2];
GetCmdArgString(sReason, sizeof(sReason));
StripQuotes(sReason);
strcopy(g_sTargetReason[client], sizeof(g_sTargetReason[]), sReason);
g_bAwaitingReason[client] = false;
// Has aborted
if (StrEqual(sReason, "!noreason") || StrEqual(sReason, "!abort"))
{
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_CallAborted");
return Plugin_Handled;
}
// Reason was too short
if (strlen(sReason) < 3)
{
g_bAwaitingReason[client] = true;
PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_OwnReasonTooShort");
return Plugin_Handled;
}
if (!PreReportCheck(client, g_iTarget[client]))
{
return Plugin_Handled;
}
if (g_bConfirmCall)
{
ConfirmCall(client);
}
else
{
if (!ReportPlayer(client, g_iTarget[client], g_sTargetReason[client]))
{
return Plugin_Handled;
}
}
// Block the chatmessage
return Plugin_Handled;
}
return Plugin_Continue;
}
stock int GetRealClientCount()
{
int count;
for (int i; i <= MaxClients; i++)
{
if (IsClientValid(i) && !IsFakeClient(i) && !IsClientSourceTV(i) && !IsClientReplay(i))
{
count++;
}
}
return count;
}
stock int GetAdminCount()
{
int count;
for (int i; i <= MaxClients; i++)
{
if (IsClientValid(i) && !IsFakeClient(i) && !IsClientSourceTV(i) && !IsClientReplay(i) && CheckCommandAccess(i, "sm_calladmin_admin", ADMFLAG_BAN, false) && Forward_OnAddToAdminCount(i))
{
count++;
}
}
return count;
}
stock void PrintNotifyMessageToAdmins(int client, int target)
{
for (int i; i <= MaxClients; i++)
{
if (IsClientValid(i) && !IsFakeClient(i) && !IsClientSourceTV(i) && !IsClientReplay(i) && CheckCommandAccess(i, "sm_calladmin_admin", ADMFLAG_BAN, false) && Forward_OnAddToAdminCount(i))
{
PrintToChat(i, "\x04[CALLADMIN]\x03 %t", "CallAdmin_AdminNotification", client, target, g_sTargetReason[client]);
}
}
}
stock void LongToIp(int long, char[] str, int maxlen)
{
int pieces[4];
pieces[0] = ((long >>> 24) & 255);
pieces[1] = ((long >>> 16) & 255);
pieces[2] = ((long >>> 8) & 255);
pieces[3] = (long & 255);
Format(str, maxlen, "%d.%d.%d.%d", pieces[0], pieces[1], pieces[2], pieces[3]);
}
// Updates the global g_sHostIP variable to the current ip of the server
// Using the int value directly provides incorrect results, when given the time it should be examined why
void UpdateHostIp()
{
char tmpString[sizeof(g_sHostIP)];
g_hHostIP.GetString(tmpString, sizeof(tmpString));
int tmpInt = StringToInt(tmpString);
LongToIp(tmpInt, g_sHostIP, sizeof(g_sHostIP));
}
stock void SetClientCookieEx(int client, Handle cookie, const char[] format, any:...)
{
char sFormatBuf[1024];
VFormat(sFormatBuf, sizeof(sFormatBuf), format, 4);
SetClientCookie(client, cookie, sFormatBuf);
}