diff --git a/addons/sourcemod/configs/shavit-styles.cfg b/addons/sourcemod/configs/shavit-styles.cfg index bbe29d6c..e5d09de6 100644 --- a/addons/sourcemod/configs/shavit-styles.cfg +++ b/addons/sourcemod/configs/shavit-styles.cfg @@ -59,6 +59,7 @@ // Special flags "special" "0" // For third-party modules. The core plugins will not need this setting. "specialstring" "" // For third-party modules. The core plugins will not need this setting. + "permission" "" // Permission required. Syntax: "flag;override". For example "p;style_tas" to require the 'p' flag or the "style_tas" override. } "1" diff --git a/addons/sourcemod/scripting/include/shavit.inc b/addons/sourcemod/scripting/include/shavit.inc index 0c483693..02744562 100644 --- a/addons/sourcemod/scripting/include/shavit.inc +++ b/addons/sourcemod/scripting/include/shavit.inc @@ -81,6 +81,7 @@ enum sChangeCommand, sClanTag, sSpecialString, + sStylePermission, STYLESTRINGS_SIZE }; @@ -1097,6 +1098,13 @@ native int Shavit_GetMapTier(const char[] map); */ native StringMap Shavit_GetMapTiers(); +/** + * Retrieves style access for a player. + * + * @return Boolean value. + */ +native bool Shavit_HasStyleAccess(int client, int style); + /** * Use this native when printing anything in chat if it's related to the timer. * This native will auto-assign colors and a chat prefix. @@ -1191,6 +1199,7 @@ public void __pl_shavit_SetNTVOptional() MarkNativeAsOptional("Shavit_GetWRName"); MarkNativeAsOptional("Shavit_GetWRRecordID"); MarkNativeAsOptional("Shavit_GetWRTime"); + MarkNativeAsOptional("Shavit_HasStyleAccess"); MarkNativeAsOptional("Shavit_InsideZone"); MarkNativeAsOptional("Shavit_IsClientCreatingZone"); MarkNativeAsOptional("Shavit_IsKZMap"); diff --git a/addons/sourcemod/scripting/shavit-core.sp b/addons/sourcemod/scripting/shavit-core.sp index cf2c4c84..aa542088 100644 --- a/addons/sourcemod/scripting/shavit-core.sp +++ b/addons/sourcemod/scripting/shavit-core.sp @@ -134,6 +134,10 @@ bool gB_StopChatSound = false; bool gB_HookedJump = false; char gS_LogPath[PLATFORM_MAX_PATH]; +// flags +int gI_StyleFlag[STYLE_LIMIT]; +char gS_StyleOverride[STYLE_LIMIT][32]; + // kz support bool gB_KZMap = false; @@ -164,6 +168,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max CreateNative("Shavit_GetSync", Native_GetSync); CreateNative("Shavit_GetTimer", Native_GetTimer); CreateNative("Shavit_GetTimerStatus", Native_GetTimerStatus); + CreateNative("Shavit_HasStyleAccess", Native_HasStyleAccess); CreateNative("Shavit_IsKZMap", Native_IsKZMap); CreateNative("Shavit_IsPracticeMode", Native_IsPracticeMode); CreateNative("Shavit_LoadSnapshot", Native_LoadSnapshot); @@ -660,7 +665,7 @@ public Action Command_Style(int client, int args) } } - menu.AddItem(sInfo, sDisplay, (gI_Style[client] == i)? ITEMDRAW_DISABLED:ITEMDRAW_DEFAULT); + menu.AddItem(sInfo, sDisplay, (gI_Style[client] == i || !Shavit_HasStyleAccess(client, i))? ITEMDRAW_DISABLED:ITEMDRAW_DEFAULT); } // should NEVER happen @@ -729,6 +734,16 @@ void ChangeClientStyle(int client, int style, bool manual) return; } + if(!Shavit_HasStyleAccess(client, style)) + { + if(manual) + { + Shavit_PrintToChat(client, "%T", "StyleNoAccess", client, gS_ChatStrings[sMessageWarning], gS_ChatStrings[sMessageText]); + } + + return; + } + if(manual) { Shavit_PrintToChat(client, "%T", "StyleSelection", client, gS_ChatStrings[sMessageStyle], gS_StyleStrings[style][sStyleName], gS_ChatStrings[sMessageText]); @@ -921,6 +936,13 @@ public int Native_GetTimerStatus(Handle handler, int numParams) return GetTimerStatus(GetNativeCell(1)); } +public int Native_HasStyleAccess(Handle handler, int numParams) +{ + int style = GetNativeCell(2); + + return CheckCommandAccess(GetNativeCell(1), (strlen(gS_StyleOverride[style]) > 0)? gS_StyleOverride[style]:"", gI_StyleFlag[style]); +} + public int Native_IsKZMap(Handle handler, int numParams) { return view_as(gB_KZMap); @@ -1149,7 +1171,7 @@ public int Native_LoadSnapshot(Handle handler, int numParams) gI_Track[client] = view_as(snapshot[iTimerTrack]); - if(gI_Style[client] != snapshot[bsStyle]) + if(gI_Style[client] != snapshot[bsStyle] && Shavit_HasStyleAccess(client, snapshot[bsStyle])) { CallOnStyleChanged(client, gI_Style[client], snapshot[bsStyle], false); } @@ -1321,7 +1343,11 @@ public void OnClientCookiesCached(int client) } int newstyle = (style >= 0 && style < gI_Styles)? style:gI_DefaultStyle; - CallOnStyleChanged(client, gI_Style[client], newstyle, false); + + if(Shavit_HasStyleAccess(client, newstyle)) + { + CallOnStyleChanged(client, gI_Style[client], newstyle, false); + } } public void OnClientPutInServer(int client) @@ -1345,6 +1371,7 @@ public void OnClientPutInServer(int client) OnClientCookiesCached(client); } + // not adding style permission check here for obvious reasons else { CallOnStyleChanged(client, 0, gI_DefaultStyle, false); @@ -1445,6 +1472,7 @@ bool LoadStyles() kv.GetString("command", gS_StyleStrings[i][sChangeCommand], 128, ""); kv.GetString("clantag", gS_StyleStrings[i][sClanTag], 128, ""); kv.GetString("specialstring", gS_StyleStrings[i][sSpecialString], 128, ""); + kv.GetString("permission", gS_StyleStrings[i][sStylePermission], 128, ""); gA_StyleSettings[i][bAutobhop] = view_as(kv.GetNum("autobhop", 1)); gA_StyleSettings[i][bEasybhop] = view_as(kv.GetNum("easybhop", 1)); @@ -1500,6 +1528,21 @@ bool LoadStyles() } } + if(StrContains(gS_StyleStrings[i][sStylePermission], ";") != -1) + { + char[][] sText = new char[2][32]; + int iCount = ExplodeString(gS_StyleStrings[i][sStylePermission], ";", sText, 2, 32); + + AdminFlag flag = Admin_Reservation; + + if(FindFlagByChar(sText[0][0], flag)) + { + gI_StyleFlag[i] = FlagToBit(flag); + } + + strcopy(gS_StyleOverride[i], 32, (iCount >= 2)? sText[1]:""); + } + i++; } diff --git a/addons/sourcemod/translations/shavit-core.phrases.txt b/addons/sourcemod/translations/shavit-core.phrases.txt index 432bdaa4..d5ada2b1 100644 --- a/addons/sourcemod/translations/shavit-core.phrases.txt +++ b/addons/sourcemod/translations/shavit-core.phrases.txt @@ -21,6 +21,11 @@ "#format" "{1:s},{2:s},{3:s}" "en" "The command ({1}{2}{3}) is disabled." } + "StyleNoAccess" + { + "#format" "{1:s},{2:s}" + "en" "You lack the {1}permissions{2} for this style." + } // ---------- Errors ---------- // "VerificationFailed" {