core/MenuStyle_Radio.cpp
author David Anderson <dvander@alliedmods.net>
Tue Sep 11 18:08:49 2007 +0000 (2007-09-11)
changeset 1408 2fd63cc4bd9c
parent 1361 591f6d2fd11d
child 1474 a3b73df84d88
permissions -rw-r--r--
timelimit function now gets initialized
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2007 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 "MenuStyle_Radio.h"
    33 #include "sm_stringutil.h"
    34 #include "UserMessages.h"
    35 #include "GameConfigs.h"
    36 #include "PlayerManager.h"
    37 #if defined MENU_DEBUG
    38 #include "Logger.h"
    39 #endif
    40 
    41 extern const char *g_RadioNumTable[];
    42 CRadioStyle g_RadioMenuStyle;
    43 int g_ShowMenuId = -1;
    44 bool g_bRadioInit = false;
    45 
    46 CRadioStyle::CRadioStyle() : m_players(new CBaseMenuPlayer[256+1])
    47 {
    48 }
    49 
    50 void CRadioStyle::OnSourceModAllInitialized()
    51 {
    52 	g_Players.AddClientListener(this);
    53 }
    54 
    55 void CRadioStyle::OnSourceModLevelChange(const char *mapName)
    56 {
    57 	if (g_bRadioInit)
    58 	{
    59 		return;
    60 	}
    61 
    62 	g_bRadioInit = true;
    63 	const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
    64 	if (!msg || msg[0] == '\0')
    65 	{
    66 		return;
    67 	}
    68 
    69 	g_ShowMenuId = g_UserMsgs.GetMessageIndex(msg);
    70 
    71 	if (!IsSupported())
    72 	{
    73 		return;
    74 	}
    75 
    76 	g_Menus.AddStyle(this);
    77 	g_Menus.SetDefaultStyle(this);
    78 
    79 	g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
    80 }
    81 
    82 void CRadioStyle::OnSourceModShutdown()
    83 {
    84 	g_Players.RemoveClientListener(this);
    85 	g_UserMsgs.UnhookUserMessage(g_ShowMenuId, this, false);
    86 
    87 	while (!m_FreeDisplays.empty())
    88 	{
    89 		delete m_FreeDisplays.front();
    90 		m_FreeDisplays.pop();
    91 	}
    92 }
    93 
    94 bool CRadioStyle::IsSupported()
    95 {
    96 	return (g_ShowMenuId != -1);
    97 }
    98 
    99 bool CRadioStyle::OnClientCommand(int client, const char *cmd)
   100 {
   101 	if (strcmp(cmd, "menuselect") == 0)
   102 	{
   103 		if (!m_players[client].bInMenu)
   104 		{
   105 			return false;
   106 		}
   107 
   108 		int arg = atoi(engine->Cmd_Argv(1));
   109 		ClientPressedKey(client, arg);
   110 		return true;
   111 	}
   112 
   113 	return false;
   114 }
   115 
   116 static unsigned int g_last_holdtime = 0;
   117 static unsigned int g_last_client_count = 0;
   118 static int g_last_clients[256];
   119 
   120 void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
   121 {
   122 	int count = pFilter->GetRecipientCount();
   123 	bf_read br(bf->GetBasePointer(), 2);
   124 
   125 	br.ReadWord();
   126 	int c = br.ReadChar();
   127 
   128 	g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
   129 
   130 	for (int i=0; i<count; i++)
   131 	{
   132 		g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
   133 	}
   134 }
   135 
   136 void CRadioStyle::OnUserMessageSent(int msg_id)
   137 {
   138 	for (unsigned int i=0; i<g_last_client_count; i++)
   139 	{
   140 		int client = g_last_clients[i];
   141 #if defined MENU_DEBUG
   142 		g_Logger.LogMessage("[SM_MENU] CRadioStyle got ShowMenu (client %d) (bInMenu %d)",
   143 			client,
   144 			m_players[client].bInExternMenu);
   145 #endif
   146 		if (m_players[client].bInMenu)
   147 		{
   148 			_CancelClientMenu(client, MenuCancel_Interrupted, true);
   149 		}
   150 		m_players[client].bInExternMenu = true;
   151 		m_players[client].menuHoldTime = g_last_holdtime;
   152 	}
   153 	g_last_client_count = 0;
   154 }
   155 
   156 void CRadioStyle::SendDisplay(int client, IMenuPanel *display)
   157 {
   158 	CRadioDisplay *rDisplay = (CRadioDisplay *)display;
   159 	rDisplay->SendRawDisplay(client, m_players[client].menuHoldTime);
   160 }
   161 
   162 IMenuPanel *CRadioStyle::CreatePanel()
   163 {
   164 	return g_RadioMenuStyle.MakeRadioDisplay();
   165 }
   166 
   167 IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
   168 {
   169 	return new CRadioMenu(pHandler, pOwner);
   170 }
   171 
   172 unsigned int CRadioStyle::GetMaxPageItems()
   173 {
   174 	return 10;
   175 }
   176 
   177 const char *CRadioStyle::GetStyleName()
   178 {
   179 	return "radio";
   180 }
   181 
   182 CBaseMenuPlayer *CRadioStyle::GetMenuPlayer(int client)
   183 {
   184 	return &m_players[client];
   185 }
   186 
   187 CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
   188 {
   189 	CRadioDisplay *display;
   190 	if (m_FreeDisplays.empty())
   191 	{
   192 		display = new CRadioDisplay();
   193 	} else {
   194 		display = m_FreeDisplays.front();
   195 		m_FreeDisplays.pop();
   196 		display->Reset();
   197 	}
   198 	return display;
   199 }
   200 
   201 void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
   202 {
   203 	m_FreeDisplays.push(display);
   204 }
   205 
   206 CRadioDisplay::CRadioDisplay()
   207 {
   208 	Reset();
   209 }
   210 
   211 CRadioDisplay::CRadioDisplay(CRadioMenu *menu)
   212 {
   213 	Reset();
   214 }
   215 
   216 bool CRadioDisplay::DrawRawLine(const char *rawline)
   217 {
   218 	m_BufferText.append(rawline);
   219 	m_BufferText.append("\n");
   220 	return true;
   221 }
   222 
   223 void CRadioDisplay::Reset()
   224 {
   225 	m_BufferText.assign("");
   226 	m_Title.assign("");
   227 	m_NextPos = 1;
   228 	keys = 0;
   229 }
   230 
   231 unsigned int CRadioDisplay::GetCurrentKey()
   232 {
   233 	return m_NextPos;
   234 }
   235 
   236 bool CRadioDisplay::SetCurrentKey(unsigned int key)
   237 {
   238 	if (key < m_NextPos || m_NextPos > 10)
   239 	{
   240 		return false;
   241 	}
   242 
   243 	m_NextPos = key;
   244 
   245 	return true;
   246 }
   247 
   248 bool CRadioDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
   249 {
   250 	return g_RadioMenuStyle.DoClientMenu(client, this, handler, time);
   251 }
   252 
   253 bool CRadioDisplay::SetExtOption(MenuOption option, const void *valuePtr)
   254 {
   255 	return false;
   256 }
   257 
   258 IMenuStyle *CRadioDisplay::GetParentStyle()
   259 {
   260 	return &g_RadioMenuStyle;
   261 }
   262 
   263 void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
   264 {
   265 	if (m_Title.size() != 0 && onlyIfEmpty)
   266 	{
   267 		return;
   268 	}
   269 	m_Title.assign(text);
   270 }
   271 
   272 unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
   273 {
   274 	if (m_NextPos > 10 || !CanDrawItem(item.style))
   275 	{
   276 		return 0;
   277 	}
   278 
   279 	if (item.style & ITEMDRAW_RAWLINE)
   280 	{
   281 		if (item.style & ITEMDRAW_SPACER)
   282 		{
   283 			m_BufferText.append(" \n");
   284 		} else {
   285 			m_BufferText.append(item.display);
   286 			m_BufferText.append("\n");
   287 		}
   288 		return 0;
   289 	} else if (item.style & ITEMDRAW_SPACER) {
   290 		m_BufferText.append(" \n");
   291 		return m_NextPos++;
   292 	} else if (item.style & ITEMDRAW_NOTEXT) {
   293 		return m_NextPos++;
   294 	}
   295 
   296 	if (item.style & ITEMDRAW_DISABLED)
   297 	{
   298 		m_BufferText.append(g_RadioNumTable[m_NextPos]);
   299 		m_BufferText.append(item.display);
   300 		m_BufferText.append("\n");
   301 	} else {
   302 		m_BufferText.append("->");
   303 		m_BufferText.append(g_RadioNumTable[m_NextPos]);
   304 		m_BufferText.append(item.display);
   305 		m_BufferText.append("\n");
   306 		keys |= (1<<(m_NextPos-1));
   307 	}
   308 
   309 	return m_NextPos++;
   310 }
   311 
   312 bool CRadioDisplay::CanDrawItem(unsigned int drawFlags)
   313 {
   314 	if ((drawFlags & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
   315 	{
   316 		return false;
   317 	}
   318 
   319 	if ((drawFlags & ITEMDRAW_DISABLED) && (drawFlags & ITEMDRAW_CONTROL))
   320 	{
   321 		return false;
   322 	}
   323 
   324 	return true;
   325 }
   326 
   327 void CRadioDisplay::SendRawDisplay(int client, unsigned int time)
   328 {
   329 	char buffer[4096];
   330 	size_t len;
   331 
   332 	len = UTIL_Format(buffer, sizeof(buffer), "%s\n%s", m_Title.c_str(), m_BufferText.c_str());
   333 
   334 	cell_t players[1] = {client};
   335 
   336 	int _sel_keys = (keys == 0) ? (1<<9) : keys;
   337 
   338 	char *ptr = buffer;
   339 	char save = 0;
   340 	while (true)
   341 	{
   342 		if (len > 240)
   343 		{
   344 			save = ptr[240];
   345 			ptr[240] = '\0';
   346 		}
   347 		bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
   348 		buffer->WriteWord(_sel_keys);
   349 		buffer->WriteChar(time ? time : -1);
   350 		buffer->WriteByte( (len > 240) ? 1 : 0 );
   351 		buffer->WriteString(ptr);
   352 		g_UserMsgs.EndMessage();
   353 		if (len > 240)
   354 		{
   355 			ptr[240] = save;
   356 			ptr = &ptr[240];
   357 			len -= 240;
   358 		} else {
   359 			break;
   360 		}
   361 	}
   362 }
   363 
   364 int CRadioDisplay::GetAmountRemaining()
   365 {
   366 	size_t amt = m_Title.size() + 1 + m_BufferText.size();
   367 	if (amt >= 511)
   368 	{
   369 		return 0;
   370 	}
   371 	return (int)(511 - amt);
   372 }
   373 
   374 void CRadioDisplay::DeleteThis()
   375 {
   376 	delete this;
   377 }
   378 
   379 bool CRadioDisplay::SetSelectableKeys(unsigned int keymap)
   380 {
   381 	keys = (signed)keymap;
   382 	return true;
   383 }
   384 
   385 CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : 
   386 CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
   387 {
   388 }
   389 
   390 bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
   391 {
   392 	return false;
   393 }
   394 
   395 IMenuPanel *CRadioMenu::CreatePanel()
   396 {
   397 	return g_RadioMenuStyle.MakeRadioDisplay(this);
   398 }
   399 
   400 bool CRadioMenu::Display(int client, unsigned int time, IMenuHandler *alt_handler)
   401 {
   402 #if defined MENU_DEBUG
   403 	g_Logger.LogMessage("[SM_MENU] CRadioMenu::Display(%p) (client %d) (time %d)",
   404 		this,
   405 		client,
   406 		time);
   407 #endif
   408 	if (m_bCancelling)
   409 	{
   410 		return false;
   411 	}
   412 
   413 	return g_RadioMenuStyle.DoClientMenu(client, this, alt_handler ? alt_handler : m_pHandler, time);
   414 }
   415 
   416 void CRadioMenu::Cancel_Finally()
   417 {
   418 	g_RadioMenuStyle.CancelMenu(this);
   419 }
   420 
   421 const char *g_RadioNumTable[11] = 
   422 {
   423 	"0. ", "1. ", "2. ", "3. ", "4. ", "5. ", "6. ", "7. ", "8. ", "9. ", "0. "
   424 };