added experimental voting API

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40883
This commit is contained in:
David Anderson 2007-06-05 16:27:45 +00:00
parent 2884483bef
commit aea69f5fe8
9 changed files with 352 additions and 285 deletions

View File

@ -12,9 +12,9 @@
* Version: $Id$ * Version: $Id$
*/ */
#include <stdarg.h>
#include <time.h> #include <time.h>
#include <stdarg.h>
#include <stdlib.h>
#include "MenuManager.h" #include "MenuManager.h"
#include "sm_stringutil.h" #include "sm_stringutil.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
@ -25,115 +25,188 @@
MenuManager g_Menus; MenuManager g_Menus;
/************************************* /*******************************
************************************* *******************************
**** BROADCAST HANDLING WRAPPERS **** ******** VOTE HANDLER *********
************************************* *******************************
*************************************/ *******************************/
BroadcastHandler::BroadcastHandler(IMenuHandler *handler) : m_pHandler(handler), numClients(0) unsigned int VoteMenuHandler::GetMenuAPIVersion2()
{
}
unsigned int BroadcastHandler::GetMenuAPIVersion2()
{ {
return m_pHandler->GetMenuAPIVersion2(); return m_pHandler->GetMenuAPIVersion2();
} }
void BroadcastHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason) bool VoteMenuHandler::IsVoteInProgress()
{
return (m_pCurMenu != NULL);
}
void VoteMenuHandler::InitializeVoting(IBaseMenu *menu)
{
m_Items = menu->GetItemCount();
if (m_Votes.size() < (size_t)m_Items)
{
/* Only clear the items we need to... */
size_t size = m_Votes.size();
for (size_t i=0; i<size; i++)
{
m_Votes[i] = 0;
}
m_Votes.resize(m_Items, 0);
} else {
for (unsigned int i=0; i<m_Items; i++)
{
m_Votes[i] = 0;
}
}
m_pCurMenu = menu;
m_pHandler->OnMenuStart(m_pCurMenu);
}
void VoteMenuHandler::StartVoting()
{
m_bStarted = true;
m_pHandler->OnMenuVoteStart(m_pCurMenu);
/* By now we know how many clients were set.
* If there are none, we should end IMMEDIATELY.
*/
if (m_Clients == 0)
{
EndVoting();
}
}
void VoteMenuHandler::DecrementPlayerCount()
{
assert(m_Clients > 0);
m_Clients--;
if (m_bStarted && m_Clients == 0)
{
EndVoting();
}
}
void VoteMenuHandler::EndVoting()
{
unsigned int chosen = 0;
/* If we got zero votes, take a shortcut. */
if (m_NumVotes == 0)
{
/* Pick a random item and then jump far, far away. */
srand((unsigned int)(time(NULL)));
chosen = (unsigned int)rand() % static_cast<unsigned int>(m_Votes.size());
goto picked_item;
}
/* We can't have more dups than this!
* This is the max number of players.
*/
unsigned int dup_array[256];
unsigned int dup_count = 0;
size_t highest = 0;
for (size_t i=1; i<m_Votes.size(); i++)
{
if (m_Votes[i] > m_Votes[highest])
{
/* If we have a new highest count, mark it and trash the duplicate
* list by setting the total to 0.
*/
highest = i;
dup_count = 0;
} else if (m_Votes[i] == m_Votes[highest]) {
/* If they're equal, mark it in the duplicate list.
* We'll add in the original later.
*/
dup_array[dup_count++] = i;
}
}
/* Check if we need to pick from the duplicate list */
if (dup_count)
{
/* Re-add the original to the list because it's not in there. */
dup_array[dup_count++] = (unsigned int)highest;
/* Pick a random slot. */
srand((unsigned int)(time(NULL)));
unsigned int r = (unsigned int)rand() % dup_count;
/* Pick the item. */
chosen = dup_array[r];
} else {
chosen = (unsigned int)highest;
}
picked_item:
m_pHandler->OnMenuVoteEnd(m_pCurMenu, chosen);
m_pHandler->OnMenuEnd(m_pCurMenu);
InternalReset();
}
void VoteMenuHandler::OnMenuStart(IBaseMenu *menu)
{
m_Clients++;
}
void VoteMenuHandler::OnMenuEnd(IBaseMenu *menu)
{
DecrementPlayerCount();
}
void VoteMenuHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
{ {
m_pHandler->OnMenuCancel(menu, client, reason); m_pHandler->OnMenuCancel(menu, client, reason);
} }
void BroadcastHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display) void VoteMenuHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display)
{ {
numClients++;
m_pHandler->OnMenuDisplay(menu, client, display); m_pHandler->OnMenuDisplay(menu, client, display);
} }
void BroadcastHandler::OnBroadcastEnd(IBaseMenu *menu) void VoteMenuHandler::OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display)
{ {
g_Menus.FreeBroadcastHandler(this); m_pHandler->OnMenuDisplayItem(menu, client, item, display);
} }
void BroadcastHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item) void VoteMenuHandler::OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style)
{ {
m_pHandler->OnMenuDrawItem(menu, client, item, style);
}
void VoteMenuHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
{
/* Check by our item count, NOT the vote array size */
if (item < m_Items)
{
m_Votes[item]++;
m_NumVotes++;
}
m_pHandler->OnMenuSelect(menu, client, item); m_pHandler->OnMenuSelect(menu, client, item);
} }
void BroadcastHandler::OnMenuEnd(IBaseMenu *menu) void VoteMenuHandler::Reset(IMenuHandler *mh)
{ {
assert(numClients > 0); m_pHandler = mh;
InternalReset();
/* Only fire if all clients have gotten a menu end */
if (--numClients == 0)
{
IMenuHandler *pHandler = m_pHandler;
OnBroadcastEnd(menu);
pHandler->OnMenuEnd(menu);
}
} }
VoteHandler::VoteHandler(IMenuVoteHandler *handler) void VoteMenuHandler::InternalReset()
: BroadcastHandler(handler), m_pVoteHandler(handler)
{ {
} m_Clients = 0;
m_Items = 0;
void VoteHandler::Initialize(IBaseMenu *menu) m_bStarted = false;
{ m_pCurMenu = NULL;
unsigned int numItems = menu->GetItemCount(); m_NumVotes = 0;
if (m_counts.size() >= numItems)
{
for (size_t i=0; i<numItems; i++)
{
m_counts[i] = 0;
}
} else {
for (size_t i=0; i<m_counts.size(); i++)
{
m_counts[i] = 0;
}
m_counts.resize(numItems, 0);
}
}
void VoteHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
{
if (item < numItems)
{
m_counts[item]++;
}
BroadcastHandler::OnMenuSelect(menu, client, item);
}
void VoteHandler::OnBroadcastEnd(IBaseMenu *menu)
{
m_ties.clear();
size_t highest = 0;
for (size_t i=1; i<numItems; i++)
{
if (m_counts[i] > m_counts[highest])
{
m_ties.clear();
highest = i;
} else if (m_counts[i] == m_counts[highest]) {
m_ties.push_back(i);
}
}
if (m_ties.size())
{
m_ties.push_back(highest);
srand(static_cast<unsigned int>(time(NULL)));
highest = m_ties[rand() % m_ties.size()];
}
m_pVoteHandler->OnMenuVoteEnd(menu, highest);
g_Menus.FreeVoteHandler(this);
} }
/******************************* /*******************************
@ -169,12 +242,6 @@ void MenuManager::OnSourceModAllShutdown()
g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent); g_HandleSys.RemoveType(m_MenuType, g_pCoreIdent);
g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent); g_HandleSys.RemoveType(m_StyleType, g_pCoreIdent);
while (!m_BroadcastHandlers.empty())
{
delete m_BroadcastHandlers.front();
m_BroadcastHandlers.pop();
}
while (!m_VoteHandlers.empty()) while (!m_VoteHandlers.empty())
{ {
delete m_VoteHandlers.front(); delete m_VoteHandlers.front();
@ -659,119 +726,34 @@ skip_search:
return display; return display;
} }
#if 0
unsigned int MenuManager::BroadcastMenu(IBaseMenu *menu,
IMenuHandler *handler,
int clients[],
unsigned int numClients,
unsigned int time)
{
BroadcastHandler *bh;
if (m_BroadcastHandlers.empty())
{
bh = new BroadcastHandler(handler);
} else {
bh = m_BroadcastHandlers.front();
m_BroadcastHandlers.pop();
bh->m_pHandler = handler;
bh->numClients = 0;
}
handler->OnMenuStart(menu);
unsigned int total = 0;
for (unsigned int i=0; i<numClients; i++)
{
/* Only continue if displaying works */
if (!menu->Display(clients[i], bh, time))
{
continue;
}
/* :TODO: Allow sourcetv only, not all bots */
CPlayer *player = g_Players.GetPlayerByIndex(clients[i]);
if (player->IsFakeClient())
{
continue;
}
total++;
}
if (!total)
{
/* End the broadcast here */
handler->OnMenuEnd(menu);
FreeBroadcastHandler(bh);
}
return total;
}
unsigned int MenuManager::VoteMenu(IBaseMenu *menu,
IMenuVoteHandler *handler,
int clients[],
unsigned int numClients,
unsigned int time)
{
VoteHandler *vh;
if (m_VoteHandlers.empty())
{
vh = new VoteHandler(handler);
} else {
vh = m_VoteHandlers.front();
m_VoteHandlers.pop();
vh->m_pHandler = handler;
vh->numClients = 0;
}
vh->Initialize(menu);
handler->OnMenuStart(menu);
unsigned int total = 0;
for (unsigned int i=0; i<numClients; i++)
{
/* Only continue if displaying works */
if (!menu->Display(clients[i], vh, time))
{
continue;
}
/* :TODO: Allow sourcetv only, not all bots */
CPlayer *player = g_Players.GetPlayerByIndex(clients[i]);
if (player->IsFakeClient())
{
continue;
}
total++;
}
if (!total)
{
/* End the broadcast here */
handler->OnMenuEnd(menu);
FreeVoteHandler(vh);
}
return total;
}
#endif
void MenuManager::FreeBroadcastHandler(BroadcastHandler *bh)
{
m_BroadcastHandlers.push(bh);
}
void MenuManager::FreeVoteHandler(VoteHandler *vh)
{
m_VoteHandlers.push(vh);
}
IMenuStyle *MenuManager::GetDefaultStyle() IMenuStyle *MenuManager::GetDefaultStyle()
{ {
return m_pDefaultStyle; return m_pDefaultStyle;
} }
IVoteMenuHandler *MenuManager::CreateVoteWrapper(IMenuHandler *mh)
{
VoteMenuHandler *vh = NULL;
if (m_VoteHandlers.empty())
{
vh = new VoteMenuHandler;
} else {
vh = m_VoteHandlers.front();
m_VoteHandlers.pop();
}
vh->Reset(mh);
return vh;
}
void MenuManager::ReleaseVoteWrapper(IVoteMenuHandler *mh)
{
if (mh == NULL)
{
return;
}
m_VoteHandlers.push((VoteMenuHandler *)mh);
}

View File

@ -25,36 +25,36 @@
using namespace SourceMod; using namespace SourceMod;
using namespace SourceHook; using namespace SourceHook;
class BroadcastHandler : public IMenuHandler class VoteMenuHandler : public IVoteMenuHandler
{ {
public:
BroadcastHandler(IMenuHandler *handler);
public: //IMenuHandler public: //IMenuHandler
unsigned int GetMenuAPIVersion2();
void OnMenuStart(IBaseMenu *menu);
void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display); void OnMenuDisplay(IBaseMenu *menu, int client, IMenuPanel *display);
void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item); void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
void OnMenuEnd(IBaseMenu *menu);
void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason); void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
unsigned int GetMenuAPIVersion2(); void OnMenuEnd(IBaseMenu *menu);
void OnMenuDrawItem(IBaseMenu *menu, int client, unsigned int item, unsigned int &style);
void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display);
public: //IVoteMenuHandler
bool IsVoteInProgress();
void InitializeVoting(IBaseMenu *menu);
void StartVoting();
public: public:
virtual void OnBroadcastEnd(IBaseMenu *menu); void Reset(IMenuHandler *mh);
public:
IMenuHandler *m_pHandler;
unsigned int numClients;
};
class VoteHandler : public BroadcastHandler
{
public:
VoteHandler(IMenuVoteHandler *handler);
public:
void Initialize(IBaseMenu *menu);
void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
void OnBroadcastEnd(IBaseMenu *menu);
private: private:
CVector<unsigned int> m_counts; void DecrementPlayerCount();
CVector<unsigned int> m_ties; void EndVoting();
unsigned int numItems; void InternalReset();
IMenuVoteHandler *m_pVoteHandler; private:
IMenuHandler *m_pHandler;
unsigned int m_Clients;
unsigned int m_Items;
CVector<unsigned int> m_Votes;
CVector<unsigned int> m_Dups;
IBaseMenu *m_pCurMenu;
bool m_bStarted;
unsigned int m_NumVotes;
}; };
class MenuManager : class MenuManager :
@ -84,35 +84,24 @@ public:
unsigned int GetStyleCount(); unsigned int GetStyleCount();
IMenuStyle *GetStyle(unsigned int index); IMenuStyle *GetStyle(unsigned int index);
IMenuStyle *FindStyleByName(const char *name); IMenuStyle *FindStyleByName(const char *name);
unsigned int BroadcastMenu(IBaseMenu *menu,
IMenuHandler *handler,
int clients[],
unsigned int numClients,
unsigned int time);
unsigned int VoteMenu(IBaseMenu *menu,
IMenuVoteHandler *handler,
int clients[],
unsigned int numClients,
unsigned int time);
IMenuStyle *GetDefaultStyle(); IMenuStyle *GetDefaultStyle();
void AddStyle(IMenuStyle *style); void AddStyle(IMenuStyle *style);
bool SetDefaultStyle(IMenuStyle *style); bool SetDefaultStyle(IMenuStyle *style);
IMenuPanel *RenderMenu(int client, menu_states_t &states, ItemOrder order); IMenuPanel *RenderMenu(int client, menu_states_t &states, ItemOrder order);
IVoteMenuHandler *CreateVoteWrapper(IMenuHandler *mh);
void ReleaseVoteWrapper(IVoteMenuHandler *mh);
public: //IHandleTypeDispatch public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object); void OnHandleDestroy(HandleType_t type, void *object);
public: public:
HandleError ReadMenuHandle(Handle_t handle, IBaseMenu **menu); HandleError ReadMenuHandle(Handle_t handle, IBaseMenu **menu);
HandleError ReadStyleHandle(Handle_t handle, IMenuStyle **style); HandleError ReadStyleHandle(Handle_t handle, IMenuStyle **style);
protected: protected:
void FreeBroadcastHandler(BroadcastHandler *bh);
void FreeVoteHandler(VoteHandler *vh);
Handle_t CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner); Handle_t CreateMenuHandle(IBaseMenu *menu, IdentityToken_t *pOwner);
Handle_t CreateStyleHandle(IMenuStyle *style); Handle_t CreateStyleHandle(IMenuStyle *style);
private: private:
int m_ShowMenu; int m_ShowMenu;
IMenuStyle *m_pDefaultStyle; IMenuStyle *m_pDefaultStyle;
CStack<BroadcastHandler *> m_BroadcastHandlers; CStack<VoteMenuHandler *> m_VoteHandlers;
CStack<VoteHandler *> m_VoteHandlers;
CVector<IMenuStyle *> m_Styles; CVector<IMenuStyle *> m_Styles;
HandleType_t m_StyleType; HandleType_t m_StyleType;
HandleType_t m_MenuType; HandleType_t m_MenuType;

View File

@ -434,12 +434,14 @@ bool BaseMenuStyle::RedoClientMenu(int client, ItemOrder order)
CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) : CBaseMenu::CBaseMenu(IMenuHandler *pHandler, IMenuStyle *pStyle, IdentityToken_t *pOwner) :
m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_ExitButton(true), m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_ExitButton(true),
m_bShouldDelete(false), m_bCancelling(false), m_pOwner(pOwner ? pOwner : g_pCoreIdent), m_bShouldDelete(false), m_bCancelling(false), m_pOwner(pOwner ? pOwner : g_pCoreIdent),
m_bDeleting(false), m_bWillFreeHandle(false), m_hHandle(BAD_HANDLE), m_pHandler(pHandler) m_bDeleting(false), m_bWillFreeHandle(false), m_hHandle(BAD_HANDLE), m_pHandler(pHandler),
m_pVoteHandler(NULL)
{ {
} }
CBaseMenu::~CBaseMenu() CBaseMenu::~CBaseMenu()
{ {
g_Menus.ReleaseVoteWrapper(m_pVoteHandler);
} }
Handle_t CBaseMenu::GetHandle() Handle_t CBaseMenu::GetHandle()
@ -647,3 +649,24 @@ void CBaseMenu::InternalDelete()
delete this; delete this;
} }
bool CBaseMenu::BroadcastVote(int clients[],
unsigned int numClients,
unsigned int maxTime,
unsigned int flags)
{
if (!m_pVoteHandler)
{
m_pVoteHandler = g_Menus.CreateVoteWrapper(m_pHandler);
} else if (m_pVoteHandler->IsVoteInProgress()) {
return false;
}
m_pVoteHandler->InitializeVoting(this);
for (unsigned int i=0; i<numClients; i++)
{
VoteDisplay(clients[i], maxTime);
}
m_pVoteHandler->StartVoting();
}

View File

@ -111,6 +111,12 @@ public:
virtual void Destroy(bool releaseHandle); virtual void Destroy(bool releaseHandle);
virtual void Cancel_Finally() =0; virtual void Cancel_Finally() =0;
virtual Handle_t GetHandle(); virtual Handle_t GetHandle();
bool BroadcastVote(int clients[],
unsigned int numClients,
unsigned int maxTime,
unsigned int flags=0);
public:
virtual void VoteDisplay(int client, unsigned int maxTime) =0;
private: private:
void InternalDelete(); void InternalDelete();
protected: protected:
@ -127,6 +133,7 @@ protected:
bool m_bWillFreeHandle; bool m_bWillFreeHandle;
Handle_t m_hHandle; Handle_t m_hHandle;
IMenuHandler *m_pHandler; IMenuHandler *m_pHandler;
IVoteMenuHandler *m_pVoteHandler;
}; };
#endif //_INCLUDE_MENUSTYLE_BASE_H #endif //_INCLUDE_MENUSTYLE_BASE_H

View File

@ -366,9 +366,24 @@ IMenuPanel *CRadioMenu::CreatePanel()
bool CRadioMenu::Display(int client, unsigned int time) bool CRadioMenu::Display(int client, unsigned int time)
{ {
if (m_bCancelling)
{
return false;
}
return g_RadioMenuStyle.DoClientMenu(client, this, m_pHandler, time); return g_RadioMenuStyle.DoClientMenu(client, this, m_pHandler, time);
} }
void CRadioMenu::VoteDisplay(int client, unsigned int maxTime)
{
if (m_bCancelling)
{
return;
}
g_RadioMenuStyle.DoClientMenu(client, this, m_pVoteHandler, maxTime);
}
void CRadioMenu::Cancel_Finally() void CRadioMenu::Cancel_Finally()
{ {
g_RadioMenuStyle.CancelMenu(this); g_RadioMenuStyle.CancelMenu(this);

View File

@ -98,6 +98,7 @@ public:
IMenuPanel *CreatePanel(); IMenuPanel *CreatePanel();
bool Display(int client, unsigned int time); bool Display(int client, unsigned int time);
void Cancel_Finally(); void Cancel_Finally();
void VoteDisplay(int client, unsigned int maxTime);
}; };
extern CRadioStyle g_RadioMenuStyle; extern CRadioStyle g_RadioMenuStyle;

View File

@ -375,6 +375,16 @@ bool CValveMenu::Display(int client, unsigned int time)
return g_ValveMenuStyle.DoClientMenu(client, this, m_pHandler, time); return g_ValveMenuStyle.DoClientMenu(client, this, m_pHandler, time);
} }
void CValveMenu::VoteDisplay(int client, unsigned int maxTime)
{
if (m_bCancelling)
{
return;
}
g_ValveMenuStyle.DoClientMenu(client, this, m_pVoteHandler, maxTime);
}
IMenuPanel *CValveMenu::CreatePanel() IMenuPanel *CValveMenu::CreatePanel()
{ {
return new CValveMenuDisplay(this); return new CValveMenuDisplay(this);

View File

@ -103,6 +103,7 @@ public: //IBaseMenu
bool SetExitButton(bool set); bool SetExitButton(bool set);
bool SetPagination(unsigned int itemsPerPage); bool SetPagination(unsigned int itemsPerPage);
bool Display(int client, unsigned int time); bool Display(int client, unsigned int time);
void VoteDisplay(int client, unsigned int maxTime);
public: //CBaseMenu public: //CBaseMenu
void Cancel_Finally(); void Cancel_Finally();
private: private:

View File

@ -23,7 +23,7 @@
#include <IHandleSys.h> #include <IHandleSys.h>
#define SMINTERFACE_MENUMANAGER_NAME "IMenuManager" #define SMINTERFACE_MENUMANAGER_NAME "IMenuManager"
#define SMINTERFACE_MENUMANAGER_VERSION 1 #define SMINTERFACE_MENUMANAGER_VERSION 2
/** /**
* @file IMenuManager.h * @file IMenuManager.h
@ -498,6 +498,23 @@ namespace SourceMod
* @return Handle_t handle value. * @return Handle_t handle value.
*/ */
virtual Handle_t GetHandle() =0; virtual Handle_t GetHandle() =0;
/**
* @brief Sends a menu to multiple clients as a vote menu. All callbacks
* will be sent as normal, except two extras, OnMenuVoteStart and
* OnMenuVoteEnd, will be called.
*
* @param clients Array of client indexes.
* @param numClients Number of client indexes in the array.
* @param maxTime Maximum amount of time to hold the vote.
* @param flags Optional voting flags (currently unused).
* @return True on success, false if a vote is already in
* progress (the menu must be cancelled first).
*/
virtual bool BroadcastVote(int clients[],
unsigned int numClients,
unsigned int maxTime,
unsigned int flags=0) =0;
}; };
/** /**
@ -600,21 +617,55 @@ namespace SourceMod
virtual void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display) virtual void OnMenuDisplayItem(IBaseMenu *menu, int client, unsigned int item, const char **display)
{ {
} }
};
/** /**
* @brief Handles a vote menu. * @brief Called when a vote has been started and displayed to
* clients. This is called after OnMenuStart() and OnMenuDisplay(),
* but before OnMenuSelect().
*
* @param menu Menu pointer.
*/ */
class IMenuVoteHandler : public IMenuHandler virtual void OnMenuVoteStart(IBaseMenu *menu)
{ {
public: }
/** /**
* @brief Called when a vote ends. * @brief Called when a vote ends. This is automatically called by the
* wrapper, and never needs to called from a style implementation.
* *
* @param menu Menu pointer. * @param menu Menu pointer.
* @param item Item position that was chosen by a majority. * @param item Item position that was chosen by a majority.
*/ */
virtual void OnMenuVoteEnd(IBaseMenu *menu, unsigned int item) =0; virtual void OnMenuVoteEnd(IBaseMenu *menu, unsigned int item)
{
}
};
/**
* @brief Contains functions for managing a vote handler.
*/
class IVoteMenuHandler : public IMenuHandler
{
public:
/**
* @brief Returns whether or not a vote is in progress.
*
* @return True if a vote is in progress, false otherwise.
*/
virtual bool IsVoteInProgress() =0;
/**
* @brief Use this to mark the vote as in progress (start).
*
* @param menu Menu pointer.
*/
virtual void InitializeVoting(IBaseMenu *menu) =0;
/**
* @brief Use this to notify that all clients' displays have been
* processed (i.e., there are no more clients to display to).
*/
virtual void StartVoting() =0;
}; };
/** /**
@ -640,39 +691,6 @@ namespace SourceMod
*/ */
virtual IMenuStyle *FindStyleByName(const char *name) =0; virtual IMenuStyle *FindStyleByName(const char *name) =0;
#if 0
/**
* @brief Broadcasts a menu to a number of clients.
*
* @param menu Menu pointer.
* @param clients Array of client indexes.
* @param numClients Number of clients in the array.
* @param time Time to hold the menu.
* @return Number of clients the menu will be waiting on.
*/
virtual unsigned int BroadcastMenu(IBaseMenu *menu,
IMenuHandler *handler,
int clients[],
unsigned int numClients,
unsigned int time) =0;
/**
* @brief Broadcasts a menu to a number of clients as a vote menu.
*
* @param menu Menu pointer.
* @param handler IMenuHandler pointer.
* @param clients Array of client indexes.
* @param numClients Number of clients in the array.
* @param time Time to hold the menu.
* @return Number of clients the menu will be waiting on.
*/
virtual unsigned int VoteMenu(IBaseMenu *menu,
IMenuVoteHandler *handler,
int clients[],
unsigned int numClients,
unsigned int time) =0;
#endif
/** /**
* @brief Returns the default draw style Core is using. * @brief Returns the default draw style Core is using.
* *
@ -695,6 +713,27 @@ namespace SourceMod
* be freed using IMenuPanel::DeleteThis. * be freed using IMenuPanel::DeleteThis.
*/ */
virtual IMenuPanel *RenderMenu(int client, menu_states_t &states, ItemOrder order) =0; virtual IMenuPanel *RenderMenu(int client, menu_states_t &states, ItemOrder order) =0;
/**
* @brief Creates a standard voting wrapper. The wrapper is not
* re-entrant; a second menu cannot be displayed on the same handler
* at the same time.
*
* @param mh Menu handler to wrap around.
* @return An IMenuHandler pointer that is a wrapper
* around IMenuHandler callbacks to invoke
* voting related callbacks.
*/
virtual IVoteMenuHandler *CreateVoteWrapper(IMenuHandler *mh) =0;
/**
* @brief Frees a standard voting wrapper.
*
* @param mh Menu handler pointer created by
* CreateVoteWrapper(). NULL values will be
* safely ignored.
*/
virtual void ReleaseVoteWrapper(IVoteMenuHandler *mh) =0;
}; };
} }