plugins/mapchooser.sp
changeset 3440 0d9a99f41a67
parent 3399 c81e3ec1123a
child 3826 cdb77388037e
     1.1 --- a/plugins/mapchooser.sp	Fri Nov 04 10:02:32 2011 -0400
     1.2 +++ b/plugins/mapchooser.sp	Sat Nov 05 20:36:20 2011 -0400
     1.3 @@ -31,6 +31,16 @@
     1.4   *
     1.5   * Version: $Id$
     1.6   */
     1.7 + 
     1.8 +//#define DEBUG
     1.9 +
    1.10 +#if defined DEBUG
    1.11 +	#define assert(%1) if (!(%1)) ThrowError("Debug Assertion Failed");
    1.12 +	#define assert_msg(%1,%2) if (!(%1)) ThrowError(%2);
    1.13 +#else
    1.14 +	#define assert(%1)
    1.15 +	#define assert_msg(%1,%2)
    1.16 +#endif
    1.17  
    1.18  #pragma semicolon 1
    1.19  #include <sourcemod>
    1.20 @@ -66,6 +76,8 @@
    1.21  new Handle:g_Cvar_DontChange = INVALID_HANDLE;
    1.22  new Handle:g_Cvar_EndOfMapVote = INVALID_HANDLE;
    1.23  new Handle:g_Cvar_VoteDuration = INVALID_HANDLE;
    1.24 +new Handle:g_Cvar_RunOff = INVALID_HANDLE;
    1.25 +new Handle:g_Cvar_RunOffPercent = INVALID_HANDLE;
    1.26  
    1.27  new Handle:g_VoteTimer = INVALID_HANDLE;
    1.28  new Handle:g_RetryTimer = INVALID_HANDLE;
    1.29 @@ -126,6 +138,8 @@
    1.30  	g_Cvar_Extend = CreateConVar("sm_mapvote_extend", "0", "Number of extensions allowed each map.", _, true, 0.0);
    1.31  	g_Cvar_DontChange = CreateConVar("sm_mapvote_dontchange", "1", "Specifies if a 'Don't Change' option should be added to early votes", _, true, 0.0);
    1.32  	g_Cvar_VoteDuration = CreateConVar("sm_mapvote_voteduration", "20", "Specifies how long the mapvote should be available for.", _, true, 5.0);
    1.33 +	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);
    1.34 +	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);
    1.35  	
    1.36  	RegAdminCmd("sm_mapvote", Command_Mapvote, ADMFLAG_CHANGEMAP, "sm_mapvote - Forces MapChooser to attempt to run a map vote now.");
    1.37  	RegAdminCmd("sm_setnextmap", Command_SetNextmap, ADMFLAG_CHANGEMAP, "sm_setnextmap <map>");
    1.38 @@ -526,6 +540,7 @@
    1.39   *
    1.40   * @param when			When the resulting map change should occur.
    1.41   * @param inputlist		Optional list of maps to use for the vote, otherwise an internal list of nominations + random maps will be used.
    1.42 + * @param noSpecials	Block special vote options like extend/nochange (upgrade this to bitflags instead?)
    1.43   */
    1.44  InitiateVote(MapChange:when, Handle:inputlist=INVALID_HANDLE)
    1.45  {
    1.46 @@ -586,6 +601,7 @@
    1.47  		{
    1.48  			GetArrayString(g_NominateList, i, map, sizeof(map));
    1.49  			AddMenuItem(g_VoteMenu, map, map);
    1.50 +			RemoveStringFromArray(g_NextMapList, map);
    1.51  			
    1.52  			/* Notify Nominations that this map is now free */
    1.53  			Call_StartForward(g_NominationsResetForward);
    1.54 @@ -598,6 +614,7 @@
    1.55  		for (new i=nominationsToAdd; i<nominateCount; i++)
    1.56  		{
    1.57  			GetArrayString(g_NominateList, i, map, sizeof(map));
    1.58 +			/* These maps shouldn't be excluded from the vote as they weren't really nominated at all */
    1.59  			
    1.60  			/* Notify Nominations that this map is now free */
    1.61  			Call_StartForward(g_NominationsResetForward);
    1.62 @@ -617,13 +634,9 @@
    1.63  			GetArrayString(g_NextMapList, count, map, sizeof(map));
    1.64  			count++;
    1.65  			
    1.66 -			//Check if this map is in the nominate list (and thus already in the vote) */
    1.67 -			if (FindStringInArray(g_NominateList, map) == -1)
    1.68 -			{
    1.69 -				/* Insert the map and increment our count */
    1.70 -				AddMenuItem(g_VoteMenu, map, map);
    1.71 -				i++;
    1.72 -			}
    1.73 +			/* Insert the map and increment our count */
    1.74 +			AddMenuItem(g_VoteMenu, map, map);
    1.75 +			i++;
    1.76  			
    1.77  			if (count >= availableMaps)
    1.78  			{
    1.79 @@ -670,19 +683,13 @@
    1.80  	PrintToChatAll("[SM] %t", "Nextmap Voting Started");
    1.81  }
    1.82  
    1.83 -public Handler_MapVoteFinished(Handle:menu,
    1.84 +public Handler_VoteFinishedGeneric(Handle:menu,
    1.85  						   num_votes, 
    1.86  						   num_clients,
    1.87  						   const client_info[][2], 
    1.88  						   num_items,
    1.89  						   const item_info[][2])
    1.90  {
    1.91 -	if (num_votes == 0)
    1.92 -	{
    1.93 -		LogError("No Votes recorded yet Advanced callback fired - Tell pRED* to fix this");
    1.94 -		return;	
    1.95 -	}
    1.96 -	
    1.97  	decl String:map[32];
    1.98  	GetMenuItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map, sizeof(map));
    1.99  
   1.100 @@ -771,6 +778,53 @@
   1.101  	}	
   1.102  }
   1.103  
   1.104 +public Handler_MapVoteFinished(Handle:menu,
   1.105 +						   num_votes, 
   1.106 +						   num_clients,
   1.107 +						   const client_info[][2], 
   1.108 +						   num_items,
   1.109 +						   const item_info[][2])
   1.110 +{
   1.111 +	if (GetConVarBool(g_Cvar_RunOff) && num_items > 1)
   1.112 +	{
   1.113 +		new Float:winningvotes = float(item_info[0][VOTEINFO_ITEM_VOTES]);
   1.114 +		new Float:required = num_votes * (GetConVarFloat(g_Cvar_RunOffPercent) / 100.0);
   1.115 +		
   1.116 +		if (winningvotes <= required)
   1.117 +		{
   1.118 +			/* Insufficient Winning margin - Lets do a runoff */
   1.119 +			g_VoteMenu = CreateMenu(Handler_MapVoteMenu, MenuAction:MENU_ACTIONS_ALL);
   1.120 +			SetMenuTitle(g_VoteMenu, "Runoff Vote Nextmap");
   1.121 +			SetVoteResultCallback(g_VoteMenu, Handler_VoteFinishedGeneric);
   1.122 +
   1.123 +			decl String:map[32];
   1.124 +			decl String:info1[32];
   1.125 +			decl String:info2[32];
   1.126 +			
   1.127 +			GetMenuItem(menu, item_info[0][VOTEINFO_ITEM_INDEX], map, sizeof(map), _, info1, sizeof(info1));
   1.128 +			AddMenuItem(g_VoteMenu, map, info1);
   1.129 +			GetMenuItem(menu, item_info[1][VOTEINFO_ITEM_INDEX], map, sizeof(map), _, info2, sizeof(info2));
   1.130 +			AddMenuItem(g_VoteMenu, map, info2);
   1.131 +			
   1.132 +			new voteDuration = GetConVarInt(g_Cvar_VoteDuration);
   1.133 +			SetMenuExitButton(g_VoteMenu, false);
   1.134 +			VoteMenuToAll(g_VoteMenu, voteDuration);
   1.135 +			
   1.136 +			/* Notify */
   1.137 +			new Float:map1percent = float(item_info[0][VOTEINFO_ITEM_VOTES])/ float(num_votes) * 100;
   1.138 +			new Float:map2percent = float(item_info[1][VOTEINFO_ITEM_VOTES])/ float(num_votes) * 100;
   1.139 +			
   1.140 +			
   1.141 +			PrintToChatAll("[SM] %t", "Starting Runoff", GetConVarFloat(g_Cvar_RunOffPercent), info1, map1percent, info2, map2percent);
   1.142 +			LogMessage("Voting for next map was indecisive, beginning runoff vote");
   1.143 +					
   1.144 +			return;
   1.145 +		}
   1.146 +	}
   1.147 +	
   1.148 +	Handler_VoteFinishedGeneric(menu, num_votes, num_clients, client_info, num_items, item_info);
   1.149 +}
   1.150 +
   1.151  public Handler_MapVoteMenu(Handle:menu, MenuAction:action, param1, param2)
   1.152  {
   1.153  	switch (action)
   1.154 @@ -865,33 +919,35 @@
   1.155  	return Plugin_Stop;
   1.156  }
   1.157  
   1.158 +bool:RemoveStringFromArray(Handle:array, String:str[])
   1.159 +{
   1.160 +	new index = FindStringInArray(array, str);
   1.161 +	if (index != -1)
   1.162 +	{
   1.163 +		RemoveFromArray(array, index);
   1.164 +		return true;
   1.165 +	}
   1.166 +	
   1.167 +	return false;
   1.168 +}
   1.169 +
   1.170  CreateNextVote()
   1.171  {
   1.172 -	if(g_NextMapList != INVALID_HANDLE)
   1.173 -	{
   1.174 -		ClearArray(g_NextMapList);
   1.175 -	}
   1.176 +	assert(g_NextMapList)
   1.177 +	ClearArray(g_NextMapList);
   1.178  	
   1.179  	decl String:map[32];
   1.180 -	new index, Handle:tempMaps  = CloneArray(g_MapList);
   1.181 +	new Handle:tempMaps  = CloneArray(g_MapList);
   1.182  	
   1.183  	GetCurrentMap(map, sizeof(map));
   1.184 -	index = FindStringInArray(tempMaps, map);
   1.185 -	if (index != -1)
   1.186 -	{
   1.187 -		RemoveFromArray(tempMaps, index);
   1.188 -	}	
   1.189 +	RemoveStringFromArray(tempMaps, map);
   1.190  	
   1.191  	if (GetConVarInt(g_Cvar_ExcludeMaps) && GetArraySize(tempMaps) > GetConVarInt(g_Cvar_ExcludeMaps))
   1.192  	{
   1.193  		for (new i = 0; i < GetArraySize(g_OldMapList); i++)
   1.194  		{
   1.195  			GetArrayString(g_OldMapList, i, map, sizeof(map));
   1.196 -			index = FindStringInArray(tempMaps, map);
   1.197 -			if (index != -1)
   1.198 -			{
   1.199 -				RemoveFromArray(tempMaps, index);
   1.200 -			}
   1.201 +			RemoveStringFromArray(tempMaps, map);
   1.202  		}	
   1.203  	}
   1.204