diff --git a/mapchooser_extended/scripting/include/nominations_extended.inc b/mapchooser_extended/scripting/include/nominations_extended.inc index 43136362..5328b5cd 100644 --- a/mapchooser_extended/scripting/include/nominations_extended.inc +++ b/mapchooser_extended/scripting/include/nominations_extended.inc @@ -9,6 +9,11 @@ native int PushMapsIntoNominationPool(ArrayList maps); native int RemoveMapFromNominationPool(char[] map); native int RemoveMapsFromNominationPool(ArrayList maps); +/** + * @MapleaderNominatedMapname is the map nominated from a map leader +*/ +native void GetMapleaderNominatedMap(char[] MapleaderNominatedMapname); + public SharedPlugin __pl_nominations_extended = { name = "nominations", diff --git a/mapchooser_extended/scripting/mapchooser_extended_avg.sp b/mapchooser_extended/scripting/mapchooser_extended_avg.sp index 493bf172..4bb1531c 100755 --- a/mapchooser_extended/scripting/mapchooser_extended_avg.sp +++ b/mapchooser_extended/scripting/mapchooser_extended_avg.sp @@ -51,6 +51,7 @@ #include #include #include +#include #include #pragma semicolon 1 @@ -236,6 +237,7 @@ public void OnPluginEnd() Call_StartForward(g_NominationsResetForward); GetArrayString(g_NominateList[i], j, oldmap, PLATFORM_MAX_PATH); Call_PushString(oldmap); + Call_PushCell(i); Call_Finish(); } } @@ -640,6 +642,7 @@ public void OnClientDisconnect(int client) char oldmap[PLATFORM_MAX_PATH]; GetArrayString(g_NominateList[client], i, oldmap, PLATFORM_MAX_PATH); Call_PushString(oldmap); + Call_PushCell(client); Call_Finish(); } @@ -1021,6 +1024,11 @@ public Handle get_most_nominated_maps() Handle most_nominated_maps = CreateArray(arraySize); StringMap sm = new StringMap(); + //november 2023 edit: now the leader can nominate one map per map played that can skip requirements: Expectation is the leader will want to lead the map. + //if leaders abuse the feature they should simply be removed from the feature. + char MapleaderNominatedMap[PLATFORM_MAX_PATH]; + GetMapleaderNominatedMap(MapleaderNominatedMap); + for (int i = 0; i < MaxClients; i++) { for (int j = 0; j < GetArraySize(g_NominateList[i]); j++) @@ -1030,12 +1038,19 @@ public Handle get_most_nominated_maps() 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 must come into the vote - if(!i) + //if i is 0 its admin nominated map that must come into the vote. + //if strequal the map was nominated by a leader and most be forced on the vote. + if(!i || StrEqual(map_iteration, MapleaderNominatedMap, false)) { nominate_count_for_particular_map = 999; } sm.SetValue(map_iteration, nominate_count_for_particular_map, true); + + /* Notify Nominations that this map is now free */ + Call_StartForward(g_NominationsResetForward); + Call_PushString(map_iteration); + Call_PushCell(i + 100); //differentiate between all other calls and the call invoked by get_most_nominated_maps() + Call_Finish(); } } static char map_[PLATFORM_MAX_PATH]; @@ -1245,27 +1260,9 @@ void InitiateVote(MapChange when, Handle inputlist=INVALID_HANDLE) if(randomizeList == INVALID_HANDLE) AddMapItem(map); - RemoveStringFromArray(g_NextMapList, map); - - /* Notify Nominations that this map is now free */ - Call_StartForward(g_NominationsResetForward); - Call_PushString(map); - Call_Finish(); } - /* Clear out the rest of the nominations array */ - for(int i = nominationsToAdd; i < nominateCount; i++) - { - //2023 edit: might need to run all g_NominateList[client] through this instead - GetArrayString(most_nominated_maps, i, map, PLATFORM_MAX_PATH); - /* These maps shouldn't be excluded from the vote as they weren't really nominated at all */ - - /* Notify Nominations that this map is now free */ - Call_StartForward(g_NominationsResetForward); - Call_PushString(map); - Call_Finish(); - } /* There should currently be 'nominationsToAdd' unique maps in the vote */ @@ -1521,7 +1518,7 @@ public void Handler_VoteFinishedGeneric(char[] map, if(fraglimit) SetConVarInt(g_Cvar_Fraglimit, fraglimit + GetConVarInt(g_Cvar_ExtendFragStep)); - CPrintToChatAll("[MCE] %t", "Current Map Extended", RoundToFloor((map_votes /num_votes)*100.0)); + PrintToChatAll("The current map has been extended. (Received %i%s of votes)", 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); @@ -1532,7 +1529,7 @@ public void Handler_VoteFinishedGeneric(char[] map, } else if(strcmp(map, VOTE_DONTCHANGE, false) == 0) { - CPrintToChatAll("[MCE] %t", "Current Map Stays", RoundToFloor((map_votes /num_votes)*100.0)); + PrintToChatAll("Current map continues! The Vote has spoken! (Received %i%s of votes)", RoundToFloor((map_votes /num_votes)*100.0), "%"); LogAction(-1, -1, "Voting for next map has finished. 'No Change' was the winner"); g_RunoffCount = 0; @@ -2027,6 +2024,7 @@ NominateResult InternalNominateMap(char[] map, int owner) GetArrayString(g_NominateList[owner], 0, oldmap, PLATFORM_MAX_PATH); Call_StartForward(g_NominationsResetForward); Call_PushString(oldmap); + Call_PushCell(owner); Call_Finish(); RemoveFromArray(g_NominateList[owner], 0); @@ -2079,6 +2077,7 @@ NominateResult InternalNominateMap(char[] map, int owner) GetArrayString(g_NominateList[owner], 0, oldmap, PLATFORM_MAX_PATH); Call_StartForward(g_NominationsResetForward); Call_PushString(oldmap); + Call_PushCell(owner); int owner_ = GetArrayCell(g_NominateOwners, 0); Call_Finish(); @@ -2123,6 +2122,7 @@ bool InternalRemoveNominationByMap(char[] map) { Call_StartForward(g_NominationsResetForward); Call_PushString(oldmap); + Call_PushCell(client); Call_Finish(); int owner = GetArrayCell(g_NominateOwners, i); @@ -2158,26 +2158,27 @@ public int Native_RemoveNominationByMap(Handle plugin, int numParams) bool InternalRemoveNominationByOwner(int owner) { - int index; + int index; - if(owner && ((index = FindValueInArray(g_NominateOwners, owner)) != -1)) - { - char oldmap[PLATFORM_MAX_PATH]; - GetArrayString(g_NominateList[owner], index, oldmap, PLATFORM_MAX_PATH); + if(owner && ((index = FindValueInArray(g_NominateOwners, owner)) != -1)) + { + char oldmap[PLATFORM_MAX_PATH]; + GetArrayString(g_NominateList[owner], index, oldmap, PLATFORM_MAX_PATH); - Call_StartForward(g_NominationsResetForward); - Call_PushString(oldmap); - Call_Finish(); + Call_StartForward(g_NominationsResetForward); + Call_PushString(oldmap); + Call_PushCell(owner); + Call_Finish(); - RemoveFromArray(g_NominateList[owner], index); + RemoveFromArray(g_NominateList[owner], index); //maybe only do once or change g_NominateOwners - RemoveFromArray(g_NominateOwners, index); - g_NominateCount--; + RemoveFromArray(g_NominateOwners, index); + g_NominateCount--; - return true; - } + return true; + } - return false; + return false; } /* native bool RemoveNominationByOwner(owner); */ @@ -2867,6 +2868,7 @@ void CheckMapRestrictions(bool time = false, bool players = false) { Call_StartForward(g_NominationsResetForward); Call_PushString(map); + Call_PushCell(client); Call_Finish(); } diff --git a/mapchooser_extended/scripting/nominations_extended.sp b/mapchooser_extended/scripting/nominations_extended.sp index 33c17687..57d688c9 100755 --- a/mapchooser_extended/scripting/nominations_extended.sp +++ b/mapchooser_extended/scripting/nominations_extended.sp @@ -39,9 +39,10 @@ #include #include #include +#include #include -#define MCE_VERSION "1.3.1" +#define MCE_VERSION "1.4.1" public Plugin myinfo = { @@ -82,6 +83,8 @@ Handle g_Cvar_VIPTimeframeMaxTime = INVALID_HANDLE; int g_Player_NominationDelay[MAXPLAYERS+1]; int g_NominationDelay; +int g_iMapleaderWhoNominatedMap = -1; +char g_cMapLeaderNominatedMap[256]; //clients ignoring maps that are unavailable bool g_bClientsIgnoring[MAXPLAYERS + 1]; @@ -135,6 +138,8 @@ public void OnPluginStart() public void OnMapStart() { + Format(g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), ""); + g_iMapleaderWhoNominatedMap = -1; if (!g_dDatabase) { //we have too many dbs so i am just re-using racetimercss @@ -259,6 +264,7 @@ public APLRes AskPluginLoad2(Handle hThis, bool bLate, char[] err, int iErrLen) CreateNative("PushMapsIntoNominationPool", Native_PushMapsIntoNominationPool); CreateNative("RemoveMapFromNominationPool", Native_RemoveMapFromNominationPool); CreateNative("RemoveMapsFromNominationPool", Native_RemoveMapsFromNominationPool); + CreateNative("GetMapleaderNominatedMap", Native_GetMapleaderNominatedMap); return APLRes_Success; } @@ -362,17 +368,38 @@ void UpdateMapTrie() delete excludeMaps; } -public void OnNominationRemoved(const char[] map) +public void OnNominationRemoved(const char[] map, int client) { int status; /* Is the map in our list? */ if(!GetTrieValue(g_mapTrie, map, status)) return; - + int newclient = 0; + //just differientiating between if nomination was removed because of starting vote or because of anything else possible. + if (client > 100) + { + newclient = client - 100; + } + else + { + newclient = client; + } + if (newclient == g_iMapleaderWhoNominatedMap && StrEqual(map, g_cMapLeaderNominatedMap, false)) + { + if (client > 100) + { + CPrintToChatAll("{darkorange}[UNLOZE Nominations] {white}The map leader {lightgreen}%N {white}nomination {red}%s {white}was forced into the mapvote.", newclient, map); + } + else + { + CPrintToChatAll("{darkorange}[UNLOZE Nominations] {white}The map leader {lightgreen}%N {white}has removed his Mapleader nomination {red}%s", newclient, map); + } + Format(g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), ""); + g_iMapleaderWhoNominatedMap = -1; + } /* Was the map disabled due to being nominated */ if((status & MAPSTATUS_EXCLUDE_NOMINATED) != MAPSTATUS_EXCLUDE_NOMINATED) return; - SetTrieValue(g_mapTrie, map, MAPSTATUS_ENABLED); } @@ -399,8 +426,8 @@ public Action Command_Addmap(int client, int args) AttemptAdminNominate(client, mapname); return Plugin_Handled; } - - if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true)) + + if(!CheckCommandAccess(client, "sm_nominate_ignore", ADMFLAG_KICK, true) ) { bool RestrictionsActive = AreRestrictionsActive(); @@ -461,6 +488,7 @@ public Action Command_Addmap(int client, int args) } } + NominateResult result = NominateMap(mapname, true, 0); if(result > Nominate_Replaced) @@ -697,49 +725,60 @@ public Action Command_Nominate(int client, int args) return Plugin_Handled; } - int Cooldown = GetMapCooldownTime(mapname); - if(RestrictionsActive && Cooldown > GetTime()) + int mapLeader = Leader_CurrentLeader(); + //2023 November edit: one map nominated by mapleader will automatically go to the vote. + if (client == mapLeader && StrEqual(g_cMapLeaderNominatedMap, "")) { - int Seconds = Cooldown - GetTime(); - CPrintToChat(client, "[NE] %t", "Map Cooldown Time Error", Seconds / 3600, (Seconds % 3600) / 60); - - return Plugin_Handled; + CPrintToChatAll("{darkorange}[UNLOZE Nominations] {white}The map leader {lightgreen}%N {white}has nominated the map {red}%s{white}. The map will be in the next mapvote.", client, mapname); + CPrintToChatAll("{lightblue}If the map is nextmap and the leader wont play it he will be removed from leader access."); + Format(g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), mapname); + g_iMapleaderWhoNominatedMap = client; } - - bool VIPRestriction = GetMapVIPRestriction(mapname, client); - if(RestrictionsActive && VIPRestriction) + else { - CPrintToChat(client, "[NE] %t", "Map Nominate VIP Error"); + int Cooldown = GetMapCooldownTime(mapname); + if(RestrictionsActive && Cooldown > GetTime()) + { + int Seconds = Cooldown - GetTime(); + CPrintToChat(client, "[NE] %t", "Map Cooldown Time Error", Seconds / 3600, (Seconds % 3600) / 60); - return Plugin_Handled; + return Plugin_Handled; + } + + bool VIPRestriction = GetMapVIPRestriction(mapname, client); + if(RestrictionsActive && VIPRestriction) + { + CPrintToChat(client, "[NE] %t", "Map Nominate VIP Error"); + + return Plugin_Handled; + } + + int TimeRestriction = GetMapTimeRestriction(mapname); + if(RestrictionsActive && TimeRestriction) + { + CPrintToChat(client, "[NE] %t", "Map Nominate Time Error", TimeRestriction / 60, TimeRestriction % 60); + + return Plugin_Handled; + } + + int AverageHourRestricted = GetAveragePlayerTimeOnServerMapRestriction(mapname); + if (AverageHourRestricted > 0) + { + PrintToChat(client, "%s requires +%i hours average. Use sm_houravg to check average.", mapname, AverageHourRestricted); + return Plugin_Handled; + } + + int PlayerRestriction = GetMapPlayerRestriction(mapname); + if(RestrictionsActive && PlayerRestriction) + { + if(PlayerRestriction < 0) + CPrintToChat(client, "[NE] %t", "Map Nominate MinPlayers Error", PlayerRestriction * -1); + else + CPrintToChat(client, "[NE] %t", "Map Nominate MaxPlayers Error", PlayerRestriction); + + return Plugin_Handled; + } } - - int TimeRestriction = GetMapTimeRestriction(mapname); - if(RestrictionsActive && TimeRestriction) - { - CPrintToChat(client, "[NE] %t", "Map Nominate Time Error", TimeRestriction / 60, TimeRestriction % 60); - - return Plugin_Handled; - } - - int AverageHourRestricted = GetAveragePlayerTimeOnServerMapRestriction(mapname); - if (AverageHourRestricted > 0) - { - PrintToChat(client, "%s requires +%i hours average. Use sm_houravg to check average.", mapname, AverageHourRestricted); - return Plugin_Handled; - } - - int PlayerRestriction = GetMapPlayerRestriction(mapname); - if(RestrictionsActive && PlayerRestriction) - { - if(PlayerRestriction < 0) - CPrintToChat(client, "[NE] %t", "Map Nominate MinPlayers Error", PlayerRestriction * -1); - else - CPrintToChat(client, "[NE] %t", "Map Nominate MaxPlayers Error", PlayerRestriction); - - return Plugin_Handled; - } - NominateResult result = NominateMap(mapname, false, client); if (result == Nominate_InvalidMap) @@ -768,7 +807,9 @@ public Action Command_Nominate(int client, int args) if(result == Nominate_Added) PrintToChatAll("[NE] %t", "Map Nominated", name, mapname); else if(result == Nominate_Replaced) + { PrintToChatAll("[NE] %t", "Map Nomination Changed", name, mapname); + } LogMessage("%s nominated %s", name, mapname); @@ -835,7 +876,15 @@ void AttemptNominate(int client, const char[] filter = "") Menu menu = g_MapMenu; menu = BuildMapMenu(filter, client); - SetMenuTitle(menu, "%T", "Nominate Title", client); + int mapLeader = Leader_CurrentLeader(); + if (client == mapLeader && StrEqual(g_cMapLeaderNominatedMap, "")) + { + SetMenuTitle(menu, "Nominate Map as Mapleader:", client); + } + else + { + SetMenuTitle(menu, "%T", "Nominate Title", client); + } DisplayMenu(menu, client, MENU_TIME_FOREVER); } @@ -918,7 +967,8 @@ bool PopulateNominateListMenu(Menu menu, int client, const char[] filter = "") int owner = GetArrayCell(OwnerList, i); int nominate_count_for_particular_map = 0; sm.GetValue(map, nominate_count_for_particular_map); - if(!owner) + //if its console its admin nomination. if its g_iMapleaderWhoNominatedMap it was map nominated by leader, also has to be correct map out of 3. + if(!owner || (owner == g_iMapleaderWhoNominatedMap && StrEqual(map, g_cMapLeaderNominatedMap))) { nominate_count_for_particular_map = 999; } @@ -958,6 +1008,12 @@ bool PopulateNominateListMenu(Menu menu, int client, const char[] filter = "") if(!owner) Format(display, sizeof(display), "%s (Admin)", display); + else if (StrEqual(map, g_cMapLeaderNominatedMap)) + { + char leadername[MAX_NAME_LENGTH]; + GetClientName(g_iMapleaderWhoNominatedMap, leadername, MAX_NAME_LENGTH); + Format(display, sizeof(display), "%s (Mapleader %s)", display, leadername); + } else Format(display, sizeof(display), "%s (%i %s)", display, nominate_count_for_particular_map, spelling); @@ -1094,7 +1150,7 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p { case MenuAction_End: { - if (menu != g_MapMenu) + if (menu != g_MapMenu && menu != null) { delete menu; } @@ -1130,7 +1186,16 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p GetClientName(param1, name, MAX_NAME_LENGTH); - if(AreRestrictionsActive() && ( + int mapLeader = Leader_CurrentLeader(); + //2023 November edit: one map nominated by mapleader will automatically go to the vote. + if (param1 == mapLeader && StrEqual(g_cMapLeaderNominatedMap, "")) + { + CPrintToChatAll("{darkorange}[UNLOZE Nominations] {white}The map leader {lightgreen}%N {white}has nominated the map {red}%s{white}. The map will be in the next mapvote.", param1, map); + CPrintToChatAll("{lightblue}If the map is nextmap and the leader wont play it he will be removed from leader access."); + Format(g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), map); + g_iMapleaderWhoNominatedMap = param1; + } + else if(AreRestrictionsActive() && ( GetMapCooldownTime(map) > GetTime() || GetMapTimeRestriction(map) || GetMapPlayerRestriction(map) || @@ -1166,7 +1231,9 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p if(result == Nominate_Added) PrintToChatAll("[NE] %t", "Map Nominated", name, map); else if(result == Nominate_Replaced) + { PrintToChatAll("[NE] %t", "Map Nomination Changed", name, map); + } LogMessage("%s nominated %s", name, map); g_Player_NominationDelay[param1] = GetTime() + GetConVarInt(g_Cvar_NominateDelay); @@ -1200,6 +1267,12 @@ public int Handler_MapSelectMenu(Menu menu, MenuAction action, int param1, int p } } + int mapLeader = Leader_CurrentLeader(); + if (param1 == mapLeader && StrEqual(g_cMapLeaderNominatedMap, "")) + { + return ITEMDRAW_DEFAULT; + } + if(AreRestrictionsActive() && ( GetMapCooldownTime(map) > GetTime() || GetMapTimeRestriction(map) || @@ -1556,6 +1629,12 @@ public int Native_RemoveMapsFromNominationPool(Handle plugin, int numArgs) return 0; } +public int Native_GetMapleaderNominatedMap(Handle plugin, int numArgs) +{ + SetNativeString(1, g_cMapLeaderNominatedMap, sizeof(g_cMapLeaderNominatedMap), true); + return 0; +} + stock int GetVIPTimeRestriction() { if (!GetConVarBool(g_Cvar_VIPTimeframe))