1.1 --- a/core/MenuVoting.cpp Fri Mar 28 06:21:34 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,413 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#include <string.h>
1.36 -#include <stdlib.h>
1.37 -#include "MenuVoting.h"
1.38 -#include "PlayerManager.h"
1.39 -#include "sourcemm_api.h"
1.40 -
1.41 -float g_next_vote = 0.0f;
1.42 -
1.43 -#if defined ORANGEBOX_BUILD
1.44 -void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
1.45 -#else
1.46 -void OnVoteDelayChange(ConVar *cvar, const char *value);
1.47 -#endif
1.48 -ConVar sm_vote_delay("sm_vote_delay",
1.49 - "30",
1.50 - 0,
1.51 - "Sets the recommended time in between public votes",
1.52 - false,
1.53 - 0.0,
1.54 - false,
1.55 - 0.0,
1.56 - OnVoteDelayChange);
1.57 -
1.58 -#if defined ORANGEBOX_BUILD
1.59 -void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue)
1.60 -#else
1.61 -void OnVoteDelayChange(ConVar *cvar, const char *value)
1.62 -#endif
1.63 -{
1.64 - /* See if the new vote delay isn't something we need to account for */
1.65 - if (sm_vote_delay.GetFloat() < 1.0f)
1.66 - {
1.67 - g_next_vote = 0.0f;
1.68 - return;
1.69 - }
1.70 -
1.71 - /* If there was never a last vote, ignore this change */
1.72 - if (g_next_vote < 0.1f)
1.73 - {
1.74 - return;
1.75 - }
1.76 -
1.77 - /* Subtract the original value, then add the new one. */
1.78 - g_next_vote -= (float)atof(value);
1.79 - g_next_vote += sm_vote_delay.GetFloat();
1.80 -}
1.81 -
1.82 -unsigned int VoteMenuHandler::GetRemainingVoteDelay()
1.83 -{
1.84 - if (g_next_vote <= gpGlobals->curtime)
1.85 - {
1.86 - return 0;
1.87 - }
1.88 -
1.89 - return (unsigned int)(g_next_vote - gpGlobals->curtime);
1.90 -}
1.91 -
1.92 -void VoteMenuHandler::OnSourceModAllInitialized()
1.93 -{
1.94 - g_Players.AddClientListener(this);
1.95 -}
1.96 -
1.97 -void VoteMenuHandler::OnSourceModShutdown()
1.98 -{
1.99 - g_Players.RemoveClientListener(this);
1.100 -}
1.101 -
1.102 -void VoteMenuHandler::OnSourceModLevelChange(const char *mapName)
1.103 -{
1.104 - g_next_vote = 0.0f;
1.105 -}
1.106 -
1.107 -unsigned int VoteMenuHandler::GetMenuAPIVersion2()
1.108 -{
1.109 - return m_pHandler->GetMenuAPIVersion2();
1.110 -}
1.111 -
1.112 -void VoteMenuHandler::OnClientDisconnected(int client)
1.113 -{
1.114 - if (!IsVoteInProgress())
1.115 - {
1.116 - return;
1.117 - }
1.118 -
1.119 - /* Wipe out their vote if they had one */
1.120 - int item;
1.121 - if ((item = m_ClientVotes[client]) >= 0)
1.122 - {
1.123 - assert((unsigned)item < m_Items);
1.124 - assert(m_Votes[item] > 0);
1.125 - m_Votes[item]--;
1.126 - m_ClientVotes[client] = -1;
1.127 - }
1.128 -}
1.129 -
1.130 -bool VoteMenuHandler::IsVoteInProgress()
1.131 -{
1.132 - return (m_pCurMenu != NULL);
1.133 -}
1.134 -
1.135 -bool VoteMenuHandler::StartVote(IBaseMenu *menu, unsigned int num_clients, int clients[], unsigned int max_time, unsigned int flags/* =0 */)
1.136 -{
1.137 - if (!InitializeVoting(menu, menu->GetHandler(), max_time, flags))
1.138 - {
1.139 - return false;
1.140 - }
1.141 -
1.142 - float fVoteDelay = sm_vote_delay.GetFloat();
1.143 - if (fVoteDelay < 1.0)
1.144 - {
1.145 - g_next_vote = 0.0;
1.146 - } else {
1.147 - /* This little trick breaks for infinite votes!
1.148 - * However, we just ignore that since those 1) shouldn't exist and
1.149 - * 2) people must be checking IsVoteInProgress() beforehand anyway.
1.150 - */
1.151 - g_next_vote = gpGlobals->curtime + fVoteDelay + (float)max_time;
1.152 - }
1.153 -
1.154 - for (unsigned int i=0; i<num_clients; i++)
1.155 - {
1.156 - menu->Display(clients[i], max_time, this);
1.157 - }
1.158 -
1.159 - StartVoting();
1.160 -
1.161 - return true;
1.162 -}
1.163 -
1.164 -bool VoteMenuHandler::InitializeVoting(IBaseMenu *menu,
1.165 - IMenuHandler *handler,
1.166 - unsigned int time,
1.167 - unsigned int flags)
1.168 -{
1.169 - if (IsVoteInProgress())
1.170 - {
1.171 - return false;
1.172 - }
1.173 -
1.174 - InternalReset();
1.175 -
1.176 - /* Mark all clients as not voting */
1.177 - for (int i=1; i<=gpGlobals->maxClients; i++)
1.178 - {
1.179 - m_ClientVotes[i] = -2;
1.180 - }
1.181 -
1.182 - m_Items = menu->GetItemCount();
1.183 -
1.184 - if (m_Votes.size() < (size_t)m_Items)
1.185 - {
1.186 - /* Only clear the items we need to... */
1.187 - size_t size = m_Votes.size();
1.188 - for (size_t i=0; i<size; i++)
1.189 - {
1.190 - m_Votes[i] = 0;
1.191 - }
1.192 - m_Votes.resize(m_Items, 0);
1.193 - } else {
1.194 - for (unsigned int i=0; i<m_Items; i++)
1.195 - {
1.196 - m_Votes[i] = 0;
1.197 - }
1.198 - }
1.199 -
1.200 - m_pCurMenu = menu;
1.201 - m_VoteTime = time;
1.202 - m_VoteFlags = flags;
1.203 - m_pHandler = handler;
1.204 -
1.205 - m_pHandler->OnMenuStart(m_pCurMenu);
1.206 -
1.207 - return true;
1.208 -}
1.209 -
1.210 -void VoteMenuHandler::StartVoting()
1.211 -{
1.212 - if (!m_pCurMenu)
1.213 - {
1.214 - return;
1.215 - }
1.216 -
1.217 - m_bStarted = true;
1.218 -
1.219 - m_pHandler->OnMenuVoteStart(m_pCurMenu);
1.220 -
1.221 - /* By now we know how many clients were set.
1.222 - * If there are none, we should end IMMEDIATELY.
1.223 - */
1.224 - if (m_Clients == 0)
1.225 - {
1.226 - EndVoting();
1.227 - }
1.228 -}
1.229 -
1.230 -void VoteMenuHandler::DecrementPlayerCount()
1.231 -{
1.232 - assert(m_Clients > 0);
1.233 -
1.234 - m_Clients--;
1.235 -
1.236 - if (m_bStarted && m_Clients == 0)
1.237 - {
1.238 - EndVoting();
1.239 - }
1.240 -}
1.241 -
1.242 -int SortVoteItems(const void *item1, const void *item2)
1.243 -{
1.244 - return ((menu_vote_result_t::menu_item_vote_t *)item2)->count
1.245 - - ((menu_vote_result_t::menu_item_vote_t *)item1)->count;
1.246 -}
1.247 -
1.248 -void VoteMenuHandler::EndVoting()
1.249 -{
1.250 - /* Set when the next delay ends. We ignore cancellation because a menu
1.251 - * was, at one point, displayed, which is all that counts. However, we
1.252 - * do re-calculate the time just in case the menu had no time limit.
1.253 - */
1.254 - float fVoteDelay = sm_vote_delay.GetFloat();
1.255 - if (fVoteDelay < 1.0)
1.256 - {
1.257 - g_next_vote = 0.0;
1.258 - } else {
1.259 - g_next_vote = gpGlobals->curtime + fVoteDelay;
1.260 - }
1.261 -
1.262 - if (m_bCancelled)
1.263 - {
1.264 - /* If we were cancelled, don't bother tabulating anything.
1.265 - * Reset just in case someone tries to redraw, which means
1.266 - * we need to save our states.
1.267 - */
1.268 - IBaseMenu *menu = m_pCurMenu;
1.269 - IMenuHandler *handler = m_pHandler;
1.270 - InternalReset();
1.271 - handler->OnMenuVoteCancel(menu, VoteCancel_Generic);
1.272 - handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
1.273 - return;
1.274 - }
1.275 -
1.276 - menu_vote_result_t vote;
1.277 - menu_vote_result_t::menu_client_vote_t client_vote[256];
1.278 - menu_vote_result_t::menu_item_vote_t item_vote[256];
1.279 -
1.280 - memset(&vote, 0, sizeof(vote));
1.281 -
1.282 - /* Build the item list */
1.283 - for (unsigned int i=0; i<m_Items; i++)
1.284 - {
1.285 - if (m_Votes[i] > 0)
1.286 - {
1.287 - item_vote[vote.num_items].count = m_Votes[i];
1.288 - item_vote[vote.num_items].item = i;
1.289 - vote.num_votes += m_Votes[i];
1.290 - vote.num_items++;
1.291 - }
1.292 - }
1.293 - vote.item_list = item_vote;
1.294 -
1.295 - if (!vote.num_votes)
1.296 - {
1.297 - IBaseMenu *menu = m_pCurMenu;
1.298 - IMenuHandler *handler = m_pHandler;
1.299 - InternalReset();
1.300 - handler->OnMenuVoteCancel(menu, VoteCancel_NoVotes);
1.301 - handler->OnMenuEnd(menu, MenuEnd_VotingCancelled);
1.302 - return;
1.303 - }
1.304 -
1.305 - /* Build the client list */
1.306 - for (int i=1; i<=gpGlobals->maxClients; i++)
1.307 - {
1.308 - if (m_ClientVotes[i] >= -1)
1.309 - {
1.310 - client_vote[vote.num_clients].client = i;
1.311 - client_vote[vote.num_clients].item = m_ClientVotes[i];
1.312 - vote.num_clients++;
1.313 - }
1.314 - }
1.315 - vote.client_list = client_vote;
1.316 -
1.317 - /* Sort the item list descending like we promised */
1.318 - qsort(item_vote,
1.319 - vote.num_items,
1.320 - sizeof(menu_vote_result_t::menu_item_vote_t),
1.321 - SortVoteItems);
1.322 -
1.323 - /* Save states, then clear what we've saved.
1.324 - * This makes us re-entrant, which is always the safe way to go.
1.325 - */
1.326 - IBaseMenu *menu = m_pCurMenu;
1.327 - IMenuHandler *handler = m_pHandler;
1.328 - InternalReset();
1.329 -
1.330 - /* Send vote info */
1.331 - handler->OnMenuVoteResults(menu, &vote);
1.332 - handler->OnMenuEnd(menu, MenuEnd_VotingDone);
1.333 -}
1.334 -
1.335 -void VoteMenuHandler::OnMenuStart(IBaseMenu *menu)
1.336 -{
1.337 - m_Clients++;
1.338 -}
1.339 -
1.340 -void VoteMenuHandler::OnMenuEnd(IBaseMenu *menu, MenuEndReason reason)
1.341 -{
1.342 - DecrementPlayerCount();
1.343 -}
1.344 -
1.345 -void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
1.346 -{
1.347 - m_pHandler->OnMenuCancel(menu, client, reason);
1.348 -}
1.349 -
1.350 -void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
1.351 -{
1.352 - m_ClientVotes[client] = -1;
1.353 - m_pHandler->OnMenuDisplay(menu, client, display);
1.354 -}
1.355 -
1.356 -unsigned int VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, IMenuPanel *panel, unsigned int item, const ItemDrawInfo &dr)
1.357 -{
1.358 - return m_pHandler->OnMenuDisplayItem(menu, client, panel, item, dr);
1.359 -}
1.360 -
1.361 -void VoteMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
1.362 -{
1.363 - m_pHandler->OnMenuDrawItem(menu, client, item, style);
1.364 -}
1.365 -
1.366 -void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
1.367 -{
1.368 - /* Check by our item count, NOT the vote array size */
1.369 - if (item < m_Items)
1.370 - {
1.371 - m_ClientVotes[client] = item;
1.372 - m_Votes[item]++;
1.373 - m_NumVotes++;
1.374 - }
1.375 -
1.376 - m_pHandler->OnMenuSelect(menu, client, item);
1.377 -}
1.378 -
1.379 -void VoteMenuHandler::OnMenuSelect2(IBaseMenu *menu, int client, unsigned int item, unsigned int item_on_page)
1.380 -{
1.381 - if (m_pHandler->GetMenuAPIVersion2() >= 13)
1.382 - {
1.383 - m_pHandler->OnMenuSelect2(menu, client, item, item_on_page);
1.384 - }
1.385 -}
1.386 -
1.387 -void VoteMenuHandler::InternalReset()
1.388 -{
1.389 - m_Clients = 0;
1.390 - m_Items = 0;
1.391 - m_bStarted = false;
1.392 - m_pCurMenu = NULL;
1.393 - m_NumVotes = 0;
1.394 - m_bCancelled = false;
1.395 - m_pHandler = NULL;
1.396 -}
1.397 -
1.398 -void VoteMenuHandler::CancelVoting()
1.399 -{
1.400 - if (m_bCancelled || !m_pCurMenu)
1.401 - {
1.402 - return;
1.403 - }
1.404 - m_bCancelled = true;
1.405 - m_pCurMenu->Cancel();
1.406 -}
1.407 -
1.408 -IBaseMenu *VoteMenuHandler::GetCurrentMenu()
1.409 -{
1.410 - return m_pCurMenu;
1.411 -}
1.412 -
1.413 -bool VoteMenuHandler::IsCancelling()
1.414 -{
1.415 - return m_bCancelled;
1.416 -}