From 540aaf2c9554f025e3980d6e63d08c2730e9acc8 Mon Sep 17 00:00:00 2001 From: Dogan Date: Wed, 16 Oct 2019 22:40:28 +0200 Subject: [PATCH] intial commit: CallAdmin with "_" until fully ready --- _CallAdmin/scripting/CallAdmin.sp | 1448 +++++++++++++++++ .../scripting/CallAdminRestrictions.sp | 0 _CallAdmin/scripting/CallAdminUsermanager.sp | 402 +++++ .../scripting/include/autoexecconfig.inc | 715 ++++++++ .../scripting/include/calladmin.inc | 0 .../scripting/include/calladmin_stocks.inc | 18 + .../include/calladmin_usermanager.inc | 83 + .../translations/calladmin.phrases.txt | 168 ++ .../calladmin_usermanager.phrases.txt | 34 + 9 files changed, 2868 insertions(+) create mode 100644 _CallAdmin/scripting/CallAdmin.sp rename calladmin_restrictions/scripting/calladmin_restrictions.sp => _CallAdmin/scripting/CallAdminRestrictions.sp (100%) create mode 100644 _CallAdmin/scripting/CallAdminUsermanager.sp create mode 100644 _CallAdmin/scripting/include/autoexecconfig.inc rename {calladmin_restrictions => _CallAdmin}/scripting/include/calladmin.inc (100%) create mode 100644 _CallAdmin/scripting/include/calladmin_stocks.inc create mode 100644 _CallAdmin/scripting/include/calladmin_usermanager.inc create mode 100644 _CallAdmin/scripting/translations/calladmin.phrases.txt create mode 100644 _CallAdmin/scripting/translations/calladmin_usermanager.phrases.txt diff --git a/_CallAdmin/scripting/CallAdmin.sp b/_CallAdmin/scripting/CallAdmin.sp new file mode 100644 index 00000000..cfe000ca --- /dev/null +++ b/_CallAdmin/scripting/CallAdmin.sp @@ -0,0 +1,1448 @@ +/** + * ----------------------------------------------------- + * 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 + */ + +#include +#include "include/autoexecconfig" +#include "include/calladmin" +#include "include/calladmin_stocks" + +#undef REQUIRE_PLUGIN +#include "include/updater" +#include +#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; + + + + +// Updater +#define UPDATER_URL "http://plugins.gugyclan.eu/calladmin/calladmin.txt" + + +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", "1", "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 OnAllPluginsLoaded() +{ + if (LibraryExists("updater")) + { + Updater_AddPlugin(UPDATER_URL); + } +} + + + + +public void OnLibraryAdded(const char[] name) +{ + if (StrEqual(name, "updater")) + { + Updater_AddPlugin(UPDATER_URL); + } +} + + + + +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 ", "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); +} \ No newline at end of file diff --git a/calladmin_restrictions/scripting/calladmin_restrictions.sp b/_CallAdmin/scripting/CallAdminRestrictions.sp similarity index 100% rename from calladmin_restrictions/scripting/calladmin_restrictions.sp rename to _CallAdmin/scripting/CallAdminRestrictions.sp diff --git a/_CallAdmin/scripting/CallAdminUsermanager.sp b/_CallAdmin/scripting/CallAdminUsermanager.sp new file mode 100644 index 00000000..5c97d58d --- /dev/null +++ b/_CallAdmin/scripting/CallAdminUsermanager.sp @@ -0,0 +1,402 @@ +/** + * ----------------------------------------------------- + * File calladmin_usermanager.sp + * Authors dordnung, Impact + * License GPLv3 + * Web https://dordnung.de, http://gugyclan.eu + * ----------------------------------------------------- + * + * CallAdmin + * Copyright (C) 2013-2018 dordnung, Impact + * + * 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 + */ + + +#include +#include "include/autoexecconfig" +#include "include/calladmin" +#include "include/calladmin_stocks" + +#undef REQUIRE_PLUGIN +#include "include/updater" +#include + +#pragma semicolon 1 +#pragma newdecls required + + +// Version cvar +ConVar g_hVersion; + +// Cvar to blacklist muted players +ConVar g_hBlacklistMuted; +bool g_bBlacklistMuted; + +// Cvar to blacklist gagged players +ConVar g_hBlacklistGagged; +bool g_bBlacklistGagged; + +// Cvar to show information +ConVar g_hShowInformation; +bool g_bShowInformation; + + + +// Is immune or on blacklist? +bool g_bClientOnBlacklist[MAXPLAYERS + 1]; +bool g_bClientImmune[MAXPLAYERS + 1]; + + + +// Updater +#define UPDATER_URL "http://plugins.gugyclan.eu/calladmin/calladmin_usermanager.txt" + + + +public Plugin myinfo = +{ + name = "CallAdmin UserManager", + author = "dordnung, Impact", + description = "The usermanagermodule for CallAdmin", + version = CALLADMIN_VERSION, + url = "https://dordnung.de" +} + + + + + + +/* + +Sourcemod + +*/ + + +// Register the library +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + RegPluginLibrary("calladmin_usermanager"); + + + // Api + CreateNative("CallAdmin_SetClientOnBlacklist", Native_SetClientOnBlacklist); + CreateNative("CallAdmin_SetClientImmune", Native_SetClientImmune); + CreateNative("CallAdmin_IsClientOnBlacklist", Native_IsClientOnBlacklist); + CreateNative("CallAdmin_IsClientImmune", Native_IsClientImmune); + + + return APLRes_Success; +} + + + +public void OnConfigsExecuted() +{ + g_bBlacklistMuted = g_hBlacklistMuted.BoolValue; + g_bBlacklistGagged = g_hBlacklistGagged.BoolValue; + g_bShowInformation = g_hShowInformation.BoolValue; +} + + + + +// Plugin Started +public void OnPluginStart() +{ + // Create config and load it + AutoExecConfig_SetFile("plugin.calladmin_usermanager"); + + + g_hVersion = AutoExecConfig_CreateConVar("sm_calladmin_usermanager_version", CALLADMIN_VERSION, "Plugin version", FCVAR_NOTIFY|FCVAR_DONTRECORD); + g_hBlacklistMuted = AutoExecConfig_CreateConVar("sm_calladmin_blacklist_muted", "0", "Disallow muted players to report a player", FCVAR_NONE); + g_hBlacklistGagged = AutoExecConfig_CreateConVar("sm_calladmin_blacklist_gagged", "1", "Disallow gagged players to report a player", FCVAR_NONE); + g_hShowInformation = AutoExecConfig_CreateConVar("sm_calladmin_show_information", "0", "Show status to player on mute/gag", FCVAR_NONE); + + + AutoExecConfig(true, "plugin.CallAdminUsermanager"); + AutoExecConfig_CleanFile(); + + + // Load translation + LoadTranslations("calladmin_usermanager.phrases"); + + + // Set Version + g_hVersion.SetString(CALLADMIN_VERSION); + + // Hook changes + g_hVersion.AddChangeHook(OnCvarChanged); + g_hBlacklistMuted.AddChangeHook(OnCvarChanged); + g_hBlacklistGagged.AddChangeHook(OnCvarChanged); + g_hShowInformation.AddChangeHook(OnCvarChanged); +} + + +// Convar Changed +public void OnCvarChanged(Handle cvar, const char[] oldValue, const char[] newValue) +{ + if (cvar == g_hBlacklistMuted) + { + g_bBlacklistMuted = g_hBlacklistMuted.BoolValue; + + // Check basecomm + if (!LibraryExists("basecomm") && g_bBlacklistMuted) + { + CallAdmin_LogMessage("Couldn't find Plugin basecomm.smx. But you've activated mute blacklisting!"); + } + } + + else if (cvar == g_hBlacklistGagged) + { + g_bBlacklistGagged = g_hBlacklistGagged.BoolValue; + + // Check basecomm + if (!LibraryExists("basecomm") && g_hBlacklistGagged) + { + CallAdmin_LogMessage("Couldn't find Plugin basecomm.smx. But you've activated gag blacklisting!"); + } + } + + else if (cvar == g_hShowInformation) + { + g_bShowInformation = g_hShowInformation.BoolValue; + } + + else if (cvar == g_hVersion) + { + g_hVersion.SetString(CALLADMIN_VERSION); + } +} + + +// Updater +public void OnAllPluginsLoaded() +{ + if (LibraryExists("updater")) + { + Updater_AddPlugin(UPDATER_URL); + } + + if (!LibraryExists("basecomm") && (g_bBlacklistMuted || g_bBlacklistGagged)) + { + CallAdmin_LogMessage("Couldn't find Plugin basecomm.smx. But you've activated mute or gag blacklisting!"); + } +} + + +// Updater +public void OnLibraryAdded(const char[] name) +{ + if (StrEqual(name, "updater")) + { + Updater_AddPlugin(UPDATER_URL); + } +} + + + + + + +/* + +NATIVES + +*/ + + +// Set client on blacklist +public int Native_SetClientOnBlacklist(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + if (IsClientValid(client)) + { + g_bClientOnBlacklist[client] = GetNativeCell(2); + } +} + + +// Set Client immune +public int Native_SetClientImmune(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + if (IsClientValid(client)) + { + g_bClientImmune[client] = GetNativeCell(2); + } +} + + +// Checks if the client is on the blacklist +public int Native_IsClientOnBlacklist(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + if (IsClientValid(client)) + { + return g_bClientOnBlacklist[client]; + } + + return false; +} + + +// Checks if the client is immune +public int Native_IsClientImmune(Handle plugin, int numParams) +{ + int client = GetNativeCell(1); + + if (IsClientValid(client)) + { + return g_bClientImmune[client]; + } + + return false; +} + + + + + +/* + +CallAdmin + +*/ + +// Client open the menu +public Action CallAdmin_OnDrawMenu(int client) +{ + // Client is on blacklist, so don't open menu + if (g_bClientOnBlacklist[client]) + { + // Info text + PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_ClientOnBlacklist"); + + return Plugin_Handled; + } + + return Plugin_Continue; +} + + +// Client will drawn to menu +public Action CallAdmin_OnDrawTarget(int client, int target) +{ + // Target is immune, so don't draw it + if (g_bClientImmune[target]) + { + return Plugin_Handled; + } + + return Plugin_Continue; +} + + +// Client will report +public Action CallAdmin_OnReportPre(int client, int target, const char[] reason) +{ + // Target is immune, so don't report + if (g_bClientImmune[target]) + { + // Info text + if (client != REPORTER_CONSOLE) + { + PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_TargetImmune", target); + } + + return Plugin_Handled; + } + + // Client is on blacklist so don't allow report + if (client != REPORTER_CONSOLE && g_bClientOnBlacklist[client]) + { + // Info text + PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_ClientOnBlacklist"); + + return Plugin_Handled; + } + + return Plugin_Continue; +} + + + + + +/* + +Basecomm + +*/ + + +// Client get muted +public void BaseComm_OnClientMute(int client, bool muteState) +{ + if (g_bBlacklistMuted && IsClientValid(client)) + { + // Show information + if (g_bShowInformation && muteState != g_bClientOnBlacklist[client]) + { + if (muteState) + { + PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_ClientBlacklistMute"); + } + else + { + PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_ClientBlacklistRemove"); + } + } + + // Set client on blacklist + g_bClientOnBlacklist[client] = muteState; + } +} + + +// Client get gagged +public void BaseComm_OnClientGag(int client, bool gagState) +{ + if (g_bBlacklistGagged && IsClientValid(client)) + { + // Show information + if (g_bShowInformation && g_bClientOnBlacklist[client] != gagState) + { + if (gagState) + { + PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_ClientBlacklistGag"); + } + else + { + PrintToChat(client, "\x04[CALLADMIN]\x03 %t", "CallAdmin_ClientBlacklistRemove"); + } + } + + // Set client on blacklist + g_bClientOnBlacklist[client] = gagState; + } +} + + +public void OnClientDisconnect_Post(int client) +{ + g_bClientOnBlacklist[client] = false; + g_bClientImmune[client] = false; +} \ No newline at end of file diff --git a/_CallAdmin/scripting/include/autoexecconfig.inc b/_CallAdmin/scripting/include/autoexecconfig.inc new file mode 100644 index 00000000..73e07d9d --- /dev/null +++ b/_CallAdmin/scripting/include/autoexecconfig.inc @@ -0,0 +1,715 @@ +#if defined _autoexecconfig_included + #endinput +#endif +#define _autoexecconfig_included + + +#include + + +// Append +#define AUTOEXEC_APPEND_BAD_FILENAME 0 +#define AUTOEXEC_APPEND_FILE_NOT_FOUND 1 +#define AUTOEXEC_APPEND_BAD_HANDLE 2 +#define AUTOEXEC_APPEND_SUCCESS 3 + + + +// Find +#define AUTOEXEC_FIND_BAD_FILENAME 10 +#define AUTOEXEC_FIND_FILE_NOT_FOUND 11 +#define AUTOEXEC_FIND_BAD_HANDLE 12 +#define AUTOEXEC_FIND_NOT_FOUND 13 +#define AUTOEXEC_FIND_SUCCESS 14 + + + +// Clean +#define AUTOEXEC_CLEAN_FILE_NOT_FOUND 20 +#define AUTOEXEC_CLEAN_BAD_HANDLE 21 +#define AUTOEXEC_CLEAN_SUCCESS 22 + + + +// General +#define AUTOEXEC_NO_CONFIG 30 + + + +// Formatter +#define AUTOEXEC_FORMAT_BAD_FILENAME 40 +#define AUTOEXEC_FORMAT_SUCCESS 41 + + + +// Global variables +static char g_sConfigFile[PLATFORM_MAX_PATH]; +static char g_sRawFileName[PLATFORM_MAX_PATH]; +static char g_sFolderPath[PLATFORM_MAX_PATH]; + +static bool g_bCreateFile = false; +static Handle g_hPluginHandle = null; + + + +// Workaround for now +static int g_iLastFindResult; +static int g_iLastAppendResult; + + + + +/** + * Returns the last result from the parser. + * + * @return Returns one of the AUTOEXEC_FIND values or -1 if not set. +*/ +stock int AutoExecConfig_GetFindResult() +{ + return g_iLastFindResult; +} + + + + + +/** + * Returns the last result from the appender. + * + * @return Returns one of the AUTOEXEC_APPEND values or -1 if not set. +*/ +stock int AutoExecConfig_GetAppendResult() +{ + return g_iLastAppendResult; +} + + +/** + * Set if the config file should be created if it doesn't exist yet. + * + * @param create True if config file should be created, false otherwise. + * @noreturn + */ +stock void AutoExecConfig_SetCreateFile(bool create) +{ + g_bCreateFile = create; +} + + +/** + * Returns if the config file should be created if it doesn't exist. + * + * @return Returns true, if the config file should be created or false if it should not. + */ +stock bool AutoExecConfig_GetCreateFile() +{ + return g_bCreateFile; +} + + +/** + * Set the plugin for which the config file should be created. + * Set to null to use the calling plugin. + * Used to print the correct filename in the top comment when creating the file. + * + * @param plugin The plugin to create convars for or null to use the calling plugin. + * @noreturn + */ +stock void AutoExecConfig_SetPlugin(Handle plugin) +{ + g_hPluginHandle = plugin; +} + + +/** + * Returns the plugin for which the config file is created. + * + * @return The plugin handle + */ +stock Handle AutoExecConfig_GetPlugin() +{ + return g_hPluginHandle; +} + + +/** + * Set the global autoconfigfile used by functions of this file. + * + * @param file Name of the config file, path and .cfg extension is being added if not given. + * @param folder Folder under cfg/ to use. By default this is "sourcemod." + * @return True if formatter returned success, false otherwise. +*/ +stock bool AutoExecConfig_SetFile(char[] file, char[] folder="sourcemod") +{ + Format(g_sConfigFile, sizeof(g_sConfigFile), "%s", file); + + // Global buffers for cfg execution + strcopy(g_sRawFileName, sizeof(g_sRawFileName), file); + strcopy(g_sFolderPath, sizeof(g_sFolderPath), folder); + + + // Format the filename + return AutoExecConfig_FormatFileName(g_sConfigFile, sizeof(g_sConfigFile), folder) == AUTOEXEC_FORMAT_SUCCESS; +} + + + + + + +/** + * Get the formatted autoconfigfile used by functions of this file. + * + * @param buffer String to format. + * @param size Maximum size of buffer + * @return True if filename was set, false otherwise. +*/ +stock bool AutoExecConfig_GetFile(char[] buffer,int size) +{ + if(strlen(g_sConfigFile) > 0) + { + strcopy(buffer, size, g_sConfigFile); + + return true; + } + + // Security for decl users + buffer[0] = '\0'; + + return false; +} + + + + + + +/** + * Creates a convar and appends it to the autoconfigfile if not found. + * FCVAR_DONTRECORD will be skipped. + * + * @param name Name of new convar. + * @param defaultValue String containing the default value of new convar. + * @param description Optional description of the convar. + * @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details. + * @param hasMin Optional boolean that determines if the convar has a minimum value. + * @param min Minimum floating point value that the convar can have if hasMin is true. + * @param hasMax Optional boolean that determines if the convar has a maximum value. + * @param max Maximum floating point value that the convar can have if hasMax is true. + * @return A handle to the newly created convar. If the convar already exists, a handle to it will still be returned. + * @error Convar name is blank or is the same as an existing console command. +*/ +stock ConVar AutoExecConfig_CreateConVar(const char[] name, const char[] defaultValue, const char[] description="", int flags=0, bool hasMin=false, float min=0.0, bool hasMax=false, float max=0.0) +{ + // If configfile was set and convar has no dontrecord flag + if(!(flags & FCVAR_DONTRECORD) && strlen(g_sConfigFile) > 0) + { + // Reset the results + g_iLastFindResult = -1; + g_iLastAppendResult = -1; + + + // Add it if not found + char buffer[64]; + + g_iLastFindResult = AutoExecConfig_FindValue(name, buffer, sizeof(buffer), true); + + // We only add this convar if it doesn't exist, or the file doesn't exist and it should be auto-generated + if(g_iLastFindResult == AUTOEXEC_FIND_NOT_FOUND || (g_iLastFindResult == AUTOEXEC_FIND_FILE_NOT_FOUND && g_bCreateFile)) + { + g_iLastAppendResult = AutoExecConfig_AppendValue(name, defaultValue, description, flags, hasMin, min, hasMax, max); + } + } + + + // Create the convar + return CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max); +} + + + + +/** + * Executes the autoconfigfile, and adds it to the OnConfigsExecuted forward. + * If we didn't created it already we let SourceMod create it. + * + * @noreturn +*/ +stock void AutoExecConfig_ExecuteFile() +{ + // Only let sourcemod create the file, if we didn't do that already. + AutoExecConfig(!g_bCreateFile, g_sRawFileName, g_sFolderPath); +} + + + + + +/** + * Formats a autoconfigfile, prefixes path and adds .cfg extension if missed. + * + * @param buffer String to format. + * @param size Maximum size of buffer. + * @return Returns one of the AUTOEXEC_FORMAT values.. +*/ +stock static int AutoExecConfig_FormatFileName(char[] buffer, int size, char[] folder="sourcemod") +{ + // No config set + if(strlen(g_sConfigFile) < 1) + { + return AUTOEXEC_NO_CONFIG; + } + + + // Can't be an cfgfile + if(StrContains(g_sConfigFile, ".cfg") == -1 && strlen(g_sConfigFile) < 4) + { + return AUTOEXEC_FORMAT_BAD_FILENAME; + } + + + // Pathprefix + char pathprefixbuffer[PLATFORM_MAX_PATH]; + if(strlen(folder) > 0) + { + Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/%s/", folder); + } + else + { + Format(pathprefixbuffer, sizeof(pathprefixbuffer), "cfg/"); + } + + + char filebuffer[PLATFORM_MAX_PATH]; + filebuffer[0] = '\0'; + + // Add path if file doesn't begin with it + if(StrContains(buffer, pathprefixbuffer) != 0) + { + StrCat(filebuffer, sizeof(filebuffer), pathprefixbuffer); + } + + StrCat(filebuffer, sizeof(filebuffer), g_sConfigFile); + + + // Add .cfg extension if file doesn't end with it + if(StrContains(filebuffer[strlen(filebuffer) - 4], ".cfg") != 0) + { + StrCat(filebuffer, sizeof(filebuffer), ".cfg"); + } + + strcopy(buffer, size, filebuffer); + + return AUTOEXEC_FORMAT_SUCCESS; +} + + + + + + +/** + * Appends a convar to the global autoconfigfile + * + * @param name Name of new convar. + * @param defaultValue String containing the default value of new convar. + * @param description Optional description of the convar. + * @param flags Optional bitstring of flags determining how the convar should be handled. See FCVAR_* constants for more details. + * @param hasMin Optional boolean that determines if the convar has a minimum value. + * @param min Minimum floating point value that the convar can have if hasMin is true. + * @param hasMax Optional boolean that determines if the convar has a maximum value. + * @param max Maximum floating point value that the convar can have if hasMax is true. + * @return Returns one of the AUTOEXEC_APPEND values +*/ +stock int AutoExecConfig_AppendValue(const char[] name, const char[] defaultValue, const char[] description, int flags, bool hasMin, float min, bool hasMax, float max) +{ + // No config set + if(strlen(g_sConfigFile) < 1) + { + return AUTOEXEC_NO_CONFIG; + } + + + char filebuffer[PLATFORM_MAX_PATH]; + strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile); + + + //PrintToServer("pathbuffer: %s", filebuffer); + + bool bFileExists = FileExists(filebuffer); + + if(g_bCreateFile || bFileExists) + { + // If the file already exists we open it in append mode, otherwise we use a write mode which creates the file + File fFile = OpenFile(filebuffer, (bFileExists ? "a" : "w")); + char writebuffer[2048]; + + + if(fFile == null) + { + return AUTOEXEC_APPEND_BAD_HANDLE; + } + + // We just created the file, so add some header about version and stuff + if(g_bCreateFile && !bFileExists) + { + fFile.WriteLine( "// This file was auto-generated by AutoExecConfig read and append beta"); + + GetPluginFilename(g_hPluginHandle, writebuffer, sizeof(writebuffer)); + Format(writebuffer, sizeof(writebuffer), "// ConVars for plugin \"%s\"", writebuffer); + fFile.WriteLine(writebuffer); + } + + // Spacer + fFile.WriteLine("\n"); + + + // This is used for multiline comments + int newlines = GetCharCountInStr('\n', description); + if(newlines == 0) + { + // We have no newlines, we can write the description to the file as is + Format(writebuffer, sizeof(writebuffer), "// %s", description); + fFile.WriteLine(writebuffer); + } + else + { + char[][] newlineBuf = new char[newlines +1][2048]; + ExplodeString(description, "\n", newlineBuf, newlines +1, 2048, false); + + // Each newline gets a commented newline + for(int i; i <= newlines; i++) + { + if(strlen(newlineBuf[i]) > 0) + { + fFile.WriteLine("// %s", newlineBuf[i]); + } + } + } + + + // Descspacer + fFile.WriteLine("// -"); + + + // Default + Format(writebuffer, sizeof(writebuffer), "// Default: \"%s\"", defaultValue); + fFile.WriteLine(writebuffer); + + + // Minimum + if(hasMin) + { + Format(writebuffer, sizeof(writebuffer), "// Minimum: \"%f\"", min); + fFile.WriteLine(writebuffer); + } + + + // Maximum + if(hasMax) + { + Format(writebuffer, sizeof(writebuffer), "// Maximum: \"%f\"", max); + fFile.WriteLine(writebuffer); + } + + + // Write end and defaultvalue + Format(writebuffer, sizeof(writebuffer), "%s \"%s\"", name, defaultValue); + fFile.WriteLine(writebuffer); + + + fFile.Close(); + + + // Clean up the file + //AutoExecConfig_CleanFile(filebuffer, false); + + + return AUTOEXEC_APPEND_SUCCESS; + } + + return AUTOEXEC_APPEND_FILE_NOT_FOUND; +} + + + + + + +/** + * Returns a convars value from the global autoconfigfile + * + * @param cvar Cvar to search for. + * @param value Buffer to store result into. + * @param size Maximum size of buffer. + * @param caseSensitive Whether or not the search should be case sensitive. + * @return Returns one of the AUTOEXEC_FIND values +*/ +stock int AutoExecConfig_FindValue(const char[] cvar, char[] value, int size, bool caseSensitive=false) +{ + // Security for decl users + value[0] = '\0'; + + + // No config set + if(strlen(g_sConfigFile) < 1) + { + return AUTOEXEC_NO_CONFIG; + } + + + char filebuffer[PLATFORM_MAX_PATH]; + strcopy(filebuffer, sizeof(filebuffer), g_sConfigFile); + + + + //PrintToServer("pathbuffer: %s", filebuffer); + + bool bFileExists = FileExists(filebuffer); + + // We want to create the config file and it doesn't exist yet. + if(g_bCreateFile && !bFileExists) + { + return AUTOEXEC_FIND_FILE_NOT_FOUND; + } + + + if(bFileExists) + { + File fFile = OpenFile(filebuffer, "r"); + int valuestart; + int valueend; + int cvarend; + + // Just an reminder to self, leave the values that high + char sConvar[64]; + char sValue[64]; + char readbuffer[2048]; + char copybuffer[2048]; + + if(fFile == null) + { + return AUTOEXEC_FIND_BAD_HANDLE; + } + + + while(!fFile.EndOfFile() && fFile.ReadLine(readbuffer, sizeof(readbuffer))) + { + // Is a comment or not valid + if(IsCharSpace(readbuffer[0]) || readbuffer[0] == '/' || !IsCharAlpha(readbuffer[0])) + { + continue; + } + + + // Has not enough spaces, must have at least 1 + if(GetCharCountInStr(' ', readbuffer) < 1) + { + continue; + } + + + // Ignore cvars which aren't quoted + if(GetCharCountInStr('"', readbuffer) != 2) + { + continue; + } + + + + // Get the start of the value + if( (valuestart = StrContains(readbuffer, "\"")) == -1 ) + { + continue; + } + + + // Get the end of the value + if( (valueend = StrContains(readbuffer[valuestart+1], "\"")) == -1 ) + { + continue; + } + + + // Get the start of the cvar, + if( (cvarend = StrContains(readbuffer, " ")) == -1 || cvarend >= valuestart) + { + continue; + } + + + // Skip if cvarendindex is before valuestartindex + if(cvarend >= valuestart) + { + continue; + } + + + // Convar + // Tempcopy for security + strcopy(copybuffer, sizeof(copybuffer), readbuffer); + copybuffer[cvarend] = '\0'; + + strcopy(sConvar, sizeof(sConvar), copybuffer); + + + // Value + // Tempcopy for security + strcopy(copybuffer, sizeof(copybuffer), readbuffer[valuestart+1]); + copybuffer[valueend] = '\0'; + + strcopy(sValue, sizeof(sValue), copybuffer); + + + //PrintToServer("Cvar %s has a value of %s", sConvar, sValue); + + if(StrEqual(sConvar, cvar, caseSensitive)) + { + Format(value, size, "%s", sConvar); + + fFile.Close(); + return AUTOEXEC_FIND_SUCCESS; + } + } + + fFile.Close(); + return AUTOEXEC_FIND_NOT_FOUND; + } + + + return AUTOEXEC_FIND_FILE_NOT_FOUND; +} + + + + + + +/** + * Cleans the global autoconfigfile from too much spaces + * + * @return One of the AUTOEXEC_CLEAN values. +*/ +stock int AutoExecConfig_CleanFile() +{ + // No config set + if(strlen(g_sConfigFile) < 1) + { + return AUTOEXEC_NO_CONFIG; + } + + + char sfile[PLATFORM_MAX_PATH]; + strcopy(sfile, sizeof(sfile), g_sConfigFile); + + + // Security + if(!FileExists(sfile)) + { + return AUTOEXEC_CLEAN_FILE_NOT_FOUND; + } + + + + char sfile2[PLATFORM_MAX_PATH]; + Format(sfile2, sizeof(sfile2), "%s_tempcopy", sfile); + + + char readbuffer[2048]; + int count; + bool firstreached; + + + // Open files + File fFile1 = OpenFile(sfile, "r"); + File fFile2 = OpenFile(sfile2, "w"); + + + + // Check filehandles + if(fFile1 == null || fFile2 == null) + { + if(fFile1 != null) + { + //PrintToServer("Handle1 invalid"); + fFile1.Close(); + } + + if(fFile2 != null) + { + //PrintToServer("Handle2 invalid"); + fFile2.Close(); + } + + return AUTOEXEC_CLEAN_BAD_HANDLE; + } + + + + while(!fFile1.EndOfFile() && fFile1.ReadLine(readbuffer, sizeof(readbuffer))) + { + // Is space + if(IsCharSpace(readbuffer[0])) + { + count++; + } + // No space, count from start + else + { + count = 0; + } + + + // Don't write more than 1 space if seperation after informations have been reached + if(count < 2 || !firstreached) + { + ReplaceString(readbuffer, sizeof(readbuffer), "\n", ""); + fFile2.WriteLine(readbuffer); + } + + + // First bigger seperation after informations has been reached + if(count == 2) + { + firstreached = true; + } + } + + + fFile1.Close(); + fFile2.Close(); + + + // This might be a risk, for now it works + DeleteFile(sfile); + RenameFile(sfile, sfile2); + + return AUTOEXEC_CLEAN_SUCCESS; +} + + + + + + +/** + * Returns how many times the given char occures in the given string. + * + * @param str String to search for in. + * @return Occurences of the given char found in string. +*/ +stock static int GetCharCountInStr(int character, const char[] str) +{ + int len = strlen(str); + int count; + + for(int i; i < len; i++) + { + if(str[i] == character) + { + count++; + } + } + + return count; +} diff --git a/calladmin_restrictions/scripting/include/calladmin.inc b/_CallAdmin/scripting/include/calladmin.inc similarity index 100% rename from calladmin_restrictions/scripting/include/calladmin.inc rename to _CallAdmin/scripting/include/calladmin.inc diff --git a/_CallAdmin/scripting/include/calladmin_stocks.inc b/_CallAdmin/scripting/include/calladmin_stocks.inc new file mode 100644 index 00000000..34ca323d --- /dev/null +++ b/_CallAdmin/scripting/include/calladmin_stocks.inc @@ -0,0 +1,18 @@ +/** Include guard */ +#if defined _calladmin_stocks_included + #endinput +#endif +#define _calladmin_stocks_included + + + + +stock bool IsClientValid(int id) +{ + if (id > 0 && id <= MaxClients && IsClientInGame(id)) + { + return true; + } + + return false; +} \ No newline at end of file diff --git a/_CallAdmin/scripting/include/calladmin_usermanager.inc b/_CallAdmin/scripting/include/calladmin_usermanager.inc new file mode 100644 index 00000000..d2161f3f --- /dev/null +++ b/_CallAdmin/scripting/include/calladmin_usermanager.inc @@ -0,0 +1,83 @@ +/** Include guard */ +#if defined _calladmin_usermanager_included + #endinput +#endif +#define _calladmin_usermanager_included + + + + +/** + * Returns whether a client is immune or not. + * If a client is immune, he can't be reported. + * + * @param client The Client. + * @return True if client is immune, false otherwise. + */ +native bool CallAdmin_IsClientImmune(int client); + + + + +/** + * Returns whether a client is on the blacklist or not. + * If a client is on the blacklist, he can't report players. + * + * @param client The Client. + * @return True if client is on blacklist, false otherwise. + */ +native bool CallAdmin_IsClientOnBlacklist(int client); + + + + +/** + * Sets whether a client is immune or not. + * If a client is immune, he can't be reported. + * + * @param client The Client. + * @param immune True to immune client, false otherwise. + * @noreturn + */ +native void CallAdmin_SetClientImmune(int client, bool immune); + + + + +/** + * Sets whether a client is in the backlist or not. + * If a client is on the blacklist, he can't report players. + * + * @param client The Client. + * @param add True to add client to blacklist, false to remove. + * @noreturn + */ +native void CallAdmin_SetClientOnBlacklist(int client, bool add); + + + + +/* Do not edit below this line */ +public SharedPlugin __pl_calladmin_usermanager = +{ + name = "calladmin_usermanager", + file = "calladmin_usermanager.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + + + + +#if !defined REQUIRE_PLUGIN +public __pl_calladmin_SetNTVOptional() +{ + MarkNativeAsOptional("CallAdmin_SetClientOnBlacklist"); + MarkNativeAsOptional("CallAdmin_SetClientImmune"); + MarkNativeAsOptional("CallAdmin_IsClientOnBlacklist"); + MarkNativeAsOptional("CallAdmin_IsClientImmune"); +} +#endif diff --git a/_CallAdmin/scripting/translations/calladmin.phrases.txt b/_CallAdmin/scripting/translations/calladmin.phrases.txt new file mode 100644 index 00000000..06236b79 --- /dev/null +++ b/_CallAdmin/scripting/translations/calladmin.phrases.txt @@ -0,0 +1,168 @@ +"Phrases" +{ + "CallAdmin_CommandNotAllowed" + { + "#format" "{1:d}" + "en" "You are not allowed to use this command for the next {1} seconds" + "de" "Du darfst diesen Befehl nicht innerhalb der nächsten {1} Sekunden benutzen" + "fr" "Vous ne pouvez pas utiliser cette commande avant {1} secondes" + "ru" "Вы не можете использовать эту команду в течение следующих {1} секунд" + } + "CallAdmin_HasReported" + { + "#format" "{1:N},{2:N},{3:s}" + "en" "{1} reported {2} for {3}" + "de" "{1} hat {2} wegen {3} gemeldet" + "fr" "{1} a signalé {2} pour {3}" + "ru" "{1} пожаловался на {2} по причине {3}" + } + "CallAdmin_YouHaveReported" + { + "#format" "{1:N},{2:s}" + "en" "You have reported {1} for {2}" + "de" "Du hast {1} wegen {2} gemeldet" + "fr" "Vous avez signalé {1} pour {2}" + "ru" "Вы успешно пожаловались на {1} по причине {2}" + } + "CallAdmin_NoPlayers" + { + "en" "There are no players you can report at this time" + "de" "Es sind derzeit keine Spieler vorhanden die du melden kannst" + "fr" "Aucun joueur ne peut être signalé pour le moment" + "ru" "В настоящее время на сервере нет игроков, на которых вы можете пожаловаться" + } + "CallAdmin_NotInGame" + { + "en" "Player is not on the server anymore" + "de" "Spieler ist nicht mehr auf dem Server" + "fr" "Le joueur n'est plus sur le serveur" + "ru" "Игрок уже покинул данный сервер" + } + "CallAdmin_SelectClient" + { + "en" "Select a client to report" + "de" "Wähle einen Spieler zum Melden" + "fr" "Sélectionnez un joueur à signaler" + "ru" "Выберите игрока, на которого вы хотите пожаловаться" + } + "CallAdmin_SelectReason" + { + "#format" "{1:N}" + "en" "Select a reason to report {1}" + "de" "Wähle einen Grund um {1} zu melden" + "fr" "Sélectionnez une raison pour signaler {1}" + "ru" "Выберите причину, по которой вы хотите пожаловаться на {1}" + } + // Used when exactly 1 admin is available + "CallAdmin_AdvertMessageSingular" + { + "#format" "{1:d}" + "en" "There is {1} admin available, type !call or /call in chat to report a player" + "de" "Es ist {1} Admin verfügbar, tippe !call oder /call in den Chat um einen Spieler zu melden" + "fr" "Il y a {1} admin disponible , tapez !call ou /call dans le chat pour signaler un joueur" + "ru" "Сейчас на сервере находится {1} администратор. Напишите в чате !call или /call, чтобы пожаловаться ему на игрока" + } + "CallAdmin_AdvertMessagePlural" + { + "#format" "{1:d}" + "en" "There are {1} admins available, type !call or /call in chat to report a player" + "de" "Es sind {1} Admins verfügbar, tippe !call oder /call in den Chat um einen Spieler zu melden" + "fr" "Il y a {1} admins disponibles , tapez !call ou /call dans le chat pour signaler un joueur" + "ru" "Администраторов на сервере в настоящее время: {1}. Напишите в чате !call или /call, чтобы пожаловаться на игрока" + } + "CallAdmin_OwnReason" + { + "en" "Own reason" + "de" "Eigener Grund" + "fr" "Raison personnelle" + "ru" "Другая причина" + } + "CallAdmin_TypeOwnReason" + { + "en" "You now can type your own banreason in the chat, please keep it short\nType '!noreason' or '!abort' to abort" + "de" "Du kannst nun deinen eigenen Bangrund in den Chat schreiben, fasse dich bitte kurz\nSchreibe '!noreason' oder '!abort' um abzubrechen" + "fr" "Vous pouvez maintenant écrire une raison personnelle dans le chat , écrivez une raison abrégée s'il vous plait\nEcrivez '!noreason' ou '!abort' pour annuler" + "ru" "Сейчас вы можете указать свою причину в чате. Будьте лаконичнее\nВведите '!noreason' или '!abort' для отмены" + } + "CallAdmin_CallAborted" + { + "en" "Your call has been aborted" + "de" "Der Meldevorgang wurde abgebrochen" + "fr" "Votre appel à été annulé" + "ru" "Ваша жалоба была отменена" + } + "CallAdmin_OwnReasonTooShort" + { + "en" "Your banreason is too short, please try it again" + "de" "Dein Bangrund ist zu kurz, bitte versuche es erneut" + "fr" "La raison du ban est trop courte , veuillez réessayer" + "ru" "Вы указали слишком короткую причину жалобы. Попробуйте ещё раз" + } + "CallAdmin_ConfirmCall" + { + "en" "Are you sure you want to call an admin?, abuse will be punished" + "de" "Bist du sicher dass du einen Admin rufen willst?, Missbrauch wird bestraft" + "fr" "Voulez-vous vraiment appeler un admin ?, les abus seront sanctionnés" + "ru" "Вы уверены, что хотите отправить жалобу администратору? Помните, что существует наказание за ложные вызовы" + } + "CallAdmin_Yes" + { + "en" "Yes" + "de" "Ja" + "fr" "Oui" + "ru" "Да" + } + "CallAdmin_No" + { + "en" "No" + "de" "Nein" + "fr" "Non" + "ru" "Нет" + } + "CallAdmin_AlreadyReported" + { + "en" "Player was already reported" + "de" "Spieler wurde bereits gemeldet" + "fr" "Joueur déjà signalé" + "ru" "На этого игрока уже пожаловались" + } + "CallAdmin_IngameAdminNotified" + { + "en" "An admin in-game was notified about your report" + "de" "Ein Admin in-game wurde über deine Meldung benachrichtigt" + "fr" "Un admin en jeu a été notifié de votre signalement" + "ru" "Администраторы, находящиеся на сервере, были проинформированы о вашей жалобе" + } + "CallAdmin_AdminNotification" + { + "#format" "{1:N},{2:N},{3:s}" + "en" "Player {1} reported {2} for {3}" + "de" "Spieler {1} hat {2} wegen {3} gemeldet" + "fr" "Le joueur {1} à signalé {2} pour {3}" + "ru" "Игрок {1} пожаловался на {2} по причине {3}" + } + "CallAdmin_ReportAlreadyHandled" + { + "en" "This report was already handled" + "de" "Diese Meldung wurde bereits erledigt" + "ru" "Эта жалоба уже была рассмотрена" + } + "CallAdmin_NoAdmin" + { + "en" "Only admins have access to this command" + "de" "Nur Admins können diesen Befehl ausführen" + "ru" "Только администраторы имеют доступ к этой команде" + } + "CallAdmin_WrongNumberOfArguments" + { + "en" "You've used a wrong number of arguments" + "de" "Du hast eine falsche Anzahl an Argumenten benutzt" + "ru" "Указано неправильное количество аргументов" + } + "CallAdmin_WrongReportID" + { + "en" "You've used a wrong report id" + "de" "Du hast eine falsche Melde-id benutzt" + "ru" "Указан неправильный ID жалобы" + } +} diff --git a/_CallAdmin/scripting/translations/calladmin_usermanager.phrases.txt b/_CallAdmin/scripting/translations/calladmin_usermanager.phrases.txt new file mode 100644 index 00000000..51e6b12e --- /dev/null +++ b/_CallAdmin/scripting/translations/calladmin_usermanager.phrases.txt @@ -0,0 +1,34 @@ +"Phrases" +{ + "CallAdmin_ClientBlacklistMute" + { + "en" "You are now, because of muting, on the blacklist. You can't report players anymore!" + "de" "Aufgrund eines Mutes bist du nun auf der Blacklist. Du kannst jetzt keine Spieler mehr reporten!" + "ru" "Из-за того, что вам был отключён микрофон, вы попали в чёрный список и больше не можете жаловаться на других игроков!" + } + "CallAdmin_ClientBlacklistGag" + { + "en" "You are now, because of gagging, on the blacklist. You can't report players anymore!" + "de" "Aufgrund eines Maulkorbes bist du nun auf der Blacklist. Du kannst jetzt keine Spieler mehr reporten!" + "ru" "Из-за того, что вам был отключён чат, вы попали в чёрный список и больше не можете жаловаться на других игроков!" + } + "CallAdmin_ClientBlacklistRemove" + { + "en" "You got removed from blacklist. You can report players again!" + "de" "Du wurdest von der Blacklist entfernt. Du kannst jetzt wieder Spieler reporten!" + "ru" "Вы были удалены из чёрного списка и теперь снова можете жаловаться на других игроков!" + } + "CallAdmin_ClientOnBlacklist" + { + "en" "You are currently on the blacklist. You can't report players!" + "de" "Du bist zurzeit auf der Blacklist. Du kannst keine Spieler reporten!" + "ru" "Вы находитесь в чёрном списке и не можете жаловаться на других игроков!" + } + "CallAdmin_TargetImmune" + { + "#format" "{1:N}" + "en" "Player {1} is immune. You can't report him." + "de" "Spieler {1} ist Immun. Du kannst ihn nicht reporten!" + "ru" "У игрока {1} есть иммунитет. Вы не можете жаловаться на него." + } +} \ No newline at end of file