1.1 --- a/core/MenuVoting.cpp Wed Sep 16 13:38:04 2009 +1200
1.2 +++ b/core/MenuVoting.cpp Thu Sep 17 18:54:40 2009 +1200
1.3 @@ -34,9 +34,55 @@
1.4 #include "MenuVoting.h"
1.5 #include "PlayerManager.h"
1.6 #include "sourcemm_api.h"
1.7 +#include <sourcemod.h>
1.8 +#include <Logger.h>
1.9 +#include <HalfLife2.h>
1.10 +#include <mathlib.h>
1.11 +#include <const.h>
1.12 +#include <Translator.h>
1.13
1.14 float g_next_vote = 0.0f;
1.15
1.16 +#define VOTE_NOT_VOTING -2
1.17 +#define VOTE_PENDING -1
1.18 +
1.19 +ConVar sm_vote_hintbox("sm_vote_progress_hintbox",
1.20 + "0",
1.21 + 0,
1.22 + "Show current vote progress in a hint box",
1.23 + true,
1.24 + 0.0,
1.25 + true,
1.26 + 1.0);
1.27 +
1.28 +ConVar sm_vote_chat("sm_vote_progress_chat",
1.29 + "0",
1.30 + 0,
1.31 + "Show current vote progress as chat messages",
1.32 + true,
1.33 + 0.0,
1.34 + true,
1.35 + 1.0);
1.36 +
1.37 +ConVar sm_vote_console("sm_vote_progress_console",
1.38 + "0",
1.39 + 0,
1.40 + "Show current vote progress as console messages",
1.41 + true,
1.42 + 0.0,
1.43 + true,
1.44 + 1.0);
1.45 +
1.46 +ConVar sm_vote_client_console("sm_vote_progress_client_console",
1.47 + "0",
1.48 + 0,
1.49 + "Show current vote progress as console messages to clients",
1.50 + true,
1.51 + 0.0,
1.52 + true,
1.53 + 1.0);
1.54 +
1.55 +
1.56 #if SOURCE_ENGINE >= SE_ORANGEBOX
1.57 void OnVoteDelayChange(IConVar *cvar, const char *value, float flOldValue);
1.58 #else
1.59 @@ -117,7 +163,7 @@
1.60 * newly connected client is not allowed to vote.
1.61 */
1.62 int item;
1.63 - if ((item = m_ClientVotes[client]) >= -1)
1.64 + if ((item = m_ClientVotes[client]) >= VOTE_PENDING)
1.65 {
1.66 if (item >= 0)
1.67 {
1.68 @@ -125,7 +171,7 @@
1.69 assert(m_Votes[item] > 0);
1.70 m_Votes[item]--;
1.71 }
1.72 - m_ClientVotes[client] = -2;
1.73 + m_ClientVotes[client] = VOTE_NOT_VOTING;
1.74 }
1.75 }
1.76
1.77 @@ -189,13 +235,13 @@
1.78 return false;
1.79 }
1.80
1.81 - return (m_ClientVotes[client] > -2);
1.82 + return (m_ClientVotes[client] > VOTE_NOT_VOTING);
1.83 }
1.84
1.85 bool VoteMenuHandler::GetClientVoteChoice(int client, unsigned int *pItem)
1.86 {
1.87 if (!IsClientInVotePool(client)
1.88 - || m_ClientVotes[client] == -1)
1.89 + || m_ClientVotes[client] == VOTE_PENDING)
1.90 {
1.91 return false;
1.92 }
1.93 @@ -223,7 +269,9 @@
1.94 assert((unsigned)m_ClientVotes[client] < m_Items);
1.95 assert(m_Votes[m_ClientVotes[client]] > 0);
1.96 m_Votes[m_ClientVotes[client]]--;
1.97 - m_ClientVotes[client] = -1;
1.98 + m_ClientVotes[client] = VOTE_PENDING;
1.99 + m_Revoting[client] = true;
1.100 + m_NumVotes--;
1.101 }
1.102
1.103 if (m_nMenuTime == MENU_TIME_FOREVER)
1.104 @@ -259,7 +307,8 @@
1.105 /* Mark all clients as not voting */
1.106 for (int i=1; i<=gpGlobals->maxClients; i++)
1.107 {
1.108 - m_ClientVotes[i] = -2;
1.109 + m_ClientVotes[i] = VOTE_NOT_VOTING;
1.110 + m_Revoting[i] = false;
1.111 }
1.112
1.113 m_Items = menu->GetItemCount();
1.114 @@ -303,6 +352,8 @@
1.115
1.116 m_pHandler->OnMenuVoteStart(m_pCurMenu);
1.117
1.118 + m_displayTimer = g_Timers.CreateTimer(this, 1.0, NULL, TIMER_FLAG_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
1.119 +
1.120 /* By now we know how many clients were set.
1.121 * If there are none, we should end IMMEDIATELY.
1.122 */
1.123 @@ -310,6 +361,8 @@
1.124 {
1.125 EndVoting();
1.126 }
1.127 +
1.128 + m_TotalClients = m_Clients;
1.129 }
1.130
1.131 void VoteMenuHandler::DecrementPlayerCount()
1.132 @@ -346,6 +399,11 @@
1.133 g_next_vote = gpGlobals->curtime + fVoteDelay;
1.134 }
1.135
1.136 + if (m_displayTimer)
1.137 + {
1.138 + g_Timers.KillTimer(m_displayTimer);
1.139 + }
1.140 +
1.141 if (m_bCancelled)
1.142 {
1.143 /* If we were cancelled, don't bother tabulating anything.
1.144 @@ -392,7 +450,7 @@
1.145 /* Build the client list */
1.146 for (int i=1; i<=gpGlobals->maxClients; i++)
1.147 {
1.148 - if (m_ClientVotes[i] >= -1)
1.149 + if (m_ClientVotes[i] >= VOTE_PENDING)
1.150 {
1.151 client_vote[vote.num_clients].client = i;
1.152 client_vote[vote.num_clients].item = m_ClientVotes[i];
1.153 @@ -436,7 +494,7 @@
1.154
1.155 void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
1.156 {
1.157 - m_ClientVotes[client] = -1;
1.158 + m_ClientVotes[client] = VOTE_PENDING;
1.159 m_pHandler->OnMenuDisplay(menu, client, display);
1.160 }
1.161
1.162 @@ -458,6 +516,55 @@
1.163 m_ClientVotes[client] = item;
1.164 m_Votes[item]++;
1.165 m_NumVotes++;
1.166 +
1.167 + if (sm_vote_chat.GetBool() || sm_vote_console.GetBool())
1.168 + {
1.169 + static char buffer[1024];
1.170 + ItemDrawInfo dr;
1.171 + menu->GetItemInfo(item, &dr);
1.172 +
1.173 + if (sm_vote_console.GetBool())
1.174 + {
1.175 + int target = SOURCEMOD_SERVER_LANGUAGE;
1.176 + CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For", &target, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
1.177 + Engine_LogPrintWrapper(buffer);
1.178 + }
1.179 +
1.180 + if (sm_vote_chat.GetBool() || sm_vote_client_console.GetBool())
1.181 + {
1.182 + int maxclients = g_Players.GetMaxClients();
1.183 + for (int i=1; i<=maxclients; i++)
1.184 + {
1.185 + CPlayer *pPlayer = g_Players.GetPlayerByIndex(i);
1.186 + assert(pPlayer);
1.187 +
1.188 + if (pPlayer->IsInGame())
1.189 + {
1.190 + if (m_Revoting[client])
1.191 + {
1.192 + CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Changed Vote", &i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
1.193 + }
1.194 + else
1.195 + {
1.196 + CoreTranslate(buffer, sizeof(buffer), "[SM] %T", 4, NULL, "Voted For", &i, g_Players.GetPlayerByIndex(client)->GetName(), dr.display);
1.197 + }
1.198 +
1.199 + if (sm_vote_chat.GetBool())
1.200 + {
1.201 + g_HL2.TextMsg(i, HUD_PRINTTALK, buffer);
1.202 + }
1.203 +
1.204 + if (sm_vote_client_console.GetBool())
1.205 + {
1.206 + engine->ClientPrintf(pPlayer->GetEdict(), buffer);
1.207 + }
1.208 + }
1.209 + }
1.210 + }
1.211 + }
1.212 +
1.213 + BuildVoteLeaders();
1.214 + DrawHintProgress();
1.215 }
1.216
1.217 m_pHandler->OnMenuSelect(menu, client, item);
1.218 @@ -480,6 +587,9 @@
1.219 m_NumVotes = 0;
1.220 m_bCancelled = false;
1.221 m_pHandler = NULL;
1.222 + m_leaderList[0] = '\0';
1.223 + m_displayTimer = NULL;
1.224 + m_TotalClients = 0;
1.225 }
1.226
1.227 void VoteMenuHandler::CancelVoting()
1.228 @@ -502,3 +612,85 @@
1.229 return m_bCancelled;
1.230 }
1.231
1.232 +void VoteMenuHandler::DrawHintProgress()
1.233 +{
1.234 + if (!sm_vote_hintbox.GetBool())
1.235 + {
1.236 + return;
1.237 + }
1.238 +
1.239 + static char buffer[1024];
1.240 +
1.241 + float timeRemaining = (m_fStartTime + m_nMenuTime) - gpGlobals->curtime;
1.242 + if (timeRemaining < 0)
1.243 + {
1.244 + timeRemaining = 0.0;
1.245 + }
1.246 +
1.247 + int iTimeRemaining = RoundFloatToInt(timeRemaining);
1.248 +
1.249 + int maxclients = g_Players.GetMaxClients();
1.250 + for (int i=1; i<=maxclients; i++)
1.251 + {
1.252 + if (g_Players.GetPlayerByIndex(i)->IsInGame())
1.253 + {
1.254 + CoreTranslate(buffer, sizeof(buffer), "%T%s", 6, NULL, "Vote Count", &i, &m_NumVotes, &m_TotalClients, &iTimeRemaining, &m_leaderList);
1.255 + g_HL2.HintTextMsg(i, buffer);
1.256 + }
1.257 + }
1.258 +}
1.259 +
1.260 +void VoteMenuHandler::BuildVoteLeaders()
1.261 +{
1.262 + if (m_NumVotes == 0 || !sm_vote_hintbox.GetBool())
1.263 + {
1.264 + return;
1.265 + }
1.266 +
1.267 + menu_vote_result_t vote;
1.268 + menu_vote_result_t::menu_item_vote_t item_vote[256];
1.269 +
1.270 + memset(&vote, 0, sizeof(vote));
1.271 +
1.272 + /* Build the item list */
1.273 + for (unsigned int i=0; i<m_Items; i++)
1.274 + {
1.275 + if (m_Votes[i] > 0)
1.276 + {
1.277 + item_vote[vote.num_items].count = m_Votes[i];
1.278 + item_vote[vote.num_items].item = i;
1.279 + vote.num_votes += m_Votes[i];
1.280 + vote.num_items++;
1.281 + }
1.282 + }
1.283 + vote.item_list = item_vote;
1.284 + assert(vote.num_votes);
1.285 +
1.286 + /* Sort the item list descending */
1.287 + qsort(item_vote,
1.288 + vote.num_items,
1.289 + sizeof(menu_vote_result_t::menu_item_vote_t),
1.290 + SortVoteItems);
1.291 +
1.292 + /* Take the top 3 (if applicable) and draw them */
1.293 + int len = 0;
1.294 + for (unsigned int i=0; i<vote.num_items && i<3; i++)
1.295 + {
1.296 + int curItem = vote.item_list[i].item;
1.297 + ItemDrawInfo dr;
1.298 + m_pCurMenu->GetItemInfo(curItem, &dr);
1.299 + len += g_SourceMod.Format(m_leaderList + len, sizeof(m_leaderList) - len, "\n%i. %s: (%i)", i+1, dr.display, vote.item_list[i].count);
1.300 + }
1.301 +}
1.302 +
1.303 +SourceMod::ResultType VoteMenuHandler::OnTimer(ITimer *pTimer, void *pData)
1.304 +{
1.305 + DrawHintProgress();
1.306 +
1.307 + return Pl_Continue;
1.308 +}
1.309 +
1.310 +void VoteMenuHandler::OnTimerEnd(ITimer *pTimer, void *pData)
1.311 +{
1.312 + m_displayTimer = NULL;
1.313 +}