core/MenuManager.cpp
changeset 877 898c39fbfde9
parent 797 8ed539963aa4
child 879 f1e33b35f3b6
     1.1 --- a/core/MenuManager.cpp	Tue Jun 05 05:45:48 2007 +0000
     1.2 +++ b/core/MenuManager.cpp	Tue Jun 05 16:27:45 2007 +0000
     1.3 @@ -12,9 +12,9 @@
     1.4   * Version: $Id$
     1.5   */
     1.6  
     1.7 -
     1.8 +#include <time.h>
     1.9  #include <stdarg.h>
    1.10 -#include <time.h>
    1.11 +#include <stdlib.h>
    1.12  #include "MenuManager.h"
    1.13  #include "sm_stringutil.h"
    1.14  #include "sourcemm_api.h"
    1.15 @@ -25,115 +25,188 @@
    1.16  
    1.17  MenuManager g_Menus;
    1.18  
    1.19 -/*************************************
    1.20 - *************************************
    1.21 - **** BROADCAST HANDLING WRAPPERS ****
    1.22 - *************************************
    1.23 - *************************************/
    1.24 +/*******************************
    1.25 + *******************************
    1.26 + ******** VOTE HANDLER *********
    1.27 + *******************************
    1.28 + *******************************/
    1.29  
    1.30 -BroadcastHandler::BroadcastHandler(IMenuHandler *handler) : m_pHandler(handler), numClients(0)
    1.31 -{
    1.32 -}
    1.33 -
    1.34 -unsigned int BroadcastHandler::GetMenuAPIVersion2()
    1.35 +unsigned int VoteMenuHandler::GetMenuAPIVersion2()
    1.36  {
    1.37  	return m_pHandler->GetMenuAPIVersion2();
    1.38  }
    1.39  
    1.40 -void BroadcastHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
    1.41 +bool VoteMenuHandler::IsVoteInProgress()
    1.42 +{
    1.43 +	return (m_pCurMenu != NULL);
    1.44 +}
    1.45 +
    1.46 +void VoteMenuHandler::InitializeVoting(IBaseMenu *menu)
    1.47 +{
    1.48 +	m_Items = menu->GetItemCount();
    1.49 +
    1.50 +	if (m_Votes.size() < (size_t)m_Items)
    1.51 +	{
    1.52 +		/* Only clear the items we need to... */
    1.53 +		size_t size = m_Votes.size();
    1.54 +		for (size_t i=0; i<size; i++)
    1.55 +		{
    1.56 +			m_Votes[i] = 0;
    1.57 +		}
    1.58 +		m_Votes.resize(m_Items, 0);
    1.59 +	} else {
    1.60 +		for (unsigned int i=0; i<m_Items; i++)
    1.61 +		{
    1.62 +			m_Votes[i] = 0;
    1.63 +		}
    1.64 +	}
    1.65 +
    1.66 +	m_pCurMenu = menu;
    1.67 +
    1.68 +	m_pHandler->OnMenuStart(m_pCurMenu);
    1.69 +}
    1.70 +
    1.71 +void VoteMenuHandler::StartVoting()
    1.72 +{
    1.73 +	m_bStarted = true;
    1.74 +
    1.75 +	m_pHandler->OnMenuVoteStart(m_pCurMenu);
    1.76 +
    1.77 +	/* By now we know how many clients were set.  
    1.78 +	 * If there are none, we should end IMMEDIATELY.
    1.79 +	 */
    1.80 +	if (m_Clients == 0)
    1.81 +	{
    1.82 +		EndVoting();
    1.83 +	}
    1.84 +}
    1.85 +
    1.86 +void VoteMenuHandler::DecrementPlayerCount()
    1.87 +{
    1.88 +	assert(m_Clients > 0);
    1.89 +
    1.90 +	m_Clients--;
    1.91 +
    1.92 +	if (m_bStarted && m_Clients == 0)
    1.93 +	{
    1.94 +		EndVoting();
    1.95 +	}
    1.96 +}
    1.97 +
    1.98 +void VoteMenuHandler::EndVoting()
    1.99 +{
   1.100 +	unsigned int chosen = 0;
   1.101 +
   1.102 +	/* If we got zero votes, take a shortcut. */
   1.103 +	if (m_NumVotes == 0)
   1.104 +	{
   1.105 +		/* Pick a random item and then jump far, far away. */
   1.106 +		srand((unsigned int)(time(NULL)));
   1.107 +		chosen = (unsigned int)rand() % static_cast<unsigned int>(m_Votes.size());
   1.108 +		goto picked_item;
   1.109 +	}
   1.110 +
   1.111 +	/* We can't have more dups than this!
   1.112 +	 * This is the max number of players.
   1.113 +	 */
   1.114 +	unsigned int dup_array[256];
   1.115 +	unsigned int dup_count = 0;
   1.116 +
   1.117 +	size_t highest = 0;
   1.118 +	for (size_t i=1; i<m_Votes.size(); i++)
   1.119 +	{
   1.120 +		if (m_Votes[i] > m_Votes[highest])
   1.121 +		{
   1.122 +			/* If we have a new highest count, mark it and trash the duplicate
   1.123 +			 * list by setting the total to 0.
   1.124 +			 */
   1.125 +			highest = i;
   1.126 +			dup_count = 0;
   1.127 +		} else if (m_Votes[i] == m_Votes[highest]) {
   1.128 +			/* If they're equal, mark it in the duplicate list.
   1.129 +			 * We'll add in the original later.
   1.130 +			 */
   1.131 +			dup_array[dup_count++] = i;
   1.132 +		}
   1.133 +	}
   1.134 +
   1.135 +	/* Check if we need to pick from the duplicate list */
   1.136 +	if (dup_count)
   1.137 +	{
   1.138 +		/* Re-add the original to the list because it's not in there. */
   1.139 +		dup_array[dup_count++] = (unsigned int)highest;
   1.140 +
   1.141 +		/* Pick a random slot. */
   1.142 +		srand((unsigned int)(time(NULL)));
   1.143 +		unsigned int r = (unsigned int)rand() % dup_count;
   1.144 +
   1.145 +		/* Pick the item. */
   1.146 +		chosen = dup_array[r];
   1.147 +	} else {
   1.148 +		chosen = (unsigned int)highest;
   1.149 +	}
   1.150 +
   1.151 +picked_item:
   1.152 +	m_pHandler->OnMenuVoteEnd(m_pCurMenu, chosen);
   1.153 +	m_pHandler->OnMenuEnd(m_pCurMenu);
   1.154 +	InternalReset();
   1.155 +}
   1.156 +
   1.157 +void VoteMenuHandler::OnMenuStart(IBaseMenu *menu)
   1.158 +{
   1.159 +	m_Clients++;
   1.160 +}
   1.161 +
   1.162 +void VoteMenuHandler::OnMenuEnd(IBaseMenu *menu)
   1.163 +{
   1.164 +	DecrementPlayerCount();
   1.165 +}
   1.166 +
   1.167 +void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
   1.168  {
   1.169  	m_pHandler->OnMenuCancel(menu, client, reason);
   1.170  }
   1.171  
   1.172 -void BroadcastHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
   1.173 +void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
   1.174  {
   1.175 -	numClients++;
   1.176  	m_pHandler->OnMenuDisplay(menu, client, display);
   1.177  }
   1.178  
   1.179 -void BroadcastHandler::OnBroadcastEnd(IBaseMenu *menu)
   1.180 +void VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display)
   1.181  {
   1.182 -	g_Menus.FreeBroadcastHandler(this);
   1.183 +	m_pHandler->OnMenuDisplayItem(menu, client, item, display);
   1.184 +}
   1.185 +
   1.186 +void VoteMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
   1.187 +{
   1.188 +	m_pHandler->OnMenuDrawItem(menu, client, item, style);
   1.189  }
   1.190  
   1.191 -void BroadcastHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
   1.192 +void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
   1.193  {
   1.194 +	/* Check by our item count, NOT the vote array size */
   1.195 +	if (item < m_Items)
   1.196 +	{
   1.197 +		m_Votes[item]++;
   1.198 +		m_NumVotes++;
   1.199 +	}
   1.200 +
   1.201  	m_pHandler->OnMenuSelect(menu, client, item);
   1.202  }
   1.203  
   1.204 -void BroadcastHandler::OnMenuEnd(IBaseMenu *menu)
   1.205 -{
   1.206 -	assert(numClients > 0);
   1.207 -
   1.208 -	/* Only fire if all clients have gotten a menu end */
   1.209 -	if (--numClients == 0)
   1.210 -	{
   1.211 -		IMenuHandler *pHandler = m_pHandler;
   1.212 -		OnBroadcastEnd(menu);
   1.213 -		pHandler->OnMenuEnd(menu);
   1.214 -	}
   1.215 -}
   1.216 -
   1.217 -VoteHandler::VoteHandler(IMenuVoteHandler *handler) 
   1.218 -: BroadcastHandler(handler), m_pVoteHandler(handler)
   1.219 +void VoteMenuHandler::Reset(IMenuHandler *mh)
   1.220  {
   1.221 -}
   1.222 -
   1.223 -void VoteHandler::Initialize(IBaseMenu *menu)
   1.224 -{
   1.225 -	unsigned int numItems = menu->GetItemCount();
   1.226 -
   1.227 -	if (m_counts.size() >= numItems)
   1.228 -	{
   1.229 -		for (size_t i=0; i<numItems; i++)
   1.230 -		{
   1.231 -			m_counts[i] = 0;
   1.232 -		}
   1.233 -	} else {
   1.234 -		for (size_t i=0; i<m_counts.size(); i++)
   1.235 -		{
   1.236 -			m_counts[i] = 0;
   1.237 -		}
   1.238 -		m_counts.resize(numItems, 0);
   1.239 -	}
   1.240 +	m_pHandler = mh;
   1.241 +	InternalReset();
   1.242  }
   1.243  
   1.244 -void VoteHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
   1.245 -{
   1.246 -	if (item < numItems)
   1.247 -	{
   1.248 -		m_counts[item]++;
   1.249 -	}
   1.250 -
   1.251 -	BroadcastHandler::OnMenuSelect(menu, client, item);
   1.252 -}
   1.253 -
   1.254 -void VoteHandler::OnBroadcastEnd(IBaseMenu *menu)
   1.255 +void VoteMenuHandler::InternalReset()
   1.256  {
   1.257 -	m_ties.clear();
   1.258 -
   1.259 -	size_t highest = 0;
   1.260 -	for (size_t i=1; i<numItems; i++)
   1.261 -	{
   1.262 -		if (m_counts[i] > m_counts[highest])
   1.263 -		{
   1.264 -			m_ties.clear();
   1.265 -			highest = i;
   1.266 -		} else if (m_counts[i] == m_counts[highest]) {
   1.267 -			m_ties.push_back(i);
   1.268 -		}
   1.269 -	}
   1.270 -
   1.271 -	if (m_ties.size())
   1.272 -	{
   1.273 -		m_ties.push_back(highest);
   1.274 -		srand(static_cast<unsigned int>(time(NULL)));
   1.275 -		highest = m_ties[rand() % m_ties.size()];
   1.276 -	}
   1.277 -
   1.278 -	m_pVoteHandler->OnMenuVoteEnd(menu, highest);
   1.279 -
   1.280 -	g_Menus.FreeVoteHandler(this);
   1.281 +	m_Clients = 0;
   1.282 +	m_Items = 0;
   1.283 +	m_bStarted = false;
   1.284 +	m_pCurMenu = NULL;
   1.285 +	m_NumVotes = 0;
   1.286  }
   1.287  
   1.288  /*******************************
   1.289 @@ -169,12 +242,6 @@
   1.290  	g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
   1.291  	g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
   1.292  
   1.293 -	while (!m_BroadcastHandlers.empty())
   1.294 -	{
   1.295 -		delete m_BroadcastHandlers.front();
   1.296 -		m_BroadcastHandlers.pop();
   1.297 -	}
   1.298 -
   1.299  	while (!m_VoteHandlers.empty())
   1.300  	{
   1.301  		delete m_VoteHandlers.front();
   1.302 @@ -659,119 +726,34 @@
   1.303  	return display;
   1.304  }
   1.305  
   1.306 -#if 0
   1.307 -unsigned int MenuManager::BroadcastMenu(IBaseMenu *menu, 
   1.308 -										IMenuHandler *handler, 
   1.309 -										int clients[], 
   1.310 -										unsigned int numClients, 
   1.311 -										unsigned int time)
   1.312 -{
   1.313 -	BroadcastHandler *bh;
   1.314 -
   1.315 -	if (m_BroadcastHandlers.empty())
   1.316 -	{
   1.317 -		bh = new BroadcastHandler(handler);
   1.318 -	} else {
   1.319 -		bh = m_BroadcastHandlers.front();
   1.320 -		m_BroadcastHandlers.pop();
   1.321 -		bh->m_pHandler = handler;
   1.322 -		bh->numClients = 0;
   1.323 -	}
   1.324 -
   1.325 -	handler->OnMenuStart(menu);
   1.326 -
   1.327 -	unsigned int total = 0;
   1.328 -	for (unsigned int i=0; i<numClients; i++)
   1.329 -	{
   1.330 -		/* Only continue if displaying works */
   1.331 -		if (!menu->Display(clients[i], bh, time))
   1.332 -		{
   1.333 -			continue;
   1.334 -		}
   1.335 -
   1.336 -		/* :TODO: Allow sourcetv only, not all bots */
   1.337 -		CPlayer *player = g_Players.GetPlayerByIndex(clients[i]);
   1.338 -		if (player->IsFakeClient())
   1.339 -		{
   1.340 -			continue;
   1.341 -		}
   1.342 -
   1.343 -		total++;
   1.344 -	}
   1.345 -
   1.346 -	if (!total)
   1.347 -	{
   1.348 -		/* End the broadcast here */
   1.349 -		handler->OnMenuEnd(menu);
   1.350 -		FreeBroadcastHandler(bh);
   1.351 -	}
   1.352 -
   1.353 -	return total;
   1.354 -}
   1.355 -
   1.356 -unsigned int MenuManager::VoteMenu(IBaseMenu *menu,
   1.357 -								   IMenuVoteHandler *handler,
   1.358 -								   int clients[],
   1.359 -								   unsigned int numClients,
   1.360 -								   unsigned int time)
   1.361 -{
   1.362 -	VoteHandler *vh;
   1.363 -
   1.364 -	if (m_VoteHandlers.empty())
   1.365 -	{
   1.366 -		vh = new VoteHandler(handler);
   1.367 -	} else {
   1.368 -		vh = m_VoteHandlers.front();
   1.369 -		m_VoteHandlers.pop();
   1.370 -		vh->m_pHandler = handler;
   1.371 -		vh->numClients = 0;
   1.372 -	}
   1.373 -
   1.374 -	vh->Initialize(menu);
   1.375 -	handler->OnMenuStart(menu);
   1.376 -
   1.377 -	unsigned int total = 0;
   1.378 -	for (unsigned int i=0; i<numClients; i++)
   1.379 -	{
   1.380 -		/* Only continue if displaying works */
   1.381 -		if (!menu->Display(clients[i], vh, time))
   1.382 -		{
   1.383 -			continue;
   1.384 -		}
   1.385 -
   1.386 -		/* :TODO: Allow sourcetv only, not all bots */
   1.387 -		CPlayer *player = g_Players.GetPlayerByIndex(clients[i]);
   1.388 -		if (player->IsFakeClient())
   1.389 -		{
   1.390 -			continue;
   1.391 -		}
   1.392 -
   1.393 -		total++;
   1.394 -	}
   1.395 -
   1.396 -	if (!total)
   1.397 -	{
   1.398 -		/* End the broadcast here */
   1.399 -		handler->OnMenuEnd(menu);
   1.400 -		FreeVoteHandler(vh);
   1.401 -	}
   1.402 -
   1.403 -	return total;
   1.404 -}
   1.405 -#endif
   1.406 -
   1.407 -void MenuManager::FreeBroadcastHandler(BroadcastHandler *bh)
   1.408 -{
   1.409 -	m_BroadcastHandlers.push(bh);
   1.410 -}
   1.411 -
   1.412 -void MenuManager::FreeVoteHandler(VoteHandler *vh)
   1.413 -{
   1.414 -	m_VoteHandlers.push(vh);
   1.415 -}
   1.416 -
   1.417  IMenuStyle *MenuManager::GetDefaultStyle()
   1.418  {
   1.419  	return m_pDefaultStyle;
   1.420  }
   1.421  
   1.422 +IVoteMenuHandler *MenuManager::CreateVoteWrapper(IMenuHandler *mh)
   1.423 +{
   1.424 +	VoteMenuHandler *vh = NULL;
   1.425 +
   1.426 +	if (m_VoteHandlers.empty())
   1.427 +	{
   1.428 +		vh = new VoteMenuHandler;
   1.429 +	} else {
   1.430 +		vh = m_VoteHandlers.front();
   1.431 +		m_VoteHandlers.pop();
   1.432 +	}
   1.433 +
   1.434 +	vh->Reset(mh);
   1.435 +
   1.436 +	return vh;
   1.437 +}
   1.438 +
   1.439 +void MenuManager::ReleaseVoteWrapper(IVoteMenuHandler *mh)
   1.440 +{
   1.441 +	if (mh == NULL)
   1.442 +	{
   1.443 +		return;
   1.444 +	}
   1.445 +
   1.446 +	m_VoteHandlers.push((VoteMenuHandler *)mh);
   1.447 +}