diff --git a/plugins/include/mapchooser.inc b/plugins/include/mapchooser.inc index c7b017e4..22468b7b 100644 --- a/plugins/include/mapchooser.inc +++ b/plugins/include/mapchooser.inc @@ -73,7 +73,7 @@ native bool:EndOfMapVoteEnabled(); * Called when mapchooser removes a nomination from its list. * Nominations cleared on map start will not trigger this forward */ -forward OnNominationRemoved(String:map[], owner); +forward OnNominationRemoved(const String:map[], owner); public SharedPlugin:__pl_mapchooser = diff --git a/plugins/mapchooser.sp b/plugins/mapchooser.sp index 743e557c..9f7b72f0 100644 --- a/plugins/mapchooser.sp +++ b/plugins/mapchooser.sp @@ -884,7 +884,8 @@ NominateResult:InternalNominateMap(String:map[], bool:force, owner) new index; - if ((index = FindValueInArray(g_NominateOwners, owner)) != -1) + /* Look to replace an existing nomination by this client - Nominations made with owner = 0 aren't replaced */ + if (owner && ((index = FindValueInArray(g_NominateOwners, owner)) != -1)) { new String:oldmap[33]; GetArrayString(g_NominateList, index, oldmap, sizeof(oldmap)); @@ -893,7 +894,6 @@ NominateResult:InternalNominateMap(String:map[], bool:force, owner) Call_PushCell(owner); Call_Finish(); - SetArrayString(g_NominateList, index, map); return Nominate_Replaced; } diff --git a/plugins/nominations.sp b/plugins/nominations.sp index dd280e85..3d2a59a7 100644 --- a/plugins/nominations.sp +++ b/plugins/nominations.sp @@ -52,6 +52,14 @@ new Handle:g_MapList = INVALID_HANDLE; new Handle:g_MapMenu = INVALID_HANDLE; new g_mapFileSerial = -1; +#define MAPSTATUS_ENABLED (1<<0) +#define MAPSTATUS_DISABLED (1<<1) +#define MAPSTATUS_EXCLUDE_CURRENT (1<<2) +#define MAPSTATUS_EXCLUDE_PREVIOUS (1<<3) +#define MAPSTATUS_EXCLUDE_NOMINATED (1<<4) + +new Handle:g_mapTrie; + public OnPluginStart() { LoadTranslations("common.phrases"); @@ -69,6 +77,8 @@ public OnPluginStart() RegConsoleCmd("sm_nominate", Command_Nominate); RegAdminCmd("sm_nominate_addmap", Command_Addmap, ADMFLAG_CHANGEMAP, "sm_nominate_addmap - Forces a map to be on the next mapvote."); + + g_mapTrie = CreateTrie(); } public OnConfigsExecuted() @@ -88,9 +98,23 @@ public OnConfigsExecuted() BuildMapMenu(); } -public OnNominationRemoved(String:map[], owner) +public OnNominationRemoved(/* const */String:map[], owner) { - AddMenuItem(g_MapMenu, map, map); + new status; + + /* Is the map in our list? */ + if (!GetTrieValue(g_mapTrie, map, status)) + { + return; + } + + /* Was the map disabled due to being nominated */ + if ((status & MAPSTATUS_EXCLUDE_NOMINATED) != MAPSTATUS_EXCLUDE_NOMINATED) + { + return; + } + + SetTrieValue(g_mapTrie, map, MAPSTATUS_ENABLED); } public Action:Command_Addmap(client, args) @@ -104,10 +128,12 @@ public Action:Command_Addmap(client, args) decl String:mapname[64]; GetCmdArg(1, mapname, sizeof(mapname)); - if (FindStringInArray(g_MapList, mapname) == -1) + + new status; + if (!GetTrieValue(g_mapTrie, mapname, status)) { ReplyToCommand(client, "%t", "Map was not found", mapname); - return Plugin_Handled; + return Plugin_Handled; } new NominateResult:result = NominateMap(mapname, true, 0); @@ -120,16 +146,9 @@ public Action:Command_Addmap(client, args) return Plugin_Handled; } - decl String:item[64]; - for (new i = 0; i < GetMenuItemCount(g_MapMenu); i++) - { - GetMenuItem(g_MapMenu, i, item, sizeof(item)); - if (strcmp(item, mapname) == 0) - { - RemoveMenuItem(g_MapMenu, i); - break; - } - } + + SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); + ReplyToCommand(client, "%t", "Map Inserted", mapname); LogAction(client, -1, "\"%L\" inserted map \"%s\".", client, mapname); @@ -185,41 +204,58 @@ public Action:Command_Nominate(client, args) decl String:mapname[64]; GetCmdArg(1, mapname, sizeof(mapname)); - decl String:item[64]; - for (new i = 0; i < GetMenuItemCount(g_MapMenu); i++) + new status; + if (!GetTrieValue(g_mapTrie, mapname, status)) { - GetMenuItem(g_MapMenu, i, item, sizeof(item)); - if (strcmp(item, mapname) == 0) - { - new NominateResult:result = NominateMap(mapname, false, client); - - if (result > Nominate_Replaced) - { - if (result == Nominate_AlreadyInVote) - { - ReplyToCommand(client, "%t", "Map Already In Vote", mapname); - } - else - { - ReplyToCommand(client, "[SM] %t", "Map Already Nominated"); - } - - return Plugin_Handled; - } - - RemoveMenuItem(g_MapMenu, i); - - decl String:name[64]; - GetClientName(client, name, sizeof(name)); - - PrintToChatAll("[SM] %t", "Map Nominated", name, mapname); - - return Plugin_Continue; - } + ReplyToCommand(client, "%t", "Map was not found", mapname); + return Plugin_Handled; } - ReplyToCommand(client, "%t", "Map was not found", mapname); - return Plugin_Handled; + if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) + { + if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT) + { + ReplyToCommand(client, "[SM] %t", "Can't Nominate Current Map"); + } + + if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS) + { + ReplyToCommand(client, "[SM] %t", "Map in Exclude List"); + } + + if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED) + { + ReplyToCommand(client, "[SM] %t", "Map Already Nominated"); + } + + return Plugin_Handled; + } + + new NominateResult:result = NominateMap(mapname, false, client); + + if (result > Nominate_Replaced) + { + if (result == Nominate_AlreadyInVote) + { + ReplyToCommand(client, "%t", "Map Already In Vote", mapname); + } + else + { + ReplyToCommand(client, "[SM] %t", "Map Already Nominated"); + } + + return Plugin_Handled; + } + + /* Map was nominated! - Disable the menu item and update the trie */ + + SetTrieValue(g_mapTrie, mapname, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); + + decl String:name[64]; + GetClientName(client, name, sizeof(name)); + PrintToChatAll("[SM] %t", "Map Nominated", name, mapname); + + return Plugin_Continue; } AttemptNominate(client) @@ -238,7 +274,9 @@ BuildMapMenu() g_MapMenu = INVALID_HANDLE; } - g_MapMenu = CreateMenu(Handler_MapSelectMenu); + ClearTrie(g_mapTrie); + + g_MapMenu = CreateMenu(Handler_MapSelectMenu, MENU_ACTIONS_DEFAULT|MenuAction_DrawItem|MenuAction_DisplayItem); decl String:map[64]; @@ -256,27 +294,32 @@ BuildMapMenu() GetCurrentMap(currentMap, sizeof(currentMap)); } + for (new i = 0; i < GetArraySize(g_MapList); i++) { - GetArrayString(g_MapList, i, map, sizeof(map)); + new status = MAPSTATUS_ENABLED; - if (GetConVarBool(g_Cvar_ExcludeOld)) - { - if (FindStringInArray(excludeMaps, map) != -1) - { - continue; - } - } + GetArrayString(g_MapList, i, map, sizeof(map)); if (GetConVarBool(g_Cvar_ExcludeCurrent)) { if (StrEqual(map, currentMap)) { - continue; + status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_CURRENT; + } + } + + /* Dont bother with this check if the current map check passed */ + if (GetConVarBool(g_Cvar_ExcludeOld) && status == MAPSTATUS_ENABLED) + { + if (FindStringInArray(excludeMaps, map) != -1) + { + status = MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_PREVIOUS; } } AddMenuItem(g_MapMenu, map, map); + SetTrieValue(g_mapTrie, map, status); } SetMenuExitButton(g_MapMenu, true); @@ -289,35 +332,96 @@ public Handler_MapSelectMenu(Handle:menu, MenuAction:action, param1, param2) case MenuAction_Select: { decl String:map[64], String:name[64]; - GetMenuItem(menu, param2, map, sizeof(map)); - + GetMenuItem(menu, param2, map, sizeof(map)); GetClientName(param1, name, 64); - new NominateResult:result = NominateMap(map, false, param1); /* Don't need to check for InvalidMap because the menu did that already */ if (result == Nominate_AlreadyInVote) { PrintToChat(param1, "[SM] %t", "Map Already Nominated"); - return; + return 0; } else if (result == Nominate_VoteFull) { PrintToChat(param1, "[SM] %t", "Max Nominations"); - return; + return 0; } - - RemoveMenuItem(menu, param2); + SetTrieValue(g_mapTrie, map, MAPSTATUS_DISABLED|MAPSTATUS_EXCLUDE_NOMINATED); + if (result == Nominate_Replaced) { PrintToChatAll("[SM] %t", "Map Nomination Changed", name, map); - return; + return 0; } PrintToChatAll("[SM] %t", "Map Nominated", name, map); } + + case MenuAction_DrawItem: + { + decl String:map[64]; + GetMenuItem(menu, param2, map, sizeof(map)); + + new status; + + if (!GetTrieValue(g_mapTrie, map, status)) + { + LogError("Menu selection of item not in trie. Major logic problem somewhere."); + return ITEMDRAW_DEFAULT; + } + + if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) + { + return ITEMDRAW_DISABLED; + } + + return ITEMDRAW_DEFAULT; + + } + + case MenuAction_DisplayItem: + { + decl String:map[64]; + GetMenuItem(menu, param2, map, sizeof(map)); + + new status; + + if (!GetTrieValue(g_mapTrie, map, status)) + { + LogError("Menu selection of item not in trie. Major logic problem somewhere."); + return 0; + } + + decl String:display[100]; + + if ((status & MAPSTATUS_DISABLED) == MAPSTATUS_DISABLED) + { + if ((status & MAPSTATUS_EXCLUDE_CURRENT) == MAPSTATUS_EXCLUDE_CURRENT) + { + Format(display, sizeof(display), "%s (%T)", map, "Current Map", param1); + return RedrawMenuItem(display); + } + + if ((status & MAPSTATUS_EXCLUDE_PREVIOUS) == MAPSTATUS_EXCLUDE_PREVIOUS) + { + Format(display, sizeof(display), "%s (%T)", map, "Recently Played", param1); + return RedrawMenuItem(display); + } + + if ((status & MAPSTATUS_EXCLUDE_NOMINATED) == MAPSTATUS_EXCLUDE_NOMINATED) + { + Format(display, sizeof(display), "%s (%T)", map, "Nominated", param1); + return RedrawMenuItem(display); + } + } + + return 0; + } } + + return 0; } \ No newline at end of file diff --git a/translations/nominations.phrases.txt b/translations/nominations.phrases.txt index 52ee3d52..cdefb1f0 100644 --- a/translations/nominations.phrases.txt +++ b/translations/nominations.phrases.txt @@ -45,4 +45,29 @@ { "en" "Nominate Map:" } + + "Can't Nominate Current Map" + { + "en" "The map you chose is the current map and cannot be nominated" + } + + "Map in Exclude List" + { + "en" "The map you chose was recently played and cannot be nominated" + } + + "Current Map" + { + "en" "Current Map" + } + + "Recently Played" + { + "en" "Recently Played" + } + + "Nominated" + { + "en" "Nominated" + } } \ No newline at end of file