From 582703c27162322cc159ba1854e16a538489046d Mon Sep 17 00:00:00 2001 From: jenz Date: Sat, 23 Sep 2023 03:03:02 +0200 Subject: [PATCH] updated translation file and mapvoting to allow weighted mapvotes --- .../scripting/mapchooser_extended_avg.sp | 338 +++++++++++++----- .../mapchooser_extended.phrases.txt | 15 +- 2 files changed, 266 insertions(+), 87 deletions(-) diff --git a/mapchooser_extended/scripting/mapchooser_extended_avg.sp b/mapchooser_extended/scripting/mapchooser_extended_avg.sp index 9b7a88f..5be318c 100755 --- a/mapchooser_extended/scripting/mapchooser_extended_avg.sp +++ b/mapchooser_extended/scripting/mapchooser_extended_avg.sp @@ -141,6 +141,9 @@ int g_mapFileSerial = -1; int g_NominateCount = 0; int g_NominateReservedCount = 0; +int g_iInterval; +float player_mapvote_worth[MAXPLAYERS + 1]; +char player_mapvote[MAXPLAYERS + 1][PLATFORM_MAX_PATH]; MapChange g_ChangeTime; //check if autismbot @@ -451,48 +454,50 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max public void OnMapStart() { - static char folder[64]; - GetGameFolderName(folder, sizeof(folder)); + ServerCommand("sm_cvar sm_vote_progress_hintbox 1"); //yeah its cheesy but does the job. + g_iInterval = 0; + static char folder[64]; + GetGameFolderName(folder, sizeof(folder)); - g_RoundCounting = RoundCounting_Standard; - g_ObjectiveEnt = -1; + g_RoundCounting = RoundCounting_Standard; + g_ObjectiveEnt = -1; - if(strcmp(folder, "tf") == 0 && GameRules_GetProp("m_bPlayingMannVsMachine")) - { - g_RoundCounting = RoundCounting_MvM; - g_ObjectiveEnt = EntIndexToEntRef(FindEntityByClassname(-1, "tf_objective_resource")); - } - else if(strcmp(folder, "csgo") == 0 && GetConVarInt(g_Cvar_GameType) == GameType_GunGame && - GetConVarInt(g_Cvar_GameMode) == GunGameMode_ArmsRace) - { - g_RoundCounting = RoundCounting_ArmsRace; - } + if(strcmp(folder, "tf") == 0 && GameRules_GetProp("m_bPlayingMannVsMachine")) + { + g_RoundCounting = RoundCounting_MvM; + g_ObjectiveEnt = EntIndexToEntRef(FindEntityByClassname(-1, "tf_objective_resource")); + } + else if(strcmp(folder, "csgo") == 0 && GetConVarInt(g_Cvar_GameType) == GameType_GunGame && + GetConVarInt(g_Cvar_GameMode) == GunGameMode_ArmsRace) + { + g_RoundCounting = RoundCounting_ArmsRace; + } - if(g_Config) - delete g_Config; + if(g_Config) + delete g_Config; - char sConfigFile[PLATFORM_MAX_PATH]; - BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/mapchooser_extended.cfg"); - if(!FileExists(sConfigFile)) - { - LogMessage("Could not find config: \"%s\"", sConfigFile); - return; - } - LogMessage("Found config: \"%s\"", sConfigFile); + char sConfigFile[PLATFORM_MAX_PATH]; + BuildPath(Path_SM, sConfigFile, sizeof(sConfigFile), "configs/mapchooser_extended.cfg"); + if(!FileExists(sConfigFile)) + { + LogMessage("Could not find config: \"%s\"", sConfigFile); + return; + } + LogMessage("Found config: \"%s\"", sConfigFile); - g_Config = new KeyValues("mapchooser_extended"); - if(!g_Config.ImportFromFile(sConfigFile)) - { - delete g_Config; - LogMessage("ImportFromFile() failed!"); - return; - } - g_Config.Rewind(); + g_Config = new KeyValues("mapchooser_extended"); + if(!g_Config.ImportFromFile(sConfigFile)) + { + delete g_Config; + LogMessage("ImportFromFile() failed!"); + return; + } + g_Config.Rewind(); - if(InternalAreRestrictionsActive()) - g_SaveCDOnMapEnd = true; - else - g_SaveCDOnMapEnd = false; + if(InternalAreRestrictionsActive()) + g_SaveCDOnMapEnd = true; + else + g_SaveCDOnMapEnd = false; } public void OnConfigsExecuted() @@ -544,6 +549,8 @@ public void OnConfigsExecuted() public void OnMapEnd() { + ServerCommand("sm_cvar sm_vote_progress_hintbox 1"); //yeah its cheesy but does the job. + g_iInterval = 0; g_HasVoteStarted = false; g_WaitingForVote = false; g_ChangeMapAtRoundEnd = false; @@ -614,6 +621,8 @@ public void OnClientDisconnect_Post(int client) public void OnClientDisconnect(int client) { is_bot_player[client] = false; + player_mapvote_worth[client] = 0.0; + Format(player_mapvote[client], 128, ""); int index = FindValueInArray(g_NominateOwners, client); if(index == -1) @@ -999,11 +1008,10 @@ public Handle get_most_nominated_maps() { char map_iteration[PLATFORM_MAX_PATH]; GetArrayString(g_NominateList[i], j, map_iteration, PLATFORM_MAX_PATH); - //PrintToChatAll("map_iteration: %s", map_iteration); int nominate_count_for_particular_map = 0; sm.GetValue(map_iteration, nominate_count_for_particular_map); nominate_count_for_particular_map++; - //if i is 0 its admin nominated map that most come into the vote + //if i is 0 its admin nominated map that must come into the vote if(!i) { nominate_count_for_particular_map = 999; @@ -1023,14 +1031,12 @@ public Handle get_most_nominated_maps() int size = keys.KeyBufferSize(j); char[] buffer = new char[size]; keys.GetKey(j, buffer, size); - //PrintToChatAll("buffer: %s", buffer); if (StrEqual(buffer, "nominated_maps")) { continue; } int value = 0; sm.GetValue(buffer, value); - //PrintToChatAll("value: %i", value); //first selection has most nominates, second selection second most etc etc if (value >= max_count) @@ -1084,7 +1090,6 @@ public Handle get_most_nominated_maps() continue; } PushArrayString(most_nominated_maps, picked_map); - //PrintToChatAll("picked_map: %s", picked_map); } delete sm; @@ -1140,6 +1145,9 @@ void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE) g_ChangeTime = when; + ServerCommand("sm_cvar sm_vote_progress_hintbox 0"); //yeah its cheesy but does the job. + g_iInterval = GetConVarInt(g_Cvar_VoteDuration); + CreateTimer(1.0, Timer_Countdown, _, TIMER_REPEAT); g_HasVoteStarted = true; @@ -1352,7 +1360,22 @@ void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE) if(GetConVarInt(g_Cvar_ShufflePerClient)) MenuShufflePerClient(g_VoteMenu, MenuRandomShuffleStart, GetMenuItemCount(g_VoteMenu) - MenuRandomShuffleStop); - VoteMenuToAll(g_VoteMenu, voteDuration); + //VoteMenuToAll(g_VoteMenu, voteDuration); + //2023 excluding nosteamers and autismbots. + + int clients[MAXPLAYERS + 1]; + int count = 0; + for (int i = 0; i <= MaxClients; i++) + { + player_mapvote_worth[i] = 0.0; + Format(player_mapvote[i], 128, ""); + if (IsValidClient(i) && PM_IsPlayerSteam(i) && !is_bot_player[i]) + { + clients[count] = i; + count++; + } + } + VoteMenu(g_VoteMenu, clients, sizeof(clients), voteDuration); /* Call OnMapVoteStarted() Forward */ Call_StartForward(g_MapVoteStartForward); // Deprecated @@ -1365,16 +1388,90 @@ void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE) CPrintToChatAll("[MCE] %t", "Nextmap Voting Started"); } -public void Handler_VoteFinishedGeneric(Handle menu, - int num_votes, - int num_clients, - const int[][] client_info, - int num_items, - const int[][] item_info) +public Action Timer_Countdown(Handle timer) { - static char map[PLATFORM_MAX_PATH]; - GetMapItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map, PLATFORM_MAX_PATH); + if (g_iInterval <= 0) + return Plugin_Stop; + float most_voted[3]; + char most_voted_map[3][PLATFORM_MAX_PATH]; + + for (int j = 0; j < 3; j++) + { + float max_count = 0.0; + StringMap sm = new StringMap(); + char picked_map[PLATFORM_MAX_PATH]; + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClient(i) && !StrEqual(player_mapvote[i], "")) + { + if (StrEqual(player_mapvote[i], most_voted_map[0]) || StrEqual(player_mapvote[i], most_voted_map[1]) || + StrEqual(player_mapvote[i], most_voted_map[2])) + { + continue; + } + float value = 0.0; + sm.GetValue(player_mapvote[i], value); + value += player_mapvote_worth[i]; + sm.SetValue(player_mapvote[i], value, true); + if (value >= max_count) + { + max_count = value; + strcopy(picked_map, sizeof(picked_map), player_mapvote[i]); + } + } + } + most_voted[j] = max_count; + Format(most_voted_map[j], PLATFORM_MAX_PATH, picked_map); + delete sm; + } + + float total_votes = 0.0; + float voted_so_far = 0.0; + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClient(i)) + { + total_votes += player_mapvote_worth[i]; + if (!StrEqual(player_mapvote[i], "")) + { + voted_so_far += player_mapvote_worth[i]; + } + } + } + //why on earth is %%%s needed for formatting it to show a % lmao. just %s, "%" or %% on their own dont work. + if (strlen(most_voted_map[2]) > 0) + { + //displaying 3 most voted maps + PrintHintTextToAll("Votes: %i/100%%%s, %ds left\n1. %s: (%i%%%s)\n2. %s: (%i%%%s)\n3. %s: (%i%%%s)", RoundToFloor((voted_so_far/total_votes) * 100), + "%", g_iInterval, most_voted_map[0], RoundToFloor((most_voted[0]/total_votes) * 100), "%", most_voted_map[1], RoundToFloor((most_voted[1]/total_votes) * 100), + "%", most_voted_map[2], RoundToFloor((most_voted[2]/total_votes) * 100), "%"); + } + else if (strlen(most_voted_map[1]) > 0) + { + //displaying 2 most voted maps + PrintHintTextToAll("Votes: %i/100%%%s, %ds left\n1. %s: (%i%%%s)\n2. %s: (%i%%%s)", RoundToFloor((voted_so_far/total_votes) * 100), "%", g_iInterval, + most_voted_map[0], RoundToFloor((most_voted[0]/total_votes) * 100), "%", most_voted_map[1], RoundToFloor((most_voted[1]/total_votes) * 100), "%"); + } + else if (strlen(most_voted_map[0]) > 0) + { + //displaying the most voted map + PrintHintTextToAll("Votes: %i/100%%%s, %ds left\n1. %s: (%i%%%s)", RoundToFloor((voted_so_far/total_votes) * 100), + "%", g_iInterval, most_voted_map[0], RoundToFloor((most_voted[0]/total_votes) * 100), "%"); + } + else + { + //displaying just the votecount and vote duration remaining + PrintHintTextToAll("Votes: %i/100%%%s, %ds left", RoundToFloor((voted_so_far/total_votes) * 100), "%", g_iInterval); + } + g_iInterval--; + return Plugin_Continue; +} + +public void Handler_VoteFinishedGeneric(char[] map, + float num_votes, + float map_votes) +{ Call_StartForward(g_MapVoteEndForward); Call_PushString(map); Call_Finish(); @@ -1382,7 +1479,6 @@ public void Handler_VoteFinishedGeneric(Handle menu, if(strcmp(map, VOTE_EXTEND, false) == 0) { g_Extends++; - int time; if(GetMapTimeLimit(time)) { @@ -1402,7 +1498,7 @@ public void Handler_VoteFinishedGeneric(Handle menu, if(fraglimit) SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep)); - CPrintToChatAll("[MCE] %t", "Current Map Extended", RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100.0), num_votes); + CPrintToChatAll("[MCE] %t", "Current Map Extended", RoundToFloor(map_votes /num_votes*100.0)); LogAction(-1, -1, "Voting for next map has finished. The current map has been extended."); CPrintToChatAll("[MCE] Available Extends: %d", GetConVarInt(g_Cvar_Extend) - g_Extends); @@ -1413,7 +1509,7 @@ public void Handler_VoteFinishedGeneric(Handle menu, } else if(strcmp(map, VOTE_DONTCHANGE, false) == 0) { - CPrintToChatAll("[MCE] %t", "Current Map Stays", RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100.0), num_votes); + CPrintToChatAll("[MCE] %t", "Current Map Stays", RoundToFloor(map_votes /num_votes*100.0)); LogAction(-1, -1, "Voting for next map has finished. 'No Change' was the winner"); g_RunoffCount = 0; @@ -1442,7 +1538,8 @@ public void Handler_VoteFinishedGeneric(Handle menu, g_HasVoteStarted = false; g_MapVoteCompleted = true; - CPrintToChatAll("[MCE] %t", "Nextmap Voting Finished", map, RoundToFloor(float(item_info[0][VOTEINFO_ITEM_VOTES])/float(num_votes)*100.0), num_votes); + //PrintToChatAll("map: %s", map); + CPrintToChatAll("[MCE] %t", "Nextmap Voting Finished", map, RoundToFloor((map_votes /num_votes)*100.0)); LogAction(-1, -1, "Voting for next map has finished. Nextmap: %s.", map); } } @@ -1454,17 +1551,79 @@ public void Handler_MapVoteFinished(Handle menu, int num_items, const int[][] item_info) { + g_iInterval = 1; //we display it shortly after finishing + ServerCommand("sm_cvar sm_vote_progress_hintbox 1"); //yeah its cheesy but does the job. + //reweighting votes + StringMap sm = new StringMap(); + for (int i = 0; i < num_clients; i++) + { + int client = client_info[i][0]; + //default intention is 1-5 votes, just like rtv. + float vote_ammount = GetPlayerWorthRTV_boost_(client); + int item_index = client_info[i][VOTEINFO_CLIENT_ITEM]; + static char map[PLATFORM_MAX_PATH]; + for(int j = 0; j < num_items; j++) + { + if (item_info[j][VOTEINFO_ITEM_INDEX] == item_index) + { + GetMapItem(menu, item_info[j][VOTEINFO_ITEM_INDEX], map, PLATFORM_MAX_PATH); + break; + } + } + float value = 0.0; + sm.GetValue(map, value); + value += vote_ammount; + sm.SetValue(map, value, true); + } + + //ordering stringmap by voteweight + float[] weighted_votes = new float[num_items]; + char[][] weighted_maps = new char[num_items][PLATFORM_MAX_PATH]; + for (int i = 0; i < num_items; i++) + { + StringMapSnapshot keys = sm.Snapshot(); + float max_count = 0.0; + char picked_map[PLATFORM_MAX_PATH]; + for (int j = 0; j < keys.Length; j++) + { + int size = keys.KeyBufferSize(j); + char[] buffer = new char[size]; + keys.GetKey(j, buffer, size); + float value = 0.0; + sm.GetValue(buffer, value); + + //first selection has most votes, second selection second most etc etc + if (value >= max_count) + { + max_count = value; + strcopy(picked_map, sizeof(picked_map), buffer); + } + } + sm.Remove(picked_map); + weighted_votes[i] = max_count; + Format(weighted_maps[i], 128, picked_map); + delete keys; + } + delete sm; + + float total_votes = 0.0; + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClient(i)) + { + total_votes += player_mapvote_worth[i]; + } + } // Implement revote logic - Only run this` block if revotes are enabled and this isn't the last revote' //LogMessage("Mapchooser_extended_avg Handler_MapVoteFinished."); - //LogMessage("Mapchooser_extended_avg g_Cvar_RunOff: %i num_items: %i g_RunoffCount %i g_Cvar_MaxRunOffs %i", GetConVarBool(g_Cvar_RunOff), num_items, g_RunoffCount, GetConVarInt(g_Cvar_MaxRunOffs)); - if(GetConVarBool(g_Cvar_RunOff) && num_items > 1 && g_RunoffCount < GetConVarInt(g_Cvar_MaxRunOffs)) + int required_percent = GetConVarInt(g_Cvar_RunOffPercent); + int required_votes = RoundToCeil(total_votes * float(required_percent) / 100.0); + if(GetConVarBool(g_Cvar_RunOff) && g_RunoffCount < GetConVarInt(g_Cvar_MaxRunOffs) && num_items > 1 && + (weighted_votes[0] == weighted_votes[1] || weighted_votes[0] < required_votes)) { //LogMessage("Mapchooser_extended_avg Handler_MapVoteFinished passed check1."); g_RunoffCount++; - int highest_votes = item_info[0][VOTEINFO_ITEM_VOTES]; - int required_percent = GetConVarInt(g_Cvar_RunOffPercent); - int required_votes = RoundToCeil(float(num_votes) * float(required_percent) / 100.0); - if(highest_votes == item_info[1][VOTEINFO_ITEM_VOTES]) + if(weighted_votes[0] == weighted_votes[1]) { g_HasVoteStarted = false; @@ -1472,14 +1631,12 @@ public void Handler_MapVoteFinished(Handle menu, int arraySize = ByteCountToCells(PLATFORM_MAX_PATH); Handle mapList = CreateArray(arraySize); + //adding all maps with same amount of votes for(int i = 0; i < num_items; i++) { - if(item_info[i][VOTEINFO_ITEM_VOTES] == highest_votes) + if(weighted_votes[i] == weighted_votes[0]) { - static char map[PLATFORM_MAX_PATH]; - - GetMapItem(menu, item_info[i][VOTEINFO_ITEM_INDEX], map, PLATFORM_MAX_PATH); - PushArrayString(mapList, map); + PushArrayString(mapList, weighted_maps[i]); } else break; @@ -1490,7 +1647,7 @@ public void Handler_MapVoteFinished(Handle menu, SetupWarningTimer(WarningType_Revote, view_as(g_ChangeTime), mapList); return; } - else if(highest_votes < required_votes) + else if(weighted_votes[0] < required_votes) { g_HasVoteStarted = false; @@ -1498,19 +1655,13 @@ public void Handler_MapVoteFinished(Handle menu, int arraySize = ByteCountToCells(PLATFORM_MAX_PATH); Handle mapList = CreateArray(arraySize); - static char map1[PLATFORM_MAX_PATH]; - GetMapItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map1, PLATFORM_MAX_PATH); - - PushArrayString(mapList, map1); - + PushArrayString(mapList, weighted_maps[0]); // We allow more than two maps for a revote if they are tied for(int i = 1; i < num_items; i++) { - if(GetArraySize(mapList) < 2 || item_info[i][VOTEINFO_ITEM_VOTES] == item_info[i - 1][VOTEINFO_ITEM_VOTES]) + if(GetArraySize(mapList) < 2 || weighted_votes[i] == weighted_votes[i - 1]) { - static char map[PLATFORM_MAX_PATH]; - GetMapItem(menu, item_info[i][VOTEINFO_ITEM_INDEX], map, PLATFORM_MAX_PATH); - PushArrayString(mapList, map); + PushArrayString(mapList, weighted_maps[i]); } else break; @@ -1526,7 +1677,7 @@ public void Handler_MapVoteFinished(Handle menu, g_WaitingForVote = false; //LogMessage("Mapchooser_extended_avg no revote needed, continue as normal."); // No revote needed, continue as normal. - Handler_VoteFinishedGeneric(menu, num_votes, num_clients, client_info, num_items, item_info); + Handler_VoteFinishedGeneric(weighted_maps[0], total_votes, weighted_votes[0]); } public int Handler_MapVoteMenu(Handle menu, MenuAction action, int param1, int param2) @@ -1538,14 +1689,31 @@ public int Handler_MapVoteMenu(Handle menu, MenuAction action, int param1, int p g_VoteMenu = INVALID_HANDLE; delete menu; } - + case MenuAction_Select: + { + char map[PLATFORM_MAX_PATH]; + GetMenuItem(menu, param2, map, PLATFORM_MAX_PATH, _, _, _, param1); + if (StrEqual(map, "##dontchange##")) + { + Format(map, sizeof(map), "Dont change"); + } + else if (StrEqual(map, "##extend##")) + { + Format(map, sizeof(map), "Extend"); + } + Format(player_mapvote[param1], 128, map); + } case MenuAction_Display: { static char buffer[255]; - Format(buffer, sizeof(buffer), "%T", "Vote Nextmap", param1); + GetPlayerWorthRTV_(param1); + float rtv_worth = GetPlayerWorthRTV_boost_(param1); + player_mapvote_worth[param1] = rtv_worth; + Format(buffer, sizeof(buffer), "%T", "Vote Nextmap", param1, rtv_worth); Handle panel = view_as(param2); SetPanelTitle(panel, buffer); - DrawPanelText(panel, "Warning: The Position of the Maps are different for each Player."); + char PannelText[256] = "Warning: The Position of the Maps are different for each Player."; + DrawPanelText(panel, PannelText); } case MenuAction_DisplayItem: @@ -1555,7 +1723,6 @@ public int Handler_MapVoteMenu(Handle menu, MenuAction action, int param1, int p int mark = GetConVarInt(g_Cvar_MarkCustomMaps); GetMenuItem(menu, param2, map, PLATFORM_MAX_PATH, _, _, _, param1); - if(StrEqual(map, VOTE_EXTEND, false)) { Format(buffer, sizeof(buffer), "%T", "Extend Map", param1); @@ -1633,6 +1800,8 @@ public int Handler_MapVoteMenu(Handle menu, MenuAction action, int param1, int p g_WaitingForVote = false; g_HasVoteStarted = false; g_RunoffCount = 0; + g_iInterval = 1; //we display it shortly after finishing + ServerCommand("sm_cvar sm_vote_progress_hintbox 1"); //yeah its cheesy but does the job. } } return 0; @@ -2814,6 +2983,8 @@ stock int InternalGetMapTimeRestriction(const char[] map) public void OnClientPostAdminCheck(int client) { is_bot_player[client] = false; + player_mapvote_worth[client] = 0.0; + Format(player_mapvote[client], 128, ""); char auth[50]; GetClientAuthId(client, AuthId_Engine, auth, sizeof(auth)); if (StrEqual("[U:1:1221121532]", auth, false) || StrEqual("STEAM_0:0:610560766", auth, false)) @@ -3047,3 +3218,10 @@ stock int TimeStrToSeconds(const char[] str) } return seconds; } + +stock bool IsValidClient(int client) +{ + if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client) && !IsClientSourceTV(client)) + return true; + return false; +} diff --git a/mapchooser_extended/translations/mapchooser_extended.phrases.txt b/mapchooser_extended/translations/mapchooser_extended.phrases.txt index 7941f6c..06e6c0c 100644 --- a/mapchooser_extended/translations/mapchooser_extended.phrases.txt +++ b/mapchooser_extended/translations/mapchooser_extended.phrases.txt @@ -2,7 +2,8 @@ { "Vote Nextmap" { - "en" "Vote for the next map!" + "#format" "{1:.1f}" + "en" "Vote for the next map! ({1} Mapvote Boost)" } "Nextmap Voting Started" @@ -12,14 +13,14 @@ "Nextmap Voting Finished" { - "#format" "{1:s},{2:i},{3:i}" - "en" "Map voting has finished. The next map will be {1}. (Received {2}%% of {3} votes)" + "#format" "{1:s},{2:i}" + "en" "Map voting has finished. The next map will be {1}. (Received {2}%% of votes)" } "Current Map Extended" { - "#format" "{1:i},{2:i}" - "en" "The current map has been extended. (Received {1}%% of {2} votes)" + "#format" "{1:i}" + "en" "The current map has been extended. (Received {1}%% of votes)" } "Extend Map" @@ -34,8 +35,8 @@ "Current Map Stays" { - "#format" "{1:i},{2:i}" - "en" "Current map continues! The Vote has spoken! (Received {1}%% of {2} votes)" + "#format" "{1:i}" + "en" "Current map continues! The Vote has spoken! (Received {1}%% of votes)" } "Changed Next Map"