core/MenuStyle_Valve.cpp
author Scott Ehlert <ds@alliedmods.net>
Sun Mar 30 07:00:22 2008 +0000 (2008-03-30)
changeset 1952 b7aa2b626807
child 2289 44045ead61cd
permissions -rw-r--r--
Spring Cleaning, Part Ichi (1)
Various minor things done to project files
Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way)
Updated regex project file and makefile
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "sm_stringutil.h"
    33 #include "PlayerManager.h"
    34 #include "MenuStyle_Valve.h"
    35 #include "Translator.h"
    36 #include "PlayerManager.h"
    37 #include "ConCmdManager.h"
    38 
    39 SH_DECL_HOOK4_void(IServerPluginHelpers, CreateMessage, SH_NOATTRIB, false, edict_t *, DIALOG_TYPE, KeyValues *, IServerPluginCallbacks *);
    40 
    41 ValveMenuStyle g_ValveMenuStyle;
    42 extern const char *g_OptionNumTable[];
    43 extern const char *g_OptionCmdTable[];
    44 CallClass<IServerPluginHelpers> *g_pSPHCC = NULL;
    45 
    46 ValveMenuStyle::ValveMenuStyle() : m_players(new CValveMenuPlayer[256+1])
    47 {
    48 }
    49 
    50 CBaseMenuPlayer *ValveMenuStyle::GetMenuPlayer(int client)
    51 {
    52 	return &m_players[client];
    53 }
    54 
    55 bool ValveMenuStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
    56 {
    57 	if (strcmp(cmdname, "sm_vmenuselect") == 0)
    58 	{
    59 		int key_press = atoi(cmd.Arg(1));
    60 		g_ValveMenuStyle.ClientPressedKey(client, key_press);
    61 		return true;
    62 	}
    63 
    64 	return false;
    65 }
    66 
    67 void ValveMenuStyle::OnSourceModAllInitialized()
    68 {
    69 	g_Players.AddClientListener(this);
    70 	SH_ADD_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
    71 	g_pSPHCC = SH_GET_CALLCLASS(serverpluginhelpers);
    72 }
    73 
    74 void ValveMenuStyle::OnSourceModShutdown()
    75 {
    76 	SH_RELEASE_CALLCLASS(g_pSPHCC);
    77 	SH_REMOVE_HOOK_MEMFUNC(IServerPluginHelpers, CreateMessage, serverpluginhelpers, this, &ValveMenuStyle::HookCreateMessage, false);
    78 	g_Players.RemoveClientListener(this);
    79 }
    80 
    81 void ValveMenuStyle::HookCreateMessage(edict_t *pEdict,
    82 									   DIALOG_TYPE type,
    83 									   KeyValues *kv,
    84 									   IServerPluginCallbacks *plugin)
    85 {
    86 	if (type != DIALOG_MENU)
    87 	{
    88 		return;
    89 	}
    90 
    91 	int client = engine->IndexOfEdict(pEdict);
    92 	if (client < 1 || client > 256)
    93 	{
    94 		return;
    95 	}
    96 
    97 	CValveMenuPlayer *player = &m_players[client];
    98 	
    99 	/* We don't care if the player is in a menu because, for all intents and purposes,
   100 	 * the menu is completely private.  Instead, we just figure out the level we'll need
   101 	 * in order to override it.
   102 	 */
   103 	player->curPrioLevel = kv->GetInt("level", player->curPrioLevel);
   104 
   105 	/* Oh no! What happens if we got a menu that overwrites ours?! */
   106 	if (player->bInMenu)
   107 	{
   108 		/* Okay, let the external menu survive for now.  It may live another 
   109 		 * day to avenge its grandfather, killed in the great Menu Interruption
   110 		 * battle.
   111 		 */
   112 		_CancelClientMenu(client, MenuCancel_Interrupted, true);
   113 	}
   114 }
   115 
   116 IMenuPanel *ValveMenuStyle::CreatePanel()
   117 {
   118 	return new CValveMenuDisplay();
   119 }
   120 
   121 IBaseMenu *ValveMenuStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
   122 {
   123 	return new CValveMenu(pHandler, pOwner);
   124 }
   125 
   126 const char *ValveMenuStyle::GetStyleName()
   127 {
   128 	return "valve";
   129 }
   130 
   131 unsigned int ValveMenuStyle::GetMaxPageItems()
   132 {
   133 	return 8;
   134 }
   135 
   136 void ValveMenuStyle::SendDisplay(int client, IMenuPanel *display)
   137 {
   138 	m_players[client].curPrioLevel--;
   139 	CValveMenuDisplay *vDisplay = (CValveMenuDisplay *)display;
   140 	vDisplay->SendRawDisplay(client, m_players[client].curPrioLevel, m_players[client].menuHoldTime);
   141 }
   142 
   143 bool ValveMenuStyle::DoClientMenu(int client, IMenuPanel *menu, IMenuHandler *mh, unsigned int time)
   144 {
   145 	if (vsp_interface == NULL)
   146 	{
   147 		return false;
   148 	}
   149 
   150 	return BaseMenuStyle::DoClientMenu(client, menu, mh, time);
   151 }
   152 
   153 bool ValveMenuStyle::DoClientMenu(int client, CBaseMenu *menu, unsigned int first_item, IMenuHandler *mh, unsigned int time)
   154 {
   155 	if (vsp_interface == NULL)
   156 	{
   157 		mh->OnMenuStart(menu);
   158 		mh->OnMenuCancel(menu, client, MenuCancel_NoDisplay);
   159 		mh->OnMenuEnd(menu, MenuEnd_Cancelled);
   160 		return false;
   161 	}
   162 
   163 	return BaseMenuStyle::DoClientMenu(client, menu, first_item, mh, time);
   164 }
   165 
   166 unsigned int ValveMenuStyle::GetApproxMemUsage()
   167 {
   168 	return sizeof(ValveMenuStyle) + (sizeof(CValveMenuPlayer) * 257);
   169 }
   170 
   171 CValveMenuDisplay::CValveMenuDisplay()
   172 {
   173 	m_pKv = NULL;
   174 	Reset();
   175 }
   176 
   177 CValveMenuDisplay::CValveMenuDisplay(CValveMenu *pMenu)
   178 {
   179 	m_pKv = NULL;
   180 	Reset();
   181 	m_pKv->SetColor("color", pMenu->m_IntroColor);
   182 	m_pKv->SetString("title", pMenu->m_IntroMsg);
   183 }
   184 
   185 void CValveMenuDisplay::DeleteThis()
   186 {
   187 	delete this;
   188 }
   189 
   190 CValveMenuDisplay::~CValveMenuDisplay()
   191 {
   192 	m_pKv->deleteThis();
   193 }
   194 
   195 IMenuStyle *CValveMenuDisplay::GetParentStyle()
   196 {
   197 	return &g_ValveMenuStyle;
   198 }
   199 
   200 void CValveMenuDisplay::Reset()
   201 {
   202 	if (m_pKv)
   203 	{
   204 		m_pKv->deleteThis();
   205 	}
   206 	m_pKv = new KeyValues("menu");
   207 	m_NextPos = 1;
   208 	m_TitleDrawn = false;
   209 }
   210 
   211 unsigned int CValveMenuDisplay::GetCurrentKey()
   212 {
   213 	return m_NextPos;
   214 }
   215 
   216 bool CValveMenuDisplay::SetCurrentKey(unsigned int key)
   217 {
   218 	if (key < m_NextPos || key > 9)
   219 	{
   220 		return false;
   221 	}
   222 
   223 	m_NextPos = key;
   224 
   225 	return true;
   226 }
   227 
   228 bool CValveMenuDisplay::SetExtOption(MenuOption option, const void *valuePtr)
   229 {
   230 	if (option == MenuOption_IntroMessage)
   231 	{
   232 		m_pKv->SetString("title", (const char *)valuePtr);
   233 		return true;
   234 	} else if (option == MenuOption_IntroColor) {
   235 		int *array = (int *)valuePtr;
   236 		m_pKv->SetColor("color", Color(array[0], array[1], array[2], array[3]));
   237 		return true;
   238 	} else if (option == MenuOption_Priority) {
   239 		m_pKv->SetInt("level", *(int *)valuePtr);
   240 		return true;
   241 	}
   242 
   243 	return false;
   244 }
   245 
   246 bool CValveMenuDisplay::CanDrawItem(unsigned int drawFlags)
   247 {
   248 	/**
   249 	 * ITEMDRAW_RAWLINE - We can't draw random text, and this doesn't add a slot,
   250 	 *  so it's completely safe to ignore it.
   251 	 * -----------------------------------------
   252 	 */
   253 	if (drawFlags & ITEMDRAW_RAWLINE)
   254 	{
   255 		return false;
   256 	}
   257 
   258 	/**
   259 	 * Special cases, explained in DrawItem()
   260 	 */
   261 	if ((drawFlags & ITEMDRAW_NOTEXT)
   262 		|| (drawFlags & ITEMDRAW_SPACER))
   263 	{
   264 		return true;
   265 	}
   266 
   267 	/**
   268 	 * We can't draw disabled text.  We could bump the position, but we
   269 	 * want DirectDraw() to find some actual items to display.
   270 	 */
   271 	if (drawFlags & ITEMDRAW_DISABLED)
   272 	{
   273 		return false;
   274 	}
   275 
   276 	return true;
   277 }
   278 
   279 unsigned int CValveMenuDisplay::DrawItem(const ItemDrawInfo &item)
   280 {
   281 	if (m_NextPos > 9 || !CanDrawItem(item.style))
   282 	{
   283 		return 0;
   284 	}
   285 
   286 	/**
   287 	 * For these cases we can't draw anything at all, but
   288 	 * we can at least bump the position since we were explicitly asked to.
   289 	 */
   290 	if ((item.style & ITEMDRAW_NOTEXT)
   291 		|| (item.style & ITEMDRAW_SPACER))
   292 	{
   293 		return m_NextPos++;
   294 	}
   295 
   296 	char buffer[255];
   297 	UTIL_Format(buffer, sizeof(buffer), "%d. %s", m_NextPos, item.display);
   298 
   299 	KeyValues *ki = m_pKv->FindKey(g_OptionNumTable[m_NextPos], true);
   300 	ki->SetString("command", g_OptionCmdTable[m_NextPos]);
   301 	ki->SetString("msg", buffer);
   302 
   303 	return m_NextPos++;
   304 }
   305 
   306 void CValveMenuDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
   307 {
   308 	if (onlyIfEmpty && m_TitleDrawn)
   309 	{
   310 		return;
   311 	}
   312 
   313 	m_pKv->SetString("msg", text);
   314 	m_TitleDrawn = true;
   315 }
   316 
   317 bool CValveMenuDisplay::DrawRawLine(const char *rawline)
   318 {
   319 	return false;
   320 }
   321 
   322 void CValveMenuDisplay::SendRawDisplay(int client, int priority, unsigned int time)
   323 {
   324 	m_pKv->SetInt("level", priority);
   325 	m_pKv->SetInt("time", time ? time : 200);
   326 
   327 	SH_CALL(g_pSPHCC, &IServerPluginHelpers::CreateMessage)(
   328 		engine->PEntityOfEntIndex(client),
   329 		DIALOG_MENU,
   330 		m_pKv,
   331 		vsp_interface);
   332 }
   333 
   334 bool CValveMenuDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
   335 {
   336 	return g_ValveMenuStyle.DoClientMenu(client, this, handler, time);
   337 }
   338 
   339 bool CValveMenuDisplay::SetSelectableKeys(unsigned int keymap)
   340 {
   341 	return false;
   342 }
   343 
   344 int CValveMenuDisplay::GetAmountRemaining()
   345 {
   346 	/* :TODO: this is a lie, but nothing really seems meaningful... */
   347 	return -1;
   348 }
   349 
   350 unsigned int CValveMenuDisplay::GetApproxMemUsage()
   351 {
   352 	return sizeof(CValveMenuDisplay) + (sizeof(KeyValues) * m_NextPos * 10);
   353 }
   354 
   355 CValveMenu::CValveMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : 
   356 CBaseMenu(pHandler, &g_ValveMenuStyle, pOwner), 
   357 	m_IntroColor(255, 0, 0, 255)
   358 {
   359 	strcpy(m_IntroMsg, "You have a menu, press ESC");
   360 	m_Pagination = 5;
   361 }
   362 
   363 void CValveMenu::Cancel_Finally()
   364 {
   365 	g_ValveMenuStyle.CancelMenu(this);
   366 }
   367 
   368 bool CValveMenu::SetPagination(unsigned int itemsPerPage)
   369 {
   370 	if (itemsPerPage > 5)
   371 	{
   372 		return false;
   373 	}
   374 
   375 	return CBaseMenu::SetPagination(itemsPerPage);
   376 }
   377 
   378 bool CValveMenu::SetExtOption(MenuOption option, const void *valuePtr)
   379 {
   380 	if (option == MenuOption_IntroMessage)
   381 	{
   382 		strncopy(m_IntroMsg, (const char *)valuePtr, sizeof(m_IntroMsg));
   383 		return true;
   384 	} else if (option == MenuOption_IntroColor) {
   385 		unsigned int *array = (unsigned int *)valuePtr;
   386 		m_IntroColor = Color(array[0], array[1], array[2], array[3]);
   387 		return true;
   388 	}
   389 
   390 	return false;
   391 }
   392 
   393 bool CValveMenu::Display(int client, unsigned int time, IMenuHandler *alt_handler)
   394 {
   395 	return DisplayAtItem(client, time, 0, alt_handler);
   396 }
   397 
   398 bool CValveMenu::DisplayAtItem(int client,
   399 							   unsigned int time,
   400 							   unsigned int start_item,
   401 							   IMenuHandler *alt_handler/* =NULL */)
   402 {
   403 	if (m_bCancelling)
   404 	{
   405 		return false;
   406 	}
   407 
   408 	return g_ValveMenuStyle.DoClientMenu(client, this, start_item, alt_handler ? alt_handler : m_pHandler, time);
   409 }
   410 
   411 IMenuPanel *CValveMenu::CreatePanel()
   412 {
   413 	return new CValveMenuDisplay(this);
   414 }
   415 
   416 void CValveMenu::SetMenuOptionFlags(unsigned int flags)
   417 {
   418 	flags |= MENUFLAG_BUTTON_EXIT;
   419 	CBaseMenu::SetMenuOptionFlags(flags);
   420 }
   421 
   422 unsigned int CValveMenu::GetApproxMemUsage()
   423 {
   424 	return sizeof(CValveMenu) + GetBaseMemUsage();
   425 }
   426 
   427 const char *g_OptionNumTable[] = 
   428 {
   429 	"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
   430 };
   431 
   432 const char *g_OptionCmdTable[] = 
   433 {
   434 	"sm_vmenuselect 0", /* INVALID! */
   435 	"sm_vmenuselect 1",
   436 	"sm_vmenuselect 2",
   437 	"sm_vmenuselect 3",
   438 	"sm_vmenuselect 4",
   439 	"sm_vmenuselect 5",
   440 	"sm_vmenuselect 6",
   441 	"sm_vmenuselect 7",
   442 	"sm_vmenuselect 8",
   443 	"sm_vmenuselect 9",
   444 	"sm_vmenuselect 10"
   445 };