core/MenuVoting.cpp
changeset 2801 f70c4df158b3
parent 2737 eb7713d87fa1
child 3004 e3ac0dc6d9a4
     1.1 --- a/core/MenuVoting.cpp	Wed Sep 16 13:38:04 2009 +1200
     1.2 +++ b/core/MenuVoting.cpp	Thu Sep 17 18:54:40 2009 +1200
     1.3 @@ -34,9 +34,55 @@
     1.4  #include "MenuVoting.h"
     1.5  #include "PlayerManager.h"
     1.6  #include "sourcemm_api.h"
     1.7 +#include <sourcemod.h>
     1.8 +#include <Logger.h>
     1.9 +#include <HalfLife2.h>
    1.10 +#include <mathlib.h>
    1.11 +#include <const.h>
    1.12 +#include <Translator.h>
    1.13  
    1.14  float g_next_vote = 0.0f;
    1.15  
    1.16 +#define VOTE_NOT_VOTING -2
    1.17 +#define VOTE_PENDING -1
    1.18 +
    1.19 +ConVar sm_vote_hintbox("sm_vote_progress_hintbox", 
    1.20 +					   "0", 
    1.21 +					   0, 
    1.22 +					   "Show current vote progress in a hint box",
    1.23 +					   true,
    1.24 +					   0.0,
    1.25 +					   true,
    1.26 +					   1.0);
    1.27 +
    1.28 +ConVar sm_vote_chat("sm_vote_progress_chat", 
    1.29 +					   "0", 
    1.30 +					   0, 
    1.31 +					   "Show current vote progress as chat messages",
    1.32 +					   true,
    1.33 +					   0.0,
    1.34 +					   true,
    1.35 +					   1.0);
    1.36 +
    1.37 +ConVar sm_vote_console("sm_vote_progress_console", 
    1.38 +					   "0", 
    1.39 +					   0, 
    1.40 +					   "Show current vote progress as console messages",
    1.41 +					   true,
    1.42 +					   0.0,
    1.43 +					   true,
    1.44 +					   1.0);
    1.45 +
    1.46 +ConVar sm_vote_client_console("sm_vote_progress_client_console", 
    1.47 +					   "0", 
    1.48 +					   0, 
    1.49 +					   "Show current vote progress as console messages to clients",
    1.50 +					   true,
    1.51 +					   0.0,
    1.52 +					   true,
    1.53 +					   1.0);
    1.54 +
    1.55 +
    1.56  #if SOURCE_ENGINE >= SE_ORANGEBOX
    1.57  void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
    1.58  #else
    1.59 @@ -117,7 +163,7 @@
    1.60  	 * newly connected client is not allowed to vote. 
    1.61  	 */
    1.62  	int item;
    1.63 -	if ((item = m_ClientVotes[client]) >= -1)
    1.64 +	if ((item = m_ClientVotes[client]) >= VOTE_PENDING)
    1.65  	{
    1.66  		if (item >= 0)
    1.67  		{
    1.68 @@ -125,7 +171,7 @@
    1.69  			assert(m_Votes[item] > 0);
    1.70  			m_Votes[item]--;
    1.71  		}
    1.72 -		m_ClientVotes[client] = -2;
    1.73 +		m_ClientVotes[client] = VOTE_NOT_VOTING;
    1.74  	}
    1.75  }
    1.76  
    1.77 @@ -189,13 +235,13 @@
    1.78  		return false;
    1.79  	}
    1.80  
    1.81 -	return (m_ClientVotes[client] > -2);
    1.82 +	return (m_ClientVotes[client] > VOTE_NOT_VOTING);
    1.83  }
    1.84  
    1.85  bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
    1.86  {
    1.87  	if (!IsClientInVotePool(client)
    1.88 -		|| m_ClientVotes[client] == -1)
    1.89 +		|| m_ClientVotes[client] == VOTE_PENDING)
    1.90  	{
    1.91  		return false;
    1.92  	}
    1.93 @@ -223,7 +269,9 @@
    1.94  		assert((unsigned)m_ClientVotes[client] < m_Items);
    1.95  		assert(m_Votes[m_ClientVotes[client]] > 0);
    1.96  		m_Votes[m_ClientVotes[client]]--;
    1.97 -		m_ClientVotes[client] = -1;
    1.98 +		m_ClientVotes[client] = VOTE_PENDING;
    1.99 +		m_Revoting[client] = true;
   1.100 +		m_NumVotes--;
   1.101  	}
   1.102  
   1.103  	if (m_nMenuTime == MENU_TIME_FOREVER)
   1.104 @@ -259,7 +307,8 @@
   1.105  	/* Mark all clients as not voting */
   1.106  	for (int i=1; i<=gpGlobals->maxClients; i++)
   1.107  	{
   1.108 -		m_ClientVotes[i] = -2;
   1.109 +		m_ClientVotes[i] = VOTE_NOT_VOTING;
   1.110 +		m_Revoting[i] = false;
   1.111  	}
   1.112  
   1.113  	m_Items = menu->GetItemCount();
   1.114 @@ -303,6 +352,8 @@
   1.115  
   1.116  	m_pHandler->OnMenuVoteStart(m_pCurMenu);
   1.117  
   1.118 +	m_displayTimer = g_Timers.CreateTimer(this, 1.0, NULL, TIMER_FLAG_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
   1.119 +
   1.120  	/* By now we know how many clients were set.  
   1.121  	 * If there are none, we should end IMMEDIATELY.
   1.122  	 */
   1.123 @@ -310,6 +361,8 @@
   1.124  	{
   1.125  		EndVoting();
   1.126  	}
   1.127 +
   1.128 +	m_TotalClients = m_Clients;
   1.129  }
   1.130  
   1.131  void VoteMenuHandler::DecrementPlayerCount()
   1.132 @@ -346,6 +399,11 @@
   1.133  		g_next_vote = gpGlobals->curtime + fVoteDelay;
   1.134  	}
   1.135  
   1.136 +	if (m_displayTimer)
   1.137 +	{
   1.138 +		g_Timers.KillTimer(m_displayTimer);
   1.139 +	}
   1.140 +
   1.141  	if (m_bCancelled)
   1.142  	{
   1.143  		/* If we were cancelled, don't bother tabulating anything.
   1.144 @@ -392,7 +450,7 @@
   1.145  	/* Build the client list */
   1.146  	for (int i=1; i<=gpGlobals->maxClients; i++)
   1.147  	{
   1.148 -		if (m_ClientVotes[i] >= -1)
   1.149 +		if (m_ClientVotes[i] >= VOTE_PENDING)
   1.150  		{
   1.151  			client_vote[vote.num_clients].client = i;
   1.152  			client_vote[vote.num_clients].item = m_ClientVotes[i];
   1.153 @@ -436,7 +494,7 @@
   1.154  
   1.155  void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
   1.156  {
   1.157 -	m_ClientVotes[client] = -1;
   1.158 +	m_ClientVotes[client] = VOTE_PENDING;
   1.159  	m_pHandler->OnMenuDisplay(menu, client, display);
   1.160  }
   1.161  
   1.162 @@ -458,6 +516,55 @@
   1.163  		m_ClientVotes[client] = item;
   1.164  		m_Votes[item]++;
   1.165  		m_NumVotes++;
   1.166 +
   1.167 +		if (sm_vote_chat.GetBool() || sm_vote_console.GetBool())
   1.168 +		{
   1.169 +			static char buffer[1024];
   1.170 +			ItemDrawInfo dr;
   1.171 +			menu->GetItemInfo(item, &dr);
   1.172 +
   1.173 +			if (sm_vote_console.GetBool())
   1.174 +			{
   1.175 +				int target = SOURCEMOD_SERVER_LANGUAGE;
   1.176 +				CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For", &target, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
   1.177 +				Engine_LogPrintWrapper(buffer);
   1.178 +			}
   1.179 +			
   1.180 +			if (sm_vote_chat.GetBool() || sm_vote_client_console.GetBool())
   1.181 +			{
   1.182 +				int maxclients = g_Players.GetMaxClients();
   1.183 +				for (int i=1; i<=maxclients; i++)
   1.184 +				{	
   1.185 +					CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
   1.186 +					assert(pPlayer);
   1.187 +
   1.188 +					if (pPlayer->IsInGame())
   1.189 +					{
   1.190 +						if (m_Revoting[client])
   1.191 +						{
   1.192 +							CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Changed Vote", &i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
   1.193 +						}
   1.194 +						else
   1.195 +						{
   1.196 +							CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For", &i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
   1.197 +						}
   1.198 +
   1.199 +						if (sm_vote_chat.GetBool())
   1.200 +						{
   1.201 +							g_HL2.TextMsg(i, HUD_PRINTTALK, buffer);
   1.202 +						}
   1.203 +
   1.204 +						if (sm_vote_client_console.GetBool())
   1.205 +						{
   1.206 +							engine->ClientPrintf(pPlayer->GetEdict(), buffer);
   1.207 +						}		
   1.208 +					}
   1.209 +				}
   1.210 +			}
   1.211 +		}
   1.212 +
   1.213 +		BuildVoteLeaders();
   1.214 +		DrawHintProgress();
   1.215  	}
   1.216  
   1.217  	m_pHandler->OnMenuSelect(menu, client, item);
   1.218 @@ -480,6 +587,9 @@
   1.219  	m_NumVotes = 0;
   1.220  	m_bCancelled = false;
   1.221  	m_pHandler = NULL;
   1.222 +	m_leaderList[0] = '\0';
   1.223 +	m_displayTimer = NULL;
   1.224 +	m_TotalClients = 0;
   1.225  }
   1.226  
   1.227  void VoteMenuHandler::CancelVoting()
   1.228 @@ -502,3 +612,85 @@
   1.229  	return m_bCancelled;
   1.230  }
   1.231  
   1.232 +void VoteMenuHandler::DrawHintProgress()
   1.233 +{
   1.234 +	if (!sm_vote_hintbox.GetBool())
   1.235 +	{
   1.236 +		return;
   1.237 +	}
   1.238 +
   1.239 +	static char buffer[1024];
   1.240 +
   1.241 +	float timeRemaining = (m_fStartTime + m_nMenuTime) - gpGlobals->curtime;
   1.242 +	if (timeRemaining < 0)
   1.243 +	{
   1.244 +		timeRemaining = 0.0;
   1.245 +	}
   1.246 +
   1.247 +	int iTimeRemaining = RoundFloatToInt(timeRemaining);
   1.248 +	
   1.249 +	int maxclients = g_Players.GetMaxClients();
   1.250 +	for (int i=1; i<=maxclients; i++)
   1.251 +	{
   1.252 +		if (g_Players.GetPlayerByIndex(i)->IsInGame())
   1.253 +		{
   1.254 +			CoreTranslate(buffer, sizeof(buffer), "%T%s", 6, NULL, "Vote Count", &i, &m_NumVotes, &m_TotalClients, &iTimeRemaining, &m_leaderList);
   1.255 +			g_HL2.HintTextMsg(i, buffer);
   1.256 +		}
   1.257 +	}
   1.258 +}
   1.259 +
   1.260 +void VoteMenuHandler::BuildVoteLeaders()
   1.261 +{
   1.262 +	if (m_NumVotes == 0 || !sm_vote_hintbox.GetBool())
   1.263 +	{
   1.264 +		return;
   1.265 +	}
   1.266 +
   1.267 +	menu_vote_result_t vote;
   1.268 +	menu_vote_result_t::menu_item_vote_t item_vote[256];
   1.269 +
   1.270 +	memset(&vote, 0, sizeof(vote));
   1.271 +
   1.272 +	/* Build the item list */
   1.273 +	for (unsigned int i=0; i<m_Items; i++)
   1.274 +	{
   1.275 +		if (m_Votes[i] > 0)
   1.276 +		{
   1.277 +			item_vote[vote.num_items].count = m_Votes[i];
   1.278 +			item_vote[vote.num_items].item = i;
   1.279 +			vote.num_votes += m_Votes[i];
   1.280 +			vote.num_items++;
   1.281 +		}
   1.282 +	}
   1.283 +	vote.item_list = item_vote;
   1.284 +	assert(vote.num_votes);
   1.285 +
   1.286 +	/* Sort the item list descending */
   1.287 +	qsort(item_vote,
   1.288 +		vote.num_items,
   1.289 +		sizeof(menu_vote_result_t::menu_item_vote_t),
   1.290 +		SortVoteItems);
   1.291 +
   1.292 +	/* Take the top 3 (if applicable) and draw them */
   1.293 +	int len = 0;
   1.294 +	for (unsigned int i=0; i<vote.num_items && i<3; i++)
   1.295 +	{
   1.296 +		int curItem = vote.item_list[i].item;
   1.297 +		ItemDrawInfo dr;
   1.298 +		m_pCurMenu->GetItemInfo(curItem, &dr);
   1.299 +		len += g_SourceMod.Format(m_leaderList + len, sizeof(m_leaderList) - len, "\n%i. %s: (%i)", i+1, dr.display, vote.item_list[i].count);
   1.300 +	}
   1.301 +}
   1.302 +
   1.303 +SourceMod::ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData)
   1.304 +{
   1.305 +	DrawHintProgress();
   1.306 +
   1.307 +	return Pl_Continue;
   1.308 +}
   1.309 +
   1.310 +void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData)
   1.311 +{
   1.312 +	m_displayTimer = NULL;
   1.313 +}