dvander@1269: /**
dvander@2737: * vim: set ts=4 sw=4 :
ds@1330: * =============================================================================
dvander@1269: * SourceMod
dvander@2737: * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
dvander@1269: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@1269: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1269: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1269: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
dvander@1269: *
dvander@1269: * Version: $Id$
dvander@1269: */
dvander@1269:
dvander@1269: #include
dvander@1269: #include
dvander@1269: #include "MenuVoting.h"
dvander@1269: #include "PlayerManager.h"
dvander@1269: #include "sourcemm_api.h"
pred@2801: #include
pred@2801: #include
pred@2801: #include
pred@2801: #include
pred@2801: #include
pred@2801: #include
dvander@1269:
dvander@1291: float g_next_vote = 0.0f;
dvander@1291:
pred@2801: #define VOTE_NOT_VOTING -2
pred@2801: #define VOTE_PENDING -1
pred@2801:
pred@2801: ConVar sm_vote_hintbox("sm_vote_progress_hintbox",
pred@2801: "0",
pred@2801: 0,
pred@2801: "Show current vote progress in a hint box",
pred@2801: true,
pred@2801: 0.0,
pred@2801: true,
pred@2801: 1.0);
pred@2801:
pred@2801: ConVar sm_vote_chat("sm_vote_progress_chat",
pred@2801: "0",
pred@2801: 0,
pred@2801: "Show current vote progress as chat messages",
pred@2801: true,
pred@2801: 0.0,
pred@2801: true,
pred@2801: 1.0);
pred@2801:
pred@2801: ConVar sm_vote_console("sm_vote_progress_console",
pred@2801: "0",
pred@2801: 0,
pred@2801: "Show current vote progress as console messages",
pred@2801: true,
pred@2801: 0.0,
pred@2801: true,
pred@2801: 1.0);
pred@2801:
pred@2801: ConVar sm_vote_client_console("sm_vote_progress_client_console",
pred@2801: "0",
pred@2801: 0,
pred@2801: "Show current vote progress as console messages to clients",
pred@2801: true,
pred@2801: 0.0,
pred@2801: true,
pred@2801: 1.0);
pred@2801:
pred@2801:
ds@2400: #if SOURCE_ENGINE >= SE_ORANGEBOX
faluco@1541: void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
faluco@1541: #else
dvander@1291: void OnVoteDelayChange(ConVar *cvar, const char *value);
faluco@1541: #endif
dvander@1291: ConVar sm_vote_delay("sm_vote_delay",
dvander@1291: "30",
dvander@1291: 0,
dvander@1291: "Sets the recommended time in between public votes",
dvander@1291: false,
dvander@1291: 0.0,
dvander@1291: false,
dvander@1291: 0.0,
dvander@1291: OnVoteDelayChange);
dvander@1291:
ds@2400: #if SOURCE_ENGINE >= SE_ORANGEBOX
faluco@1541: void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue)
faluco@1541: #else
dvander@1291: void OnVoteDelayChange(ConVar *cvar, const char *value)
faluco@1541: #endif
dvander@1291: {
dvander@1291: /* See if the new vote delay isn't something we need to account for */
dvander@1291: if (sm_vote_delay.GetFloat() < 1.0f)
dvander@1291: {
dvander@1291: g_next_vote = 0.0f;
dvander@1291: return;
dvander@1291: }
dvander@1291:
dvander@1291: /* If there was never a last vote, ignore this change */
dvander@1291: if (g_next_vote < 0.1f)
dvander@1291: {
dvander@1291: return;
dvander@1291: }
dvander@1291:
dvander@1291: /* Subtract the original value, then add the new one. */
dvander@1291: g_next_vote -= (float)atof(value);
dvander@1291: g_next_vote += sm_vote_delay.GetFloat();
dvander@1291: }
dvander@1291:
dvander@1291: unsigned int VoteMenuHandler::GetRemainingVoteDelay()
dvander@1291: {
dvander@1291: if (g_next_vote <= gpGlobals->curtime)
dvander@1291: {
dvander@1291: return 0;
dvander@1291: }
dvander@1291:
dvander@1291: return (unsigned int)(g_next_vote - gpGlobals->curtime);
dvander@1291: }
dvander@1291:
dvander@1269: void VoteMenuHandler::OnSourceModAllInitialized()
dvander@1269: {
dvander@1269: g_Players.AddClientListener(this);
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::OnSourceModShutdown()
dvander@1269: {
dvander@1269: g_Players.RemoveClientListener(this);
dvander@1269: }
dvander@1269:
dvander@1291: void VoteMenuHandler::OnSourceModLevelChange(const char *mapName)
dvander@1291: {
dvander@1291: g_next_vote = 0.0f;
dvander@1291: }
dvander@1291:
dvander@1269: unsigned int VoteMenuHandler::GetMenuAPIVersion2()
dvander@1269: {
dvander@1269: return m_pHandler->GetMenuAPIVersion2();
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::OnClientDisconnected(int client)
dvander@1269: {
dvander@1269: if (!IsVoteInProgress())
dvander@1269: {
dvander@1269: return;
dvander@1269: }
dvander@1269:
dvander@2056: /* Wipe out their vote if they had one. We have to make sure the the the
dvander@2056: * newly connected client is not allowed to vote.
dvander@2056: */
dvander@1269: int item;
pred@2801: if ((item = m_ClientVotes[client]) >= VOTE_PENDING)
dvander@1269: {
dvander@2056: if (item >= 0)
dvander@2056: {
dvander@2056: assert((unsigned)item < m_Items);
dvander@2056: assert(m_Votes[item] > 0);
dvander@2056: m_Votes[item]--;
dvander@2056: }
pred@2801: m_ClientVotes[client] = VOTE_NOT_VOTING;
dvander@1269: }
dvander@1269: }
dvander@1269:
dvander@1269: bool VoteMenuHandler::IsVoteInProgress()
dvander@1269: {
dvander@1269: return (m_pCurMenu != NULL);
dvander@1269: }
dvander@1269:
dvander@2056: bool VoteMenuHandler::StartVote(IBaseMenu *menu,
dvander@2056: unsigned int num_clients,
dvander@2056: int clients[],
dvander@2056: unsigned int max_time,
dvander@2056: unsigned int flags/* =0 */)
dvander@1269: {
dvander@1269: if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags))
dvander@1269: {
dvander@1269: return false;
dvander@1269: }
dvander@1269:
dvander@2056: /* Note: we can use game time and not universal time because
dvander@2056: * if we're voting then players are in-game.
dvander@2056: */
dvander@2056:
dvander@1291: float fVoteDelay = sm_vote_delay.GetFloat();
dvander@1291: if (fVoteDelay < 1.0)
dvander@1291: {
dvander@1291: g_next_vote = 0.0;
dvander@2056: }
dvander@2056: else
dvander@2056: {
dvander@1291: /* This little trick breaks for infinite votes!
dvander@1291: * However, we just ignore that since those 1) shouldn't exist and
dvander@1291: * 2) people must be checking IsVoteInProgress() beforehand anyway.
dvander@1291: */
dvander@1291: g_next_vote = gpGlobals->curtime + fVoteDelay + (float)max_time;
dvander@1291: }
dvander@1291:
dvander@2056: m_fStartTime = gpGlobals->curtime;
dvander@2056: m_nMenuTime = max_time;
dvander@2056:
dvander@1269: for (unsigned int i=0; i 256)
dvander@2056: {
dvander@2056: continue;
dvander@2056: }
dvander@1269: menu->Display(clients[i], max_time, this);
dvander@1269: }
dvander@1269:
dvander@1269: StartVoting();
dvander@1269:
dvander@1269: return true;
dvander@1269: }
dvander@1269:
dvander@2056: bool VoteMenuHandler::IsClientInVotePool(int client)
dvander@2056: {
dvander@2056: if (client < 1
dvander@2056: || client > g_Players.MaxClients()
dvander@2056: || m_pCurMenu == NULL)
dvander@2056: {
dvander@2056: return false;
dvander@2056: }
dvander@2056:
pred@2801: return (m_ClientVotes[client] > VOTE_NOT_VOTING);
dvander@2056: }
dvander@2056:
dvander@2056: bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
dvander@2056: {
dvander@2056: if (!IsClientInVotePool(client)
pred@2801: || m_ClientVotes[client] == VOTE_PENDING)
dvander@2056: {
dvander@2056: return false;
dvander@2056: }
dvander@2056:
dvander@2056: *pItem = m_ClientVotes[client];
dvander@2056:
dvander@2056: return true;
dvander@2056: }
dvander@2056:
dvander@2737: bool VoteMenuHandler::RedrawToClient(int client, bool revotes)
dvander@2056: {
dvander@2056: unsigned int time_limit;
dvander@2056:
dvander@2056: if (!IsClientInVotePool(client))
dvander@2056: {
dvander@2056: return false;
dvander@2056: }
dvander@2056:
dvander@2737: if (m_ClientVotes[client] >= 0)
dvander@2737: {
dvander@2737: if ((m_VoteFlags & VOTEFLAG_NO_REVOTES) == VOTEFLAG_NO_REVOTES || !revotes)
dvander@2737: {
dvander@2737: return false;
dvander@2737: }
dvander@2737: assert((unsigned)m_ClientVotes[client] < m_Items);
dvander@2737: assert(m_Votes[m_ClientVotes[client]] > 0);
dvander@2737: m_Votes[m_ClientVotes[client]]--;
pred@2801: m_ClientVotes[client] = VOTE_PENDING;
pred@2801: m_Revoting[client] = true;
pred@2801: m_NumVotes--;
dvander@2737: }
dvander@2737:
dvander@2056: if (m_nMenuTime == MENU_TIME_FOREVER)
dvander@2056: {
dvander@2056: time_limit = m_nMenuTime;
dvander@2056: }
dvander@2056: else
dvander@2056: {
dvander@2056: time_limit = (int)((float)m_nMenuTime - (gpGlobals->curtime - m_fStartTime));
dvander@2056:
dvander@2056: /* Make sure this doesn't round to zero */
dvander@2056: if (time_limit == MENU_TIME_FOREVER)
dvander@2056: {
dvander@2056: time_limit = 1;
dvander@2056: }
dvander@2056: }
dvander@2056:
dvander@2056: return m_pCurMenu->Display(client, time_limit, this);
dvander@2056: }
dvander@2056:
dvander@1269: bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
dvander@1269: IMenuHandler *handler,
dvander@1269: unsigned int time,
dvander@1269: unsigned int flags)
dvander@1269: {
dvander@1269: if (IsVoteInProgress())
dvander@1269: {
dvander@1269: return false;
dvander@1269: }
dvander@1269:
dvander@1269: InternalReset();
dvander@1269:
dvander@1269: /* Mark all clients as not voting */
dvander@1269: for (int i=1; i<=gpGlobals->maxClients; i++)
dvander@1269: {
pred@2801: m_ClientVotes[i] = VOTE_NOT_VOTING;
pred@2801: m_Revoting[i] = false;
dvander@1269: }
dvander@1269:
dvander@1269: m_Items = menu->GetItemCount();
dvander@1269:
dvander@1269: if (m_Votes.size() < (size_t)m_Items)
dvander@1269: {
dvander@1269: /* Only clear the items we need to... */
dvander@1269: size_t size = m_Votes.size();
dvander@1269: for (size_t i=0; iOnMenuStart(m_pCurMenu);
dvander@1269:
dvander@1269: return true;
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::StartVoting()
dvander@1269: {
dvander@1269: if (!m_pCurMenu)
dvander@1269: {
dvander@1269: return;
dvander@1269: }
dvander@1269:
dvander@1269: m_bStarted = true;
dvander@1269:
dvander@1269: m_pHandler->OnMenuVoteStart(m_pCurMenu);
dvander@1269:
pred@2801: m_displayTimer = g_Timers.CreateTimer(this, 1.0, NULL, TIMER_FLAG_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
pred@2801:
dvander@1269: /* By now we know how many clients were set.
dvander@1269: * If there are none, we should end IMMEDIATELY.
dvander@1269: */
dvander@1269: if (m_Clients == 0)
dvander@1269: {
dvander@1269: EndVoting();
dvander@1269: }
pred@2801:
pred@2801: m_TotalClients = m_Clients;
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::DecrementPlayerCount()
dvander@1269: {
dvander@1269: assert(m_Clients > 0);
dvander@1269:
dvander@1269: m_Clients--;
dvander@1269:
dvander@1269: if (m_bStarted && m_Clients == 0)
dvander@1269: {
dvander@1269: EndVoting();
dvander@1269: }
dvander@1269: }
dvander@1269:
dvander@1269: int SortVoteItems(const void *item1, const void *item2)
dvander@1269: {
dvander@1269: return ((menu_vote_result_t::menu_item_vote_t *)item2)->count
dvander@1269: - ((menu_vote_result_t::menu_item_vote_t *)item1)->count;
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::EndVoting()
dvander@1269: {
dvander@1291: /* Set when the next delay ends. We ignore cancellation because a menu
dvander@1291: * was, at one point, displayed, which is all that counts. However, we
dvander@1291: * do re-calculate the time just in case the menu had no time limit.
dvander@1291: */
dvander@1291: float fVoteDelay = sm_vote_delay.GetFloat();
dvander@1291: if (fVoteDelay < 1.0)
dvander@1291: {
dvander@1291: g_next_vote = 0.0;
dvander@2056: }
dvander@2056: else
dvander@2056: {
dvander@1291: g_next_vote = gpGlobals->curtime + fVoteDelay;
dvander@1291: }
dvander@1291:
pred@2801: if (m_displayTimer)
pred@2801: {
pred@2801: g_Timers.KillTimer(m_displayTimer);
pred@2801: }
pred@2801:
dvander@1269: if (m_bCancelled)
dvander@1269: {
dvander@1269: /* If we were cancelled, don't bother tabulating anything.
dvander@1269: * Reset just in case someone tries to redraw, which means
dvander@1269: * we need to save our states.
dvander@1269: */
dvander@1269: IBaseMenu *menu = m_pCurMenu;
dvander@1269: IMenuHandler *handler = m_pHandler;
dvander@1269: InternalReset();
dvander@1296: handler->OnMenuVoteCancel(menu, VoteCancel_Generic);
dvander@1269: handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
dvander@1269: return;
dvander@1269: }
dvander@1269:
dvander@1269: menu_vote_result_t vote;
dvander@1269: menu_vote_result_t::menu_client_vote_t client_vote[256];
dvander@1269: menu_vote_result_t::menu_item_vote_t item_vote[256];
dvander@1269:
dvander@1269: memset(&vote, 0, sizeof(vote));
dvander@1269:
dvander@1269: /* Build the item list */
dvander@1269: for (unsigned int i=0; i 0)
dvander@1269: {
dvander@1269: item_vote[vote.num_items].count = m_Votes[i];
dvander@1269: item_vote[vote.num_items].item = i;
dvander@1269: vote.num_votes += m_Votes[i];
dvander@1269: vote.num_items++;
dvander@1269: }
dvander@1269: }
dvander@1269: vote.item_list = item_vote;
dvander@1269:
dvander@1269: if (!vote.num_votes)
dvander@1269: {
dvander@1269: IBaseMenu *menu = m_pCurMenu;
dvander@1269: IMenuHandler *handler = m_pHandler;
dvander@1269: InternalReset();
dvander@1296: handler->OnMenuVoteCancel(menu, VoteCancel_NoVotes);
dvander@1296: handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
dvander@1269: return;
dvander@1269: }
dvander@1269:
dvander@1269: /* Build the client list */
dvander@1269: for (int i=1; i<=gpGlobals->maxClients; i++)
dvander@1269: {
pred@2801: if (m_ClientVotes[i] >= VOTE_PENDING)
dvander@1269: {
dvander@1269: client_vote[vote.num_clients].client = i;
dvander@1269: client_vote[vote.num_clients].item = m_ClientVotes[i];
dvander@1269: vote.num_clients++;
dvander@1269: }
dvander@1269: }
dvander@1269: vote.client_list = client_vote;
dvander@1269:
dvander@1269: /* Sort the item list descending like we promised */
dvander@1269: qsort(item_vote,
dvander@1269: vote.num_items,
dvander@1269: sizeof(menu_vote_result_t::menu_item_vote_t),
dvander@1269: SortVoteItems);
dvander@1269:
dvander@1269: /* Save states, then clear what we've saved.
dvander@1269: * This makes us re-entrant, which is always the safe way to go.
dvander@1269: */
dvander@1269: IBaseMenu *menu = m_pCurMenu;
dvander@1269: IMenuHandler *handler = m_pHandler;
dvander@1269: InternalReset();
dvander@1269:
dvander@1269: /* Send vote info */
dvander@1269: handler->OnMenuVoteResults(menu, &vote);
dvander@1269: handler->OnMenuEnd(menu, MenuEnd_VotingDone);
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::OnMenuStart(IBaseMenu *menu)
dvander@1269: {
dvander@1269: m_Clients++;
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
dvander@1269: {
dvander@1269: DecrementPlayerCount();
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
dvander@1269: {
dvander@1269: m_pHandler->OnMenuCancel(menu, client, reason);
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
dvander@1269: {
pred@2801: m_ClientVotes[client] = VOTE_PENDING;
dvander@1269: m_pHandler->OnMenuDisplay(menu, client, display);
dvander@1269: }
dvander@1269:
dvander@1269: unsigned int VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr)
dvander@1269: {
dvander@1269: return m_pHandler->OnMenuDisplayItem(menu, client, panel, item, dr);
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
dvander@1269: {
dvander@1269: m_pHandler->OnMenuDrawItem(menu, client, item, style);
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
dvander@1269: {
dvander@1269: /* Check by our item count, NOT the vote array size */
dvander@1269: if (item < m_Items)
dvander@1269: {
dvander@1269: m_ClientVotes[client] = item;
dvander@1269: m_Votes[item]++;
dvander@1269: m_NumVotes++;
pred@2801:
pred@2801: if (sm_vote_chat.GetBool() || sm_vote_console.GetBool())
pred@2801: {
pred@2801: static char buffer[1024];
pred@2801: ItemDrawInfo dr;
pred@2801: menu->GetItemInfo(item, &dr);
pred@2801:
pred@2801: if (sm_vote_console.GetBool())
pred@2801: {
pred@2801: int target = SOURCEMOD_SERVER_LANGUAGE;
pred@2801: CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For", &target, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
pred@2801: Engine_LogPrintWrapper(buffer);
pred@2801: }
pred@2801:
pred@2801: if (sm_vote_chat.GetBool() || sm_vote_client_console.GetBool())
pred@2801: {
pred@2801: int maxclients = g_Players.GetMaxClients();
pred@2801: for (int i=1; i<=maxclients; i++)
pred@2801: {
pred@2801: CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
pred@2801: assert(pPlayer);
pred@2801:
pred@2801: if (pPlayer->IsInGame())
pred@2801: {
pred@2801: if (m_Revoting[client])
pred@2801: {
pred@2801: CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Changed Vote", &i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
pred@2801: }
pred@2801: else
pred@2801: {
pred@2801: CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For", &i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
pred@2801: }
pred@2801:
pred@2801: if (sm_vote_chat.GetBool())
pred@2801: {
pred@2801: g_HL2.TextMsg(i, HUD_PRINTTALK, buffer);
pred@2801: }
pred@2801:
pred@2801: if (sm_vote_client_console.GetBool())
pred@2801: {
pred@2801: engine->ClientPrintf(pPlayer->GetEdict(), buffer);
pred@2801: }
pred@2801: }
pred@2801: }
pred@2801: }
pred@2801: }
pred@2801:
pred@2801: BuildVoteLeaders();
pred@2801: DrawHintProgress();
dvander@1269: }
dvander@1269:
dvander@1269: m_pHandler->OnMenuSelect(menu, client, item);
dvander@1269: }
dvander@1269:
dvander@1474: void VoteMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page)
dvander@1474: {
dvander@1474: if (m_pHandler->GetMenuAPIVersion2() >= 13)
dvander@1474: {
dvander@1474: m_pHandler->OnMenuSelect2(menu, client, item, item_on_page);
dvander@1474: }
dvander@1474: }
dvander@1474:
dvander@1269: void VoteMenuHandler::InternalReset()
dvander@1269: {
dvander@1269: m_Clients = 0;
dvander@1269: m_Items = 0;
dvander@1269: m_bStarted = false;
dvander@1269: m_pCurMenu = NULL;
dvander@1269: m_NumVotes = 0;
dvander@1269: m_bCancelled = false;
dvander@1269: m_pHandler = NULL;
pred@2801: m_leaderList[0] = '\0';
pred@2801: m_displayTimer = NULL;
pred@2801: m_TotalClients = 0;
dvander@1269: }
dvander@1269:
dvander@1269: void VoteMenuHandler::CancelVoting()
dvander@1269: {
dvander@1269: if (m_bCancelled || !m_pCurMenu)
dvander@1269: {
dvander@1269: return;
dvander@1269: }
dvander@1269: m_bCancelled = true;
dvander@1269: m_pCurMenu->Cancel();
dvander@1269: }
dvander@1269:
dvander@1269: IBaseMenu *VoteMenuHandler::GetCurrentMenu()
dvander@1269: {
dvander@1269: return m_pCurMenu;
dvander@1269: }
dvander@1269:
dvander@1269: bool VoteMenuHandler::IsCancelling()
dvander@1269: {
dvander@1269: return m_bCancelled;
dvander@1269: }
dvander@2737:
pred@2801: void VoteMenuHandler::DrawHintProgress()
pred@2801: {
pred@2801: if (!sm_vote_hintbox.GetBool())
pred@2801: {
pred@2801: return;
pred@2801: }
pred@2801:
pred@2801: static char buffer[1024];
pred@2801:
pred@2801: float timeRemaining = (m_fStartTime + m_nMenuTime) - gpGlobals->curtime;
pred@2801: if (timeRemaining < 0)
pred@2801: {
pred@2801: timeRemaining = 0.0;
pred@2801: }
pred@2801:
pred@2801: int iTimeRemaining = RoundFloatToInt(timeRemaining);
pred@2801:
pred@2801: int maxclients = g_Players.GetMaxClients();
pred@2801: for (int i=1; i<=maxclients; i++)
pred@2801: {
pred@2801: if (g_Players.GetPlayerByIndex(i)->IsInGame())
pred@2801: {
pred@2801: CoreTranslate(buffer, sizeof(buffer), "%T%s", 6, NULL, "Vote Count", &i, &m_NumVotes, &m_TotalClients, &iTimeRemaining, &m_leaderList);
pred@2801: g_HL2.HintTextMsg(i, buffer);
pred@2801: }
pred@2801: }
pred@2801: }
pred@2801:
pred@2801: void VoteMenuHandler::BuildVoteLeaders()
pred@2801: {
pred@2801: if (m_NumVotes == 0 || !sm_vote_hintbox.GetBool())
pred@2801: {
pred@2801: return;
pred@2801: }
pred@2801:
pred@2801: menu_vote_result_t vote;
pred@2801: menu_vote_result_t::menu_item_vote_t item_vote[256];
pred@2801:
pred@2801: memset(&vote, 0, sizeof(vote));
pred@2801:
pred@2801: /* Build the item list */
pred@2801: for (unsigned int i=0; i 0)
pred@2801: {
pred@2801: item_vote[vote.num_items].count = m_Votes[i];
pred@2801: item_vote[vote.num_items].item = i;
pred@2801: vote.num_votes += m_Votes[i];
pred@2801: vote.num_items++;
pred@2801: }
pred@2801: }
pred@2801: vote.item_list = item_vote;
pred@2801: assert(vote.num_votes);
pred@2801:
pred@2801: /* Sort the item list descending */
pred@2801: qsort(item_vote,
pred@2801: vote.num_items,
pred@2801: sizeof(menu_vote_result_t::menu_item_vote_t),
pred@2801: SortVoteItems);
pred@2801:
pred@2801: /* Take the top 3 (if applicable) and draw them */
pred@2801: int len = 0;
pred@2801: for (unsigned int i=0; iGetItemInfo(curItem, &dr);
pred@2801: len += g_SourceMod.Format(m_leaderList + len, sizeof(m_leaderList) - len, "\n%i. %s: (%i)", i+1, dr.display, vote.item_list[i].count);
pred@2801: }
pred@2801: }
pred@2801:
pred@2801: SourceMod::ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData)
pred@2801: {
pred@2801: DrawHintProgress();
pred@2801:
pred@2801: return Pl_Continue;
pred@2801: }
pred@2801:
pred@2801: void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData)
pred@2801: {
pred@2801: m_displayTimer = NULL;
pred@2801: }