diff --git a/SprayManager/scripting/SprayManager.sp b/SprayManager/scripting/SprayManager.sp index 7b69dcf3..1db4f6b3 100644 --- a/SprayManager/scripting/SprayManager.sp +++ b/SprayManager/scripting/SprayManager.sp @@ -2,6 +2,7 @@ #include #include +#include #include #undef REQUIRE_PLUGIN @@ -25,6 +26,8 @@ Handle g_hDatabase = null; Handle g_hTraceTimer = null; Handle g_hRoundEndTimer = null; Handle g_hTopMenu = null; +Handle g_hWantsToSeeNSFWCookie = null; + ConVar g_cvarHookedDecalFrequency = null; ConVar g_cvarDecalFrequency = null; ConVar g_cvarUseProximityCheck = null; @@ -32,6 +35,9 @@ ConVar g_cvarSendSpraysToConnectingClients = null; ConVar g_cvarUsePersistentSprays = null; ConVar g_cvarMaxSprayLifetime = null; +int g_iNSFWDecalIndex; +int g_iHiddenDecalIndex; +int g_iTransparentDecalIndex; int g_iOldDecalFreqVal; int g_iAllowSpray; @@ -39,6 +45,7 @@ bool g_bLoadedLate; bool g_bSQLite; bool g_bGotBans; bool g_bGotBlacklist; +bool g_bGotNSFWList; bool g_bFullyConnected; bool g_bSkipDecalHook; @@ -47,11 +54,6 @@ 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_iClientToClientSprayLifetime[MAXPLAYERS + 1][MAXPLAYERS + 1]; int g_iClientSprayLifetime[MAXPLAYERS + 1] = { 2, ... }; int g_iSprayLifetime[MAXPLAYERS + 1]; @@ -63,7 +65,16 @@ int g_iSprayTraceTarget[MAXPLAYERS + 1]; int g_iBanTarget[MAXPLAYERS + 1]; int g_iDecalEntity[MAXPLAYERS + 1]; -float ACTUAL_NULL_VECTOR[3]; +bool g_bWantsToSeeNSFWSprays[MAXPLAYERS + 1]; +bool g_bHasNSFWSpray[MAXPLAYERS + 1]; +bool g_bMarkedNSFWByAdmin[MAXPLAYERS + 1]; +bool g_bSprayBanned[MAXPLAYERS + 1]; +bool g_bSprayHashBanned[MAXPLAYERS + 1]; +bool g_bInvokedThroughTopMenu[MAXPLAYERS + 1]; +bool g_bInvokedThroughListMenu[MAXPLAYERS + 1]; +bool g_bHasSprayHidden[MAXPLAYERS + 1][MAXPLAYERS + 1]; + +float ACTUAL_NULL_VECTOR[3] = { 16384.0, ... }; //durr float g_fNextSprayTime[MAXPLAYERS + 1]; float g_vecSprayOrigin[MAXPLAYERS + 1][3]; float g_SprayAABB[MAXPLAYERS + 1][AABBTotalPoints]; @@ -73,8 +84,8 @@ public Plugin myinfo = name = "Spray Manager", description = "A plugin to help manage player sprays.", author = "Obus", - version = "2.0.5", - url = "https://github.com/CSSZombieEscape/sm-plugins/tree/master/SprayManager" + version = "2.1.0", + url = "" } public APLRes AskPluginLoad2(Handle hThis, bool bLate, char[] err, int iErrLen) @@ -88,6 +99,21 @@ public void OnPluginStart() { LoadTranslations("common.phrases"); + AddFileToDownloadsTable("materials/decals/spraymanager/1.vtf"); + AddFileToDownloadsTable("materials/decals/spraymanager/1.vmt"); + + AddFileToDownloadsTable("materials/decals/spraymanager/2.vtf"); + AddFileToDownloadsTable("materials/decals/spraymanager/2.vmt"); + + AddFileToDownloadsTable("materials/decals/spraymanager/3.vtf"); + AddFileToDownloadsTable("materials/decals/spraymanager/3.vmt"); + + RegConsoleCmd("sm_marknsfw", Command_MarkNSFW, "Marks your spray as NSFW"); + RegConsoleCmd("sm_marksfw", Command_MarkSFW, "Marks your spray as SFW"); + RegConsoleCmd("sm_nsfw", Command_NSFW, "Opt-in or out of seeing NSFW sprays"); + RegConsoleCmd("sm_hs", Command_HideSpray, "Hides a players spray"); + RegConsoleCmd("sm_us", Command_UnhideSpray, "Unhides a players spray"); + 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"); @@ -96,10 +122,14 @@ public void OnPluginStart() 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_forcensfw", Command_ForceNSFW, ADMFLAG_GENERIC, "Forces a spray to be marked NSFW"); + RegAdminCmd("sm_forcesfw", Command_ForceSFW, ADMFLAG_GENERIC, "Forces a spray to be marked SFW"); 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"); + g_hWantsToSeeNSFWCookie = RegClientCookie("spraymanager_wanttoseensfw", "Does this client want to see NSFW sprays?", CookieAccess_Private); + AddTempEntHook("Player Decal", HookDecal); AddNormalSoundHook(HookSprayer); @@ -128,8 +158,6 @@ public void OnPluginStart() g_hTraceTimer = CreateTimer(0.25, Timer_PerformPlayerTraces, _, TIMER_REPEAT); - InitializeSQL(); - if (g_bLoadedLate) { for (int i = 1; i <= MaxClients; i++) @@ -138,8 +166,11 @@ public void OnPluginStart() continue; OnClientPutInServer(i); + OnClientCookiesCached(i); } } + + InitializeSQL(); } public void OnPluginEnd() @@ -175,6 +206,13 @@ public void OnPluginEnd() g_cvarHookedDecalFrequency.IntValue = g_iOldDecalFreqVal; } +public void OnMapStart() +{ + g_iNSFWDecalIndex = PrecacheDecal("decals/spraymanager/1.vtf", true); + g_iHiddenDecalIndex = PrecacheDecal("decals/spraymanager/2.vtf", true); + g_iTransparentDecalIndex = PrecacheDecal("decals/spraymanager/3.vtf", true); +} + public void OnMapEnd() { if (g_hRoundEndTimer != null) @@ -185,23 +223,14 @@ public void OnClientPutInServer(int client) { if (QueryClientConVar(client, "r_spray_lifetime", CvarQueryFinished_SprayLifeTime) == QUERYCOOKIE_FAILED) g_iClientSprayLifetime[client] = 2; +} - if (g_cvarSendSpraysToConnectingClients.BoolValue) - { - for (int i = 1; i <= MaxClients; i++) - { - if (!IsValidClient(i) || IsFakeClient(i)) - continue; +public void OnClientCookiesCached(int client) +{ + char sWantsToSeeNSFW[8]; + GetClientCookie(client, g_hWantsToSeeNSFWCookie, sWantsToSeeNSFW, sizeof(sWantsToSeeNSFW)); - if (IsVectorZero(g_vecSprayOrigin[i])) - continue; - - g_bSkipDecalHook = true; - SprayClientDecalToOne(i, client, g_iDecalEntity[i], g_vecSprayOrigin[i]); - g_iClientToClientSprayLifetime[client][i] = 0; - g_bSkipDecalHook = false; - } - } + g_bWantsToSeeNSFWSprays[client] = view_as(StringToInt(sWantsToSeeNSFW)); } public void CvarQueryFinished_SprayLifeTime(QueryCookie cookie, int client, ConVarQueryResult res, const char[] sCvarName, const char[] sCvarVal) @@ -214,9 +243,7 @@ public void CvarQueryFinished_SprayLifeTime(QueryCookie cookie, int client, ConV int iVal = StringToInt(sCvarVal); - iVal = iVal <= 0 ? 1 : iVal > 1000 ? 1000 : iVal; - - g_iClientSprayLifetime[client] = iVal; + g_iClientSprayLifetime[client] = iVal <= 0 ? 1 : iVal > 1000 ? 1000 : iVal; } public void OnClientPostAdminCheck(int client) @@ -224,8 +251,33 @@ public void OnClientPostAdminCheck(int client) if (g_hDatabase != null) { ClearPlayerInfo(client); + GetPlayerDecalFile(client, g_sSprayHash[client], sizeof(g_sSprayHash[])); UpdatePlayerInfo(client); UpdateSprayHashInfo(client); + UpdateNSFWInfo(client); + } + + if (g_cvarSendSpraysToConnectingClients.BoolValue) + { + for (int i = 1; i <= MaxClients; i++) + { + if (!IsValidClient(i) || IsFakeClient(i)) + continue; + + if (IsVectorZero(g_vecSprayOrigin[i])) + continue; + + if (g_bHasNSFWSpray[i] && !g_bWantsToSeeNSFWSprays[client]) + { + PaintWorldDecalToOne(g_iNSFWDecalIndex, g_vecSprayOrigin[i], client); + continue; + } + + g_bSkipDecalHook = true; + SprayClientDecalToOne(i, client, g_iDecalEntity[i], g_vecSprayOrigin[i]); + g_iClientToClientSprayLifetime[client][i] = 0; + g_bSkipDecalHook = false; + } } } @@ -233,6 +285,17 @@ public void OnClientDisconnect(int client) { if (IsValidClient(client)) { + for (int i = 1; i <= MaxClients; i++) + { + if (!IsValidClient(i)) + continue; + + if (!g_bHasSprayHidden[i][client] && g_bWantsToSeeNSFWSprays[i]) + continue; + + PaintWorldDecalToOne(g_iTransparentDecalIndex, g_vecSprayOrigin[client], i); + } + g_bSkipDecalHook = true; SprayClientDecalToAll(client, 0, ACTUAL_NULL_VECTOR); g_bSkipDecalHook = false; @@ -245,7 +308,7 @@ public Action CS_OnTerminateRound(float &fDelay, CSRoundEndReason &reason) { if (g_cvarUsePersistentSprays.BoolValue) { - g_hRoundEndTimer = CreateTimer(fDelay, Timer_ProcessPersistentSprays); + g_hRoundEndTimer = CreateTimer(fDelay + 0.5, Timer_ProcessPersistentSprays); return Plugin_Continue; } @@ -264,9 +327,9 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse) { if (!g_bSprayBanned[client] && !g_bSprayHashBanned[client]) { - if (IsPlayerAlive(client)) - if (TracePlayerAnglesRanged(client, 128.0)) - return Plugin_Continue; + //if (IsPlayerAlive(client)) + //if (TracePlayerAnglesRanged(client, 128.0)) + //return Plugin_Continue; ForceSpray(client, client, false); g_fNextSprayTime[client] = 0.0; @@ -1355,6 +1418,299 @@ int MenuHandler_Menu_ConfirmUnban(Menu hMenu, MenuAction action, int iParam1, in } } +public Action Command_MarkNSFW(int client, int argc) +{ + if (!client) + { + PrintToServer("[SprayManager] Cannot use command from server console."); + return Plugin_Handled; + } + + if (!IsValidClient(client)) + { + ReplyToCommand(client, "[SprayManager] Unable to update status, please wait a few seconds and try again."); + return Plugin_Handled; + } + + if (g_hDatabase == null || !g_bFullyConnected) + { + ReplyToCommand(client, "\x01\x04[SprayManager]\x01 Unable to update status, please wait a few seconds and try again."); + return Plugin_Handled; + } + + if (g_bMarkedNSFWByAdmin[client] || g_bHasNSFWSpray[client]) + { + PrintToChat(client, "\x01\x04[SprayManager]\x01 Your spray is already marked as NSFW."); + return Plugin_Handled; + } + + g_bHasNSFWSpray[client] = true; + + char sQuery[256]; + char sClientSteamID[32]; + + GetClientAuthId(client, AuthId_Steam2, sClientSteamID, sizeof(sClientSteamID)); + Format(sQuery, sizeof(sQuery), "INSERT INTO `spraynsfwlist` (`sprayhash`, `sprayersteamid`, `setbyadmin`) VALUES ('%s', '%s', '%d');", g_sSprayHash[client], sClientSteamID, 0); + SQL_TQuery(g_hDatabase, DummyCallback, sQuery); + + for (int i = 1; i <= MaxClients; i++) + { + if (!IsValidClient(i)) + continue; + + for (int x = 1; x <= MaxClients; x++) + { + if (!IsValidClient(x)) + continue; + + if (g_bHasSprayHidden[i][x]) + continue; + + if (g_bWantsToSeeNSFWSprays[i]) + continue; + + PaintWorldDecalToOne(g_bHasNSFWSpray[x] ? g_iNSFWDecalIndex : g_iTransparentDecalIndex, g_vecSprayOrigin[x], i); + g_bSkipDecalHook = true; + SprayClientDecalToOne(x, i, g_bHasNSFWSpray[x] ? 0 : g_iDecalEntity[x], g_bHasNSFWSpray[x] ? ACTUAL_NULL_VECTOR : g_vecSprayOrigin[x]); + g_iClientToClientSprayLifetime[i][x] = g_bHasNSFWSpray[x] ? g_iClientToClientSprayLifetime[i][x] : 0; + g_bSkipDecalHook = false; + } + } + + PrintToChat(client, "\x01\x04[SprayManager]\x01 Your spray is now marked as NSFW."); + + return Plugin_Continue; +} + +public Action Command_MarkSFW(int client, int argc) +{ + if (!client) + { + PrintToServer("[SprayManager] Cannot use command from server console."); + return Plugin_Handled; + } + + if (!IsValidClient(client)) + { + ReplyToCommand(client, "[SprayManager] Unable to update status, please wait a few seconds and try again."); + return Plugin_Handled; + } + + if (g_hDatabase == null || !g_bFullyConnected) + { + ReplyToCommand(client, "\x01\x04[SprayManager]\x01 Unable to update status, please wait a few seconds and try again."); + return Plugin_Handled; + } + + if (g_bMarkedNSFWByAdmin[client]) + { + PrintToChat(client, "\x01\x04[SprayManager]\x01 Your spray has been marked as NSFW by an admin, you cannot change this."); + return Plugin_Handled; + } + + if (!g_bHasNSFWSpray[client]) + { + PrintToChat(client, "\x01\x04[SprayManager]\x01 Your spray is already marked as SFW."); + return Plugin_Handled; + } + + g_bHasNSFWSpray[client] = false; + + char sQuery[256]; + + Format(sQuery, sizeof(sQuery), "DELETE FROM `spraynsfwlist` WHERE `sprayhash` = '%s';", g_sSprayHash[client]); + SQL_TQuery(g_hDatabase, DummyCallback, sQuery); + + for (int i = 1; i <= MaxClients; i++) + { + if (!IsValidClient(i)) + continue; + + if (g_bHasSprayHidden[i][client]) + continue; + + if (g_bWantsToSeeNSFWSprays[i]) + continue; + + PaintWorldDecalToOne(g_iTransparentDecalIndex, g_vecSprayOrigin[client], i); + g_bSkipDecalHook = true; + SprayClientDecalToOne(client, i, g_iDecalEntity[client], g_vecSprayOrigin[client]); + g_iClientToClientSprayLifetime[i][client] = 0; + g_bSkipDecalHook = false; + } + + PrintToChat(client, "\x01\x04[SprayManager]\x01 Your spray is now marked as SFW."); + + return Plugin_Continue; +} + +public Action Command_NSFW(int client, int argc) +{ + if (!client) + { + ReplyToCommand(client, "[SprayManager] Cannot use command from server console."); + return Plugin_Handled; + } + + if (!AreClientCookiesCached(client)) + { + PrintToChat(client, "\x01\x04[SprayManager]\x01 Could not update status, please wait a few seconds and try again."); + return Plugin_Handled; + } + + g_bWantsToSeeNSFWSprays[client] = !g_bWantsToSeeNSFWSprays[client]; + + SetClientCookie(client, g_hWantsToSeeNSFWCookie, g_bWantsToSeeNSFWSprays[client] ? "1" : "0"); + + PrintToChat(client, "\x01\x04[SprayManager]\x01 You can %s", g_bWantsToSeeNSFWSprays[client] ? "now see \x07BF49FFNSFW\x01 sprays." : "no longer see \x07BF49FFNSFW\x01 sprays."); + + for (int i = 1; i <= MaxClients; i++) + { + if (!IsValidClient(i)) + continue; + + if (!g_bHasNSFWSpray[i]) + continue; + + if (g_bHasSprayHidden[client][i]) + continue; + + PaintWorldDecalToOne(g_bWantsToSeeNSFWSprays[client] ? g_iTransparentDecalIndex : g_iNSFWDecalIndex, g_vecSprayOrigin[i], client); + g_bSkipDecalHook = true; + SprayClientDecalToOne(i, client, g_bWantsToSeeNSFWSprays[client] ? g_iDecalEntity[i] : 0, g_bWantsToSeeNSFWSprays[client] ? g_vecSprayOrigin[i] : ACTUAL_NULL_VECTOR); + g_iClientToClientSprayLifetime[client][i] = g_bWantsToSeeNSFWSprays[client] ? 0 : g_iClientToClientSprayLifetime[client][i]; + g_bSkipDecalHook = false; + } + + return Plugin_Handled; +} + +public Action Command_HideSpray(int client, int argc) +{ + if (!client) + { + ReplyToCommand(client, "[SprayManager] Cannot use command from server console."); + return Plugin_Handled; + } + + if (argc > 0) + { + int iTarget; + char sArg[64]; + + GetCmdArg(1, sArg, sizeof(sArg)); + + if ((iTarget = FindTarget(client, sArg, false, false)) <= 0) + return Plugin_Handled; + + g_bHasSprayHidden[client][iTarget] = true; + PrintToChat(client, "\x01\x04[SprayManager]\x01 You have hidden \x04%N\x01's spray.", iTarget); + + PaintWorldDecalToOne(g_iHiddenDecalIndex, g_vecSprayOrigin[iTarget], client); + g_bSkipDecalHook = true; + SprayClientDecalToOne(iTarget, client, 0, ACTUAL_NULL_VECTOR); + g_bSkipDecalHook = false; + + return Plugin_Handled; + } + + float vecEndPos[3]; + + if (TracePlayerAngles(client, vecEndPos)) + { + for (int i = 1; i <= MaxClients; i++) + { + if (!IsPointInsideAABB(vecEndPos, g_SprayAABB[i])) + continue; + + g_bHasSprayHidden[client][i] = true; + PrintToChat(client, "\x01\x04[SprayManager]\x01 You have hidden \x04%N\x01's spray.", i); + + PaintWorldDecalToOne(g_iHiddenDecalIndex, g_vecSprayOrigin[i], client); + g_bSkipDecalHook = true; + SprayClientDecalToOne(i, client, 0, ACTUAL_NULL_VECTOR); + g_bSkipDecalHook = false; + + return Plugin_Handled; + } + } + + PrintToChat(client, "\x01\x04[SprayManager]\x01 No spray could be found."); + + return Plugin_Handled; +} + +public Action Command_UnhideSpray(int client, int argc) +{ + if (!client) + { + ReplyToCommand(client, "[SprayManager] Cannot use command from server console."); + return Plugin_Handled; + } + + if (argc > 0) + { + int iTarget; + char sArg[64]; + + GetCmdArg(1, sArg, sizeof(sArg)); + + if ((iTarget = FindTarget(client, sArg, false, false)) <= 0) + return Plugin_Handled; + + g_bHasSprayHidden[client][iTarget] = false; + PrintToChat(client, "\x01\x04[SprayManager]\x01 You have unhidden \x04%N\x01's spray.", iTarget); + + PaintWorldDecalToOne(g_iTransparentDecalIndex, g_vecSprayOrigin[iTarget], client); + + if (!g_bWantsToSeeNSFWSprays[client] && g_bHasNSFWSpray[iTarget]) + { + PaintWorldDecalToOne(g_iNSFWDecalIndex, g_vecSprayOrigin[iTarget], client); + return Plugin_Handled; + } + + g_bSkipDecalHook = true; + SprayClientDecalToOne(iTarget, client, g_iDecalEntity[iTarget], g_vecSprayOrigin[iTarget]); + g_iClientToClientSprayLifetime[client][iTarget] = 0; + g_bSkipDecalHook = false; + + return Plugin_Handled; + } + + float vecEndPos[3]; + + if (TracePlayerAngles(client, vecEndPos)) + { + for (int i = 1; i <= MaxClients; i++) + { + if (!IsPointInsideAABB(vecEndPos, g_SprayAABB[i])) + continue; + + g_bHasSprayHidden[client][i] = false; + PrintToChat(client, "\x01\x04[SprayManager]\x01 You have unhidden \x04%N\x01's spray.", i); + + PaintWorldDecalToOne(g_iTransparentDecalIndex, g_vecSprayOrigin[i], client); + + if (!g_bWantsToSeeNSFWSprays[client] && g_bHasNSFWSpray[i]) + { + PaintWorldDecalToOne(g_iNSFWDecalIndex, g_vecSprayOrigin[i], client); + return Plugin_Handled; + } + + g_bSkipDecalHook = true; + SprayClientDecalToOne(i, client, g_iDecalEntity[i], g_vecSprayOrigin[i]); + g_iClientToClientSprayLifetime[client][i] = 0; + g_bSkipDecalHook = false; + + return Plugin_Handled; + } + } + + PrintToChat(client, "\x01\x04[SprayManager]\x01 No spray could be found."); + + return Plugin_Handled; +} + public Action Command_AdminSpray(int client, int argc) { if (!client) @@ -1610,6 +1966,96 @@ public Action Command_RemoveSpray(int client, int argc) return Plugin_Handled; } +public Action Command_ForceNSFW(int client, int argc) +{ + if (!client) + { + ReplyToCommand(client, "[SprayManager] Cannot use command from server console."); + return Plugin_Handled; + } + + if (argc > 0) + { + int iTarget; + char sTarget[32]; + + GetCmdArg(1, sTarget, sizeof(sTarget)); + + if ((iTarget = FindTarget(client, sTarget)) <= 0) + return Plugin_Handled; + + AdminForceSprayNSFW(iTarget); + PrintToChat(client, "\x01\x04[SprayManager]\x01 Marked \x04%N\x01's spray as NSFW.", iTarget); + + return Plugin_Handled; + } + + float vecEndPos[3]; + + if (TracePlayerAngles(client, vecEndPos)) + { + for (int i = 1; i <= MaxClients; i++) + { + if (!IsPointInsideAABB(vecEndPos, g_SprayAABB[i])) + continue; + + AdminForceSprayNSFW(i); + PrintToChat(client, "\x01\x04[SprayManager]\x01 Marked \x04%N\x01's spray as NSFW.", i); + + return Plugin_Handled; + } + } + + PrintToChat(client, "\x01\x04[SprayManager]\x01 No spray could be found."); + + return Plugin_Handled; +} + +public Action Command_ForceSFW(int client, int argc) +{ + if (!client) + { + ReplyToCommand(client, "[SprayManager] Cannot use command from server console."); + return Plugin_Handled; + } + + if (argc > 0) + { + int iTarget; + char sTarget[32]; + + GetCmdArg(1, sTarget, sizeof(sTarget)); + + if ((iTarget = FindTarget(client, sTarget)) <= 0) + return Plugin_Handled; + + AdminForceSpraySFW(iTarget); + PrintToChat(client, "\x01\x04[SprayManager]\x01 Marked \x04%N\x01's spray as SFW.", iTarget); + + return Plugin_Handled; + } + + float vecEndPos[3]; + + if (TracePlayerAngles(client, vecEndPos)) + { + for (int i = 1; i <= MaxClients; i++) + { + if (!IsPointInsideAABB(vecEndPos, g_SprayAABB[i])) + continue; + + AdminForceSpraySFW(i); + PrintToChat(client, "\x01\x04[SprayManager]\x01 Marked \x04%N\x01's spray as SFW.", i); + + return Plugin_Handled; + } + } + + PrintToChat(client, "\x01\x04[SprayManager]\x01 No spray could be found."); + + return Plugin_Handled; +} + public Action Command_SprayManager_UpdateInfo(int client, int argc) { for (int i = 1; i <= MaxClients; i++) @@ -1620,6 +2066,7 @@ public Action Command_SprayManager_UpdateInfo(int client, int argc) ClearPlayerInfo(i); UpdatePlayerInfo(i); UpdateSprayHashInfo(i); + UpdateNSFWInfo(i); } ReplyToCommand(client, "[SprayManager] Refreshed database."); @@ -1641,10 +2088,10 @@ public Action HookDecal(const char[] sTEName, const int[] iClients, int iNumClie } float vecOrigin[3]; - float AABBTemp[AABBTotalPoints]; - TE_ReadVector("m_vecOrigin", vecOrigin); + float AABBTemp[AABBTotalPoints]; + AABBTemp[AABBMinX] = vecOrigin[0] - 32.0; AABBTemp[AABBMaxX] = vecOrigin[0] + 32.0; AABBTemp[AABBMinY] = vecOrigin[1] - 32.0; @@ -1680,9 +2127,6 @@ public Action HookDecal(const char[] sTEName, const int[] iClients, int iNumClie if (g_fNextSprayTime[client] > GetGameTime()) return Plugin_Handled; - char sSteamID[32]; - GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID)); - if (!CheckCommandAccess(client, "sm_sprayban", ADMFLAG_GENERIC)) { if (g_cvarUseProximityCheck.BoolValue) @@ -1714,23 +2158,59 @@ public Action HookDecal(const char[] sTEName, const int[] iClients, int iNumClie } } - g_iAllowSpray = 0; + int iClientCount = GetClientCount(true); - g_iSprayLifetime[client] = 0; + int[] iarrValidClients = new int[iClientCount]; + int[] iarrHiddenClients = new int[iClientCount]; + int[] iarrNoNSFWClients = new int[iClientCount]; + int iCurValidIdx; + int iCurHiddenIdx; + int iCurNoNSFWIdx; - UpdateClientToClientSprayLifeTime(client, 0); + for (int i = 1; i <= MaxClients; i++) + { + if (!IsClientInGame(i)) + continue; + + if (g_bHasSprayHidden[i][client]) + { + iarrHiddenClients[iCurHiddenIdx++] = i; + continue; + } + + if (g_bHasNSFWSpray[client] && !g_bWantsToSeeNSFWSprays[i]) + { + iarrNoNSFWClients[iCurNoNSFWIdx++] = i; + continue; + } + + iarrValidClients[iCurValidIdx++] = i; + } + + if (!IsVectorZero(g_vecSprayOrigin[client])) + { + PaintWorldDecalToSelected(g_iTransparentDecalIndex, g_vecSprayOrigin[client], iarrNoNSFWClients, iCurNoNSFWIdx); + PaintWorldDecalToSelected(g_iTransparentDecalIndex, g_vecSprayOrigin[client], iarrHiddenClients, iCurHiddenIdx); + } + + PaintWorldDecalToSelected(g_iHiddenDecalIndex, vecOrigin, iarrHiddenClients, iCurHiddenIdx); + PaintWorldDecalToSelected(g_iNSFWDecalIndex, vecOrigin, iarrNoNSFWClients, iCurNoNSFWIdx); + + g_bSkipDecalHook = true; + SprayClientDecalToSelected(client, g_iDecalEntity[client], vecOrigin, iarrValidClients, iCurValidIdx); + g_bSkipDecalHook = false; g_vecSprayOrigin[client] = vecOrigin; - + g_iAllowSpray = 0; + g_iSprayLifetime[client] = 0; + UpdateClientToClientSprayLifeTime(client, 0); g_SprayAABB[client] = AABBTemp; ArrayList PosArray = new ArrayList(3, 0); - PosArray.PushArray(vecOrigin, 3); - RequestFrame(FrameAfterSpray, PosArray); - return Plugin_Continue; + return Plugin_Handled; } public void FrameAfterSpray(ArrayList Data) @@ -1775,7 +2255,7 @@ public Action Timer_PerformPlayerTraces(Handle hTimer) char sSteamID[32]; GetClientAuthId(x, AuthId_Steam2, sSteamID, sizeof(sSteamID)); - PrintHintText(i, "Sprayed by: %N (%s)", x, sSteamID); + PrintHintText(i, "Sprayed by: %N (%s) [%s]", x, sSteamID, g_bHasNSFWSpray[x] ? "NSFW" : "SFW"); StopSound(i, SNDCHAN_STATIC, "UI/hint.wav"); bLookingatSpray[i] = true; @@ -1818,7 +2298,21 @@ public Action Timer_ProcessPersistentSprays(Handle hThis) if (!IsVectorZero(g_vecSprayOrigin[x])) g_iClientToClientSprayLifetime[i][x]++; - if (g_iClientToClientSprayLifetime[i][x] >= g_iClientSprayLifetime[i]) + bool bDoNotSpray; + + if (g_bHasSprayHidden[i][x]) + { + PaintWorldDecalToOne(g_iHiddenDecalIndex, g_vecSprayOrigin[x], i); + bDoNotSpray = true; + } + + if (!g_bWantsToSeeNSFWSprays[i] && g_bHasNSFWSpray[x] && !bDoNotSpray) + { + PaintWorldDecalToOne(g_iNSFWDecalIndex, g_vecSprayOrigin[x], i); + bDoNotSpray = true; + } + + if (g_iClientToClientSprayLifetime[i][x] >= g_iClientSprayLifetime[i] && !bDoNotSpray) { g_bSkipDecalHook = true; SprayClientDecalToOne(x, i, g_iDecalEntity[x], g_vecSprayOrigin[x]); @@ -1847,6 +2341,23 @@ public Action Timer_ResetOldSprays(Handle hThis) SprayClientDecalToAll(i, 0, ACTUAL_NULL_VECTOR); g_iSprayLifetime[i] = 0; } + else + { + for (int x = 1; x <= MaxClients; x++) + { + if (!IsValidClient(x) || IsFakeClient(x)) + continue; + + if (g_bHasSprayHidden[x][i]) + { + PaintWorldDecalToOne(g_iHiddenDecalIndex, g_vecSprayOrigin[i], x); + continue; + } + + if (!g_bWantsToSeeNSFWSprays[x] && g_bHasNSFWSpray[i]) + PaintWorldDecalToOne(g_iNSFWDecalIndex, g_vecSprayOrigin[i], x); + } + } } g_hRoundEndTimer = null; @@ -1868,12 +2379,7 @@ public void OnSQLConnected(Handle hParent, Handle hChild, const char[] err, any if (hChild == null) { LogError("Failed to connect to database, retrying in 10 seconds. (%s)", err); - - if (CreateTimer(10.0, ReconnectSQL) == null) - { - LogError("Failed to create re-connector timer, trying to reconnect now."); - InitializeSQL(); - } + CreateTimer(10.0, ReconnectSQL); return; } @@ -1888,6 +2394,7 @@ public void OnSQLConnected(Handle hParent, Handle hChild, const char[] err, any SQL_TQuery(g_hDatabase, OnSQLTableCreated, "CREATE TABLE IF NOT EXISTS `spraymanager` (`steamid` VARCHAR(32) NOT NULL, `name` VARCHAR(32) NOT NULL, `unbantime` INT, `issuersteamid` VARCHAR(32), `issuername` VARCHAR(32) NOT NULL, `issuedtime` INT, `issuedreason` VARCHAR(64) NOT NULL, PRIMARY KEY(steamid)) CHARACTER SET utf8 COLLATE utf8_general_ci;"); SQL_TQuery(g_hDatabase, OnSQLSprayBlacklistCreated, "CREATE TABLE IF NOT EXISTS `sprayblacklist` (`sprayhash` VARCHAR(16) NOT NULL, `sprayer` VARCHAR(32) NOT NULL, `sprayersteamid` VARCHAR(32), PRIMARY KEY(sprayhash)) CHARACTER SET utf8 COLLATE utf8_general_ci;"); + SQL_TQuery(g_hDatabase, OnSQLNSFWListCreated, "CREATE TABLE IF NOT EXISTS `spraynsfwlist` (`sprayhash` VARCHAR(16) NOT NULL, `sprayersteamid` VARCHAR(32), `setbyadmin` TINYINT, PRIMARY KEY(sprayhash)) CHARACTER SET utf8 COLLATE utf8_general_ci"); g_bSQLite = false; } @@ -1895,6 +2402,7 @@ public void OnSQLConnected(Handle hParent, Handle hChild, const char[] err, any { SQL_TQuery(g_hDatabase, OnSQLTableCreated, "CREATE TABLE IF NOT EXISTS `spraymanager` (`steamid` TEXT NOT NULL, `name` TEXT DEFAULT 'unknown', `unbantime` INTEGER, `issuersteamid` TEXT, `issuername` TEXT DEFAULT 'unknown', `issuedtime` INTEGER NOT NULL, `issuedreason` TEXT DEFAULT 'none', PRIMARY KEY(steamid));"); SQL_TQuery(g_hDatabase, OnSQLSprayBlacklistCreated, "CREATE TABLE IF NOT EXISTS `sprayblacklist` (`sprayhash` TEXT NOT NULL, `sprayer` TEXT DEFAULT 'unknown', `sprayersteamid` TEXT, PRIMARY KEY(sprayhash));"); + SQL_TQuery(g_hDatabase, OnSQLNSFWListCreated, "CREATE TABLE IF NOT EXISTS `spraynsfwlist` (`sprayhash` TEXT NOT NULL, `sprayersteamid` TEXT, `setbyadmin` INTEGER, PRIMARY KEY(sprayhash));"); g_bSQLite = true; } @@ -1912,39 +2420,17 @@ public void OnSQLTableCreated(Handle hParent, Handle hChild, const char[] err, a if (hChild == null) { LogError("Database error while creating/checking for \"spraymanager\" table, retrying in 10 seconds. (%s)", err); - - if (CreateTimer(10.0, RetryMainTableCreation) == null) - { - LogError("Failed to create re-query timer, trying to query now."); - - if (g_bSQLite) - SQL_TQuery(g_hDatabase, OnSQLTableCreated, "CREATE TABLE IF NOT EXISTS `spraymanager` (`steamid` TEXT NOT NULL, `name` TEXT DEFAULT 'unknown', `unbantime` INTEGER, `issuersteamid` TEXT, `issuername` TEXT DEFAULT 'unknown', `issuedtime` INTEGER NOT NULL, `issuedreason` TEXT DEFAULT 'none', PRIMARY KEY(steamid));"); - else - SQL_TQuery(g_hDatabase, OnSQLTableCreated, "CREATE TABLE IF NOT EXISTS `spraymanager` (`steamid` VARCHAR(32) NOT NULL, `name` VARCHAR(32) NOT NULL, `unbantime` INT, `issuersteamid` VARCHAR(32), `issuername` VARCHAR(32) NOT NULL, `issuedtime` INT, `issuedreason` VARCHAR(64) NOT NULL, PRIMARY KEY(steamid)) CHARACTER SET utf8 COLLATE utf8_general_ci;"); - } + CreateTimer(10.0, RetryMainTableCreation); return; } g_bGotBans = true; - if (g_bGotBlacklist) + if (g_bGotBlacklist && g_bGotNSFWList) { if (g_bLoadedLate) - { - if (CreateTimer(2.5, RetryUpdatingPlayerInfo) == null) - { - LogError("Failed to create player info updater timer, attempting to update info now."); - - for (int i = 1; i <= MaxClients; i++) - { - if (!IsValidClient) - continue; - - OnClientPostAdminCheck(i); - } - } - } + CreateTimer(2.5, RetryUpdatingPlayerInfo); LogMessage("Successfully connected to %s database!", g_bSQLite ? "SQLite" : "mySQL"); @@ -1965,39 +2451,17 @@ public void OnSQLSprayBlacklistCreated(Handle hParent, Handle hChild, const char if (hChild == null) { LogError("Database error while creating/checking for \"sprayblacklist\" table, retrying in 10 seconds. (%s)", err); - - if (CreateTimer(10.0, RetryBlacklistTableCreation) == null) - { - LogError("Failed to create re-query timer, trying to query now."); - - if (g_bSQLite) - SQL_TQuery(g_hDatabase, OnSQLSprayBlacklistCreated, "CREATE TABLE IF NOT EXISTS `sprayblacklist` (`sprayhash` TEXT NOT NULL, `sprayer` TEXT DEFAULT 'unknown', `sprayersteamid` TEXT NOT NULL, PRIMARY KEY(sprayhash));"); - else - SQL_TQuery(g_hDatabase, OnSQLSprayBlacklistCreated, "CREATE TABLE IF NOT EXISTS `sprayblacklist` (`sprayhash` VARCHAR(16) NOT NULL, `sprayer` VARCHAR(32) NOT NULL, `sprayersteamid` VARCHAR(32) NOT NULL, PRIMARY KEY(sprayhash)) CHARACTER SET utf8 COLLATE utf8_general_ci;"); - } + CreateTimer(10.0, RetryBlacklistTableCreation); return; } g_bGotBlacklist = true; - if (g_bGotBans) + if (g_bGotBans && g_bGotNSFWList) { if (g_bLoadedLate) - { - if (CreateTimer(2.5, RetryUpdatingPlayerInfo) == null) - { - LogError("Failed to create player info updater timer, attempting to update info now."); - - for (int i = 1; i <= MaxClients; i++) - { - if (!IsValidClient) - continue; - - OnClientPostAdminCheck(i); - } - } - } + CreateTimer(2.5, RetryUpdatingPlayerInfo); LogMessage("Successfully connected to %s database!", g_bSQLite ? "SQLite" : "mySQL"); @@ -2013,11 +2477,42 @@ public Action RetryBlacklistTableCreation(Handle hTimer) SQL_TQuery(g_hDatabase, OnSQLSprayBlacklistCreated, "CREATE TABLE IF NOT EXISTS `sprayblacklist` (`sprayhash` VARCHAR(16) NOT NULL, `sprayer` VARCHAR(32) NOT NULL, `sprayersteamid` VARCHAR(32) NOT NULL, PRIMARY KEY(sprayhash)) CHARACTER SET utf8 COLLATE utf8_general_ci;"); } +public void OnSQLNSFWListCreated(Handle hParent, Handle hChild, const char[] err, any data) +{ + if (hChild == null) + { + LogError("Database error while creating/checking for \"spraynsfwlist\" table, retrying in 10 seconds. (%s)", err); + CreateTimer(10.0, RetryNSFWlistTableCreation); + + return; + } + + g_bGotNSFWList = true; + + if (g_bGotBans && g_bGotBlacklist) + { + if (g_bLoadedLate) + CreateTimer(2.5, RetryUpdatingPlayerInfo); + + LogMessage("Successfully connected to %s database!", g_bSQLite ? "SQLite" : "mySQL"); + + g_bFullyConnected = true; + } +} + +public Action RetryNSFWlistTableCreation(Handle hTimer) +{ + if (g_bSQLite) + SQL_TQuery(g_hDatabase, OnSQLNSFWListCreated, "CREATE TABLE IF NOT EXISTS `spraynsfwlist` (`sprayhash` TEXT NOT NULL, `sprayersteamid` TEXT, `setbyadmin` INTEGER, PRIMARY KEY(sprayhash));"); + else + SQL_TQuery(g_hDatabase, OnSQLNSFWListCreated, "CREATE TABLE IF NOT EXISTS `spraynsfwlist` (`sprayhash` VARCHAR(16) NOT NULL, `sprayersteamid` VARCHAR(32), `setbyadmin` TINYINT PRIMARY KEY(sprayhash)) CHARACTER SET utf8 COLLATE utf8_general_ci"); +} + public Action RetryUpdatingPlayerInfo(Handle hTimer) { for (int i = 1; i <= MaxClients; i++) { - if (!IsValidClient) + if (!IsValidClient(i)) continue; OnClientPostAdminCheck(i); @@ -2218,6 +2713,78 @@ bool UnbanClientSpray(int client, int target) return true; } +void AdminForceSprayNSFW(int client) +{ + char sQuery[256]; + char sClientSteamID[32]; + + GetClientAuthId(client, AuthId_Steam2, sClientSteamID, sizeof(sClientSteamID)); + Format(sQuery, sizeof(sQuery), "INSERT INTO `spraynsfwlist` (`sprayhash`, `sprayersteamid`, `setbyadmin`) VALUES ('%s', '%s', '%d');", g_sSprayHash[client], sClientSteamID, 1); + + SQL_TQuery(g_hDatabase, DummyCallback, sQuery); + + g_bHasNSFWSpray[client] = true; + g_bMarkedNSFWByAdmin[client] = true; + + for (int i = 1; i <= MaxClients; i++) + { + if (!IsValidClient(i)) + continue; + + for (int x = 1; x <= MaxClients; x++) + { + if (!IsValidClient(x)) + continue; + + if (g_bHasSprayHidden[i][x]) + continue; + + if (g_bWantsToSeeNSFWSprays[i]) + continue; + + PaintWorldDecalToOne(g_iNSFWDecalIndex, g_vecSprayOrigin[x], i); + g_bSkipDecalHook = true; + SprayClientDecalToOne(x, i, 0, ACTUAL_NULL_VECTOR); + g_bSkipDecalHook = false; + } + } +} + +void AdminForceSpraySFW(int client) +{ + char sQuery[256]; + char sClientSteamID[32]; + + GetClientAuthId(client, AuthId_Steam2, sClientSteamID, sizeof(sClientSteamID)); + Format(sQuery, sizeof(sQuery), "DELETE FROM `spraynsfwlist` WHERE `sprayhash` = '%s';", g_sSprayHash[client]); + + SQL_TQuery(g_hDatabase, DummyCallback, sQuery); + + g_bHasNSFWSpray[client] = false; + g_bMarkedNSFWByAdmin[client] = false; + + for (int i = 1; i <= MaxClients; i++) + { + if (!IsValidClient(i)) + continue; + + for (int x = 1; x <= MaxClients; x++) + { + if (!IsValidClient(x)) + continue; + + if (g_bHasSprayHidden[i][x]) + continue; + + PaintWorldDecalToOne(g_iTransparentDecalIndex, g_vecSprayOrigin[x], i); + g_bSkipDecalHook = true; + SprayClientDecalToOne(x, i, g_iDecalEntity[x], g_vecSprayOrigin[x]); + g_iClientToClientSprayLifetime[i][x] = 0; + g_bSkipDecalHook = false; + } + } +} + void UpdatePlayerInfo(int client) { if (!IsValidClient(client)) @@ -2245,12 +2812,24 @@ void UpdateSprayHashInfo(int client) char sSprayQuery[128]; - GetPlayerDecalFile(client, g_sSprayHash[client], sizeof(g_sSprayHash[])); Format(sSprayQuery, sizeof(sSprayQuery), "SELECT * FROM `sprayblacklist` WHERE `sprayhash` = '%s';", g_sSprayHash[client]); - SQL_TQuery(g_hDatabase, OnSQLCheckSprayHashBanQuery, sSprayQuery, client, DBPrio_High); } +void UpdateNSFWInfo(int client) +{ + if (!IsValidClient(client)) + return; + + if (g_hDatabase == null || !g_bFullyConnected) + return; + + char sSprayQuery[128]; + + Format(sSprayQuery, sizeof(sSprayQuery), "SELECT * FROM `spraynsfwlist` WHERE `sprayhash` = '%s';", g_sSprayHash[client]); + SQL_TQuery(g_hDatabase, OnSQLCheckNSFWSprayHashQuery, sSprayQuery, client); +} + public void DummyCallback(Handle hOwner, Handle hChild, const char[] err, any data) { if (hOwner == null || hChild == null) @@ -2265,12 +2844,7 @@ public void OnSQLCheckBanQuery(Handle hParent, Handle hChild, const char[] err, if (hChild == null) { LogError("An error occurred while querying the database for a user ban, retrying in 10 seconds. (%s)", err); - - if (CreateTimer(10.0, RetryPlayerInfoUpdate, client) == null) - { - LogError("Failed to create query timer, trying to query now."); - UpdatePlayerInfo(client); - } + CreateTimer(10.0, RetryPlayerInfoUpdate, client); return; } @@ -2295,12 +2869,7 @@ public void OnSQLCheckSprayHashBanQuery(Handle hParent, Handle hChild, const cha if (hChild == null) { LogError("An error occurred while querying the database for a spray ban, retrying in 10 seconds. (%s)", err); - - if (CreateTimer(10.0, RetrySprayHashUpdate, client) == null) - { - LogError("Failed to create spray query timer, trying to query now."); - UpdateSprayHashInfo(client); - } + CreateTimer(10.0, RetrySprayHashUpdate, client); return; } @@ -2309,6 +2878,30 @@ public void OnSQLCheckSprayHashBanQuery(Handle hParent, Handle hChild, const cha g_bSprayHashBanned[client] = true; } +public void OnSQLCheckNSFWSprayHashQuery(Handle hParent, Handle hChild, const char[] err, any client) +{ + if (!IsValidClient(client)) + return; + + if (hChild == null) + { + LogError("An error occurred while querying the NSFW database for a spray, retrying in 10 seconds. (%s)", err); + CreateTimer(10.0, RetryNSFWSprayLookup, client); + + return; + } + + if (SQL_FetchRow(hChild)) + { + g_bHasNSFWSpray[client] = true; + + char sSetByAdmin[8]; + SQL_FetchString(hChild, 2, sSetByAdmin, sizeof(sSetByAdmin)); + + g_bMarkedNSFWByAdmin[client] = view_as(StringToInt(sSetByAdmin)); + } +} + public Action RetryPlayerInfoUpdate(Handle hTimer, any client) { UpdatePlayerInfo(client); @@ -2319,7 +2912,12 @@ public Action RetrySprayHashUpdate(Handle hTimer, any client) UpdateSprayHashInfo(client); } -bool ForceSpray(int client, int target, bool bPlaySound=true) +public Action RetryNSFWSprayLookup(Handle hTimer, any client) +{ + UpdateNSFWInfo(client); +} + +stock bool ForceSpray(int client, int target, bool bPlaySound=true) { if (!IsValidClient(target)) return false; @@ -2341,7 +2939,7 @@ bool ForceSpray(int client, int target, bool bPlaySound=true) return false; } -bool SprayClientDecalToAll(int client, int iEntity, float vecOrigin[3]) +stock bool SprayClientDecalToAll(int client, int iEntity, const float vecOrigin[3]) { if (!IsValidClient(client)) return false; @@ -2355,7 +2953,21 @@ bool SprayClientDecalToAll(int client, int iEntity, float vecOrigin[3]) return true; } -bool SprayClientDecalToOne(int client, int target, int iEntity, float vecOrigin[3]) +stock bool SprayClientDecalToSelected(int client, int iEntity, const float vecOrigin[3], int[] iClients, int iNumClients) +{ + if (!IsValidClient(client)) + return false; + + TE_Start("Player Decal"); + TE_WriteVector("m_vecOrigin", vecOrigin); + TE_WriteNum("m_nEntity", iEntity); + TE_WriteNum("m_nPlayer", client); + TE_Send(iClients, iNumClients); + + return true; +} + +stock bool SprayClientDecalToOne(int client, int target, int iEntity, const float vecOrigin[3]) { if (!IsValidClient(client)) return false; @@ -2369,7 +2981,23 @@ bool SprayClientDecalToOne(int client, int target, int iEntity, float vecOrigin[ return true; } -bool TracePlayerAngles(int client, float vecResult[3]) +stock void PaintWorldDecalToSelected(int iDecalIndex, const float vecOrigin[3], int[] iClients, int iNumClients) +{ + TE_Start("World Decal"); + TE_WriteVector("m_vecOrigin", vecOrigin); + TE_WriteNum("m_nIndex", iDecalIndex); + TE_Send(iClients, iNumClients); +} + +stock void PaintWorldDecalToOne(int iDecalIndex, const float vecOrigin[3], int target) +{ + TE_Start("World Decal"); + TE_WriteVector("m_vecOrigin", vecOrigin); + TE_WriteNum("m_nIndex", iDecalIndex); + TE_SendToClient(target); +} + +stock bool TracePlayerAngles(int client, float vecResult[3]) { if (!IsValidClient(client)) return false; @@ -2403,7 +3031,7 @@ bool TracePlayerAngles(int client, float vecResult[3]) return false; } -bool TracePlayerAnglesRanged(int client, float fMaxDistance) +stock bool TracePlayerAnglesRanged(int client, float fMaxDistance) { if (!IsValidClient(client)) return false; @@ -2437,7 +3065,7 @@ bool TracePlayerAnglesRanged(int client, float fMaxDistance) return false; } -void ClearPlayerInfo(int client) +stock void ClearPlayerInfo(int client) { strcopy(g_sBanIssuer[client], sizeof(g_sBanIssuer[]), ""); strcopy(g_sBanIssuerSID[client], sizeof(g_sBanIssuerSID[]), ""); @@ -2448,14 +3076,17 @@ void ClearPlayerInfo(int client) g_iClientSprayLifetime[client] = 2; g_iSprayLifetime[client] = 0; ResetClientToClientSprayLifeTime(client); + ResetHiddenSprayArray(client); g_iSprayBanTimestamp[client] = 0; g_iSprayUnbanTimestamp[client] = -1; g_fNextSprayTime[client] = 0.0; g_vecSprayOrigin[client] = ACTUAL_NULL_VECTOR; g_SprayAABB[client] = view_as({ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }); //??? + g_bHasNSFWSpray[client] = false; + g_bMarkedNSFWByAdmin[client] = false; } -void UpdateClientToClientSprayLifeTime(int client, int iLifeTime) +stock void UpdateClientToClientSprayLifeTime(int client, int iLifeTime) { for (int i = 1; i <= MaxClients; i++) { @@ -2463,7 +3094,7 @@ void UpdateClientToClientSprayLifeTime(int client, int iLifeTime) } } -void ResetClientToClientSprayLifeTime(int client) +stock void ResetClientToClientSprayLifeTime(int client) { for (int i = 1; i <= MaxClients; i++) { @@ -2472,7 +3103,16 @@ void ResetClientToClientSprayLifeTime(int client) } } -void FormatRemainingTime(int iTimestamp, char[] sBuffer, int iBuffSize) +stock void ResetHiddenSprayArray(int client) +{ + for (int i = 1; i <= MaxClients; i++) + { + g_bHasSprayHidden[i][client] = false; + g_bHasSprayHidden[client][i] = false; + } +} + +stock void FormatRemainingTime(int iTimestamp, char[] sBuffer, int iBuffSize) { if (!iTimestamp) { @@ -2507,7 +3147,7 @@ void FormatRemainingTime(int iTimestamp, char[] sBuffer, int iBuffSize) Format(sBuffer, iBuffSize, "%d %s", seconds, SingularOrMultiple(seconds) ? "Seconds":"Second"); } -bool IsPointInsideAABB(float vecPoint[3], float AABB[6]) +stock bool IsPointInsideAABB(float vecPoint[3], float AABB[6]) { if (vecPoint[0] >= AABB[AABBMinX] && vecPoint[0] <= AABB[AABBMaxX] && vecPoint[1] >= AABB[AABBMinY] && vecPoint[1] <= AABB[AABBMaxY] && @@ -2519,7 +3159,7 @@ bool IsPointInsideAABB(float vecPoint[3], float AABB[6]) return false; } -bool CheckForAABBCollision(float AABB1[6], float AABB2[6]) +stock bool CheckForAABBCollision(float AABB1[6], float AABB2[6]) { if (AABB1[AABBMinX] > AABB2[AABBMaxX]) return false; if (AABB1[AABBMinY] > AABB2[AABBMaxY]) return false; @@ -2531,12 +3171,12 @@ bool CheckForAABBCollision(float AABB1[6], float AABB2[6]) return true; } -bool IsVectorZero(float vecPos[3]) +stock bool IsVectorZero(float vecPos[3]) { return ((vecPos[0] == 0.0) && (vecPos[1] == 0.0) && (vecPos[2] == 0.0)); } -bool SingularOrMultiple(int num) +stock bool SingularOrMultiple(int num) { if (!num || num > 1) return true; @@ -2544,12 +3184,12 @@ bool SingularOrMultiple(int num) return false; } -bool TraceEntityFilter_FilterPlayers(int entity, int contentsMask) +stock bool TraceEntityFilter_FilterPlayers(int entity, int contentsMask) { return entity > MaxClients; } -bool IsValidClient(int client) +stock bool IsValidClient(int client) { if (client <= 0 || client > MaxClients || !IsClientInGame(client)) return false;