#pragma semicolon 1 #include #include #include #undef REQUIRE_PLUGIN #include #define REQUIRE_PLUGIN #pragma newdecls required enum { AABBMinX = 0, AABBMaxX = 1, AABBMinY = 2, AABBMaxY = 3, AABBMinZ = 4, AABBMaxZ = 5, AABBTotalPoints = 6 } Handle g_hDatabase = null; Handle g_hTraceTimer = null; Handle g_hTopMenu = null; ConVar g_cvarHookedDecalFrequency = null; ConVar g_cvarDecalFrequency = null; ConVar g_cvarUseProximityCheck = null; bool g_bLoadedLate; bool g_bAllowSpray; bool g_bSQLite; bool g_bGotBans; bool g_bGotBlacklist; bool g_bFullyConnected; char g_sBanIssuer[MAXPLAYERS + 1][64]; char g_sBanIssuerSID[MAXPLAYERS + 1][32]; char g_sBanReason[MAXPLAYERS + 1][32]; char g_sSprayHash[MAXPLAYERS + 1][16]; bool g_bSprayBanned[MAXPLAYERS + 1]; bool g_bSprayHashBanned[MAXPLAYERS + 1]; bool g_bInvokedThroughTopMenu[MAXPLAYERS + 1]; bool g_bInvokedThroughListMenu[MAXPLAYERS + 1]; int g_iSprayLifetime[MAXPLAYERS + 1]; int g_iSprayBanTimestamp[MAXPLAYERS + 1]; int g_iSprayUnbanTimestamp[MAXPLAYERS + 1] = { -1, ... }; int g_iSprayBanTarget[MAXPLAYERS + 1]; int g_iSprayUnbanTarget[MAXPLAYERS + 1]; int g_iSprayTraceTarget[MAXPLAYERS + 1]; int g_iBanTarget[MAXPLAYERS + 1]; float ACTUAL_NULL_VECTOR[3]; float g_fNextSprayTime[MAXPLAYERS + 1]; float g_vecSprayOrigin[MAXPLAYERS + 1][3]; float g_SprayAABB[MAXPLAYERS + 1][AABBTotalPoints]; public Plugin myinfo = { name = "Spray Manager", description = "A plugin to help manage player sprays.", author = "Obus", version = "1.2.2", url = "https://github.com/CSSZombieEscape/sm-plugins/tree/master/SprayManager" } public APLRes AskPluginLoad2(Handle hThis, bool bLate, char[] err, int iErrLen) { g_bLoadedLate = bLate; return APLRes_Success; } public void OnPluginStart() { LoadTranslations("common.phrases"); RegAdminCmd("sm_spray", Command_AdminSpray, ADMFLAG_GENERIC, "Spray a clients spray"); RegAdminCmd("sm_sprayban", Command_SprayBan, ADMFLAG_GENERIC, "Ban a client from spraying"); RegAdminCmd("sm_sprayunban", Command_SprayUnban, ADMFLAG_GENERIC, "Unban a client and allow them to spray"); RegAdminCmd("sm_banspray", Command_BanSpray, ADMFLAG_GENERIC, "Ban a clients spray from being sprayed (Note: This will not spray-ban the client, it will only ban the spray which they are currently using)"); RegAdminCmd("sm_unbanspray", Command_UnbanSpray, ADMFLAG_GENERIC, "Unban a clients spray (Note: This will not spray-unban the client, it will only unban the spray which they are currently using)"); RegAdminCmd("sm_tracespray", Command_TraceSpray, ADMFLAG_GENERIC, "Finds a spray under your crosshair"); RegAdminCmd("sm_spraytrace", Command_TraceSpray, ADMFLAG_GENERIC, "Finds a spray under your crosshair"); RegAdminCmd("sm_removespray", Command_RemoveSpray, ADMFLAG_GENERIC, "Finds and removes a spray under your crosshair"); RegAdminCmd("sm_spraymanagerupdatedb", Command_SprayManager_UpdateInfo, ADMFLAG_CHEATS, "Updates all clients info"); RegAdminCmd("sm_spraymanagerrefreshdb", Command_SprayManager_UpdateInfo, ADMFLAG_CHEATS, "Updates all clients info"); RegAdminCmd("sm_spraymanagerreloaddb", Command_SprayManager_UpdateInfo, ADMFLAG_CHEATS, "Updates all clients info"); AddTempEntHook("Player Decal", HookDecal); AddNormalSoundHook(HookSprayer); TopMenu hTopMenu; if (LibraryExists("adminmenu") && ((hTopMenu = GetAdminTopMenu()) != INVALID_HANDLE)) OnAdminMenuReady(hTopMenu); if (g_cvarHookedDecalFrequency != null) delete g_cvarHookedDecalFrequency; if (g_cvarDecalFrequency != null) delete g_cvarDecalFrequency; if (g_cvarUseProximityCheck != null) delete g_cvarUseProximityCheck; g_cvarHookedDecalFrequency = FindConVar("decalfrequency"); g_cvarHookedDecalFrequency.IntValue = 0; g_cvarDecalFrequency = CreateConVar("sm_decalfrequency", "10", "Controls how often clients can spray", FCVAR_NOTIFY); HookConVarChange(g_cvarHookedDecalFrequency, CVarHook_DecalFrequency); g_cvarUseProximityCheck = CreateConVar("sm_spraymanager_blockoverspraying", "1", "Allows or disallows people to overspray other people.", FCVAR_NOTIFY); AutoExecConfig(true, "plugin.spraymanager"); if (g_hDatabase != null) delete g_hDatabase; g_hTraceTimer = CreateTimer(0.25, PerformPlayerTraces, _, TIMER_REPEAT); InitializeSQL(); } public void OnPluginEnd() { for (int i = 1; i <= MaxClients; i++) { if (!IsValidClient(i) || IsFakeClient(i)) continue; if (g_vecSprayOrigin[i][0] == 0.0) continue; g_bAllowSpray = true; SprayClientDecal(i, 0, ACTUAL_NULL_VECTOR); } RemoveTempEntHook("Player Decal", HookDecal); RemoveNormalSoundHook(HookSprayer); if (g_hDatabase != null) { SQL_UnlockDatabase(g_hDatabase); delete g_hDatabase; } if (g_hTraceTimer != null) KillTimer(g_hTraceTimer); } public void OnClientPostAdminCheck(int client) { if (g_hDatabase != null) { ClearPlayerInfo(client); UpdatePlayerInfo(client); UpdateSprayHashInfo(client); } } public void OnClientDisconnect(int client) { g_bAllowSpray = true; SprayClientDecal(client, 0, ACTUAL_NULL_VECTOR); ClearPlayerInfo(client); } public Action CS_OnTerminateRound(float &fDelay, CSRoundEndReason &reason) { for (int i = 1; i <= MaxClients; i++) { if (!IsValidClient(i)) continue; if (!IsVectorZero(g_vecSprayOrigin[i])) g_iSprayLifetime[i]++; if (g_iSprayLifetime[i] >= 2) { g_bAllowSpray = true; SprayClientDecal(i, 0, ACTUAL_NULL_VECTOR); g_iSprayLifetime[i] = 0; } } } public Action OnPlayerRunCmd(int client, int &buttons, int &impulse) { if (!impulse || impulse != 201) return Plugin_Continue; if (CheckCommandAccess(client, "sm_sprayban", ADMFLAG_GENERIC)) { if (!g_bSprayBanned[client] && !g_bSprayHashBanned[client]) { if (IsPlayerAlive(client)) if (TracePlayerAnglesRanged(client, 128.0)) return Plugin_Continue; ForceSpray(client, client, false); g_fNextSprayTime[client] = 0.0; } } return Plugin_Continue; } public void OnAdminMenuReady(Handle hAdminMenu) { if (hAdminMenu == g_hTopMenu) return; g_hTopMenu = CloneHandle(hAdminMenu); TopMenuObject hMenuObj = AddToTopMenu(g_hTopMenu, "SprayManagerCommands", TopMenuObject_Category, TopMenu_Main_Handler, INVALID_TOPMENUOBJECT); if (hMenuObj == INVALID_TOPMENUOBJECT) return; AddToTopMenu(g_hTopMenu, "SprayManager_Spraybanlist", TopMenuObject_Item, Handler_SprayBanList, hMenuObj); AddToTopMenu(g_hTopMenu, "SprayManager_Tracespray", TopMenuObject_Item, Handler_TraceSpray, hMenuObj, "sm_tracespray", ADMFLAG_GENERIC); AddToTopMenu(g_hTopMenu, "SprayManager_Spray", TopMenuObject_Item, Handler_Spray, hMenuObj, "sm_spray", ADMFLAG_GENERIC); AddToTopMenu(g_hTopMenu, "SprayManager_Sprayban", TopMenuObject_Item, Handler_SprayBan, hMenuObj, "sm_sprayban", ADMFLAG_GENERIC); AddToTopMenu(g_hTopMenu, "SprayManager_Sprayunban", TopMenuObject_Item, Handler_SprayUnban, hMenuObj, "sm_sprayunban", ADMFLAG_GENERIC); AddToTopMenu(g_hTopMenu, "SprayManager_Banspray", TopMenuObject_Item, Handler_BanSpray, hMenuObj, "sm_banspray", ADMFLAG_GENERIC); AddToTopMenu(g_hTopMenu, "SprayManager_Unbanspray", TopMenuObject_Item, Handler_UnbanSpray, hMenuObj, "sm_unbanspray", ADMFLAG_GENERIC); } public void OnLibraryRemoved(const char[] sLibraryName) { if (StrEqual(sLibraryName, "adminmenu")) delete g_hTopMenu; } public void TopMenu_Main_Handler(Handle hMenu, TopMenuAction hAction, TopMenuObject hObjID, int iParam1, char[] sBuffer, int iBufflen) { if (hAction == TopMenuAction_DisplayOption) Format(sBuffer, iBufflen, "%s", "SprayManager Commands", iParam1); else if (hAction == TopMenuAction_DisplayTitle) Format(sBuffer, iBufflen, "%s", "SprayManager Commands:", iParam1); } public void Handler_SprayBanList(Handle hMenu, TopMenuAction hAction, TopMenuObject hObjID, int iParam1, char[] sBuffer, int iBufflen) { if (hAction == TopMenuAction_DisplayOption) Format(sBuffer, iBufflen, "%s", "List Spray Banned Clients", iParam1); else if (hAction == TopMenuAction_SelectOption) Menu_ListBans(iParam1); } public void Handler_TraceSpray(Handle hMenu, TopMenuAction hAction, TopMenuObject hObjID, int iParam1, char[] sBuffer, int iBufflen) { if (hAction == TopMenuAction_DisplayOption) { Format(sBuffer, iBufflen, "%s", "Trace a Spray", iParam1); } else if (hAction == TopMenuAction_SelectOption) { float vecEndPos[3]; if (TracePlayerAngles(iParam1, vecEndPos)) { for (int i = 1; i <= MaxClients; i++) { if (IsPointInsideAABB(vecEndPos, g_SprayAABB[i])) { g_bInvokedThroughTopMenu[iParam1] = true; Menu_Trace(iParam1, i); return; } } } PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Trace did not hit any sprays."); if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } } public void Handler_Spray(Handle hMenu, TopMenuAction hAction, TopMenuObject hObjID, int iParam1, char[] sBuffer, int iBufflen) { if (hAction == TopMenuAction_DisplayOption) Format(sBuffer, iBufflen, "%s", "Spray a Client's Spray", iParam1); else if (hAction == TopMenuAction_SelectOption) Menu_Spray(iParam1); } public void Handler_SprayBan(Handle hMenu, TopMenuAction hAction, TopMenuObject hObjID, int iParam1, char[] sBuffer, int iBufflen) { if (hAction == TopMenuAction_DisplayOption) Format(sBuffer, iBufflen, "%s", "Spray Ban a Client", iParam1); else if (hAction == TopMenuAction_SelectOption) Menu_SprayBan(iParam1); } public void Handler_SprayUnban(Handle hMenu, TopMenuAction hAction, TopMenuObject hObjID, int iParam1, char[] sBuffer, int iBufflen) { if (hAction == TopMenuAction_DisplayOption) Format(sBuffer, iBufflen, "%s", "Spray Unban a Client", iParam1); else if (hAction == TopMenuAction_SelectOption) Menu_SprayUnban(iParam1); } public void Handler_BanSpray(Handle hMenu, TopMenuAction hAction, TopMenuObject hObjID, int iParam1, char[] sBuffer, int iBufflen) { if (hAction == TopMenuAction_DisplayOption) Format(sBuffer, iBufflen, "%s", "Ban a Client's Spray", iParam1); else if (hAction == TopMenuAction_SelectOption) Menu_BanSpray(iParam1); } public void Handler_UnbanSpray(Handle hMenu, TopMenuAction hAction, TopMenuObject hObjID, int iParam1, char[] sBuffer, int iBufflen) { if (hAction == TopMenuAction_DisplayOption) Format(sBuffer, iBufflen, "%s", "Unban a Client's Spray", iParam1); else if (hAction == TopMenuAction_SelectOption) Menu_UnbanSpray(iParam1); } void Menu_ListBans(int client) { if (!IsValidClient(client)) return; int iBannedClients; Menu ListMenu = new Menu(MenuHandler_Menu_ListBans); ListMenu.SetTitle("[SprayManager] Banned Clients:"); ListMenu.ExitBackButton = true; for (int i = 1; i <= MaxClients; i++) { if (!IsValidClient(i)) continue; if (g_bSprayBanned[i] || g_bSprayHashBanned[i]) { char sUserID[16]; char sBuff[64]; int iUserID = GetClientUserId(i); Format(sBuff, sizeof(sBuff), "%N (#%i)", i, iUserID); Format(sUserID, sizeof(sUserID), "%d", iUserID); ListMenu.AddItem(sUserID, sBuff); iBannedClients++; } } if (!iBannedClients) ListMenu.AddItem("", "No Banned Clients.", ITEMDRAW_DISABLED); ListMenu.Display(client, MENU_TIME_FOREVER); } int MenuHandler_Menu_ListBans(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack && g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } case MenuAction_Select: { char sOption[32]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = GetClientOfUserId(StringToInt(sOption)); if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); else CloseHandle(hMenu); } else { g_bInvokedThroughListMenu[iParam1] = true; Menu_ListBans_Target(iParam1, target); } } } } void Menu_Trace(int client, int target) { char sSteamID[32]; GetClientAuthId(target, AuthId_Steam2, sSteamID, sizeof(sSteamID)); Menu TraceMenu = new Menu(MenuHandler_Menu_Trace); TraceMenu.SetTitle("Sprayed by: %N (%s)", target, sSteamID); if (g_bInvokedThroughTopMenu[client]) TraceMenu.ExitBackButton = true; TraceMenu.AddItem("1", "Warn Client"); TraceMenu.AddItem("2", "Slap and Warn Client"); TraceMenu.AddItem("3", "Kick Client"); TraceMenu.AddItem("4", "Spray Ban Client"); TraceMenu.AddItem("5", "Ban Clients Spray"); TraceMenu.AddItem("", "", ITEMDRAW_SPACER); TraceMenu.AddItem("6", "Ban Client"); g_iSprayTraceTarget[client] = target; TraceMenu.Display(client, MENU_TIME_FOREVER); } int MenuHandler_Menu_Trace(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack && g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } case MenuAction_Select: { char sOption[2]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = g_iSprayTraceTarget[iParam1]; if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); g_bInvokedThroughTopMenu[iParam1] = false; if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); else CloseHandle(hMenu); } else { switch (StringToInt(sOption)) { case 1: { PrintToChat(target, "\x01\x04[SprayManager]\x01 Your spray is not allowed, change it."); Menu_Trace(iParam1, target); } case 2: { SlapPlayer(target, 0); PrintToChat(target, "\x01\x04[SprayManager]\x01 Your spray is not allowed, change it."); Menu_Trace(iParam1, target); } case 3: { g_bInvokedThroughTopMenu[iParam1] = false; KickClient(target, "Your spray is not allowed, change it"); } case 4: { Menu TraceSpraySprayBan = new Menu(MenuHandler_Menu_Trace_SprayBan); TraceSpraySprayBan.SetTitle("[SprayManager] Select a Spray Ban Length for %N (#%i)", target, GetClientUserId(target)); TraceSpraySprayBan.ExitBackButton = true; TraceSpraySprayBan.AddItem("10", "10 Minutes"); TraceSpraySprayBan.AddItem("30", "30 Minutes"); TraceSpraySprayBan.AddItem("60", "1 Hour"); TraceSpraySprayBan.AddItem("1440", "1 Day"); TraceSpraySprayBan.AddItem("10080", "1 Week"); TraceSpraySprayBan.AddItem("40320", "1 Month"); TraceSpraySprayBan.AddItem("0", "Permanent"); g_iSprayBanTarget[iParam1] = target; TraceSpraySprayBan.Display(iParam1, MENU_TIME_FOREVER); } case 5: { if (BanClientSpray(target)) PrintToChatAll("\x01\x04[SprayManager] %N\x01 banned \x04%N\x01's spray.", iParam1, target); else PrintToChat(iParam1, "\x01\x04[SprayManager] %N\x01's spray is already blacklisted.", target); } case 6: { Menu TraceSprayBan = new Menu(MenuHandler_Menu_Trace_Ban); TraceSprayBan.SetTitle("[SprayManager] Select a Ban Length for %N (#%i)", target, GetClientUserId(target)); TraceSprayBan.ExitBackButton = true; TraceSprayBan.AddItem("10", "10 Minutes"); TraceSprayBan.AddItem("30", "30 Minutes"); TraceSprayBan.AddItem("60", "1 Hour"); TraceSprayBan.AddItem("1440", "1 Day"); TraceSprayBan.AddItem("10080", "1 Week"); TraceSprayBan.AddItem("40320", "1 Month"); TraceSprayBan.AddItem("0", "Permanent"); g_iBanTarget[iParam1] = target; TraceSprayBan.Display(iParam1, MENU_TIME_FOREVER); } } } } } } int MenuHandler_Menu_Trace_SprayBan(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack) { if (IsValidClient(g_iSprayBanTarget[iParam1])) { Menu_Trace(iParam1, g_iSprayBanTarget[iParam1]); } else if (g_hTopMenu != INVALID_HANDLE) { g_bInvokedThroughTopMenu[iParam1] = false; DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } else { g_bInvokedThroughTopMenu[iParam1] = false; CloseHandle(hMenu); } } } case MenuAction_Select: { char sOption[8]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = g_iSprayBanTarget[iParam1]; if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); g_iSprayBanTarget[iParam1] = 0; g_bInvokedThroughTopMenu[iParam1] = false; if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); else CloseHandle(hMenu); } else { if (SprayBanClient(iParam1, target, StringToInt(sOption), "Inappropriate Spray")) PrintToChatAll("\x01\x04[SprayManager] %N\x01 spray banned \x04%N\x01.", iParam1, target); g_iSprayBanTarget[iParam1] = 0; g_bInvokedThroughTopMenu[iParam1] = false; } } } } int MenuHandler_Menu_Trace_Ban(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack) { if (IsValidClient(g_iBanTarget[iParam1])) { Menu_Trace(iParam1, g_iBanTarget[iParam1]); } else if (g_hTopMenu != INVALID_HANDLE) { g_bInvokedThroughTopMenu[iParam1] = false; DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } else { g_bInvokedThroughTopMenu[iParam1] = false; CloseHandle(hMenu); } } } case MenuAction_Select: { char sOption[8]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = g_iBanTarget[iParam1]; if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); g_iBanTarget[iParam1] = 0; g_bInvokedThroughTopMenu[iParam1] = false; if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); else CloseHandle(hMenu); } else { FakeClientCommandEx(iParam1, "sm_ban \"#%i\" \"%s\" \"Inappropriate spray\"", GetClientUserId(g_iBanTarget[iParam1]), sOption); g_iBanTarget[iParam1] = 0; g_bInvokedThroughTopMenu[iParam1] = false; } } } } void Menu_Spray(int client) { if (!IsValidClient(client)) return; Menu SprayMenu = new Menu(MenuHandler_Menu_Spray); SprayMenu.SetTitle("[SprayManager] Select a Client to Force Spray:"); SprayMenu.ExitBackButton = true; for (int i = 1; i <= MaxClients; i++) { if (!IsValidClient(i) || IsFakeClient(i)) continue; char sUserID[16]; char sBuff[64]; int iUserID = GetClientUserId(i); Format(sUserID, sizeof(sUserID), "%d", iUserID); if (g_bSprayBanned[i] && g_bSprayHashBanned[i]) { Format(sBuff, sizeof(sBuff), "%N (#%i) [Spray & Hash Banned]", i, iUserID); SprayMenu.AddItem(sUserID, sBuff); } else if (g_bSprayBanned[i]) { Format(sBuff, sizeof(sBuff), "%N (#%i) [Spray Banned]", i, iUserID); SprayMenu.AddItem(sUserID, sBuff); } else if (g_bSprayHashBanned[i]) { Format(sBuff, sizeof(sBuff), "%N (#%i) [Hash Banned]", i, iUserID); SprayMenu.AddItem(sUserID, sBuff); } else { Format(sBuff, sizeof(sBuff), "%N (#%i)", i, iUserID); SprayMenu.AddItem(sUserID, sBuff); } } SprayMenu.Display(client, MENU_TIME_FOREVER); } int MenuHandler_Menu_Spray(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack && g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } case MenuAction_Select: { char sOption[8]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = GetClientOfUserId(StringToInt(sOption)); if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); else CloseHandle(hMenu); } else { g_bAllowSpray = true; ForceSpray(iParam1, target); PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Sprayed \x04%N\x01's spray(s).", target); Menu_Spray(iParam1); } } } } void Menu_SprayBan(int client) { if (!IsValidClient(client)) return; Menu SprayBanMenu = new Menu(MenuHandler_Menu_SprayBan); SprayBanMenu.SetTitle("[SprayManager] Select a Client to Spray Ban:"); SprayBanMenu.ExitBackButton = true; int iClientsToDisplay; for (int i = 1; i <= MaxClients; i++) { if (IsValidClient(i) && !g_bSprayBanned[i]) { char sUserID[16]; char sBuff[64]; int iUserID = GetClientUserId(i); Format(sBuff, sizeof(sBuff), "%N (#%i)", i, iUserID); Format(sUserID, sizeof(sUserID), "%d", iUserID); SprayBanMenu.AddItem(sUserID, sBuff); iClientsToDisplay++; } } if (!iClientsToDisplay) SprayBanMenu.AddItem("", "No Clients to Display.", ITEMDRAW_DISABLED); SprayBanMenu.Display(client, MENU_TIME_FOREVER); } int MenuHandler_Menu_SprayBan(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack && g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } case MenuAction_Select: { char sOption[32]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = GetClientOfUserId(StringToInt(sOption)); if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); else CloseHandle(hMenu); } else { Menu SprayBanLengthMenu = new Menu(MenuHandler_Menu_SprayBan_Length); SprayBanLengthMenu.SetTitle("[SprayManager] Choose a Spray Ban Length for %N (#%i)", target, GetClientUserId(target)); SprayBanLengthMenu.ExitBackButton = true; SprayBanLengthMenu.AddItem("10", "10 Minutes"); SprayBanLengthMenu.AddItem("30", "30 Minutes"); SprayBanLengthMenu.AddItem("60", "1 Hour"); SprayBanLengthMenu.AddItem("1440", "1 Day"); SprayBanLengthMenu.AddItem("10080", "1 Week"); SprayBanLengthMenu.AddItem("40320", "1 Month"); SprayBanLengthMenu.AddItem("0", "Permanent"); g_iSprayBanTarget[iParam1] = target; SprayBanLengthMenu.Display(iParam1, MENU_TIME_FOREVER); } } } } int MenuHandler_Menu_SprayBan_Length(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack) Menu_SprayBan(iParam1); } case MenuAction_Select: { char sOption[8]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = g_iSprayBanTarget[iParam1]; if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); g_iSprayBanTarget[iParam1] = 0; Menu_SprayBan(iParam1); } else { if (SprayBanClient(iParam1, target, StringToInt(sOption), "Inappropriate Spray")) PrintToChatAll("\x01\x04[SprayManager] %N\x01 spray banned \x04%N\x01.", iParam1, target); g_iSprayBanTarget[iParam1] = 0; } } } } void Menu_SprayUnban(int client) { if (!IsValidClient(client)) return; int iBannedClients; Menu SprayUnbanMenu = new Menu(MenuHandler_Menu_SprayUnban); SprayUnbanMenu.SetTitle("[SprayManager] Select a Client to Unban:"); SprayUnbanMenu.ExitBackButton = true; for (int i = 1; i <= MaxClients; i++) { if (!IsValidClient(i)) continue; if (g_bSprayBanned[i] || g_bSprayHashBanned[i]) { char sUserID[16]; char sBuff[64]; int iUserID = GetClientUserId(i); Format(sBuff, sizeof(sBuff), "%N (#%i)", i, iUserID); Format(sUserID, sizeof(sUserID), "%d", iUserID); SprayUnbanMenu.AddItem(sUserID, sBuff); iBannedClients++; } } if (!iBannedClients) SprayUnbanMenu.AddItem("", "No Banned Clients.", ITEMDRAW_DISABLED); SprayUnbanMenu.Display(client, MENU_TIME_FOREVER); } int MenuHandler_Menu_SprayUnban(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack && g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } case MenuAction_Select: { char sOption[32]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = GetClientOfUserId(StringToInt(sOption)); if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); g_iSprayUnbanTarget[iParam1] = 0; Menu_SprayUnban(iParam1); } else { g_bInvokedThroughListMenu[iParam1] = false; Menu_ListBans_Target(iParam1, target); } } } } void Menu_BanSpray(int client) { if (!IsValidClient(client)) return; int iClientsToDisplay; Menu BanSprayMenu = new Menu(MenuHandler_Menu_BanSpray); BanSprayMenu.SetTitle("[SprayManager] Select a Client to Ban their Spray:"); BanSprayMenu.ExitBackButton = true; for (int i = 1; i <= MaxClients; i++) { if (IsValidClient(i) && !g_bSprayHashBanned[i]) { char sUserID[16]; char sBuff[64]; int iUserID = GetClientUserId(i); Format(sBuff, sizeof(sBuff), "%N (#%i)", i, iUserID); Format(sUserID, sizeof(sUserID), "%d", iUserID); BanSprayMenu.AddItem(sUserID, sBuff); iClientsToDisplay++; } } if (!iClientsToDisplay) BanSprayMenu.AddItem("", "No Clients to Display.", ITEMDRAW_DISABLED); BanSprayMenu.Display(client, MENU_TIME_FOREVER); } int MenuHandler_Menu_BanSpray(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack && g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } case MenuAction_Select: { char sOption[32]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = GetClientOfUserId(StringToInt(sOption)); if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); Menu_BanSpray(iParam1); } else { if (BanClientSpray(target)) PrintToChatAll("\x01\x04[SprayManager] %N\x01 banned \x04%N\x01's spray.", iParam1, target); else PrintToChat(iParam1, "\x01\x04[SprayManager] %N\x01's spray is already blacklisted.", target); } } } } void Menu_UnbanSpray(int client) { if (!IsValidClient(client)) return; Menu UnbanSprayMenu = new Menu(MenuHandler_Menu_UnbanSpray); UnbanSprayMenu.SetTitle("[SprayManager] Select a Client to Unban their Spray:"); UnbanSprayMenu.ExitBackButton = true; int iBannedClients; for (int i = 1; i <= MaxClients; i++) { if (IsValidClient(i) && g_bSprayHashBanned[i]) { char sUserID[16]; char sBuff[64]; int iUserID = GetClientUserId(i); Format(sBuff, sizeof(sBuff), "%N (#%i)", i, iUserID); Format(sUserID, sizeof(sUserID), "%d", iUserID); UnbanSprayMenu.AddItem(sUserID, sBuff); iBannedClients++; } } if (!iBannedClients) UnbanSprayMenu.AddItem("", "No Banned Clients.", ITEMDRAW_DISABLED); UnbanSprayMenu.Display(client, MENU_TIME_FOREVER); } int MenuHandler_Menu_UnbanSpray(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack && g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); } case MenuAction_Select: { char sOption[32]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = GetClientOfUserId(StringToInt(sOption)); if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); Menu_UnbanSpray(iParam1); } else { if (UnbanClientSpray(target)) PrintToChatAll("\x01\x04[SprayManager] %N\x01 unbanned \x04%N\x01's spray.", iParam1, target); else PrintToChat(iParam1, "\x01\x04[SprayManager] %N\x01's spray is not blacklisted.", target); } } } } void Menu_ListBans_Target(int client, int target) { Menu ListTargetMenu = new Menu(MenuHandler_Menu_ListBans_Target); ListTargetMenu.SetTitle("[SprayManager] Banned Client: %N (#%i)", target, GetClientUserId(target)); ListTargetMenu.ExitBackButton = true; char sBanType[32]; char sUserID[32]; int iUserID = GetClientUserId(target); Format(sUserID, sizeof(sUserID), "%d", iUserID); if (g_bSprayHashBanned[target] && !g_bSprayBanned[target]) { strcopy(sBanType, sizeof(sBanType), "Type: Hash"); ListTargetMenu.AddItem("", sBanType, ITEMDRAW_DISABLED); ListTargetMenu.AddItem("", "", ITEMDRAW_SPACER); ListTargetMenu.AddItem(sUserID, "Unban Client?"); ListTargetMenu.Display(client, MENU_TIME_FOREVER); return; } char sBanExpiryDate[64]; char sBanIssuedDate[64]; char sBanDuration[64]; char sBannedBy[128]; char sBanReason[64]; int iBanExpiryDate = g_iSprayUnbanTimestamp[target]; int iBanIssuedDate = g_iSprayBanTimestamp[target]; int iBanDuration = iBanExpiryDate ? ((iBanExpiryDate - iBanIssuedDate) / 60) : 0; if (iBanExpiryDate) { FormatTime(sBanExpiryDate, sizeof(sBanExpiryDate), NULL_STRING, iBanExpiryDate); Format(sBanDuration, sizeof(sBanDuration), "%i %s", iBanDuration, SingularOrMultiple(iBanDuration) ? "Minutes" : "Minute"); } else { strcopy(sBanExpiryDate, sizeof(sBanExpiryDate), "Never"); strcopy(sBanDuration, sizeof(sBanDuration), "Permanent"); } FormatTime(sBanIssuedDate, sizeof(sBanIssuedDate), NULL_STRING, iBanIssuedDate); Format(sBannedBy, sizeof(sBannedBy), "Banned by: %s (%s)", g_sBanIssuer[target], g_sBanIssuerSID[target]); Format(sBanDuration, sizeof(sBanDuration), "Duration: %s", sBanDuration); Format(sBanExpiryDate, sizeof(sBanExpiryDate), "Expires: %s", sBanExpiryDate); Format(sBanIssuedDate, sizeof(sBanIssuedDate), "Issued on: %s", sBanIssuedDate); Format(sBanReason, sizeof(sBanReason), "Reason: %s", g_sBanReason[target]); if (g_bSprayBanned[target] && g_bSprayHashBanned[target]) strcopy(sBanType, sizeof(sBanType), "Type: Spray & Hash"); else if (g_bSprayBanned[target]) strcopy(sBanType, sizeof(sBanType), "Type: Spray"); ListTargetMenu.AddItem("", sBanType, ITEMDRAW_DISABLED); ListTargetMenu.AddItem("", sBannedBy, ITEMDRAW_DISABLED); ListTargetMenu.AddItem("", sBanIssuedDate, ITEMDRAW_DISABLED); ListTargetMenu.AddItem("", sBanExpiryDate, ITEMDRAW_DISABLED); ListTargetMenu.AddItem("", sBanDuration, ITEMDRAW_DISABLED); ListTargetMenu.AddItem("", sBanReason, ITEMDRAW_DISABLED); ListTargetMenu.AddItem(sUserID, "Unban Client?"); ListTargetMenu.Display(client, MENU_TIME_FOREVER); } int MenuHandler_Menu_ListBans_Target(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack) { if (g_bInvokedThroughListMenu[iParam1]) Menu_ListBans(iParam1); else Menu_SprayUnban(iParam1); } } case MenuAction_Select: { char sOption[32]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = GetClientOfUserId(StringToInt(sOption)); if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); Menu_ListBans(iParam1); } else { Menu MenuConfirmUnban = new Menu(MenuHandler_Menu_ConfirmUnban); MenuConfirmUnban.SetTitle("[SprayManager] Unban %N?", target); MenuConfirmUnban.ExitBackButton = true; MenuConfirmUnban.AddItem("Y", "Yes."); MenuConfirmUnban.AddItem("N", "No."); g_iSprayUnbanTarget[iParam1] = target; MenuConfirmUnban.Display(iParam1, MENU_TIME_FOREVER); } } } } int MenuHandler_Menu_ConfirmUnban(Menu hMenu, MenuAction action, int iParam1, int iParam2) { switch (action) { case MenuAction_End: CloseHandle(hMenu); case MenuAction_Cancel: { if (iParam2 == MenuCancel_ExitBack) { if (IsValidClient(g_iSprayUnbanTarget[iParam1])) Menu_ListBans_Target(iParam1, g_iSprayUnbanTarget[iParam1]); else if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); else CloseHandle(hMenu); } } case MenuAction_Select: { char sOption[2]; hMenu.GetItem(iParam2, sOption, sizeof(sOption)); int target = g_iSprayUnbanTarget[iParam1]; if (!IsValidClient(target)) { PrintToChat(iParam1, "\x01\x04[SprayManager]\x01 Target no longer available."); g_iSprayUnbanTarget[iParam1] = 0; if (g_hTopMenu != INVALID_HANDLE) DisplayTopMenu(g_hTopMenu, iParam1, TopMenuPosition_LastCategory); else CloseHandle(hMenu); } else { if (sOption[0] == 'Y') { if (g_bSprayHashBanned[target] && g_bSprayBanned[target]) { PrintToChatAll("\x01\x04[SprayManager] %N\x01 spray unbanned \x04%N\x01.", iParam1, target); SprayUnbanClient(target); UnbanClientSpray(target); } else if (g_bSprayBanned[target]) { PrintToChatAll("\x01\x04[SprayManager] %N\x01 spray unbanned \x04%N\x01.", iParam1, target); SprayUnbanClient(target); } else if (g_bSprayHashBanned[target]) { PrintToChatAll("\x01\x04[SprayManager] %N\x01 unbanned \x04%N\x01's spray.", iParam1, target); UnbanClientSpray(target); } g_iSprayUnbanTarget[iParam1] = 0; } else if (sOption[0] == 'N') { Menu_ListBans_Target(iParam1, g_iSprayUnbanTarget[iParam1]); g_iSprayUnbanTarget[iParam1] = 0; } } } } } public Action Command_AdminSpray(int client, int argc) { if (!client) { PrintToServer("[SprayManager] Cannot use command from server console."); return Plugin_Handled; } if (argc > 0) { char sArgs[64]; char sTargetName[MAX_TARGET_LENGTH]; int iTargets[MAXPLAYERS]; int iTargetCount; bool bIsML; GetCmdArg(1, sArgs, sizeof(sArgs)); if ((iTargetCount = ProcessTargetString(sArgs, client, iTargets, MAXPLAYERS, COMMAND_FILTER_NO_BOTS, sTargetName, sizeof(sTargetName), bIsML)) <= 0) { ReplyToTargetError(client, iTargetCount); return Plugin_Handled; } for (int i = 0; i < iTargetCount; i++) { g_bAllowSpray = true; ForceSpray(client, iTargets[i], false); } PrintToChat(client, "\x01\x04[SprayManager]\x01 Sprayed \x04%s\x01's spray(s).", sTargetName); return Plugin_Handled; } float vecEndPos[3]; TracePlayerAngles(client, vecEndPos); g_bAllowSpray = true; ForceSpray(client, client, false); PrintToChat(client, "\x01\x04[SprayManager]\x01 Sprayed your own spray."); return Plugin_Handled; } public Action Command_SprayBan(int client, int argc) { if (argc < 2) { ReplyToCommand(client, "[SprayManager] Usage: sm_sprayban