behold with your eyes and view upon what are MENUS
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40775
This commit is contained in:
parent
30f50e6ded
commit
d7b2f9a721
@ -42,6 +42,7 @@ ConCmdManager::ConCmdManager() : m_Strings(1024)
|
|||||||
m_pExecCmd = NULL;
|
m_pExecCmd = NULL;
|
||||||
m_pServerCfgFile = NULL;
|
m_pServerCfgFile = NULL;
|
||||||
m_pServerCfgFwd = NULL;
|
m_pServerCfgFwd = NULL;
|
||||||
|
m_CmdClient = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConCmdManager::~ConCmdManager()
|
ConCmdManager::~ConCmdManager()
|
||||||
|
@ -111,6 +111,11 @@ private:
|
|||||||
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
|
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
|
||||||
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
|
||||||
void OnExecCmd();
|
void OnExecCmd();
|
||||||
|
public:
|
||||||
|
inline int GetCommandClient()
|
||||||
|
{
|
||||||
|
return m_CmdClient;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
Trie *m_pCmds; /* command lookup */
|
Trie *m_pCmds; /* command lookup */
|
||||||
Trie *m_pCmdGrps; /* command group lookup */
|
Trie *m_pCmdGrps; /* command group lookup */
|
||||||
|
676
core/MenuManager.cpp
Normal file
676
core/MenuManager.cpp
Normal file
@ -0,0 +1,676 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "MenuManager.h"
|
||||||
|
#include "sm_stringutil.h"
|
||||||
|
#include "sourcemm_api.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
|
#include "MenuStyle_Valve.h"
|
||||||
|
|
||||||
|
MenuManager g_Menus;
|
||||||
|
|
||||||
|
/*************************************
|
||||||
|
*************************************
|
||||||
|
**** BROADCAST HANDLING WRAPPERS ****
|
||||||
|
*************************************
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
BroadcastHandler::BroadcastHandler(IMenuHandler *handler) : m_pHandler(handler), numClients(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int BroadcastHandler::GetMenuAPIVersion2()
|
||||||
|
{
|
||||||
|
return m_pHandler->GetMenuAPIVersion2();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadcastHandler::OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason)
|
||||||
|
{
|
||||||
|
m_pHandler->OnMenuCancel(menu, client, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadcastHandler::OnMenuDisplay(IBaseMenu *menu, int client, IMenuDisplay *display)
|
||||||
|
{
|
||||||
|
numClients++;
|
||||||
|
m_pHandler->OnMenuDisplay(menu, client, display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadcastHandler::OnBroadcastEnd(IBaseMenu *menu)
|
||||||
|
{
|
||||||
|
g_Menus.FreeBroadcastHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadcastHandler::OnMenuSelect(IBaseMenu *menu, int client, unsigned int item)
|
||||||
|
{
|
||||||
|
m_pHandler->OnMenuSelect(menu, client, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BroadcastHandler::OnMenuEnd(IBaseMenu *menu)
|
||||||
|
{
|
||||||
|
assert(numClients > 0);
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
: BroadcastHandler(handler), m_pVoteHandler(handler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoteHandler::Initialize(IBaseMenu *menu)
|
||||||
|
{
|
||||||
|
unsigned int numItems = menu->GetItemCount();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
*******************************
|
||||||
|
******** MENU MANAGER *********
|
||||||
|
*******************************
|
||||||
|
*******************************/
|
||||||
|
|
||||||
|
MenuManager::MenuManager()
|
||||||
|
{
|
||||||
|
m_ShowMenu = -1;
|
||||||
|
m_pDefaultStyle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::OnSourceModAllInitialized()
|
||||||
|
{
|
||||||
|
int num = g_SMAPI->GetUserMessageCount();
|
||||||
|
if (num >= 1)
|
||||||
|
{
|
||||||
|
for (int i=0; i<num; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(g_SMAPI->GetUserMessage(i, NULL), "ShowMenu") == 0)
|
||||||
|
{
|
||||||
|
m_ShowMenu = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* :TODO: styles */
|
||||||
|
m_Styles.push_back(&g_ValveMenuStyle);
|
||||||
|
SetDefaultStyle(&g_ValveMenuStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::OnSourceModAllShutdown()
|
||||||
|
{
|
||||||
|
while (!m_BroadcastHandlers.empty())
|
||||||
|
{
|
||||||
|
delete m_BroadcastHandlers.front();
|
||||||
|
m_BroadcastHandlers.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!m_VoteHandlers.empty())
|
||||||
|
{
|
||||||
|
delete m_VoteHandlers.front();
|
||||||
|
m_VoteHandlers.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MenuManager::SetDefaultStyle(IMenuStyle *style)
|
||||||
|
{
|
||||||
|
if (!style)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pDefaultStyle = style;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMenuStyle *MenuManager::GetStyle(unsigned int index)
|
||||||
|
{
|
||||||
|
if (index >= GetStyleCount())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_Styles[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int MenuManager::GetStyleCount()
|
||||||
|
{
|
||||||
|
return (unsigned int)m_Styles.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
IMenuStyle *MenuManager::FindStyleByName(const char *name)
|
||||||
|
{
|
||||||
|
unsigned int count = GetStyleCount();
|
||||||
|
for (unsigned int i=0; i<count; i++)
|
||||||
|
{
|
||||||
|
IMenuStyle *ptr = GetStyle(i);
|
||||||
|
if (strcasecmp(ptr->GetStyleName(), name) == 0)
|
||||||
|
{
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsSlotItem(IMenuDisplay *display,
|
||||||
|
unsigned int style)
|
||||||
|
{
|
||||||
|
if (!display->CanDrawItem(style))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((style & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (style & ITEMDRAW_RAWLINE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMenuDisplay *MenuManager::RenderMenu(int client, menu_states_t &md, ItemOrder order)
|
||||||
|
{
|
||||||
|
IBaseMenu *menu = md.menu;
|
||||||
|
|
||||||
|
if (!menu)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int position;
|
||||||
|
ItemDrawInfo draw;
|
||||||
|
} drawItems[10];
|
||||||
|
|
||||||
|
/* Figure out how many items to draw */
|
||||||
|
IMenuStyle *style = menu->GetDrawStyle();
|
||||||
|
unsigned int pgn = menu->GetPagination();
|
||||||
|
unsigned int maxItems = style->GetMaxPageItems();
|
||||||
|
if (pgn != MENU_NO_PAGINATION)
|
||||||
|
{
|
||||||
|
maxItems = pgn;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int totalItems = menu->GetItemCount();
|
||||||
|
unsigned int startItem = 0;
|
||||||
|
|
||||||
|
/* For pagination, find the starting point. */
|
||||||
|
if (pgn != MENU_NO_PAGINATION)
|
||||||
|
{
|
||||||
|
if (order == ItemOrder_Ascending)
|
||||||
|
{
|
||||||
|
startItem = md.lastItem;
|
||||||
|
/* This shouldn't happen with well-coded menus.
|
||||||
|
* If the item is out of bounds, switch the order to
|
||||||
|
* Items_Descending and make us start from the top.
|
||||||
|
*/
|
||||||
|
if (startItem >= totalItems)
|
||||||
|
{
|
||||||
|
startItem = totalItems - 1;
|
||||||
|
order = ItemOrder_Descending;
|
||||||
|
}
|
||||||
|
} else if (order == ItemOrder_Descending) {
|
||||||
|
startItem = md.firstItem;
|
||||||
|
/* This shouldn't happen with well-coded menus.
|
||||||
|
* If searching backwards doesn't give us enough room,
|
||||||
|
* start from the beginning and change to ascending.
|
||||||
|
*/
|
||||||
|
if (startItem <= maxItems)
|
||||||
|
{
|
||||||
|
startItem = 0;
|
||||||
|
order = ItemOrder_Ascending;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get our Display pointer and initialize some crap */
|
||||||
|
IMenuDisplay *display = menu->CreateDisplay();
|
||||||
|
IMenuHandler *mh = md.mh;
|
||||||
|
bool foundExtra = false;
|
||||||
|
unsigned int extraItem = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We keep searching until:
|
||||||
|
* 1) There are no more items
|
||||||
|
* 2) We reach one OVER the maximum number of slot items
|
||||||
|
* 3) We have reached maxItems and pagination is MENU_NO_PAGINATION
|
||||||
|
*/
|
||||||
|
unsigned int i = startItem;
|
||||||
|
unsigned int foundItems = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
ItemDrawInfo &dr = drawItems[foundItems].draw;
|
||||||
|
/* Is the item valid? */
|
||||||
|
if (menu->GetItemInfo(i, &dr) != NULL)
|
||||||
|
{
|
||||||
|
/* Ask the user to change the style, if necessary */
|
||||||
|
mh->OnMenuDrawItem(menu, client, i, dr.style);
|
||||||
|
/* Check if it's renderable */
|
||||||
|
if (IsSlotItem(display, dr.style))
|
||||||
|
{
|
||||||
|
/* If we've already found the max number of items,
|
||||||
|
* This means we should just cancel out and log our
|
||||||
|
* "last item."
|
||||||
|
*/
|
||||||
|
if (foundItems >= maxItems)
|
||||||
|
{
|
||||||
|
foundExtra = true;
|
||||||
|
extraItem = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
drawItems[foundItems++].position = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If there's no pagination, stop once the menu is full. */
|
||||||
|
if (pgn == MENU_NO_PAGINATION)
|
||||||
|
{
|
||||||
|
/* If we've filled up, then stop */
|
||||||
|
if (foundItems >= maxItems)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* If we're descending and this is the first item, stop */
|
||||||
|
if (order == ItemOrder_Descending)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
/* If we're ascending and this is the last item, stop */
|
||||||
|
else if (order == ItemOrder_Ascending)
|
||||||
|
{
|
||||||
|
if (i >= totalItems - 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There were no items to draw! */
|
||||||
|
if (!foundItems)
|
||||||
|
{
|
||||||
|
delete display;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check initial buttons */
|
||||||
|
bool displayPrev = false;
|
||||||
|
bool displayNext = false;
|
||||||
|
if (foundExtra)
|
||||||
|
{
|
||||||
|
if (order == ItemOrder_Descending)
|
||||||
|
{
|
||||||
|
displayPrev = true;
|
||||||
|
md.firstItem = extraItem;
|
||||||
|
} else if (order == ItemOrder_Ascending) {
|
||||||
|
displayNext = true;
|
||||||
|
md.lastItem = extraItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we're paginated, we have to find if there is another page.
|
||||||
|
* Sadly, the only way to do this is to try drawing more items!
|
||||||
|
*/
|
||||||
|
if (pgn != MENU_NO_PAGINATION)
|
||||||
|
{
|
||||||
|
unsigned int lastItem = 0;
|
||||||
|
ItemDrawInfo dr;
|
||||||
|
/* Find the last feasible item to search from. */
|
||||||
|
if (order == ItemOrder_Descending)
|
||||||
|
{
|
||||||
|
lastItem = drawItems[0].position;
|
||||||
|
if (lastItem >= totalItems - 1)
|
||||||
|
{
|
||||||
|
goto skip_search;
|
||||||
|
}
|
||||||
|
while (++lastItem < totalItems)
|
||||||
|
{
|
||||||
|
if (menu->GetItemInfo(lastItem, &dr) != NULL)
|
||||||
|
{
|
||||||
|
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
|
||||||
|
if (IsSlotItem(display, dr.style))
|
||||||
|
{
|
||||||
|
displayNext = true;
|
||||||
|
md.lastItem = lastItem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (order == ItemOrder_Ascending) {
|
||||||
|
lastItem = drawItems[0].position;
|
||||||
|
if (lastItem == 0)
|
||||||
|
{
|
||||||
|
goto skip_search;
|
||||||
|
}
|
||||||
|
lastItem--;
|
||||||
|
while (lastItem-- != 0)
|
||||||
|
{
|
||||||
|
if (menu->GetItemInfo(lastItem, &dr) != NULL)
|
||||||
|
{
|
||||||
|
mh->OnMenuDrawItem(menu, client, lastItem, dr.style);
|
||||||
|
if (IsSlotItem(display, dr.style))
|
||||||
|
{
|
||||||
|
displayPrev = true;
|
||||||
|
md.firstItem = lastItem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skip_search:
|
||||||
|
|
||||||
|
/* Draw the item according to the order */
|
||||||
|
menu_slots_t *slots = md.slots;
|
||||||
|
unsigned int position = 0; /* Keep track of the last position */
|
||||||
|
if (order == ItemOrder_Ascending)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<foundItems; i++)
|
||||||
|
{
|
||||||
|
ItemDrawInfo &dr = drawItems[i].draw;
|
||||||
|
menu->GetItemInfo(drawItems[i].position, &dr);
|
||||||
|
mh->OnMenuDisplayItem(menu, client, drawItems[i].position, &(dr.display));
|
||||||
|
if ((position = display->DrawItem(dr)) != 0)
|
||||||
|
{
|
||||||
|
slots[position].item = drawItems[i].position;
|
||||||
|
slots[position].type = ItemSel_Item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (order == ItemOrder_Descending) {
|
||||||
|
unsigned int i = foundItems;
|
||||||
|
/* NOTE: There will always be at least one item because
|
||||||
|
* of the check earlier.
|
||||||
|
*/
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
ItemDrawInfo &dr = drawItems[i].draw;
|
||||||
|
menu->GetItemInfo(drawItems[i].position, &dr);
|
||||||
|
mh->OnMenuDisplayItem(menu, client, drawItems[i].position, &(dr.display));
|
||||||
|
if ((position = display->DrawItem(dr)) != 0)
|
||||||
|
{
|
||||||
|
slots[position].item = drawItems[i].position;
|
||||||
|
slots[position].type = ItemSel_Item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, we need to check if we need to add anything extra */
|
||||||
|
if (pgn != MENU_NO_PAGINATION)
|
||||||
|
{
|
||||||
|
bool canDrawDisabled = display->CanDrawItem(ITEMDRAW_DISABLED);
|
||||||
|
bool exitButton = menu->GetExitButton();
|
||||||
|
char text[50];
|
||||||
|
|
||||||
|
/* Calculate how many items we are allowed for control stuff */
|
||||||
|
unsigned int padding = style->GetMaxPageItems() - maxItems;
|
||||||
|
|
||||||
|
/* Add the number of available slots */
|
||||||
|
padding += (maxItems - foundItems);
|
||||||
|
|
||||||
|
/* Someday, if we are able to re-enable this, we will be very lucky men. */
|
||||||
|
#if 0
|
||||||
|
if (!style->FeatureExists(MenuStyleFeature_ImplicitExit))
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
/* Even if we don't draw an exit button, we invalidate the slot. */
|
||||||
|
padding--;
|
||||||
|
#if 0
|
||||||
|
} else {
|
||||||
|
/* Otherwise, we don't draw anything and leave the slot available */
|
||||||
|
exitButton = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Subtract two slots for the displayNext/displayPrev padding */
|
||||||
|
padding -= 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We allow next/prev to be undrawn if neither exists.
|
||||||
|
* Thus, we only need padding if one of them will be drawn,
|
||||||
|
* or the exit button will be drawn.
|
||||||
|
*/
|
||||||
|
ItemDrawInfo padItem(NULL, ITEMDRAW_SPACER);
|
||||||
|
if (exitButton || (displayNext || displayPrev))
|
||||||
|
{
|
||||||
|
/* Add spacers so we can pad to the end */
|
||||||
|
unsigned int null_pos = 0;
|
||||||
|
for (unsigned int i=0; i<padding; i++)
|
||||||
|
{
|
||||||
|
position = display->DrawItem(padItem);
|
||||||
|
slots[position].type = ItemSel_None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItemDrawInfo dr(text, 0);
|
||||||
|
|
||||||
|
/* PREVIOUS */
|
||||||
|
if (displayPrev || canDrawDisabled)
|
||||||
|
{
|
||||||
|
CorePlayerTranslate(client, text, sizeof(text), "Back", NULL);
|
||||||
|
dr.style = displayPrev ? 0 : ITEMDRAW_DISABLED;
|
||||||
|
position = display->DrawItem(dr);
|
||||||
|
slots[position].type = ItemSel_Back;
|
||||||
|
} else if ((displayNext || canDrawDisabled) || exitButton) {
|
||||||
|
/* If we can't display this,
|
||||||
|
* but there is a "next" or "exit" button, we need to pad!
|
||||||
|
*/
|
||||||
|
position = display->DrawItem(padItem);
|
||||||
|
slots[position].type = ItemSel_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NEXT */
|
||||||
|
if (displayNext || canDrawDisabled)
|
||||||
|
{
|
||||||
|
CorePlayerTranslate(client, text, sizeof(text), "Next", NULL);
|
||||||
|
dr.style = displayNext ? 0 : ITEMDRAW_DISABLED;
|
||||||
|
position = display->DrawItem(dr);
|
||||||
|
slots[position].type = ItemSel_Next;
|
||||||
|
} else if (exitButton) {
|
||||||
|
/* If we can't display this,
|
||||||
|
* but there is an exit button, we need to pad!
|
||||||
|
*/
|
||||||
|
position = display->DrawItem(padItem);
|
||||||
|
slots[position].type = ItemSel_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EXIT */
|
||||||
|
if (exitButton)
|
||||||
|
{
|
||||||
|
CorePlayerTranslate(client, text, sizeof(text), "Exit", NULL);
|
||||||
|
dr.style = 0;
|
||||||
|
position = display->DrawItem(dr);
|
||||||
|
slots[position].type = ItemSel_Exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lastly, fill in any slots we could have missed */
|
||||||
|
for (unsigned int i = position + 1; i < 10; i++)
|
||||||
|
{
|
||||||
|
slots[i].type = ItemSel_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do title stuff */
|
||||||
|
mh->OnMenuDisplay(menu, client, display);
|
||||||
|
display->DrawTitle(menu->GetDefaultTitle(), true);
|
||||||
|
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::FreeBroadcastHandler(BroadcastHandler *bh)
|
||||||
|
{
|
||||||
|
m_BroadcastHandlers.push(bh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuManager::FreeVoteHandler(VoteHandler *vh)
|
||||||
|
{
|
||||||
|
m_VoteHandlers.push(vh);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMenuStyle *MenuManager::GetDefaultStyle()
|
||||||
|
{
|
||||||
|
return m_pDefaultStyle;
|
||||||
|
}
|
||||||
|
|
110
core/MenuManager.h
Normal file
110
core/MenuManager.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is not open source and may not be copied without explicit
|
||||||
|
* written permission of AlliedModders LLC. This file may not be redistributed
|
||||||
|
* in whole or significant part.
|
||||||
|
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_SOURCEMOD_MENUMANAGER_H_
|
||||||
|
#define _INCLUDE_SOURCEMOD_MENUMANAGER_H_
|
||||||
|
|
||||||
|
#include <IMenuManager.h>
|
||||||
|
#include <sh_vector.h>
|
||||||
|
#include <sh_stack.h>
|
||||||
|
#include <sh_list.h>
|
||||||
|
#include "sm_memtable.h"
|
||||||
|
#include "sm_globals.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
using namespace SourceHook;
|
||||||
|
|
||||||
|
class BroadcastHandler : public IMenuHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BroadcastHandler(IMenuHandler *handler);
|
||||||
|
public: //IMenuHandler
|
||||||
|
void OnMenuDisplay(IBaseMenu *menu, int client, IMenuDisplay *display);
|
||||||
|
void OnMenuSelect(IBaseMenu *menu, int client, unsigned int item);
|
||||||
|
void OnMenuEnd(IBaseMenu *menu);
|
||||||
|
void OnMenuCancel(IBaseMenu *menu, int client, MenuCancelReason reason);
|
||||||
|
unsigned int GetMenuAPIVersion2();
|
||||||
|
public:
|
||||||
|
virtual void OnBroadcastEnd(IBaseMenu *menu);
|
||||||
|
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:
|
||||||
|
CVector<unsigned int> m_counts;
|
||||||
|
CVector<unsigned int> m_ties;
|
||||||
|
unsigned int numItems;
|
||||||
|
IMenuVoteHandler *m_pVoteHandler;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MenuManager :
|
||||||
|
public IMenuManager,
|
||||||
|
public SMGlobalClass
|
||||||
|
{
|
||||||
|
friend class BroadcastHandler;
|
||||||
|
friend class VoteHandler;
|
||||||
|
public:
|
||||||
|
MenuManager();
|
||||||
|
public: //SMGlobalClass
|
||||||
|
void OnSourceModAllInitialized();
|
||||||
|
void OnSourceModAllShutdown();
|
||||||
|
public: //IMenuManager
|
||||||
|
virtual const char *GetInterfaceName()
|
||||||
|
{
|
||||||
|
return SMINTERFACE_MENUMANAGER_NAME;
|
||||||
|
}
|
||||||
|
virtual unsigned int GetInterfaceVersion()
|
||||||
|
{
|
||||||
|
return SMINTERFACE_MENUMANAGER_VERSION;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
unsigned int GetStyleCount();
|
||||||
|
IMenuStyle *GetStyle(unsigned int index);
|
||||||
|
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();
|
||||||
|
bool SetDefaultStyle(IMenuStyle *style);
|
||||||
|
IMenuDisplay *RenderMenu(int client, menu_states_t &states, ItemOrder order);
|
||||||
|
protected:
|
||||||
|
void FreeBroadcastHandler(BroadcastHandler *bh);
|
||||||
|
void FreeVoteHandler(VoteHandler *vh);
|
||||||
|
private:
|
||||||
|
int m_ShowMenu;
|
||||||
|
IMenuStyle *m_pDefaultStyle;
|
||||||
|
CStack<BroadcastHandler *> m_BroadcastHandlers;
|
||||||
|
CStack<VoteHandler *> m_VoteHandlers;
|
||||||
|
CVector<IMenuStyle *> m_Styles;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern MenuManager g_Menus;
|
||||||
|
|
||||||
|
#endif //_INCLUDE_SOURCEMOD_MENUMANAGER_H_
|
162
core/MenuStyle_Base.cpp
Normal file
162
core/MenuStyle_Base.cpp
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is not open source and may not be copied without explicit
|
||||||
|
* written permission of AlliedModders LLC. This file may not be redistributed
|
||||||
|
* in whole or significant part.
|
||||||
|
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "sm_stringutil.h"
|
||||||
|
#include "MenuStyle_Base.h"
|
||||||
|
|
||||||
|
CBaseMenu::CBaseMenu(IMenuStyle *pStyle) :
|
||||||
|
m_pStyle(pStyle), m_Strings(512), m_Pagination(7), m_ExitButton(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CBaseMenu::~CBaseMenu()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBaseMenu::AppendItem(const char *info, const ItemDrawInfo &draw)
|
||||||
|
{
|
||||||
|
if (m_Pagination == MENU_NO_PAGINATION
|
||||||
|
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CItem item;
|
||||||
|
|
||||||
|
item.infoString = m_Strings.AddString(info);
|
||||||
|
if (draw.display)
|
||||||
|
{
|
||||||
|
item.displayString = m_Strings.AddString(draw.display);
|
||||||
|
}
|
||||||
|
item.style = draw.style;
|
||||||
|
|
||||||
|
|
||||||
|
m_items.push_back(item);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBaseMenu::InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw)
|
||||||
|
{
|
||||||
|
if (m_Pagination == MENU_NO_PAGINATION
|
||||||
|
&& m_items.size() >= m_pStyle->GetMaxPageItems())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position >= m_items.size())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CItem item;
|
||||||
|
item.infoString = m_Strings.AddString(info);
|
||||||
|
if (draw.display)
|
||||||
|
{
|
||||||
|
item.displayString = m_Strings.AddString(draw.display);
|
||||||
|
}
|
||||||
|
item.style = draw.style;
|
||||||
|
|
||||||
|
CVector<CItem>::iterator iter = m_items.iterAt(position);
|
||||||
|
m_items.insert(iter, item);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBaseMenu::RemoveItem(unsigned int position)
|
||||||
|
{
|
||||||
|
if (position >= m_items.size())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_items.erase(m_items.iterAt(position));
|
||||||
|
|
||||||
|
if (m_items.size() == 0)
|
||||||
|
{
|
||||||
|
m_Strings.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBaseMenu::RemoveAllItems()
|
||||||
|
{
|
||||||
|
m_items.clear();
|
||||||
|
m_Strings.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *CBaseMenu::GetItemInfo(unsigned int position, ItemDrawInfo *draw/* =NULL */)
|
||||||
|
{
|
||||||
|
if (position >= m_items.size())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (draw)
|
||||||
|
{
|
||||||
|
draw->display = m_Strings.GetString(m_items[position].displayString);
|
||||||
|
draw->style = m_items[position].style;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_Strings.GetString(m_items[position].infoString);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CBaseMenu::GetItemCount()
|
||||||
|
{
|
||||||
|
return m_items.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBaseMenu::SetPagination(unsigned int itemsPerPage)
|
||||||
|
{
|
||||||
|
if (itemsPerPage > 7)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Pagination = itemsPerPage;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CBaseMenu::GetPagination()
|
||||||
|
{
|
||||||
|
return m_Pagination;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMenuStyle *CBaseMenu::GetDrawStyle()
|
||||||
|
{
|
||||||
|
return m_pStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBaseMenu::SetDefaultTitle(const char *message)
|
||||||
|
{
|
||||||
|
m_Title.assign(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *CBaseMenu::GetDefaultTitle()
|
||||||
|
{
|
||||||
|
return m_Title.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBaseMenu::GetExitButton()
|
||||||
|
{
|
||||||
|
return m_ExitButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBaseMenu::SetExitButton(bool set)
|
||||||
|
{
|
||||||
|
m_ExitButton = set;
|
||||||
|
return true;
|
||||||
|
}
|
69
core/MenuStyle_Base.h
Normal file
69
core/MenuStyle_Base.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is not open source and may not be copied without explicit
|
||||||
|
* written permission of AlliedModders LLC. This file may not be redistributed
|
||||||
|
* in whole or significant part.
|
||||||
|
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_MENUSTYLE_BASE_H
|
||||||
|
#define _INCLUDE_MENUSTYLE_BASE_H
|
||||||
|
|
||||||
|
#include <IMenuManager.h>
|
||||||
|
#include <sh_string.h>
|
||||||
|
#include <sh_vector.h>
|
||||||
|
#include "sm_memtable.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
using namespace SourceHook;
|
||||||
|
|
||||||
|
class CItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CItem()
|
||||||
|
{
|
||||||
|
infoString = -1;
|
||||||
|
displayString = -1;
|
||||||
|
style = 0;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
int infoString;
|
||||||
|
int displayString;
|
||||||
|
unsigned int style;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBaseMenu : public IBaseMenu
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBaseMenu(IMenuStyle *pStyle);
|
||||||
|
virtual ~CBaseMenu();
|
||||||
|
public:
|
||||||
|
virtual bool AppendItem(const char *info, const ItemDrawInfo &draw);
|
||||||
|
virtual bool InsertItem(unsigned int position, const char *info, const ItemDrawInfo &draw);
|
||||||
|
virtual bool RemoveItem(unsigned int position);
|
||||||
|
virtual void RemoveAllItems();
|
||||||
|
virtual const char *GetItemInfo(unsigned int position, ItemDrawInfo *draw=NULL);
|
||||||
|
virtual unsigned int GetItemCount();
|
||||||
|
virtual bool SetPagination(unsigned int itemsPerPage);
|
||||||
|
virtual unsigned int GetPagination();
|
||||||
|
virtual IMenuStyle *GetDrawStyle();
|
||||||
|
virtual void SetDefaultTitle(const char *message);
|
||||||
|
virtual const char *GetDefaultTitle();
|
||||||
|
virtual bool GetExitButton();
|
||||||
|
virtual bool SetExitButton(bool set);
|
||||||
|
protected:
|
||||||
|
String m_Title;
|
||||||
|
IMenuStyle *m_pStyle;
|
||||||
|
unsigned int m_Pagination;
|
||||||
|
CVector<CItem> m_items;
|
||||||
|
BaseStringTable m_Strings;
|
||||||
|
bool m_ExitButton;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //_INCLUDE_MENUSTYLE_BASE_H
|
796
core/MenuStyle_Valve.cpp
Normal file
796
core/MenuStyle_Valve.cpp
Normal file
@ -0,0 +1,796 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is not open source and may not be copied without explicit
|
||||||
|
* written permission of AlliedModders LLC. This file may not be redistributed
|
||||||
|
* in whole or significant part.
|
||||||
|
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sm_stringutil.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
|
#include "MenuStyle_Valve.h"
|
||||||
|
#include "Translator.h"
|
||||||
|
#include "PlayerManager.h"
|
||||||
|
#include "ConCmdManager.h"
|
||||||
|
|
||||||
|
SH_DECL_HOOK4_void(IServerPluginHelpers, CreateMessage, SH_NOATTRIB, false, edict_t *, DIALOG_TYPE, KeyValues *, IServerPluginCallbacks *);
|
||||||
|
|
||||||
|
ValveMenuStyle g_ValveMenuStyle;
|
||||||
|
const char *g_OptionNumTable[];
|
||||||
|
const char *g_OptionCmdTable[];
|
||||||
|
IServerPluginCallbacks *g_pVSPHandle = NULL;
|
||||||
|
CallClass<IServerPluginHelpers> *g_pSPHCC = NULL;
|
||||||
|
|
||||||
|
class TestHandler : public IMenuHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void OnMenuEnd(IBaseMenu *menu)
|
||||||
|
{
|
||||||
|
menu->Destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ValveMenuStyle::ValveMenuStyle() : m_players(new CValveMenuPlayer[256+1]), m_WatchList(256)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValveMenuStyle::OnClientCommand(int client)
|
||||||
|
{
|
||||||
|
const char *cmd = engine->Cmd_Argv(0);
|
||||||
|
|
||||||
|
if (strcmp(cmd, "sm_vmenuselect") == 0)
|
||||||
|
{
|
||||||
|
int key_press = atoi(engine->Cmd_Argv(1));
|
||||||
|
g_ValveMenuStyle.ClientPressedKey(client, key_press);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(cmd, "sm_test") == 0)
|
||||||
|
{
|
||||||
|
IBaseMenu *menu = g_ValveMenuStyle.CreateMenu();
|
||||||
|
menu->AppendItem("test1", ItemDrawInfo("Test #1", 0));
|
||||||
|
menu->AppendItem("test2", ItemDrawInfo("Test #2", 0));
|
||||||
|
menu->AppendItem("test3", ItemDrawInfo("Test #3", 0));
|
||||||
|
menu->AppendItem("test4", ItemDrawInfo("Test #4", 0));
|
||||||
|
menu->AppendItem("test5", ItemDrawInfo("Test #5", 0));
|
||||||
|
menu->AppendItem("test6", ItemDrawInfo("Test #6", 0));
|
||||||
|
menu->AppendItem("test7", ItemDrawInfo("Test #7", 0));
|
||||||
|
menu->AppendItem("test8", ItemDrawInfo("Test #8", 0));
|
||||||
|
menu->AppendItem("test9", ItemDrawInfo("Test #9", 0));
|
||||||
|
menu->AppendItem("test10", ItemDrawInfo("Test #10", 0));
|
||||||
|
menu->AppendItem("test11", ItemDrawInfo("Test #11", 0));
|
||||||
|
menu->AppendItem("test12", ItemDrawInfo("Test #12", 0));
|
||||||
|
menu->AppendItem("test13", ItemDrawInfo("Test #13", 0));
|
||||||
|
menu->AppendItem("test14", ItemDrawInfo("Test #14", 0));
|
||||||
|
menu->AppendItem("test15", ItemDrawInfo("Test #15", 0));
|
||||||
|
menu->AppendItem("test16", ItemDrawInfo("Test #16", 0));
|
||||||
|
menu->AppendItem("test17", ItemDrawInfo("Test #17", 0));
|
||||||
|
menu->AppendItem("test18", ItemDrawInfo("Test #18", 0));
|
||||||
|
menu->AppendItem("test19", ItemDrawInfo("Test #19", 0));
|
||||||
|
menu->AppendItem("test20", ItemDrawInfo("Test #20", 0));
|
||||||
|
|
||||||
|
menu->Display(client, new TestHandler, 20);
|
||||||
|
return true;
|
||||||
|
} else if (strcmp(cmd, "gaben") == 0) {
|
||||||
|
KeyValues *kv = new KeyValues("menu");
|
||||||
|
kv->SetString("msg", "hi");
|
||||||
|
serverpluginhelpers->CreateMessage(engine->PEntityOfEntIndex(client), DIALOG_MENU, kv, g_pVSPHandle);
|
||||||
|
kv->deleteThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValveMenuStyle::OnSourceModAllInitialized()
|
||||||
|
{
|
||||||
|
g_Players.AddClientListener(this);
|
||||||
|
SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
|
||||||
|
g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValveMenuStyle::OnSourceModShutdown()
|
||||||
|
{
|
||||||
|
SH_RELEASE_CALLCLASS(g_pSPHCC);
|
||||||
|
SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
|
||||||
|
g_Players.RemoveClientListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValveMenuStyle::OnClientDisconnected(int client)
|
||||||
|
{
|
||||||
|
CValveMenuPlayer *player = &m_players[client];
|
||||||
|
if (!player->bInMenu)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu_states_t &states = player->states;
|
||||||
|
states.mh->OnMenuCancel(states.menu, client, MenuCancel_Disconnect);
|
||||||
|
states.mh->OnMenuEnd(states.menu);
|
||||||
|
|
||||||
|
if (player->menuHoldTime)
|
||||||
|
{
|
||||||
|
m_WatchList.remove(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
player->bInMenu = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
|
||||||
|
DIALOG_TYPE type,
|
||||||
|
KeyValues *kv,
|
||||||
|
IServerPluginCallbacks *plugin)
|
||||||
|
{
|
||||||
|
if (type != DIALOG_MENU)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int client = engine->IndexOfEdict(pEdict);
|
||||||
|
if (client < 1 || client > 256)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CValveMenuPlayer *player = &m_players[client];
|
||||||
|
|
||||||
|
/* We don't care if the player is in a menu because, for all intents and purposes,
|
||||||
|
* the menu is completely private. Instead, we just figure out the level we'll need
|
||||||
|
* in order to override it.
|
||||||
|
*/
|
||||||
|
player->curPrioLevel = kv->GetInt("level", player->curPrioLevel);
|
||||||
|
|
||||||
|
/* Oh no! What happens if we got a menu that overwrites ours?! */
|
||||||
|
if (player->bInMenu)
|
||||||
|
{
|
||||||
|
/* Okay, let the external menu survive for now. It may live another
|
||||||
|
* day to avenge its grandfather, killed in the great Menu Interruption
|
||||||
|
* battle.
|
||||||
|
*/
|
||||||
|
_CancelMenu(client, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValveMenuStyle::OnSourceModVSPReceived(IServerPluginCallbacks *iface)
|
||||||
|
{
|
||||||
|
g_pVSPHandle = iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMenuDisplay *ValveMenuStyle::CreateDisplay()
|
||||||
|
{
|
||||||
|
return new CValveMenuDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
IBaseMenu *ValveMenuStyle::CreateMenu()
|
||||||
|
{
|
||||||
|
return new CValveMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *ValveMenuStyle::GetStyleName()
|
||||||
|
{
|
||||||
|
return "valve";
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int ValveMenuStyle::GetMaxPageItems()
|
||||||
|
{
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_lookup[256];
|
||||||
|
void ValveMenuStyle::ProcessWatchList()
|
||||||
|
{
|
||||||
|
if (!m_WatchList.size())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FastLink<int>::iterator iter;
|
||||||
|
|
||||||
|
unsigned int total = 0;
|
||||||
|
for (iter=m_WatchList.begin(); iter!=m_WatchList.end(); ++iter)
|
||||||
|
{
|
||||||
|
do_lookup[total++] = (*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
int client;
|
||||||
|
CValveMenuPlayer *player;
|
||||||
|
float curTime = gpGlobals->curtime;
|
||||||
|
for (unsigned int i=0; i<total; i++)
|
||||||
|
{
|
||||||
|
client = do_lookup[i];
|
||||||
|
player = &m_players[client];
|
||||||
|
if (!player->bInMenu || !player->menuHoldTime)
|
||||||
|
{
|
||||||
|
m_WatchList.remove(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (curTime > player->menuStartTime + player->menuHoldTime)
|
||||||
|
{
|
||||||
|
_CancelMenu(i, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValveMenuStyle::_CancelMenu(int client, bool bAutoIgnore)
|
||||||
|
{
|
||||||
|
CValveMenuPlayer *player = &m_players[client];
|
||||||
|
menu_states_t &states = player->states;
|
||||||
|
|
||||||
|
bool bOldIgnore = player->bAutoIgnore;
|
||||||
|
if (bAutoIgnore)
|
||||||
|
{
|
||||||
|
player->bAutoIgnore = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save states */
|
||||||
|
IMenuHandler *mh = states.mh;
|
||||||
|
IBaseMenu *menu = states.menu;
|
||||||
|
|
||||||
|
/* Clear menu */
|
||||||
|
player->bInMenu = false;
|
||||||
|
if (player->menuHoldTime)
|
||||||
|
{
|
||||||
|
m_WatchList.remove(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fire callbacks */
|
||||||
|
mh->OnMenuCancel(menu, client, MenuCancel_Interrupt);
|
||||||
|
mh->OnMenuEnd(menu);
|
||||||
|
|
||||||
|
if (bAutoIgnore)
|
||||||
|
{
|
||||||
|
player->bAutoIgnore = bOldIgnore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValveMenuStyle::CancelMenu(CValveMenu *menu)
|
||||||
|
{
|
||||||
|
int maxClients = g_Players.GetMaxClients();
|
||||||
|
for (int i=1; i<=maxClients; i++)
|
||||||
|
{
|
||||||
|
if (m_players[i].bInMenu)
|
||||||
|
{
|
||||||
|
menu_states_t &states = m_players[i].states;
|
||||||
|
if (states.menu == menu)
|
||||||
|
{
|
||||||
|
_CancelMenu(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValveMenuStyle::CancelClientMenu(int client, bool autoIgnore)
|
||||||
|
{
|
||||||
|
if (client < 1 || client > 256 || !m_players[client].bInMenu)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_CancelMenu(client, autoIgnore);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ValveMenuStyle::ClientPressedKey(int client, unsigned int key_press)
|
||||||
|
{
|
||||||
|
CValveMenuPlayer *player = &m_players[client];
|
||||||
|
|
||||||
|
/* First question: Are we in a menu? */
|
||||||
|
if (!player->bInMenu)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cancel = false;
|
||||||
|
unsigned int item = 0;
|
||||||
|
MenuCancelReason reason = MenuCancel_Exit;
|
||||||
|
menu_states_t &states = player->states;
|
||||||
|
|
||||||
|
assert(states.mh != NULL);
|
||||||
|
|
||||||
|
if (states.menu == NULL)
|
||||||
|
{
|
||||||
|
item = key_press;
|
||||||
|
} else if (key_press < 1 || key_press > 8) {
|
||||||
|
cancel = true;
|
||||||
|
} else {
|
||||||
|
ItemSelection type = states.slots[key_press].type;
|
||||||
|
|
||||||
|
/* For navigational items, we're going to redisplay */
|
||||||
|
if (type == ItemSel_Back)
|
||||||
|
{
|
||||||
|
if (!RedoClientMenu(client, ItemOrder_Descending))
|
||||||
|
{
|
||||||
|
cancel = true;
|
||||||
|
reason = MenuCancel_NoDisplay;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (type == ItemSel_Next) {
|
||||||
|
if (!RedoClientMenu(client, ItemOrder_Ascending))
|
||||||
|
{
|
||||||
|
cancel = true; /* I like Saltines. */
|
||||||
|
reason = MenuCancel_NoDisplay;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (type == ItemSel_Exit || type == ItemSel_None) {
|
||||||
|
cancel = true;
|
||||||
|
} else {
|
||||||
|
item = states.slots[key_press].item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save variables */
|
||||||
|
IMenuHandler *mh = states.mh;
|
||||||
|
IBaseMenu *menu = states.menu;
|
||||||
|
|
||||||
|
/* Clear states */
|
||||||
|
player->bInMenu = false;
|
||||||
|
if (player->menuHoldTime)
|
||||||
|
{
|
||||||
|
m_WatchList.remove(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancel)
|
||||||
|
{
|
||||||
|
mh->OnMenuCancel(menu, client, reason);
|
||||||
|
} else {
|
||||||
|
mh->OnMenuSelect(menu, client, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
mh->OnMenuEnd(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValveMenuStyle::DoClientMenu(int client, CValveMenuDisplay *menu, IMenuHandler *mh, unsigned int time)
|
||||||
|
{
|
||||||
|
if (!g_pVSPHandle || !mh)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||||
|
if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CValveMenuPlayer *player = &m_players[client];
|
||||||
|
if (player->bAutoIgnore)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For the duration of this, we are going to totally ignore whether
|
||||||
|
* the player is already in a menu or not (except to cancel the old one).
|
||||||
|
* Instead, we are simply going to ignore any further menu displays, so
|
||||||
|
* this display can't be interrupted.
|
||||||
|
*/
|
||||||
|
player->bAutoIgnore = true;
|
||||||
|
|
||||||
|
/* Cancel any old menus */
|
||||||
|
menu_states_t &states = player->states;
|
||||||
|
if (player->bInMenu)
|
||||||
|
{
|
||||||
|
/* We need to cancel the old menu */
|
||||||
|
if (player->menuHoldTime)
|
||||||
|
{
|
||||||
|
m_WatchList.remove(client);
|
||||||
|
}
|
||||||
|
states.mh->OnMenuCancel(states.menu, client, MenuCancel_Interrupt);
|
||||||
|
states.mh->OnMenuEnd(states.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
states.firstItem = 0;
|
||||||
|
states.lastItem = 0;
|
||||||
|
states.menu = NULL;
|
||||||
|
states.mh = mh;
|
||||||
|
states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
|
||||||
|
player->curPrioLevel--;
|
||||||
|
player->bInMenu = true;
|
||||||
|
player->menuStartTime = gpGlobals->curtime;
|
||||||
|
player->menuHoldTime = time;
|
||||||
|
|
||||||
|
if (time)
|
||||||
|
{
|
||||||
|
m_WatchList.push_back(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the display */
|
||||||
|
menu->SendRawDisplay(client, player->curPrioLevel, time);
|
||||||
|
|
||||||
|
/* We can be interrupted again! */
|
||||||
|
player->bAutoIgnore = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValveMenuStyle::DoClientMenu(int client, CValveMenu *menu, IMenuHandler *mh, unsigned int time)
|
||||||
|
{
|
||||||
|
mh->OnMenuStart(menu);
|
||||||
|
|
||||||
|
if (!g_pVSPHandle || !mh)
|
||||||
|
{
|
||||||
|
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
||||||
|
mh->OnMenuEnd(menu);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
|
||||||
|
if (!pPlayer || pPlayer->IsFakeClient() || !pPlayer->IsInGame())
|
||||||
|
{
|
||||||
|
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
||||||
|
mh->OnMenuEnd(menu);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CValveMenuPlayer *player = &m_players[client];
|
||||||
|
if (player->bAutoIgnore)
|
||||||
|
{
|
||||||
|
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
||||||
|
mh->OnMenuEnd(menu);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For the duration of this, we are going to totally ignore whether
|
||||||
|
* the player is already in a menu or not (except to cancel the old one).
|
||||||
|
* Instead, we are simply going to ignore any further menu displays, so
|
||||||
|
* this display can't be interrupted.
|
||||||
|
*/
|
||||||
|
player->bAutoIgnore = true;
|
||||||
|
|
||||||
|
/* Cancel any old menus */
|
||||||
|
menu_states_t &states = player->states;
|
||||||
|
if (player->bInMenu)
|
||||||
|
{
|
||||||
|
/* We need to cancel the old menu */
|
||||||
|
if (player->menuHoldTime)
|
||||||
|
{
|
||||||
|
m_WatchList.remove(client);
|
||||||
|
}
|
||||||
|
states.mh->OnMenuCancel(states.menu, client, MenuCancel_Interrupt);
|
||||||
|
states.mh->OnMenuEnd(states.menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
states.firstItem = 0;
|
||||||
|
states.lastItem = 0;
|
||||||
|
states.menu = menu;
|
||||||
|
states.mh = mh;
|
||||||
|
states.apiVers = SMINTERFACE_MENUMANAGER_VERSION;
|
||||||
|
|
||||||
|
IMenuDisplay *display = g_Menus.RenderMenu(client, states, ItemOrder_Ascending);
|
||||||
|
if (!display)
|
||||||
|
{
|
||||||
|
player->bAutoIgnore = false;
|
||||||
|
player->bInMenu = false;
|
||||||
|
mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
|
||||||
|
mh->OnMenuEnd(menu);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, set our states */
|
||||||
|
player->curPrioLevel--;
|
||||||
|
player->bInMenu = true;
|
||||||
|
player->menuStartTime = gpGlobals->curtime;
|
||||||
|
player->menuHoldTime = time;
|
||||||
|
|
||||||
|
if (time)
|
||||||
|
{
|
||||||
|
m_WatchList.push_back(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw the display */
|
||||||
|
CValveMenuDisplay *vDisplay = (CValveMenuDisplay *)display;
|
||||||
|
vDisplay->SendRawDisplay(client, player->curPrioLevel, time);
|
||||||
|
|
||||||
|
/* Free the display pointer */
|
||||||
|
delete display;
|
||||||
|
|
||||||
|
/* We can be interrupted again! */
|
||||||
|
player->bAutoIgnore = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ValveMenuStyle::RedoClientMenu(int client, ItemOrder order)
|
||||||
|
{
|
||||||
|
CValveMenuPlayer *player = &m_players[client];
|
||||||
|
menu_states_t &states = player->states;
|
||||||
|
|
||||||
|
player->bAutoIgnore = true;
|
||||||
|
IMenuDisplay *display = g_Menus.RenderMenu(client, states, order);
|
||||||
|
if (!display)
|
||||||
|
{
|
||||||
|
if (player->menuHoldTime)
|
||||||
|
{
|
||||||
|
m_WatchList.remove(client);
|
||||||
|
}
|
||||||
|
player->bAutoIgnore = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CValveMenuDisplay *vDisplay = (CValveMenuDisplay *)display;
|
||||||
|
vDisplay->SendRawDisplay(client, --player->curPrioLevel, player->menuHoldTime);
|
||||||
|
|
||||||
|
delete display;
|
||||||
|
|
||||||
|
player->bAutoIgnore = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuSource ValveMenuStyle::GetClientMenu(int client, void **object)
|
||||||
|
{
|
||||||
|
if (client < 1 || client > 256 || !m_players[client].bInMenu)
|
||||||
|
{
|
||||||
|
return MenuSource_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
IBaseMenu *menu;
|
||||||
|
if ((menu=m_players[client].states.menu) != NULL)
|
||||||
|
{
|
||||||
|
if (object)
|
||||||
|
{
|
||||||
|
*object = menu;
|
||||||
|
}
|
||||||
|
return MenuSource_BaseMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MenuSource_Display;
|
||||||
|
}
|
||||||
|
|
||||||
|
CValveMenuDisplay::CValveMenuDisplay()
|
||||||
|
{
|
||||||
|
m_pKv = NULL;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
CValveMenuDisplay::CValveMenuDisplay(CValveMenu *pMenu)
|
||||||
|
{
|
||||||
|
m_pKv = NULL;
|
||||||
|
Reset();
|
||||||
|
m_pKv->SetColor("color", pMenu->m_IntroColor);
|
||||||
|
m_pKv->SetString("title", pMenu->m_IntroMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
CValveMenuDisplay::~CValveMenuDisplay()
|
||||||
|
{
|
||||||
|
m_pKv->deleteThis();
|
||||||
|
}
|
||||||
|
|
||||||
|
IMenuStyle *CValveMenuDisplay::GetParentStyle()
|
||||||
|
{
|
||||||
|
return &g_ValveMenuStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CValveMenuDisplay::Reset()
|
||||||
|
{
|
||||||
|
if (m_pKv)
|
||||||
|
{
|
||||||
|
m_pKv->deleteThis();
|
||||||
|
}
|
||||||
|
m_pKv = new KeyValues("menu");
|
||||||
|
m_NextPos = 1;
|
||||||
|
m_TitleDrawn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenuDisplay::SetExtOption(MenuOption option, const void *valuePtr)
|
||||||
|
{
|
||||||
|
if (option == MenuOption_IntroMessage)
|
||||||
|
{
|
||||||
|
m_pKv->SetString("title", (const char *)valuePtr);
|
||||||
|
return true;
|
||||||
|
} else if (option == MenuOption_IntroColor) {
|
||||||
|
int *array = (int *)valuePtr;
|
||||||
|
m_pKv->SetColor("color", Color(array[0], array[1], array[2], array[3]));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenuDisplay::CanDrawItem(unsigned int drawFlags)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ITEMDRAW_RAWLINE - We can't draw random text, and this doesn't add a slot,
|
||||||
|
* so it's completely safe to ignore it.
|
||||||
|
* -----------------------------------------
|
||||||
|
*/
|
||||||
|
if (drawFlags & ITEMDRAW_RAWLINE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special cases, explained in DrawItem()
|
||||||
|
*/
|
||||||
|
if ((drawFlags & ITEMDRAW_NOTEXT)
|
||||||
|
|| (drawFlags & ITEMDRAW_SPACER))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We can't draw disabled text. We could bump the position, but we
|
||||||
|
* want DirectDraw() to find some actual items to display.
|
||||||
|
*/
|
||||||
|
if (drawFlags & ITEMDRAW_DISABLED)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CValveMenuDisplay::DrawItem(const ItemDrawInfo &item)
|
||||||
|
{
|
||||||
|
if (m_NextPos > 9 || !CanDrawItem(item.style))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For these cases we can't draw anything at all, but
|
||||||
|
* we can at least bump the position since we were explicitly asked to.
|
||||||
|
*/
|
||||||
|
if ((item.style & ITEMDRAW_NOTEXT)
|
||||||
|
|| (item.style & ITEMDRAW_SPACER))
|
||||||
|
{
|
||||||
|
return m_NextPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[255];
|
||||||
|
UTIL_Format(buffer, sizeof(buffer), "%d. %s", m_NextPos, item.display);
|
||||||
|
|
||||||
|
KeyValues *ki = m_pKv->FindKey(g_OptionNumTable[m_NextPos], true);
|
||||||
|
ki->SetString("command", g_OptionCmdTable[m_NextPos]);
|
||||||
|
ki->SetString("msg", buffer);
|
||||||
|
|
||||||
|
return m_NextPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CValveMenuDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
|
||||||
|
{
|
||||||
|
if (onlyIfEmpty && m_TitleDrawn)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pKv->SetString("msg", text);
|
||||||
|
m_TitleDrawn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenuDisplay::DrawRawLine(const char *rawline)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CValveMenuDisplay::SendRawDisplay(int client, int priority, unsigned int time)
|
||||||
|
{
|
||||||
|
m_pKv->SetInt("level", priority);
|
||||||
|
m_pKv->SetInt("time", time);
|
||||||
|
|
||||||
|
SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)(
|
||||||
|
engine->PEntityOfEntIndex(client),
|
||||||
|
DIALOG_MENU,
|
||||||
|
m_pKv,
|
||||||
|
g_pVSPHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenuDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
|
||||||
|
{
|
||||||
|
return g_ValveMenuStyle.DoClientMenu(client, this, handler, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
CValveMenu::CValveMenu() : CBaseMenu(&g_ValveMenuStyle),
|
||||||
|
m_IntroColor(255, 0, 0, 255), m_bShouldDelete(false), m_bCancelling(false)
|
||||||
|
{
|
||||||
|
strcpy(m_IntroMsg, "You have a menu, press ESC");
|
||||||
|
m_Pagination = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CValveMenu::Cancel()
|
||||||
|
{
|
||||||
|
if (m_bCancelling)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bCancelling = true;
|
||||||
|
g_ValveMenuStyle.CancelMenu(this);
|
||||||
|
m_bCancelling = false;
|
||||||
|
|
||||||
|
if (m_bShouldDelete)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CValveMenu::Destroy()
|
||||||
|
{
|
||||||
|
if (!m_bCancelling || m_bShouldDelete)
|
||||||
|
{
|
||||||
|
Cancel();
|
||||||
|
delete this;
|
||||||
|
} else {
|
||||||
|
m_bShouldDelete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenu::SetPagination(unsigned int itemsPerPage)
|
||||||
|
{
|
||||||
|
if (itemsPerPage < 1 || itemsPerPage > 5)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBaseMenu::SetPagination(itemsPerPage);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenu::SetExtOption(MenuOption option, const void *valuePtr)
|
||||||
|
{
|
||||||
|
if (option == MenuOption_IntroMessage)
|
||||||
|
{
|
||||||
|
strncopy(m_IntroMsg, (const char *)valuePtr, sizeof(m_IntroMsg));
|
||||||
|
return true;
|
||||||
|
} else if (option == MenuOption_IntroColor) {
|
||||||
|
unsigned int *array = (unsigned int *)valuePtr;
|
||||||
|
m_IntroColor = Color(array[0], array[1], array[2], array[3]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenu::Display(int client, IMenuHandler *handler, unsigned int time)
|
||||||
|
{
|
||||||
|
if (m_bCancelling)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_ValveMenuStyle.DoClientMenu(client, this, handler, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMenuDisplay *CValveMenu::CreateDisplay()
|
||||||
|
{
|
||||||
|
return new CValveMenuDisplay(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenu::GetExitButton()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CValveMenu::SetExitButton(bool set)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *g_OptionNumTable[11] =
|
||||||
|
{
|
||||||
|
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *g_OptionCmdTable[11] =
|
||||||
|
{
|
||||||
|
"sm_vmenuselect 0", /* INVALID! */
|
||||||
|
"sm_vmenuselect 1",
|
||||||
|
"sm_vmenuselect 2",
|
||||||
|
"sm_vmenuselect 3",
|
||||||
|
"sm_vmenuselect 4",
|
||||||
|
"sm_vmenuselect 5",
|
||||||
|
"sm_vmenuselect 6",
|
||||||
|
"sm_vmenuselect 7",
|
||||||
|
"sm_vmenuselect 8",
|
||||||
|
"sm_vmenuselect 9",
|
||||||
|
"sm_vmenuselect 10"
|
||||||
|
};
|
127
core/MenuStyle_Valve.h
Normal file
127
core/MenuStyle_Valve.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* ===============================================================
|
||||||
|
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
|
||||||
|
* ===============================================================
|
||||||
|
*
|
||||||
|
* This file is not open source and may not be copied without explicit
|
||||||
|
* written permission of AlliedModders LLC. This file may not be redistributed
|
||||||
|
* in whole or significant part.
|
||||||
|
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_MENUSTYLE_VALVE_H
|
||||||
|
#define _INCLUDE_MENUSTYLE_VALVE_H
|
||||||
|
|
||||||
|
#include "sm_globals.h"
|
||||||
|
#include "MenuManager.h"
|
||||||
|
#include "MenuStyle_Base.h"
|
||||||
|
#include "sourcemm_api.h"
|
||||||
|
#include "KeyValues.h"
|
||||||
|
#include <IPlayerHelpers.h>
|
||||||
|
#include "sm_fastlink.h"
|
||||||
|
|
||||||
|
using namespace SourceMod;
|
||||||
|
|
||||||
|
class CValveMenuPlayer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CValveMenuPlayer() : bInMenu(false), bAutoIgnore(false), curPrioLevel(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
menu_states_t states;
|
||||||
|
bool bInMenu;
|
||||||
|
bool bAutoIgnore;
|
||||||
|
int curPrioLevel;
|
||||||
|
float menuStartTime;
|
||||||
|
unsigned int menuHoldTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CValveMenu;
|
||||||
|
class CValveMenuDisplay;
|
||||||
|
|
||||||
|
class ValveMenuStyle :
|
||||||
|
public SMGlobalClass,
|
||||||
|
public IMenuStyle,
|
||||||
|
public IClientListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ValveMenuStyle();
|
||||||
|
bool DoClientMenu(int client, CValveMenu *menu, IMenuHandler *mh, unsigned int time);
|
||||||
|
bool DoClientMenu(int client, CValveMenuDisplay *menu, IMenuHandler *mh, unsigned int time);
|
||||||
|
void ClientPressedKey(int client, unsigned int key_press);
|
||||||
|
bool OnClientCommand(int client);
|
||||||
|
void CancelMenu(CValveMenu *menu);
|
||||||
|
void ProcessWatchList();
|
||||||
|
public: //SMGlobalClass
|
||||||
|
void OnSourceModAllInitialized();
|
||||||
|
void OnSourceModShutdown();
|
||||||
|
void OnSourceModVSPReceived(IServerPluginCallbacks *iface);
|
||||||
|
public: //IClientListener
|
||||||
|
void OnClientDisconnected(int client);
|
||||||
|
public: //IMenuStyle
|
||||||
|
const char *GetStyleName();
|
||||||
|
IMenuDisplay *CreateDisplay();
|
||||||
|
IBaseMenu *CreateMenu();
|
||||||
|
unsigned int GetMaxPageItems();
|
||||||
|
MenuSource GetClientMenu(int client, void **object);
|
||||||
|
bool CancelClientMenu(int client, bool autoIgnore=false);
|
||||||
|
private:
|
||||||
|
bool RedoClientMenu(int client, ItemOrder order);
|
||||||
|
void HookCreateMessage(edict_t *pEdict, DIALOG_TYPE type, KeyValues *kv, IServerPluginCallbacks *plugin);
|
||||||
|
void _CancelMenu(int client, bool bAutoIgnore=false);
|
||||||
|
private:
|
||||||
|
CValveMenuPlayer *m_players;
|
||||||
|
FastLink<int> m_WatchList;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CValveMenu;
|
||||||
|
|
||||||
|
class CValveMenuDisplay : public IMenuDisplay
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CValveMenuDisplay();
|
||||||
|
CValveMenuDisplay(CValveMenu *pMenu);
|
||||||
|
~CValveMenuDisplay();
|
||||||
|
public:
|
||||||
|
IMenuStyle *GetParentStyle();
|
||||||
|
void Reset();
|
||||||
|
void DrawTitle(const char *text, bool onlyIfEmpty=false);
|
||||||
|
unsigned int DrawItem(const ItemDrawInfo &item);
|
||||||
|
bool DrawRawLine(const char *rawline);
|
||||||
|
bool SendDisplay(int client, IMenuHandler *handler, unsigned int time);
|
||||||
|
bool SetExtOption(MenuOption option, const void *valuePtr);
|
||||||
|
bool CanDrawItem(unsigned int drawFlags);
|
||||||
|
void SendRawDisplay(int client, int priority, unsigned int time);
|
||||||
|
private:
|
||||||
|
KeyValues *m_pKv;
|
||||||
|
unsigned int m_NextPos;
|
||||||
|
bool m_TitleDrawn;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CValveMenu : public CBaseMenu
|
||||||
|
{
|
||||||
|
friend class CValveMenuDisplay;
|
||||||
|
public:
|
||||||
|
CValveMenu();
|
||||||
|
public:
|
||||||
|
bool SetExtOption(MenuOption option, const void *valuePtr);
|
||||||
|
IMenuDisplay *CreateDisplay();
|
||||||
|
bool GetExitButton();
|
||||||
|
bool SetExitButton(bool set);
|
||||||
|
bool SetPagination(unsigned int itemsPerPage);
|
||||||
|
bool Display(int client, IMenuHandler *handler, unsigned int time);
|
||||||
|
void Cancel();
|
||||||
|
void Destroy();
|
||||||
|
private:
|
||||||
|
Color m_IntroColor;
|
||||||
|
char m_IntroMsg[128];
|
||||||
|
bool m_bCancelling;
|
||||||
|
bool m_bShouldDelete;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern ValveMenuStyle g_ValveMenuStyle;
|
||||||
|
|
||||||
|
#endif //_INCLUDE_MENUSTYLE_VALVE_H
|
@ -17,6 +17,7 @@
|
|||||||
#include "ShareSys.h"
|
#include "ShareSys.h"
|
||||||
#include "AdminCache.h"
|
#include "AdminCache.h"
|
||||||
#include "ConCmdManager.h"
|
#include "ConCmdManager.h"
|
||||||
|
#include "MenuStyle_Valve.h"
|
||||||
|
|
||||||
PlayerManager g_Players;
|
PlayerManager g_Players;
|
||||||
|
|
||||||
@ -398,6 +399,12 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
|
|||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool result = g_ValveMenuStyle.OnClientCommand(client);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
res = Pl_Handled;
|
||||||
|
}
|
||||||
|
|
||||||
res = g_ConCmds.DispatchClientCommand(client, (ResultType)res);
|
res = g_ConCmds.DispatchClientCommand(client, (ResultType)res);
|
||||||
|
|
||||||
if (res >= Pl_Handled)
|
if (res >= Pl_Handled)
|
||||||
|
@ -227,6 +227,18 @@
|
|||||||
RelativePath="..\MemoryUtils.cpp"
|
RelativePath="..\MemoryUtils.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\MenuManager.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\MenuStyle_Base.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\MenuStyle_Valve.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\PlayerManager.cpp"
|
RelativePath="..\PlayerManager.cpp"
|
||||||
>
|
>
|
||||||
@ -333,6 +345,18 @@
|
|||||||
RelativePath="..\MemoryUtils.h"
|
RelativePath="..\MemoryUtils.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\MenuManager.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\MenuStyle_Base.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\MenuStyle_Valve.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\PlayerManager.h"
|
RelativePath="..\PlayerManager.h"
|
||||||
>
|
>
|
||||||
@ -341,6 +365,10 @@
|
|||||||
RelativePath="..\sm_autonatives.h"
|
RelativePath="..\sm_autonatives.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\sm_fastlink.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\sm_globals.h"
|
RelativePath="..\sm_globals.h"
|
||||||
>
|
>
|
||||||
@ -438,6 +466,10 @@
|
|||||||
RelativePath="..\..\public\IMemoryUtils.h"
|
RelativePath="..\..\public\IMemoryUtils.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\public\IMenuManager.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\public\IPlayerHelpers.h"
|
RelativePath="..\..\public\IPlayerHelpers.h"
|
||||||
>
|
>
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "Translator.h"
|
#include "Translator.h"
|
||||||
#include "ForwardSys.h"
|
#include "ForwardSys.h"
|
||||||
#include "TimerSys.h"
|
#include "TimerSys.h"
|
||||||
|
#include "MenuStyle_Valve.h"
|
||||||
|
|
||||||
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
|
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
|
||||||
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
|
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
|
||||||
@ -43,6 +44,7 @@ ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn;
|
|||||||
IVirtualMachine *g_pVM;
|
IVirtualMachine *g_pVM;
|
||||||
IdentityToken_t *g_pCoreIdent = NULL;
|
IdentityToken_t *g_pCoreIdent = NULL;
|
||||||
float g_LastTime = 0.0f;
|
float g_LastTime = 0.0f;
|
||||||
|
float g_LastMenuTime = 0.0f;
|
||||||
float g_LastAuthCheck = 0.0f;
|
float g_LastAuthCheck = 0.0f;
|
||||||
IForward *g_pOnGameFrame = NULL;
|
IForward *g_pOnGameFrame = NULL;
|
||||||
IForward *g_pOnMapEnd = NULL;
|
IForward *g_pOnMapEnd = NULL;
|
||||||
@ -264,6 +266,7 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch
|
|||||||
m_IsMapLoading = true;
|
m_IsMapLoading = true;
|
||||||
m_ExecPluginReload = true;
|
m_ExecPluginReload = true;
|
||||||
g_LastTime = 0.0f;
|
g_LastTime = 0.0f;
|
||||||
|
g_LastMenuTime = 0.0f;
|
||||||
g_LastAuthCheck = 0.0f;
|
g_LastAuthCheck = 0.0f;
|
||||||
g_SimTicks.ticking = true;
|
g_SimTicks.ticking = true;
|
||||||
g_SimTicks.tickcount = 0;
|
g_SimTicks.tickcount = 0;
|
||||||
@ -384,6 +387,12 @@ void SourceModBase::GameFrame(bool simulating)
|
|||||||
g_LastTime = curtime;
|
g_LastTime = curtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_SimTicks.tickcount && (curtime - g_LastMenuTime >= 1.0f))
|
||||||
|
{
|
||||||
|
g_ValveMenuStyle.ProcessWatchList();
|
||||||
|
g_LastMenuTime = curtime;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_pOnGameFrame && g_pOnGameFrame->GetFunctionCount())
|
if (g_pOnGameFrame && g_pOnGameFrame->GetFunctionCount())
|
||||||
{
|
{
|
||||||
g_pOnGameFrame->Execute(NULL);
|
g_pOnGameFrame->Execute(NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user