Added support for runoff voting in mapchooser (bug 4218, r=dvander).
This commit is contained in:
		
							parent
							
								
									e18faf085f
								
							
						
					
					
						commit
						3b12883a1b
					
				@ -31,6 +31,16 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Version: $Id$
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
//#define DEBUG
 | 
			
		||||
 | 
			
		||||
#if defined DEBUG
 | 
			
		||||
	#define assert(%1) if (!(%1)) ThrowError("Debug Assertion Failed");
 | 
			
		||||
	#define assert_msg(%1,%2) if (!(%1)) ThrowError(%2);
 | 
			
		||||
#else
 | 
			
		||||
	#define assert(%1)
 | 
			
		||||
	#define assert_msg(%1,%2)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#pragma semicolon 1
 | 
			
		||||
#include <sourcemod>
 | 
			
		||||
@ -66,6 +76,8 @@ new Handle:g_Cvar_Extend = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_Cvar_DontChange = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_Cvar_EndOfMapVote = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_Cvar_VoteDuration = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_Cvar_RunOff = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_Cvar_RunOffPercent = INVALID_HANDLE;
 | 
			
		||||
 | 
			
		||||
new Handle:g_VoteTimer = INVALID_HANDLE;
 | 
			
		||||
new Handle:g_RetryTimer = INVALID_HANDLE;
 | 
			
		||||
@ -126,6 +138,8 @@ public OnPluginStart()
 | 
			
		||||
	g_Cvar_Extend = CreateConVar("sm_mapvote_extend", "0", "Number of extensions allowed each map.", _, true, 0.0);
 | 
			
		||||
	g_Cvar_DontChange = CreateConVar("sm_mapvote_dontchange", "1", "Specifies if a 'Don't Change' option should be added to early votes", _, true, 0.0);
 | 
			
		||||
	g_Cvar_VoteDuration = CreateConVar("sm_mapvote_voteduration", "20", "Specifies how long the mapvote should be available for.", _, true, 5.0);
 | 
			
		||||
	g_Cvar_RunOff = CreateConVar("sm_mapvote_runoff", "0", "Hold run of votes if winning choice is less than a certain margin", _, true, 0.0, true, 1.0);
 | 
			
		||||
	g_Cvar_RunOffPercent = CreateConVar("sm_mapvote_runoffpercent", "50", "If winning choice has less than this percent of votes, hold a runoff", _, true, 0.0, true, 100.0);
 | 
			
		||||
	
 | 
			
		||||
	RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now.");
 | 
			
		||||
	RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap <map>");
 | 
			
		||||
@ -526,6 +540,7 @@ public Action:Command_Mapvote(client, args)
 | 
			
		||||
 *
 | 
			
		||||
 * @param when			When the resulting map change should occur.
 | 
			
		||||
 * @param inputlist		Optional list of maps to use for the vote, otherwise an internal list of nominations + random maps will be used.
 | 
			
		||||
 * @param noSpecials	Block special vote options like extend/nochange (upgrade this to bitflags instead?)
 | 
			
		||||
 */
 | 
			
		||||
InitiateVote(MapChange:when, Handle:inputlist=INVALID_HANDLE)
 | 
			
		||||
{
 | 
			
		||||
@ -586,6 +601,7 @@ InitiateVote(MapChange:when, Handle:inputlist=INVALID_HANDLE)
 | 
			
		||||
		{
 | 
			
		||||
			GetArrayString(g_NominateList, i, map, sizeof(map));
 | 
			
		||||
			AddMenuItem(g_VoteMenu, map, map);
 | 
			
		||||
			RemoveStringFromArray(g_NextMapList, map);
 | 
			
		||||
			
 | 
			
		||||
			/* Notify Nominations that this map is now free */
 | 
			
		||||
			Call_StartForward(g_NominationsResetForward);
 | 
			
		||||
@ -598,6 +614,7 @@ InitiateVote(MapChange:when, Handle:inputlist=INVALID_HANDLE)
 | 
			
		||||
		for (new i=nominationsToAdd; i<nominateCount; i++)
 | 
			
		||||
		{
 | 
			
		||||
			GetArrayString(g_NominateList, i, map, sizeof(map));
 | 
			
		||||
			/* 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);
 | 
			
		||||
@ -617,13 +634,9 @@ InitiateVote(MapChange:when, Handle:inputlist=INVALID_HANDLE)
 | 
			
		||||
			GetArrayString(g_NextMapList, count, map, sizeof(map));
 | 
			
		||||
			count++;
 | 
			
		||||
			
 | 
			
		||||
			//Check if this map is in the nominate list (and thus already in the vote) */
 | 
			
		||||
			if (FindStringInArray(g_NominateList, map) == -1)
 | 
			
		||||
			{
 | 
			
		||||
				/* Insert the map and increment our count */
 | 
			
		||||
				AddMenuItem(g_VoteMenu, map, map);
 | 
			
		||||
				i++;
 | 
			
		||||
			}
 | 
			
		||||
			/* Insert the map and increment our count */
 | 
			
		||||
			AddMenuItem(g_VoteMenu, map, map);
 | 
			
		||||
			i++;
 | 
			
		||||
			
 | 
			
		||||
			if (count >= availableMaps)
 | 
			
		||||
			{
 | 
			
		||||
@ -670,19 +683,13 @@ InitiateVote(MapChange:when, Handle:inputlist=INVALID_HANDLE)
 | 
			
		||||
	PrintToChatAll("[SM] %t", "Nextmap Voting Started");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public Handler_MapVoteFinished(Handle:menu,
 | 
			
		||||
public Handler_VoteFinishedGeneric(Handle:menu,
 | 
			
		||||
						   num_votes, 
 | 
			
		||||
						   num_clients,
 | 
			
		||||
						   const client_info[][2], 
 | 
			
		||||
						   num_items,
 | 
			
		||||
						   const item_info[][2])
 | 
			
		||||
{
 | 
			
		||||
	if (num_votes == 0)
 | 
			
		||||
	{
 | 
			
		||||
		LogError("No Votes recorded yet Advanced callback fired - Tell pRED* to fix this");
 | 
			
		||||
		return;	
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	decl String:map[32];
 | 
			
		||||
	GetMenuItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map, sizeof(map));
 | 
			
		||||
 | 
			
		||||
@ -771,6 +778,53 @@ public Handler_MapVoteFinished(Handle:menu,
 | 
			
		||||
	}	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public Handler_MapVoteFinished(Handle:menu,
 | 
			
		||||
						   num_votes, 
 | 
			
		||||
						   num_clients,
 | 
			
		||||
						   const client_info[][2], 
 | 
			
		||||
						   num_items,
 | 
			
		||||
						   const item_info[][2])
 | 
			
		||||
{
 | 
			
		||||
	if (GetConVarBool(g_Cvar_RunOff) && num_items > 1)
 | 
			
		||||
	{
 | 
			
		||||
		new Float:winningvotes = float(item_info[0][VOTEINFO_ITEM_VOTES]);
 | 
			
		||||
		new Float:required = num_votes * (GetConVarFloat(g_Cvar_RunOffPercent) / 100.0);
 | 
			
		||||
		
 | 
			
		||||
		if (winningvotes <= required)
 | 
			
		||||
		{
 | 
			
		||||
			/* Insufficient Winning margin - Lets do a runoff */
 | 
			
		||||
			g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction:MENU_ACTIONS_ALL);
 | 
			
		||||
			SetMenuTitle(g_VoteMenu, "Runoff Vote Nextmap");
 | 
			
		||||
			SetVoteResultCallback(g_VoteMenu, Handler_VoteFinishedGeneric);
 | 
			
		||||
 | 
			
		||||
			decl String:map[32];
 | 
			
		||||
			decl String:info1[32];
 | 
			
		||||
			decl String:info2[32];
 | 
			
		||||
			
 | 
			
		||||
			GetMenuItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map, sizeof(map), _, info1, sizeof(info1));
 | 
			
		||||
			AddMenuItem(g_VoteMenu, map, info1);
 | 
			
		||||
			GetMenuItem(menu, item_info[1][VOTEINFO_ITEM_INDEX], map, sizeof(map), _, info2, sizeof(info2));
 | 
			
		||||
			AddMenuItem(g_VoteMenu, map, info2);
 | 
			
		||||
			
 | 
			
		||||
			new voteDuration = GetConVarInt(g_Cvar_VoteDuration);
 | 
			
		||||
			SetMenuExitButton(g_VoteMenu, false);
 | 
			
		||||
			VoteMenuToAll(g_VoteMenu, voteDuration);
 | 
			
		||||
			
 | 
			
		||||
			/* Notify */
 | 
			
		||||
			new Float:map1percent = float(item_info[0][VOTEINFO_ITEM_VOTES])/ float(num_votes) * 100;
 | 
			
		||||
			new Float:map2percent = float(item_info[1][VOTEINFO_ITEM_VOTES])/ float(num_votes) * 100;
 | 
			
		||||
			
 | 
			
		||||
			
 | 
			
		||||
			PrintToChatAll("[SM] %t", "Starting Runoff", GetConVarFloat(g_Cvar_RunOffPercent), info1, map1percent, info2, map2percent);
 | 
			
		||||
			LogMessage("Voting for next map was indecisive, beginning runoff vote");
 | 
			
		||||
					
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	Handler_VoteFinishedGeneric(menu, num_votes, num_clients, client_info, num_items, item_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2)
 | 
			
		||||
{
 | 
			
		||||
	switch (action)
 | 
			
		||||
@ -865,33 +919,35 @@ public Action:Timer_ChangeMap(Handle:hTimer, Handle:dp)
 | 
			
		||||
	return Plugin_Stop;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CreateNextVote()
 | 
			
		||||
bool:RemoveStringFromArray(Handle:array, String:str[])
 | 
			
		||||
{
 | 
			
		||||
	if(g_NextMapList != INVALID_HANDLE)
 | 
			
		||||
	{
 | 
			
		||||
		ClearArray(g_NextMapList);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	decl String:map[32];
 | 
			
		||||
	new index, Handle:tempMaps  = CloneArray(g_MapList);
 | 
			
		||||
	
 | 
			
		||||
	GetCurrentMap(map, sizeof(map));
 | 
			
		||||
	index = FindStringInArray(tempMaps, map);
 | 
			
		||||
	new index = FindStringInArray(array, str);
 | 
			
		||||
	if (index != -1)
 | 
			
		||||
	{
 | 
			
		||||
		RemoveFromArray(tempMaps, index);
 | 
			
		||||
	}	
 | 
			
		||||
		RemoveFromArray(array, index);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CreateNextVote()
 | 
			
		||||
{
 | 
			
		||||
	assert(g_NextMapList)
 | 
			
		||||
	ClearArray(g_NextMapList);
 | 
			
		||||
	
 | 
			
		||||
	decl String:map[32];
 | 
			
		||||
	new Handle:tempMaps  = CloneArray(g_MapList);
 | 
			
		||||
	
 | 
			
		||||
	GetCurrentMap(map, sizeof(map));
 | 
			
		||||
	RemoveStringFromArray(tempMaps, map);
 | 
			
		||||
	
 | 
			
		||||
	if (GetConVarInt(g_Cvar_ExcludeMaps) && GetArraySize(tempMaps) > GetConVarInt(g_Cvar_ExcludeMaps))
 | 
			
		||||
	{
 | 
			
		||||
		for (new i = 0; i < GetArraySize(g_OldMapList); i++)
 | 
			
		||||
		{
 | 
			
		||||
			GetArrayString(g_OldMapList, i, map, sizeof(map));
 | 
			
		||||
			index = FindStringInArray(tempMaps, map);
 | 
			
		||||
			if (index != -1)
 | 
			
		||||
			{
 | 
			
		||||
				RemoveFromArray(tempMaps, index);
 | 
			
		||||
			}
 | 
			
		||||
			RemoveStringFromArray(tempMaps, map);
 | 
			
		||||
		}	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,13 +12,13 @@
 | 
			
		||||
 | 
			
		||||
	"Nextmap Voting Finished"
 | 
			
		||||
	{
 | 
			
		||||
		"#format"			"{1:s},{2:i},{3:i}"
 | 
			
		||||
		"#format"		"{1:s},{2:i},{3:i}"
 | 
			
		||||
		"en"			"Map voting has finished. The next map will be {1}. (Received {2}%% of {3} votes)"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"Current Map Extended"
 | 
			
		||||
	{
 | 
			
		||||
		"#format"			"{1:i},{2:i}"
 | 
			
		||||
		"#format"		"{1:i},{2:i}"
 | 
			
		||||
		"en"			"The current map has been extended. (Received {1}%% of {2} votes)"
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
@ -34,13 +34,19 @@
 | 
			
		||||
 | 
			
		||||
	"Current Map Stays"
 | 
			
		||||
	{
 | 
			
		||||
		"#format"			"{1:i},{2:i}"
 | 
			
		||||
		"#format"		"{1:i},{2:i}"
 | 
			
		||||
		"en"			"Current map continues! The Vote has spoken! (Received {1}%% of {2} votes)"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"Changed Next Map"
 | 
			
		||||
	{
 | 
			
		||||
		"#format"		"{1:s}"
 | 
			
		||||
		"en"		"Changed nextmap to \"{1}\"."	
 | 
			
		||||
		"en"			"Changed nextmap to \"{1}\"."	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	"Starting Runoff"
 | 
			
		||||
	{
 | 
			
		||||
		"#format"		"{1:.0f},{2:s},{3:.0f},{4:s},{5:.0f}"
 | 
			
		||||
		"en"			"No map got over {1}%% votes ({2} [{3}%%] & {4} [{5}%%]), starting runoff vote"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user