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 +}