diff --git a/entWatch4/scripting/entWatch-restrictions_playtime.sp b/entWatch4/scripting/entWatch-restrictions_playtime.sp new file mode 100644 index 0000000..de0195b --- /dev/null +++ b/entWatch4/scripting/entWatch-restrictions_playtime.sp @@ -0,0 +1,555 @@ +//==================================================================================================== +// +// Name: [entWatch] Restrictions +// Author: zaCade & Prometheum +// Description: Handle the restrictions of [entWatch] +// +//==================================================================================================== +#include + +#pragma newdecls required + +#include +#include +#include +#include +#include + +//2026: add playtime requirements for being unrestricted +#include + + +/* FORWARDS */ +Handle g_hFwd_OnClientRestricted; +Handle g_hFwd_OnClientUnrestricted; + +/* COOKIES */ +Handle g_hCookie_RestrictIssued; +Handle g_hCookie_RestrictExpire; +Handle g_hCookie_RestrictLength; + +/* BOOLEANS */ +bool g_bRestrictedTemp[MAXPLAYERS+1]; +bool g_bDontSpamMsg[MAXPLAYERS+1] + +/* INTERGERS */ +int g_iRestrictIssued[MAXPLAYERS+1]; +int g_iRestrictLength[MAXPLAYERS+1]; +int g_iRestrictExpire[MAXPLAYERS+1]; +int g_iClientHours[MAXPLAYERS + 1]; + +/* STRINGMAPS */ +StringMap g_hTrie_Storage; + +/* CONVARS */ +ConVar g_cvarHourRequirement = null; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "[entWatch] Restrictions", + author = "zaCade & Prometheum", + description = "Handle the restrictions of [entWatch]", + version = "4.0.1" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public APLRes AskPluginLoad2(Handle hMyself, bool bLate, char[] sError, int errorSize) +{ + CreateNative("EW_ClientRestrict", Native_ClientRestrict); + CreateNative("EW_ClientUnrestrict", Native_ClientUnrestrict); + CreateNative("EW_ClientRestricted", Native_ClientRestricted); + + RegPluginLibrary("entWatch-restrictions"); + return APLRes_Success; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + LoadTranslations("common.phrases"); + LoadTranslations("entWatch.restrictions.phrases"); + + g_hFwd_OnClientRestricted = CreateGlobalForward("EW_OnClientRestricted", ET_Ignore, Param_Cell, Param_Cell, Param_Cell); + g_hFwd_OnClientUnrestricted = CreateGlobalForward("EW_OnClientUnrestricted", ET_Ignore, Param_Cell, Param_Cell); + + g_hCookie_RestrictIssued = RegClientCookie("EW_RestrictIssued", "", CookieAccess_Private); + g_hCookie_RestrictExpire = RegClientCookie("EW_RestrictExpire", "", CookieAccess_Private); + g_hCookie_RestrictLength = RegClientCookie("EW_RestrictLength", "", CookieAccess_Private); + + g_hTrie_Storage = new StringMap(); + + RegAdminCmd("sm_eban", Command_ClientRestrict, ADMFLAG_BAN); + RegAdminCmd("sm_eunban", Command_ClientUnrestrict, ADMFLAG_UNBAN); + + RegConsoleCmd("sm_restrictions", Command_DisplayRestrictions); + RegConsoleCmd("sm_ebanlist", Command_DisplayRestrictions); + RegConsoleCmd("sm_status", Command_DisplayStatus); + + for (int client = 1; client <= MaxClients; client++) + { + if (IsClientConnected(client)) + OnClientPutInServer(client); + + if (AreClientCookiesCached(client)) + OnClientCookiesCached(client); + } + + g_cvarHourRequirement = CreateConVar("sm_entwatch_hour_requirement", "10", "Using the unloze play time plugin to set a minimum amount of hours for allowing players access to items."); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnMapStart() +{ + g_hTrie_Storage.Clear(); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientPutInServer(int client) +{ + char sAddress[32]; + GetClientIP(client, sAddress, sizeof(sAddress)); + + g_bDontSpamMsg[client] = false; + bool bRestrictedTemp; + if (g_hTrie_Storage.GetValue(sAddress, bRestrictedTemp)) + { + g_bRestrictedTemp[client] = bRestrictedTemp; + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientCookiesCached(int client) +{ + g_iRestrictIssued[client] = GetClientCookieInt(client, g_hCookie_RestrictIssued); + g_iRestrictExpire[client] = GetClientCookieInt(client, g_hCookie_RestrictExpire); + g_iRestrictLength[client] = GetClientCookieInt(client, g_hCookie_RestrictLength); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnClientDisconnect(int client) +{ + if (g_bRestrictedTemp[client]) + { + char sAddress[32]; + GetClientIP(client, sAddress, sizeof(sAddress)); + + g_hTrie_Storage.SetArray(sAddress, g_bRestrictedTemp[client], true); + } + + g_bDontSpamMsg[client] = false; + g_bRestrictedTemp[client] = false; + g_iRestrictIssued[client] = 0; + g_iRestrictExpire[client] = 0; + g_iRestrictLength[client] = 0; + g_iClientHours[client] = 0; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_ClientRestrict(int client, int args) +{ + if (!GetCmdArgs()) + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%sUsage: sm_eban <#userid/name> [duration]", "E01B5D", "F16767"); + return Plugin_Handled; + } + + char sArguments[2][32]; + GetCmdArg(1, sArguments[0], sizeof(sArguments[])); + GetCmdArg(2, sArguments[1], sizeof(sArguments[])); + + int target; + if ((target = FindTarget(client, sArguments[0], true)) == -1) + return Plugin_Handled; + + if (GetCmdArgs() >= 2) + { + int length = StringToInt(sArguments[1]); + + if (ClientRestrict(client, target, length)) + { + if (length && length >= 60) + { + length /= 60; + CPrintToChatAll("\x07%s[entWatch] \x07%s%N\x07%s restricted \x07%s%N\x07%s for \x07%s%d\x07%s hours Playtime.", "E01B5D", "EDEDED", client, "F16767", "EDEDED", target, "F16767", "EDEDED", length, "F16767"); + LogAction(client, target, "%L restricted %L for %d hours playtime.", client, target, length); + } + else if (!length) + { + CPrintToChatAll("\x07%s[entWatch] \x07%s%N\x07%s restricted \x07%s%N\x07%s permanently.", "E01B5D", "EDEDED", client, "F16767", "EDEDED", target, "F16767"); + LogAction(client, target, "%L restricted %L permanently.", client, target); + } + } + } + else + { + if (ClientRestrict(client, target, -1)) + { + CPrintToChatAll("\x07%s[entWatch] \x07%s%N\x07%s restricted \x07%s%N\x07%s temporarily.", "E01B5D", "EDEDED", client, "F16767", "EDEDED", target, "F16767"); + LogAction(client, target, "%L restricted %L temporarily.", client, target); + } + } + + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_ClientUnrestrict(int client, int args) +{ + if (!GetCmdArgs()) + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%sUsage: sm_eunban <#userid/name>", "E01B5D", "F16767"); + return Plugin_Handled; + } + + char sArguments[1][32]; + GetCmdArg(1, sArguments[0], sizeof(sArguments[])); + + int target; + if ((target = FindTarget(client, sArguments[0], true)) == -1) + return Plugin_Handled; + + if (ClientUnrestrict(client, target)) + { + CPrintToChatAll("\x07%s[entWatch] \x07%s%N\x07%s unrestricted \x07%s%N\x07%s.", "E01B5D", "EDEDED", client, "F16767", "EDEDED", target, "F16767"); + LogAction(client, target, "%L unrestricted %L.", client, target); + } + + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_DisplayRestrictions(int client, int args) +{ + char aBuf[1024]; + char aBuf2[MAX_NAME_LENGTH]; + + for (int i = 1; i <= MaxClients; i++) + { + if (IsClientInGame(i) && !IsFakeClient(i)) + { + if (ClientRestricted(i)) + { + GetClientName(i, aBuf2, sizeof(aBuf2)); + StrCat(aBuf, sizeof(aBuf), aBuf2); + StrCat(aBuf, sizeof(aBuf), ", "); + } + } + } + + if (strlen(aBuf)) + { + aBuf[strlen(aBuf) - 2] = 0; + CReplyToCommand(client, "\x07%s[entWatch] \x07%sCurrently restricted clients: \x07%s%s", "E01B5D", "F16767", "EDEDED", aBuf); + } + else + CReplyToCommand(client, "\x07%s[entWatch] \x07%sCurrently restricted clients: \x07%snone", "E01B5D", "F16767", "EDEDED"); + + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action Command_DisplayStatus(int client, int args) +{ + if (CheckCommandAccess(client, "", ADMFLAG_BAN) && GetCmdArgs()) + { + char sArguments[1][32]; + GetCmdArg(1, sArguments[0], sizeof(sArguments[])); + + int target; + if ((target = FindTarget(client, sArguments[0], true)) == -1) + return Plugin_Handled; + + if (!AreClientCookiesCached(target)) + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%s%N\x07%s their cookies are still loading.", "E01B5D", "EDEDED", target, "F16767"); + return Plugin_Handled; + } + else if (g_bRestrictedTemp[target]) + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%s%N\x07%s is currently temporarily restricted.", "E01B5D", "EDEDED", target, "F16767"); + return Plugin_Handled; + } + else if (g_iRestrictIssued[target] && g_iRestrictExpire[target] == 0) + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%s%N\x07%s is currently permanently restricted.", "E01B5D", "EDEDED", target, "F16767"); + return Plugin_Handled; + } + else if (g_iRestrictIssued[target] && g_iRestrictExpire[target] >= g_iClientHours[target]) + { + char sTimeRemaining[64]; + int iTimeRemaining = g_iRestrictExpire[target] - g_iClientHours[target]; //its just hours now + Format(sTimeRemaining, sizeof(sTimeRemaining), "%d Hours Playtime", iTimeRemaining); + + CReplyToCommand(client, "\x07%s[entWatch] \x07%s%N\x07%s is currently restricted for another \x07%s%s\x07%s.", "E01B5D", "EDEDED", target, "F16767", "EDEDED", sTimeRemaining, "F16767"); + return Plugin_Handled; + } + else + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%s%N\x07%s is currently not restricted.", "E01B5D", "EDEDED", target, "F16767"); + return Plugin_Handled; + } + } + else + { + if (!AreClientCookiesCached(client)) + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%sYour cookies are still loading.", "E01B5D", "F16767"); + return Plugin_Handled; + } + else if (g_bRestrictedTemp[client]) + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%sYou are currently temporarily restricted.", "E01B5D", "F16767"); + return Plugin_Handled; + } + else if (g_iRestrictIssued[client] && g_iRestrictExpire[client] == 0) + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%sYou are currently permanently restricted.", "E01B5D", "F16767"); + return Plugin_Handled; + } + else if (g_iRestrictIssued[client] && g_iRestrictExpire[client] >= g_iClientHours[client]) + { + char sTimeRemaining[64]; + int iTimeRemaining = g_iRestrictExpire[client] - g_iClientHours[client]; //its just hours now + Format(sTimeRemaining, sizeof(sTimeRemaining), "%d Hours Playtime", iTimeRemaining); + + CReplyToCommand(client, "\x07%s[entWatch] \x07%sYou are currently restricted for another \x07%s%s\x07%s.", "E01B5D", "F16767", "EDEDED", sTimeRemaining, "F16767"); + return Plugin_Handled; + } + else + { + CReplyToCommand(client, "\x07%s[entWatch] \x07%sYou are currently not restricted.", "E01B5D", "F16767"); + return Plugin_Handled; + } + } +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action EW_OnClientItemCanPickup(int client, int index) +{ + return ClientRestricted(client)?Plugin_Handled:Plugin_Continue; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action EW_OnClientItemCanActivate(int client, int index) +{ + return ClientRestricted(client)?Plugin_Handled:Plugin_Continue; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock bool ClientRestrict(int client, int target, int length) +{ + if (!Client_IsValid(client) || !Client_IsValid(target) || !AreClientCookiesCached(target) || ClientRestricted(target)) + { + if (Client_IsValid(client) && Client_IsValid(target) && ClientRestricted(target)) + { + CPrintToChat(client, "\x07%s[entWatch] \x07%s The player \x07%s%N\x07%s is already restricted.", "E01B5D", "EDEDED", "EDEDED", target, "F16767"); + } + return false; + } + + if (length == -1) + { + g_bRestrictedTemp[target] = true; + } + else if (length == 0) + { + g_bRestrictedTemp[target] = false; + g_iRestrictIssued[target] = g_iClientHours[target]; + g_iRestrictExpire[target] = 0; + g_iRestrictLength[target] = 0; + + SetClientCookieInt(target, g_hCookie_RestrictIssued, GetTime()); + SetClientCookieInt(target, g_hCookie_RestrictExpire, 0); + SetClientCookieInt(target, g_hCookie_RestrictLength, 0); + } + else + { + if (length < 60) + { + CPrintToChat(client, "\x07%s[entWatch] \x07%sEban length is now rounded in hours so minimum value has to be 60.", "E01B5D", "EDEDED"); + return false; + } + //2026 edit. we now use ingame play time of the client instead of real time. + length /= 60; + g_bRestrictedTemp[target] = false; + g_iRestrictIssued[target] = g_iClientHours[target]; + g_iRestrictExpire[target] = g_iClientHours[target] + length; + g_iRestrictLength[target] = length; + + SetClientCookieInt(target, g_hCookie_RestrictIssued, g_iRestrictIssued[target]); + SetClientCookieInt(target, g_hCookie_RestrictExpire, g_iRestrictExpire[target]); + SetClientCookieInt(target, g_hCookie_RestrictLength, length); + } + + Call_StartForward(g_hFwd_OnClientRestricted); + Call_PushCell(client); + Call_PushCell(target); + Call_PushCell(length); + Call_Finish(); + + return true; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock bool ClientUnrestrict(int client, int target) +{ + if (!Client_IsValid(client) || !Client_IsValid(target) || !AreClientCookiesCached(target) || !ClientRestricted(target)) + return false; + + g_bRestrictedTemp[target] = false; + g_iRestrictIssued[target] = 0; + g_iRestrictExpire[target] = 0; + g_iRestrictLength[target] = 0; + + SetClientCookieInt(target, g_hCookie_RestrictIssued, 0); + SetClientCookieInt(target, g_hCookie_RestrictExpire, 0); + SetClientCookieInt(target, g_hCookie_RestrictLength, 0); + + Call_StartForward(g_hFwd_OnClientUnrestricted); + Call_PushCell(client); + Call_PushCell(target); + Call_Finish(); + + return true; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock bool ClientRestricted(int client) +{ + if (!Client_IsValid(client)) + return false; + + //Block them when loading cookies.. + if (!AreClientCookiesCached(client)) + return true; + + //Temporary restriction. + if (g_bRestrictedTemp[client]) + return true; + + //Permanent restriction. + if (g_iRestrictIssued[client] && g_iRestrictExpire[client] == 0) + return true; + + //Normal restriction. + if (g_iRestrictIssued[client] && g_iRestrictExpire[client] >= g_iClientHours[client]) + return true; + + //hour requirement for picking up items + if (g_iClientHours[client] <= g_cvarHourRequirement.IntValue) + { + if (!g_bDontSpamMsg[client]) + { + CPrintToChat(client, "\x07%s[entWatch] \x07%s You have \x07%s%i\x07%s hours playtime and need more than %i hours for picking up items.", "E01B5D", "EDEDED", "EDEDED", g_iClientHours[client], "EDEDED", g_cvarHourRequirement.IntValue); + g_bDontSpamMsg[client] = true; + CreateTimer(1.0, allow_message_again, GetClientSerial(client)); + } + return true; + } + + return false; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int Native_ClientRestrict(Handle hPlugin, int numParams) +{ + return ClientRestrict(GetNativeCell(1), GetNativeCell(2), GetNativeCell(3)); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int Native_ClientUnrestrict(Handle hPlugin, int numParams) +{ + return ClientUnrestrict(GetNativeCell(1), GetNativeCell(2)); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int Native_ClientRestricted(Handle hPlugin, int numParams) +{ + return ClientRestricted(GetNativeCell(1)); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock void SetClientCookieInt(int client, Handle hCookie, int value) +{ + char sValue[32]; + IntToString(value, sValue, sizeof(sValue)); + + SetClientCookie(client, hCookie, sValue); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +stock int GetClientCookieInt(int client, Handle hCookie) +{ + char sValue[32]; + GetClientCookie(client, hCookie, sValue, sizeof(sValue)); + + return StringToInt(sValue); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: 2026 getting the ingame play time of the players. called with OnClientPostAdminCheck() forward and timer every 10 minutes +//---------------------------------------------------------------------------------------------------- +public void GetPlayerHoursServer(int client, int hours) +{ + g_iClientHours[client] = hours; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Action allow_message_again(Handle hTimer, int Serial) +{ + int client; + if ((client = GetClientFromSerial(Serial)) == 0) + { + return Plugin_Handled; + } + if (Client_IsValid(client)) + { + g_bDontSpamMsg[client] = false; + } + return Plugin_Handled; +}