3 * ================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * ================================================================
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License,
10 * version 3.0, as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to
21 * link the code of this program (as well as its derivative works) to
22 * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any
23 * Game MODs that run on software by the Valve Corporation. You must
24 * obey the GNU General Public License in all respects for all other
25 * code used. Additionally, AlliedModders LLC grants this exception
26 * to all derivative works. AlliedModders LLC defines further
27 * exceptions, found in LICENSE.txt (as of this writing, version
28 * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
35 #include "MenuVoting.h"
36 #include "PlayerManager.h"
37 #include "sourcemm_api.h"
39 void VoteMenuHandler::OnSourceModAllInitialized()
41 g_Players.AddClientListener(this);
44 void VoteMenuHandler::OnSourceModShutdown()
46 g_Players.RemoveClientListener(this);
49 unsigned int VoteMenuHandler::GetMenuAPIVersion2()
51 return m_pHandler->GetMenuAPIVersion2();
54 void VoteMenuHandler::OnClientDisconnected(int client)
56 if (!IsVoteInProgress())
61 /* Wipe out their vote if they had one */
63 if ((item = m_ClientVotes[client]) >= 0)
65 assert((unsigned)item < m_Items);
66 assert(m_Votes[item] > 0);
68 m_ClientVotes[client] = -1;
72 bool VoteMenuHandler::IsVoteInProgress()
74 return (m_pCurMenu != NULL);
77 bool VoteMenuHandler::StartVote(IBaseMenu *menu, unsigned int num_clients, int clients[], unsigned int max_time, unsigned int flags/* =0 */)
79 if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags))
84 for (unsigned int i=0; i<num_clients; i++)
86 menu->Display(clients[i], max_time, this);
94 bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
95 IMenuHandler *handler,
99 if (IsVoteInProgress())
106 /* Mark all clients as not voting */
107 for (int i=1; i<=gpGlobals->maxClients; i++)
109 m_ClientVotes[i] = -2;
112 m_Items = menu->GetItemCount();
114 if (m_Votes.size() < (size_t)m_Items)
116 /* Only clear the items we need to... */
117 size_t size = m_Votes.size();
118 for (size_t i=0; i<size; i++)
122 m_Votes.resize(m_Items, 0);
124 for (unsigned int i=0; i<m_Items; i++)
133 m_pHandler = handler;
135 m_pHandler->OnMenuStart(m_pCurMenu);
140 void VoteMenuHandler::StartVoting()
149 m_pHandler->OnMenuVoteStart(m_pCurMenu);
151 /* By now we know how many clients were set.
152 * If there are none, we should end IMMEDIATELY.
160 void VoteMenuHandler::DecrementPlayerCount()
162 assert(m_Clients > 0);
166 if (m_bStarted && m_Clients == 0)
172 int SortVoteItems(const void *item1, const void *item2)
174 return ((menu_vote_result_t::menu_item_vote_t *)item2)->count
175 - ((menu_vote_result_t::menu_item_vote_t *)item1)->count;
178 void VoteMenuHandler::EndVoting()
182 /* If we were cancelled, don't bother tabulating anything.
183 * Reset just in case someone tries to redraw, which means
184 * we need to save our states.
186 IBaseMenu *menu = m_pCurMenu;
187 IMenuHandler *handler = m_pHandler;
189 handler->OnMenuVoteCancel(menu);
190 handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
194 menu_vote_result_t vote;
195 menu_vote_result_t::menu_client_vote_t client_vote[256];
196 menu_vote_result_t::menu_item_vote_t item_vote[256];
198 memset(&vote, 0, sizeof(vote));
200 /* Build the item list */
201 for (unsigned int i=0; i<m_Items; i++)
205 item_vote[vote.num_items].count = m_Votes[i];
206 item_vote[vote.num_items].item = i;
207 vote.num_votes += m_Votes[i];
211 vote.item_list = item_vote;
215 IBaseMenu *menu = m_pCurMenu;
216 IMenuHandler *handler = m_pHandler;
218 handler->OnMenuVoteCancel(menu);
219 handler->OnMenuEnd(menu, MenuEnd_NoVotes);
223 /* Build the client list */
224 for (int i=1; i<=gpGlobals->maxClients; i++)
226 if (m_ClientVotes[i] >= -1)
228 client_vote[vote.num_clients].client = i;
229 client_vote[vote.num_clients].item = m_ClientVotes[i];
233 vote.client_list = client_vote;
235 /* Sort the item list descending like we promised */
238 sizeof(menu_vote_result_t::menu_item_vote_t),
241 /* Save states, then clear what we've saved.
242 * This makes us re-entrant, which is always the safe way to go.
244 IBaseMenu *menu = m_pCurMenu;
245 IMenuHandler *handler = m_pHandler;
249 handler->OnMenuVoteResults(menu, &vote);
250 handler->OnMenuEnd(menu, MenuEnd_VotingDone);
253 void VoteMenuHandler::OnMenuStart(IBaseMenu *menu)
258 void VoteMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
260 DecrementPlayerCount();
263 void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
265 m_pHandler->OnMenuCancel(menu, client, reason);
268 void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
270 m_ClientVotes[client] = -1;
271 m_pHandler->OnMenuDisplay(menu, client, display);
274 unsigned int VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr)
276 return m_pHandler->OnMenuDisplayItem(menu, client, panel, item, dr);
279 void VoteMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
281 m_pHandler->OnMenuDrawItem(menu, client, item, style);
284 void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
286 /* Check by our item count, NOT the vote array size */
289 m_ClientVotes[client] = item;
294 m_pHandler->OnMenuSelect(menu, client, item);
297 void VoteMenuHandler::InternalReset()
304 m_bCancelled = false;
308 void VoteMenuHandler::CancelVoting()
310 if (m_bCancelled || !m_pCurMenu)
315 m_pCurMenu->Cancel();
318 IBaseMenu *VoteMenuHandler::GetCurrentMenu()
323 bool VoteMenuHandler::IsCancelling()