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