core/MenuStyle_Valve.cpp
author David Anderson <dvander@alliedmods.net>
Wed Jun 06 22:31:54 2007 +0000 (2007-06-06)
changeset 896 e30eef2642ba
parent 877 898c39fbfde9
child 997 2fc3152c3118
permissions -rw-r--r--
added config options for chat triggers
     1 /**
     2  * vim: set ts=4 :
     3  * ===============================================================
     4  * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
     5  * ===============================================================
     6  *
     7  * This file is not open source and may not be copied without explicit
     8  * written permission of AlliedModders LLC.  This file may not be redistributed 
     9  * in whole or significant part.
    10  * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
    11  *
    12  * Version: $Id$
    13  */
    14 
    15 #include "sm_stringutil.h"
    16 #include "PlayerManager.h"
    17 #include "MenuStyle_Valve.h"
    18 #include "Translator.h"
    19 #include "PlayerManager.h"
    20 #include "ConCmdManager.h"
    21 
    22 SH_DECL_HOOK4_void(IServerPluginHelpers, CreateMessage, SH_NOATTRIB, false, edict_t *, DIALOG_TYPE, KeyValues *, IServerPluginCallbacks *);
    23 
    24 ValveMenuStyle g_ValveMenuStyle;
    25 extern const char *g_OptionNumTable[];
    26 extern const char *g_OptionCmdTable[];
    27 IServerPluginCallbacks *g_pVSPHandle = NULL;
    28 CallClass<IServerPluginHelpers> *g_pSPHCC = NULL;
    29 
    30 ValveMenuStyle::ValveMenuStyle() : m_players(new CValveMenuPlayer[256+1])
    31 {
    32 }
    33 
    34 CBaseMenuPlayer *ValveMenuStyle::GetMenuPlayer(int client)
    35 {
    36 	return &m_players[client];
    37 }
    38 
    39 bool ValveMenuStyle::OnClientCommand(int client)
    40 {
    41 	const char *cmd = engine->Cmd_Argv(0);
    42 
    43 	if (strcmp(cmd, "sm_vmenuselect") == 0)
    44 	{
    45 		int key_press = atoi(engine->Cmd_Argv(1));
    46 		g_ValveMenuStyle.ClientPressedKey(client, key_press);
    47 		return true;
    48 	}
    49 
    50 	return false;
    51 }
    52 
    53 void ValveMenuStyle::OnSourceModAllInitialized()
    54 {
    55 	g_Players.AddClientListener(this);
    56 	SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
    57 	g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
    58 }
    59 
    60 void ValveMenuStyle::OnSourceModShutdown()
    61 {
    62 	SH_RELEASE_CALLCLASS(g_pSPHCC);
    63 	SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
    64 	g_Players.RemoveClientListener(this);
    65 }
    66 
    67 void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
    68 									   DIALOG_TYPE type,
    69 									   KeyValues *kv,
    70 									   IServerPluginCallbacks *plugin)
    71 {
    72 	if (type != DIALOG_MENU)
    73 	{
    74 		return;
    75 	}
    76 
    77 	int client = engine->IndexOfEdict(pEdict);
    78 	if (client < 1 || client > 256)
    79 	{
    80 		return;
    81 	}
    82 
    83 	CValveMenuPlayer *player = &m_players[client];
    84 	
    85 	/* We don't care if the player is in a menu because, for all intents and purposes,
    86 	 * the menu is completely private.  Instead, we just figure out the level we'll need
    87 	 * in order to override it.
    88 	 */
    89 	player->curPrioLevel = kv->GetInt("level", player->curPrioLevel);
    90 
    91 	/* Oh no! What happens if we got a menu that overwrites ours?! */
    92 	if (player->bInMenu)
    93 	{
    94 		/* Okay, let the external menu survive for now.  It may live another 
    95 		 * day to avenge its grandfather, killed in the great Menu Interruption
    96 		 * battle.
    97 		 */
    98 		_CancelClientMenu(client, true);
    99 	}
   100 }
   101 
   102 void ValveMenuStyle::OnSourceModVSPReceived(IServerPluginCallbacks *iface)
   103 {
   104 	g_pVSPHandle = iface;
   105 }
   106 
   107 IMenuPanel *ValveMenuStyle::CreatePanel()
   108 {
   109 	return new CValveMenuDisplay();
   110 }
   111 
   112 IBaseMenu *ValveMenuStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
   113 {
   114 	return new CValveMenu(pHandler, pOwner);
   115 }
   116 
   117 const char *ValveMenuStyle::GetStyleName()
   118 {
   119 	return "valve";
   120 }
   121 
   122 unsigned int ValveMenuStyle::GetMaxPageItems()
   123 {
   124 	return 8;
   125 }
   126 
   127 void ValveMenuStyle::SendDisplay(int client, IMenuPanel *display)
   128 {
   129 	m_players[client].curPrioLevel--;
   130 	CValveMenuDisplay *vDisplay = (CValveMenuDisplay *)display;
   131 	vDisplay->SendRawDisplay(client, m_players[client].curPrioLevel, m_players[client].menuHoldTime);
   132 }
   133 
   134 bool ValveMenuStyle::DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time)
   135 {
   136 	if (!g_pVSPHandle)
   137 	{
   138 		return false;
   139 	}
   140 
   141 	return BaseMenuStyle::DoClientMenu(client, menu, mh, time);
   142 }
   143 
   144 bool ValveMenuStyle::DoClientMenu(int client, CBaseMenu *menu, IMenuHandler *mh, unsigned int time)
   145 {
   146 	if (!g_pVSPHandle)
   147 	{
   148 		mh->OnMenuStart(menu);
   149 		mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
   150 		mh->OnMenuEnd(menu);
   151 		return false;
   152 	}
   153 
   154 	return BaseMenuStyle::DoClientMenu(client, menu, mh, time);
   155 }
   156 
   157 CValveMenuDisplay::CValveMenuDisplay()
   158 {
   159 	m_pKv = NULL;
   160 	Reset();
   161 }
   162 
   163 CValveMenuDisplay::CValveMenuDisplay(CValveMenu *pMenu)
   164 {
   165 	m_pKv = NULL;
   166 	Reset();
   167 	m_pKv->SetColor("color", pMenu->m_IntroColor);
   168 	m_pKv->SetString("title", pMenu->m_IntroMsg);
   169 }
   170 
   171 void CValveMenuDisplay::DeleteThis()
   172 {
   173 	delete this;
   174 }
   175 
   176 CValveMenuDisplay::~CValveMenuDisplay()
   177 {
   178 	m_pKv->deleteThis();
   179 }
   180 
   181 IMenuStyle *CValveMenuDisplay::GetParentStyle()
   182 {
   183 	return &g_ValveMenuStyle;
   184 }
   185 
   186 void CValveMenuDisplay::Reset()
   187 {
   188 	if (m_pKv)
   189 	{
   190 		m_pKv->deleteThis();
   191 	}
   192 	m_pKv = new KeyValues("menu");
   193 	m_NextPos = 1;
   194 	m_TitleDrawn = false;
   195 }
   196 
   197 unsigned int CValveMenuDisplay::GetCurrentKey()
   198 {
   199 	return m_NextPos;
   200 }
   201 
   202 bool CValveMenuDisplay::SetCurrentKey(unsigned int key)
   203 {
   204 	if (key < m_NextPos || key > 9)
   205 	{
   206 		return false;
   207 	}
   208 
   209 	m_NextPos = key;
   210 
   211 	return true;
   212 }
   213 
   214 bool CValveMenuDisplay::SetExtOption(MenuOption option, const void *valuePtr)
   215 {
   216 	if (option == MenuOption_IntroMessage)
   217 	{
   218 		m_pKv->SetString("title", (const char *)valuePtr);
   219 		return true;
   220 	} else if (option == MenuOption_IntroColor) {
   221 		int *array = (int *)valuePtr;
   222 		m_pKv->SetColor("color", Color(array[0], array[1], array[2], array[3]));
   223 		return true;
   224 	} else if (option == MenuOption_Priority) {
   225 		m_pKv->SetInt("level", *(int *)valuePtr);
   226 		return true;
   227 	}
   228 
   229 	return false;
   230 }
   231 
   232 bool CValveMenuDisplay::CanDrawItem(unsigned int drawFlags)
   233 {
   234 	/**
   235 	 * ITEMDRAW_RAWLINE - We can't draw random text, and this doesn't add a slot,
   236 	 *  so it's completely safe to ignore it.
   237 	 * -----------------------------------------
   238 	 */
   239 	if (drawFlags & ITEMDRAW_RAWLINE)
   240 	{
   241 		return false;
   242 	}
   243 
   244 	/**
   245 	 * Special cases, explained in DrawItem()
   246 	 */
   247 	if ((drawFlags & ITEMDRAW_NOTEXT)
   248 		|| (drawFlags & ITEMDRAW_SPACER))
   249 	{
   250 		return true;
   251 	}
   252 
   253 	/**
   254 	 * We can't draw disabled text.  We could bump the position, but we
   255 	 * want DirectDraw() to find some actual items to display.
   256 	 */
   257 	if (drawFlags & ITEMDRAW_DISABLED)
   258 	{
   259 		return false;
   260 	}
   261 
   262 	return true;
   263 }
   264 
   265 unsigned int CValveMenuDisplay::DrawItem(const ItemDrawInfo &item)
   266 {
   267 	if (m_NextPos > 9 || !CanDrawItem(item.style))
   268 	{
   269 		return 0;
   270 	}
   271 
   272 	/**
   273 	 * For these cases we can't draw anything at all, but
   274 	 * we can at least bump the position since we were explicitly asked to.
   275 	 */
   276 	if ((item.style & ITEMDRAW_NOTEXT)
   277 		|| (item.style & ITEMDRAW_SPACER))
   278 	{
   279 		return m_NextPos++;
   280 	}
   281 
   282 	char buffer[255];
   283 	UTIL_Format(buffer, sizeof(buffer), "%d. %s", m_NextPos, item.display);
   284 
   285 	KeyValues *ki = m_pKv->FindKey(g_OptionNumTable[m_NextPos], true);
   286 	ki->SetString("command", g_OptionCmdTable[m_NextPos]);
   287 	ki->SetString("msg", buffer);
   288 
   289 	return m_NextPos++;
   290 }
   291 
   292 void CValveMenuDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
   293 {
   294 	if (onlyIfEmpty && m_TitleDrawn)
   295 	{
   296 		return;
   297 	}
   298 
   299 	m_pKv->SetString("msg", text);
   300 	m_TitleDrawn = true;
   301 }
   302 
   303 bool CValveMenuDisplay::DrawRawLine(const char *rawline)
   304 {
   305 	return false;
   306 }
   307 
   308 void CValveMenuDisplay::SendRawDisplay(int client, int priority, unsigned int time)
   309 {
   310 	m_pKv->SetInt("level", priority);
   311 	m_pKv->SetInt("time", time ? time : 200);
   312 
   313 	SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)(
   314 		engine->PEntityOfEntIndex(client),
   315 		DIALOG_MENU,
   316 		m_pKv,
   317 		g_pVSPHandle);
   318 }
   319 
   320 bool CValveMenuDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
   321 {
   322 	return g_ValveMenuStyle.DoClientMenu(client, this, handler, time);
   323 }
   324 
   325 bool CValveMenuDisplay::SetSelectableKeys(unsigned int keymap)
   326 {
   327 	return false;
   328 }
   329 
   330 CValveMenu::CValveMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : 
   331 CBaseMenu(pHandler, &g_ValveMenuStyle, pOwner), 
   332 	m_IntroColor(255, 0, 0, 255)
   333 {
   334 	strcpy(m_IntroMsg, "You have a menu, press ESC");
   335 	m_Pagination = 5;
   336 }
   337 
   338 void CValveMenu::Cancel_Finally()
   339 {
   340 	g_ValveMenuStyle.CancelMenu(this);
   341 }
   342 
   343 bool CValveMenu::SetPagination(unsigned int itemsPerPage)
   344 {
   345 	if (itemsPerPage > 5)
   346 	{
   347 		return false;
   348 	}
   349 
   350 	return CBaseMenu::SetPagination(itemsPerPage);
   351 }
   352 
   353 bool CValveMenu::SetExtOption(MenuOption option, const void *valuePtr)
   354 {
   355 	if (option == MenuOption_IntroMessage)
   356 	{
   357 		strncopy(m_IntroMsg, (const char *)valuePtr, sizeof(m_IntroMsg));
   358 		return true;
   359 	} else if (option == MenuOption_IntroColor) {
   360 		unsigned int *array = (unsigned int *)valuePtr;
   361 		m_IntroColor = Color(array[0], array[1], array[2], array[3]);
   362 		return true;
   363 	}
   364 
   365 	return false;
   366 }
   367 
   368 bool CValveMenu::Display(int client, unsigned int time)
   369 {
   370 	if (m_bCancelling)
   371 	{
   372 		return false;
   373 	}
   374 
   375 	return g_ValveMenuStyle.DoClientMenu(client, this, m_pHandler, time);
   376 }
   377 
   378 void CValveMenu::VoteDisplay(int client, unsigned int maxTime)
   379 {
   380 	if (m_bCancelling)
   381 	{
   382 		return;
   383 	}
   384 
   385 	g_ValveMenuStyle.DoClientMenu(client, this, m_pVoteHandler, maxTime);
   386 }
   387 
   388 IMenuPanel *CValveMenu::CreatePanel()
   389 {
   390 	return new CValveMenuDisplay(this);
   391 }
   392 
   393 bool CValveMenu::GetExitButton()
   394 {
   395 	return true;
   396 }
   397 
   398 bool CValveMenu::SetExitButton(bool set)
   399 {
   400 	return false;
   401 }
   402 
   403 const char *g_OptionNumTable[] = 
   404 {
   405 	"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
   406 };
   407 
   408 const char *g_OptionCmdTable[] = 
   409 {
   410 	"sm_vmenuselect 0", /* INVALID! */
   411 	"sm_vmenuselect 1",
   412 	"sm_vmenuselect 2",
   413 	"sm_vmenuselect 3",
   414 	"sm_vmenuselect 4",
   415 	"sm_vmenuselect 5",
   416 	"sm_vmenuselect 6",
   417 	"sm_vmenuselect 7",
   418 	"sm_vmenuselect 8",
   419 	"sm_vmenuselect 9",
   420 	"sm_vmenuselect 10"
   421 };