core/MenuVoting.cpp
author David Anderson <dvander@alliedmods.net>
Fri Jul 11 06:51:21 2008 +0000 (2008-07-11)
branchrefac-jit
changeset 2192 7602d7fb60d9
parent 2168 c24a6fa957db
permissions -rw-r--r--
fixed a compat regression, forgot msvc does funky things with overloaded virtual calls
dvander@2168
     1
/**
dvander@2168
     2
 * vim: set ts=4 :
dvander@2168
     3
 * =============================================================================
dvander@2168
     4
 * SourceMod
dvander@2168
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
dvander@2168
     6
 * =============================================================================
dvander@2168
     7
 *
dvander@2168
     8
 * This program is free software; you can redistribute it and/or modify it under
dvander@2168
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
dvander@2168
    10
 * Free Software Foundation.
dvander@2168
    11
 * 
dvander@2168
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
dvander@2168
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@2168
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
dvander@2168
    15
 * details.
dvander@2168
    16
 *
dvander@2168
    17
 * You should have received a copy of the GNU General Public License along with
dvander@2168
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@2168
    19
 *
dvander@2168
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
dvander@2168
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
dvander@2168
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
dvander@2168
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
dvander@2168
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
dvander@2168
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
dvander@2168
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
dvander@2168
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@2168
    28
 *
dvander@2168
    29
 * Version: $Id$
dvander@2168
    30
 */
dvander@2168
    31
dvander@2168
    32
#include <string.h>
dvander@2168
    33
#include <stdlib.h>
dvander@2168
    34
#include "MenuVoting.h"
dvander@2168
    35
#include "PlayerManager.h"
dvander@2168
    36
#include "sourcemm_api.h"
dvander@2168
    37
dvander@2168
    38
float g_next_vote = 0.0f;
dvander@2168
    39
dvander@2168
    40
#if defined ORANGEBOX_BUILD
dvander@2168
    41
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
dvander@2168
    42
#else
dvander@2168
    43
void OnVoteDelayChange(ConVar *cvar, const char *value);
dvander@2168
    44
#endif
dvander@2168
    45
ConVar sm_vote_delay("sm_vote_delay",
dvander@2168
    46
					 "30",
dvander@2168
    47
					 0,
dvander@2168
    48
					 "Sets the recommended time in between public votes",
dvander@2168
    49
					 false,
dvander@2168
    50
					 0.0,
dvander@2168
    51
					 false,
dvander@2168
    52
					 0.0,
dvander@2168
    53
					 OnVoteDelayChange);
dvander@2168
    54
dvander@2168
    55
#if defined ORANGEBOX_BUILD
dvander@2168
    56
void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue)
dvander@2168
    57
#else
dvander@2168
    58
void OnVoteDelayChange(ConVar *cvar, const char *value)
dvander@2168
    59
#endif
dvander@2168
    60
{
dvander@2168
    61
	/* See if the new vote delay isn't something we need to account for */
dvander@2168
    62
	if (sm_vote_delay.GetFloat() < 1.0f)
dvander@2168
    63
	{
dvander@2168
    64
		g_next_vote = 0.0f;
dvander@2168
    65
		return;
dvander@2168
    66
	}
dvander@2168
    67
dvander@2168
    68
	/* If there was never a last vote, ignore this change */
dvander@2168
    69
	if (g_next_vote < 0.1f)
dvander@2168
    70
	{
dvander@2168
    71
		return;
dvander@2168
    72
	}
dvander@2168
    73
dvander@2168
    74
	/* Subtract the original value, then add the new one. */
dvander@2168
    75
	g_next_vote -= (float)atof(value);
dvander@2168
    76
	g_next_vote += sm_vote_delay.GetFloat();
dvander@2168
    77
}
dvander@2168
    78
dvander@2168
    79
unsigned int VoteMenuHandler::GetRemainingVoteDelay()
dvander@2168
    80
{
dvander@2168
    81
	if (g_next_vote <= gpGlobals->curtime)
dvander@2168
    82
	{
dvander@2168
    83
		return 0;
dvander@2168
    84
	}
dvander@2168
    85
dvander@2168
    86
	return (unsigned int)(g_next_vote - gpGlobals->curtime);
dvander@2168
    87
}
dvander@2168
    88
dvander@2168
    89
void VoteMenuHandler::OnSourceModAllInitialized()
dvander@2168
    90
{
dvander@2168
    91
	g_Players.AddClientListener(this);
dvander@2168
    92
}
dvander@2168
    93
dvander@2168
    94
void VoteMenuHandler::OnSourceModShutdown()
dvander@2168
    95
{
dvander@2168
    96
	g_Players.RemoveClientListener(this);
dvander@2168
    97
}
dvander@2168
    98
dvander@2168
    99
void VoteMenuHandler::OnSourceModLevelChange(const char *mapName)
dvander@2168
   100
{
dvander@2168
   101
	g_next_vote = 0.0f;
dvander@2168
   102
}
dvander@2168
   103
dvander@2168
   104
unsigned int VoteMenuHandler::GetMenuAPIVersion2()
dvander@2168
   105
{
dvander@2168
   106
	return m_pHandler->GetMenuAPIVersion2();
dvander@2168
   107
}
dvander@2168
   108
dvander@2168
   109
void VoteMenuHandler::OnClientDisconnected(int client)
dvander@2168
   110
{
dvander@2168
   111
	if (!IsVoteInProgress())
dvander@2168
   112
	{
dvander@2168
   113
		return;
dvander@2168
   114
	}
dvander@2168
   115
dvander@2168
   116
	/* Wipe out their vote if they had one.  We have to make sure the the the
dvander@2168
   117
	 * newly connected client is not allowed to vote. 
dvander@2168
   118
	 */
dvander@2168
   119
	int item;
dvander@2168
   120
	if ((item = m_ClientVotes[client]) >= -1)
dvander@2168
   121
	{
dvander@2168
   122
		if (item >= 0)
dvander@2168
   123
		{
dvander@2168
   124
			assert((unsigned)item < m_Items);
dvander@2168
   125
			assert(m_Votes[item] > 0);
dvander@2168
   126
			m_Votes[item]--;
dvander@2168
   127
		}
dvander@2168
   128
		m_ClientVotes[client] = -2;
dvander@2168
   129
	}
dvander@2168
   130
}
dvander@2168
   131
dvander@2168
   132
bool VoteMenuHandler::IsVoteInProgress()
dvander@2168
   133
{
dvander@2168
   134
	return (m_pCurMenu != NULL);
dvander@2168
   135
}
dvander@2168
   136
dvander@2168
   137
bool VoteMenuHandler::StartVote(IBaseMenu *menu,
dvander@2168
   138
								unsigned int num_clients,
dvander@2168
   139
								int clients[],
dvander@2168
   140
								unsigned int max_time,
dvander@2168
   141
								unsigned int flags/* =0 */)
dvander@2168
   142
{
dvander@2168
   143
	if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags))
dvander@2168
   144
	{
dvander@2168
   145
		return false;
dvander@2168
   146
	}
dvander@2168
   147
dvander@2168
   148
	/* Note: we can use game time and not universal time because 
dvander@2168
   149
	 * if we're voting then players are in-game.
dvander@2168
   150
	 */
dvander@2168
   151
dvander@2168
   152
	float fVoteDelay = sm_vote_delay.GetFloat();
dvander@2168
   153
	if (fVoteDelay < 1.0)
dvander@2168
   154
	{
dvander@2168
   155
		g_next_vote = 0.0;
dvander@2168
   156
	}
dvander@2168
   157
	else
dvander@2168
   158
	{
dvander@2168
   159
		/* This little trick breaks for infinite votes!
dvander@2168
   160
		 * However, we just ignore that since those 1) shouldn't exist and 
dvander@2168
   161
		 * 2) people must be checking IsVoteInProgress() beforehand anyway.
dvander@2168
   162
		 */
dvander@2168
   163
		g_next_vote = gpGlobals->curtime + fVoteDelay + (float)max_time;
dvander@2168
   164
	}
dvander@2168
   165
dvander@2168
   166
	m_fStartTime = gpGlobals->curtime;
dvander@2168
   167
	m_nMenuTime = max_time;
dvander@2168
   168
dvander@2168
   169
	for (unsigned int i=0; i<num_clients; i++)
dvander@2168
   170
	{
dvander@2168
   171
		if (clients[i] < 1 || clients[i] > 256)
dvander@2168
   172
		{
dvander@2168
   173
			continue;
dvander@2168
   174
		}
dvander@2168
   175
		menu->Display(clients[i], max_time, this);
dvander@2168
   176
	}
dvander@2168
   177
dvander@2168
   178
	StartVoting();
dvander@2168
   179
dvander@2168
   180
	return true;
dvander@2168
   181
}
dvander@2168
   182
dvander@2168
   183
bool VoteMenuHandler::IsClientInVotePool(int client)
dvander@2168
   184
{
dvander@2168
   185
	if (client < 1 
dvander@2168
   186
		|| client > g_Players.MaxClients() 
dvander@2168
   187
		|| m_pCurMenu == NULL)
dvander@2168
   188
	{
dvander@2168
   189
		return false;
dvander@2168
   190
	}
dvander@2168
   191
dvander@2168
   192
	return (m_ClientVotes[client] > -2);
dvander@2168
   193
}
dvander@2168
   194
dvander@2168
   195
bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
dvander@2168
   196
{
dvander@2168
   197
	if (!IsClientInVotePool(client)
dvander@2168
   198
		|| m_ClientVotes[client] == -1)
dvander@2168
   199
	{
dvander@2168
   200
		return false;
dvander@2168
   201
	}
dvander@2168
   202
dvander@2168
   203
	*pItem = m_ClientVotes[client];
dvander@2168
   204
dvander@2168
   205
	return true;
dvander@2168
   206
}
dvander@2168
   207
dvander@2168
   208
bool VoteMenuHandler::RedrawToClient(int client)
dvander@2168
   209
{
dvander@2168
   210
	unsigned int time_limit;
dvander@2168
   211
dvander@2168
   212
	if (!IsClientInVotePool(client))
dvander@2168
   213
	{
dvander@2168
   214
		return false;
dvander@2168
   215
	}
dvander@2168
   216
dvander@2168
   217
	if (m_nMenuTime == MENU_TIME_FOREVER)
dvander@2168
   218
	{
dvander@2168
   219
		time_limit = m_nMenuTime;
dvander@2168
   220
	}
dvander@2168
   221
	else
dvander@2168
   222
	{
dvander@2168
   223
		time_limit = (int)((float)m_nMenuTime - (gpGlobals->curtime - m_fStartTime));
dvander@2168
   224
		
dvander@2168
   225
		/* Make sure this doesn't round to zero */
dvander@2168
   226
		if (time_limit == MENU_TIME_FOREVER)
dvander@2168
   227
		{
dvander@2168
   228
			time_limit = 1;
dvander@2168
   229
		}
dvander@2168
   230
	}
dvander@2168
   231
dvander@2168
   232
	return m_pCurMenu->Display(client, time_limit, this);
dvander@2168
   233
}
dvander@2168
   234
dvander@2168
   235
bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu, 
dvander@2168
   236
									   IMenuHandler *handler,
dvander@2168
   237
									   unsigned int time,
dvander@2168
   238
									   unsigned int flags)
dvander@2168
   239
{
dvander@2168
   240
	if (IsVoteInProgress())
dvander@2168
   241
	{
dvander@2168
   242
		return false;
dvander@2168
   243
	}
dvander@2168
   244
dvander@2168
   245
	InternalReset();
dvander@2168
   246
dvander@2168
   247
	/* Mark all clients as not voting */
dvander@2168
   248
	for (int i=1; i<=gpGlobals->maxClients; i++)
dvander@2168
   249
	{
dvander@2168
   250
		m_ClientVotes[i] = -2;
dvander@2168
   251
	}
dvander@2168
   252
dvander@2168
   253
	m_Items = menu->GetItemCount();
dvander@2168
   254
dvander@2168
   255
	if (m_Votes.size() < (size_t)m_Items)
dvander@2168
   256
	{
dvander@2168
   257
		/* Only clear the items we need to... */
dvander@2168
   258
		size_t size = m_Votes.size();
dvander@2168
   259
		for (size_t i=0; i<size; i++)
dvander@2168
   260
		{
dvander@2168
   261
			m_Votes[i] = 0;
dvander@2168
   262
		}
dvander@2168
   263
		m_Votes.resize(m_Items, 0);
dvander@2168
   264
	}
dvander@2168
   265
	else
dvander@2168
   266
	{
dvander@2168
   267
		for (unsigned int i=0; i<m_Items; i++)
dvander@2168
   268
		{
dvander@2168
   269
			m_Votes[i] = 0;
dvander@2168
   270
		}
dvander@2168
   271
	}
dvander@2168
   272
dvander@2168
   273
	m_pCurMenu = menu;
dvander@2168
   274
	m_VoteTime = time;
dvander@2168
   275
	m_VoteFlags = flags;
dvander@2168
   276
	m_pHandler = handler;
dvander@2168
   277
dvander@2168
   278
	m_pHandler->OnMenuStart(m_pCurMenu);
dvander@2168
   279
dvander@2168
   280
	return true;
dvander@2168
   281
}
dvander@2168
   282
dvander@2168
   283
void VoteMenuHandler::StartVoting()
dvander@2168
   284
{
dvander@2168
   285
	if (!m_pCurMenu)
dvander@2168
   286
	{
dvander@2168
   287
		return;
dvander@2168
   288
	}
dvander@2168
   289
dvander@2168
   290
	m_bStarted = true;
dvander@2168
   291
dvander@2168
   292
	m_pHandler->OnMenuVoteStart(m_pCurMenu);
dvander@2168
   293
dvander@2168
   294
	/* By now we know how many clients were set.  
dvander@2168
   295
	 * If there are none, we should end IMMEDIATELY.
dvander@2168
   296
	 */
dvander@2168
   297
	if (m_Clients == 0)
dvander@2168
   298
	{
dvander@2168
   299
		EndVoting();
dvander@2168
   300
	}
dvander@2168
   301
}
dvander@2168
   302
dvander@2168
   303
void VoteMenuHandler::DecrementPlayerCount()
dvander@2168
   304
{
dvander@2168
   305
	assert(m_Clients > 0);
dvander@2168
   306
dvander@2168
   307
	m_Clients--;
dvander@2168
   308
dvander@2168
   309
	if (m_bStarted && m_Clients == 0)
dvander@2168
   310
	{
dvander@2168
   311
		EndVoting();
dvander@2168
   312
	}
dvander@2168
   313
}
dvander@2168
   314
dvander@2168
   315
int SortVoteItems(const void *item1, const void *item2)
dvander@2168
   316
{
dvander@2168
   317
	return ((menu_vote_result_t::menu_item_vote_t *)item2)->count 
dvander@2168
   318
		- ((menu_vote_result_t::menu_item_vote_t *)item1)->count;
dvander@2168
   319
}
dvander@2168
   320
dvander@2168
   321
void VoteMenuHandler::EndVoting()
dvander@2168
   322
{
dvander@2168
   323
	/* Set when the next delay ends.  We ignore cancellation because a menu
dvander@2168
   324
	 * was, at one point, displayed, which is all that counts.  However, we
dvander@2168
   325
	 * do re-calculate the time just in case the menu had no time limit.
dvander@2168
   326
	 */
dvander@2168
   327
	float fVoteDelay = sm_vote_delay.GetFloat();
dvander@2168
   328
	if (fVoteDelay < 1.0)
dvander@2168
   329
	{
dvander@2168
   330
		g_next_vote = 0.0;
dvander@2168
   331
	}
dvander@2168
   332
	else
dvander@2168
   333
	{
dvander@2168
   334
		g_next_vote = gpGlobals->curtime + fVoteDelay;
dvander@2168
   335
	}
dvander@2168
   336
dvander@2168
   337
	if (m_bCancelled)
dvander@2168
   338
	{
dvander@2168
   339
		/* If we were cancelled, don't bother tabulating anything.
dvander@2168
   340
		 * Reset just in case someone tries to redraw, which means
dvander@2168
   341
		 * we need to save our states.
dvander@2168
   342
		 */
dvander@2168
   343
		IBaseMenu *menu = m_pCurMenu;
dvander@2168
   344
		IMenuHandler *handler = m_pHandler;
dvander@2168
   345
		InternalReset();
dvander@2168
   346
		handler->OnMenuVoteCancel(menu, VoteCancel_Generic);
dvander@2168
   347
		handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
dvander@2168
   348
		return;
dvander@2168
   349
	}
dvander@2168
   350
dvander@2168
   351
	menu_vote_result_t vote;
dvander@2168
   352
	menu_vote_result_t::menu_client_vote_t client_vote[256];
dvander@2168
   353
	menu_vote_result_t::menu_item_vote_t item_vote[256];
dvander@2168
   354
dvander@2168
   355
	memset(&vote, 0, sizeof(vote));
dvander@2168
   356
dvander@2168
   357
	/* Build the item list */
dvander@2168
   358
	for (unsigned int i=0; i<m_Items; i++)
dvander@2168
   359
	{
dvander@2168
   360
		if (m_Votes[i] > 0)
dvander@2168
   361
		{
dvander@2168
   362
			item_vote[vote.num_items].count = m_Votes[i];
dvander@2168
   363
			item_vote[vote.num_items].item = i;
dvander@2168
   364
			vote.num_votes += m_Votes[i];
dvander@2168
   365
			vote.num_items++;
dvander@2168
   366
		}
dvander@2168
   367
	}
dvander@2168
   368
	vote.item_list = item_vote;
dvander@2168
   369
dvander@2168
   370
	if (!vote.num_votes)
dvander@2168
   371
	{
dvander@2168
   372
		IBaseMenu *menu = m_pCurMenu;
dvander@2168
   373
		IMenuHandler *handler = m_pHandler;
dvander@2168
   374
		InternalReset();
dvander@2168
   375
		handler->OnMenuVoteCancel(menu, VoteCancel_NoVotes);
dvander@2168
   376
		handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
dvander@2168
   377
		return;
dvander@2168
   378
	}
dvander@2168
   379
dvander@2168
   380
	/* Build the client list */
dvander@2168
   381
	for (int i=1; i<=gpGlobals->maxClients; i++)
dvander@2168
   382
	{
dvander@2168
   383
		if (m_ClientVotes[i] >= -1)
dvander@2168
   384
		{
dvander@2168
   385
			client_vote[vote.num_clients].client = i;
dvander@2168
   386
			client_vote[vote.num_clients].item = m_ClientVotes[i];
dvander@2168
   387
			vote.num_clients++;
dvander@2168
   388
		}
dvander@2168
   389
	}
dvander@2168
   390
	vote.client_list = client_vote;
dvander@2168
   391
dvander@2168
   392
	/* Sort the item list descending like we promised */
dvander@2168
   393
	qsort(item_vote,
dvander@2168
   394
		vote.num_items,
dvander@2168
   395
		sizeof(menu_vote_result_t::menu_item_vote_t),
dvander@2168
   396
		SortVoteItems);
dvander@2168
   397
dvander@2168
   398
	/* Save states, then clear what we've saved.
dvander@2168
   399
	 * This makes us re-entrant, which is always the safe way to go.
dvander@2168
   400
	 */
dvander@2168
   401
	IBaseMenu *menu = m_pCurMenu;
dvander@2168
   402
	IMenuHandler *handler = m_pHandler;
dvander@2168
   403
	InternalReset();
dvander@2168
   404
dvander@2168
   405
	/* Send vote info */
dvander@2168
   406
	handler->OnMenuVoteResults(menu, &vote);
dvander@2168
   407
	handler->OnMenuEnd(menu, MenuEnd_VotingDone);
dvander@2168
   408
}
dvander@2168
   409
dvander@2168
   410
void VoteMenuHandler::OnMenuStart(IBaseMenu *menu)
dvander@2168
   411
{
dvander@2168
   412
	m_Clients++;
dvander@2168
   413
}
dvander@2168
   414
dvander@2168
   415
void VoteMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
dvander@2168
   416
{
dvander@2168
   417
	DecrementPlayerCount();
dvander@2168
   418
}
dvander@2168
   419
dvander@2168
   420
void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
dvander@2168
   421
{
dvander@2168
   422
	m_pHandler->OnMenuCancel(menu, client, reason);
dvander@2168
   423
}
dvander@2168
   424
dvander@2168
   425
void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
dvander@2168
   426
{
dvander@2168
   427
	m_ClientVotes[client] = -1;
dvander@2168
   428
	m_pHandler->OnMenuDisplay(menu, client, display);
dvander@2168
   429
}
dvander@2168
   430
dvander@2168
   431
unsigned int VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr)
dvander@2168
   432
{
dvander@2168
   433
	return m_pHandler->OnMenuDisplayItem(menu, client, panel, item, dr);
dvander@2168
   434
}
dvander@2168
   435
dvander@2168
   436
void VoteMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
dvander@2168
   437
{
dvander@2168
   438
	m_pHandler->OnMenuDrawItem(menu, client, item, style);
dvander@2168
   439
}
dvander@2168
   440
dvander@2168
   441
void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
dvander@2168
   442
{
dvander@2168
   443
	/* Check by our item count, NOT the vote array size */
dvander@2168
   444
	if (item < m_Items)
dvander@2168
   445
	{
dvander@2168
   446
		m_ClientVotes[client] = item;
dvander@2168
   447
		m_Votes[item]++;
dvander@2168
   448
		m_NumVotes++;
dvander@2168
   449
	}
dvander@2168
   450
dvander@2168
   451
	m_pHandler->OnMenuSelect(menu, client, item);
dvander@2168
   452
}
dvander@2168
   453
dvander@2168
   454
void VoteMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page)
dvander@2168
   455
{
dvander@2168
   456
	if (m_pHandler->GetMenuAPIVersion2() >= 13)
dvander@2168
   457
	{
dvander@2168
   458
		m_pHandler->OnMenuSelect2(menu, client, item, item_on_page);
dvander@2168
   459
	}
dvander@2168
   460
}
dvander@2168
   461
dvander@2168
   462
void VoteMenuHandler::InternalReset()
dvander@2168
   463
{
dvander@2168
   464
	m_Clients = 0;
dvander@2168
   465
	m_Items = 0;
dvander@2168
   466
	m_bStarted = false;
dvander@2168
   467
	m_pCurMenu = NULL;
dvander@2168
   468
	m_NumVotes = 0;
dvander@2168
   469
	m_bCancelled = false;
dvander@2168
   470
	m_pHandler = NULL;
dvander@2168
   471
}
dvander@2168
   472
dvander@2168
   473
void VoteMenuHandler::CancelVoting()
dvander@2168
   474
{
dvander@2168
   475
	if (m_bCancelled || !m_pCurMenu)
dvander@2168
   476
	{
dvander@2168
   477
		return;
dvander@2168
   478
	}
dvander@2168
   479
	m_bCancelled = true;
dvander@2168
   480
	m_pCurMenu->Cancel();
dvander@2168
   481
}
dvander@2168
   482
dvander@2168
   483
IBaseMenu *VoteMenuHandler::GetCurrentMenu()
dvander@2168
   484
{
dvander@2168
   485
	return m_pCurMenu;
dvander@2168
   486
}
dvander@2168
   487
dvander@2168
   488
bool VoteMenuHandler::IsCancelling()
dvander@2168
   489
{
dvander@2168
   490
	return m_bCancelled;
dvander@2168
   491
}