core/MenuStyle_Radio.cpp
author Phong Dang <teame06@gmail.com>
Wed Aug 01 07:29:40 2007 +0000 (2007-08-01)
changeset 1241 2e8046793bc9
parent 1231 17badaf66ce4
child 1251 7f9d418693a8
permissions -rw-r--r--
Added check to make sure player are alive to perform sm_slap, sm_burn, sm_slay.
     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 
     9  * modify it under the terms of the GNU General Public License, 
    10  * version 3.0, as published by the Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16  *
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to 
    21  * link the code of this program (as well as its derivative works) to 
    22  * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
    23  * Game MODs that run on software by the Valve Corporation.  You must 
    24  * obey the GNU General Public License in all respects for all other 
    25  * code used. Additionally, AlliedModders LLC grants this exception 
    26  * to all derivative works. AlliedModders LLC defines further 
    27  * exceptions, found in LICENSE.txt (as of this writing, version 
    28  * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
    29  *
    30  * Version: $Id$
    31  */
    32 
    33 #include "MenuStyle_Radio.h"
    34 #include "sm_stringutil.h"
    35 #include "UserMessages.h"
    36 #include "GameConfigs.h"
    37 #include "PlayerManager.h"
    38 #if defined MENU_DEBUG
    39 #include "Logger.h"
    40 #endif
    41 
    42 extern const char *g_RadioNumTable[];
    43 CRadioStyle g_RadioMenuStyle;
    44 int g_ShowMenuId = -1;
    45 bool g_bRadioInit = false;
    46 
    47 CRadioStyle::CRadioStyle() : m_players(new CBaseMenuPlayer[256+1])
    48 {
    49 }
    50 
    51 void CRadioStyle::OnSourceModAllInitialized()
    52 {
    53 	g_Players.AddClientListener(this);
    54 }
    55 
    56 void CRadioStyle::OnSourceModLevelChange(const char *mapName)
    57 {
    58 	if (g_bRadioInit)
    59 	{
    60 		return;
    61 	}
    62 
    63 	g_bRadioInit = true;
    64 	const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
    65 	if (!msg || msg[0] == '\0')
    66 	{
    67 		return;
    68 	}
    69 
    70 	g_ShowMenuId = g_UserMsgs.GetMessageIndex(msg);
    71 
    72 	if (!IsSupported())
    73 	{
    74 		return;
    75 	}
    76 
    77 	g_Menus.AddStyle(this);
    78 	g_Menus.SetDefaultStyle(this);
    79 
    80 	g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
    81 }
    82 
    83 void CRadioStyle::OnSourceModShutdown()
    84 {
    85 	g_Players.RemoveClientListener(this);
    86 	g_UserMsgs.UnhookUserMessage(g_ShowMenuId, this, false);
    87 
    88 	while (!m_FreeDisplays.empty())
    89 	{
    90 		delete m_FreeDisplays.front();
    91 		m_FreeDisplays.pop();
    92 	}
    93 }
    94 
    95 bool CRadioStyle::IsSupported()
    96 {
    97 	return (g_ShowMenuId != -1);
    98 }
    99 
   100 bool CRadioStyle::OnClientCommand(int client)
   101 {
   102 	const char *cmd = engine->Cmd_Argv(0);
   103 
   104 	if (strcmp(cmd, "menuselect") == 0)
   105 	{
   106 		if (!m_players[client].bInMenu)
   107 		{
   108 			return false;
   109 		}
   110 
   111 		int arg = atoi(engine->Cmd_Argv(1));
   112 		ClientPressedKey(client, arg);
   113 		return true;
   114 	}
   115 
   116 	return false;
   117 }
   118 
   119 static unsigned int g_last_holdtime = 0;
   120 static unsigned int g_last_client_count = 0;
   121 static int g_last_clients[256];
   122 
   123 void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
   124 {
   125 	int count = pFilter->GetRecipientCount();
   126 	bf_read br(bf->GetBasePointer(), 2);
   127 
   128 	br.ReadWord();
   129 	int c = br.ReadChar();
   130 
   131 	g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
   132 
   133 	for (int i=0; i<count; i++)
   134 	{
   135 		g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
   136 	}
   137 }
   138 
   139 void CRadioStyle::OnUserMessageSent(int msg_id)
   140 {
   141 	for (unsigned int i=0; i<g_last_client_count; i++)
   142 	{
   143 		int client = g_last_clients[i];
   144 #if defined MENU_DEBUG
   145 		g_Logger.LogMessage("[SM_MENU] CRadioStyle got ShowMenu (client %d) (bInMenu %d)",
   146 			client,
   147 			m_players[client].bInExternMenu);
   148 #endif
   149 		if (m_players[client].bInMenu)
   150 		{
   151 			_CancelClientMenu(client, MenuCancel_Interrupted, true);
   152 		}
   153 		m_players[client].bInExternMenu = true;
   154 		m_players[client].menuHoldTime = g_last_holdtime;
   155 	}
   156 	g_last_client_count = 0;
   157 }
   158 
   159 void CRadioStyle::SendDisplay(int client, IMenuPanel *display)
   160 {
   161 	CRadioDisplay *rDisplay = (CRadioDisplay *)display;
   162 	rDisplay->SendRawDisplay(client, m_players[client].menuHoldTime);
   163 }
   164 
   165 IMenuPanel *CRadioStyle::CreatePanel()
   166 {
   167 	return g_RadioMenuStyle.MakeRadioDisplay();
   168 }
   169 
   170 IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
   171 {
   172 	return new CRadioMenu(pHandler, pOwner);
   173 }
   174 
   175 unsigned int CRadioStyle::GetMaxPageItems()
   176 {
   177 	return 10;
   178 }
   179 
   180 const char *CRadioStyle::GetStyleName()
   181 {
   182 	return "radio";
   183 }
   184 
   185 CBaseMenuPlayer *CRadioStyle::GetMenuPlayer(int client)
   186 {
   187 	return &m_players[client];
   188 }
   189 
   190 CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
   191 {
   192 	CRadioDisplay *display;
   193 	if (m_FreeDisplays.empty())
   194 	{
   195 		display = new CRadioDisplay();
   196 	} else {
   197 		display = m_FreeDisplays.front();
   198 		m_FreeDisplays.pop();
   199 		display->Reset();
   200 	}
   201 	return display;
   202 }
   203 
   204 void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
   205 {
   206 	m_FreeDisplays.push(display);
   207 }
   208 
   209 CRadioDisplay::CRadioDisplay()
   210 {
   211 	Reset();
   212 }
   213 
   214 CRadioDisplay::CRadioDisplay(CRadioMenu *menu)
   215 {
   216 	Reset();
   217 }
   218 
   219 bool CRadioDisplay::DrawRawLine(const char *rawline)
   220 {
   221 	m_BufferText.append(rawline);
   222 	m_BufferText.append("\n");
   223 	return true;
   224 }
   225 
   226 void CRadioDisplay::Reset()
   227 {
   228 	m_BufferText.assign("");
   229 	m_Title.assign("");
   230 	m_NextPos = 1;
   231 	keys = 0;
   232 }
   233 
   234 unsigned int CRadioDisplay::GetCurrentKey()
   235 {
   236 	return m_NextPos;
   237 }
   238 
   239 bool CRadioDisplay::SetCurrentKey(unsigned int key)
   240 {
   241 	if (key < m_NextPos || m_NextPos > 10)
   242 	{
   243 		return false;
   244 	}
   245 
   246 	m_NextPos = key;
   247 
   248 	return true;
   249 }
   250 
   251 bool CRadioDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
   252 {
   253 	return g_RadioMenuStyle.DoClientMenu(client, this, handler, time);
   254 }
   255 
   256 bool CRadioDisplay::SetExtOption(MenuOption option, const void *valuePtr)
   257 {
   258 	return false;
   259 }
   260 
   261 IMenuStyle *CRadioDisplay::GetParentStyle()
   262 {
   263 	return &g_RadioMenuStyle;
   264 }
   265 
   266 void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
   267 {
   268 	if (m_Title.size() != 0 && onlyIfEmpty)
   269 	{
   270 		return;
   271 	}
   272 	m_Title.assign(text);
   273 }
   274 
   275 unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
   276 {
   277 	if (m_NextPos > 10 || !CanDrawItem(item.style))
   278 	{
   279 		return 0;
   280 	}
   281 
   282 	if (item.style & ITEMDRAW_RAWLINE)
   283 	{
   284 		if (item.style & ITEMDRAW_SPACER)
   285 		{
   286 			m_BufferText.append(" \n");
   287 		} else {
   288 			m_BufferText.append(item.display);
   289 			m_BufferText.append("\n");
   290 		}
   291 		return 0;
   292 	} else if (item.style & ITEMDRAW_SPACER) {
   293 		m_BufferText.append(" \n");
   294 		return m_NextPos++;
   295 	} else if (item.style & ITEMDRAW_NOTEXT) {
   296 		return m_NextPos++;
   297 	}
   298 
   299 	if (item.style & ITEMDRAW_DISABLED)
   300 	{
   301 		m_BufferText.append(g_RadioNumTable[m_NextPos]);
   302 		m_BufferText.append(item.display);
   303 		m_BufferText.append("\n");
   304 	} else {
   305 		m_BufferText.append("->");
   306 		m_BufferText.append(g_RadioNumTable[m_NextPos]);
   307 		m_BufferText.append(item.display);
   308 		m_BufferText.append("\n");
   309 		keys |= (1<<(m_NextPos-1));
   310 	}
   311 
   312 	return m_NextPos++;
   313 }
   314 
   315 bool CRadioDisplay::CanDrawItem(unsigned int drawFlags)
   316 {
   317 	if ((drawFlags & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
   318 	{
   319 		return false;
   320 	}
   321 
   322 	if ((drawFlags & ITEMDRAW_DISABLED) && (drawFlags & ITEMDRAW_CONTROL))
   323 	{
   324 		return false;
   325 	}
   326 
   327 	return true;
   328 }
   329 
   330 void CRadioDisplay::SendRawDisplay(int client, unsigned int time)
   331 {
   332 	char buffer[4096];
   333 	size_t len;
   334 
   335 	len = UTIL_Format(buffer, sizeof(buffer), "%s\n%s", m_Title.c_str(), m_BufferText.c_str());
   336 
   337 	cell_t players[1] = {client};
   338 
   339 	int _sel_keys = (keys == 0) ? (1<<9) : keys;
   340 
   341 	char *ptr = buffer;
   342 	char save = 0;
   343 	while (true)
   344 	{
   345 		if (len > 240)
   346 		{
   347 			save = ptr[240];
   348 			ptr[240] = '\0';
   349 		}
   350 		bf_write *buffer = g_UserMsgs.StartMessage(g_ShowMenuId, players, 1, 0);
   351 		buffer->WriteWord(_sel_keys);
   352 		buffer->WriteChar(time ? time : -1);
   353 		buffer->WriteByte( (len > 240) ? 1 : 0 );
   354 		buffer->WriteString(ptr);
   355 		g_UserMsgs.EndMessage();
   356 		if (len > 240)
   357 		{
   358 			ptr[240] = save;
   359 			ptr = &ptr[240];
   360 			len -= 240;
   361 		} else {
   362 			break;
   363 		}
   364 	}
   365 }
   366 
   367 void CRadioDisplay::DeleteThis()
   368 {
   369 	delete this;
   370 }
   371 
   372 bool CRadioDisplay::SetSelectableKeys(unsigned int keymap)
   373 {
   374 	keys = (signed)keymap;
   375 	return true;
   376 }
   377 
   378 CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : 
   379 CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
   380 {
   381 }
   382 
   383 bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
   384 {
   385 	return false;
   386 }
   387 
   388 IMenuPanel *CRadioMenu::CreatePanel()
   389 {
   390 	return g_RadioMenuStyle.MakeRadioDisplay(this);
   391 }
   392 
   393 bool CRadioMenu::Display(int client, unsigned int time)
   394 {
   395 #if defined MENU_DEBUG
   396 	g_Logger.LogMessage("[SM_MENU] CRadioMenu::Display(%p) (client %d) (time %d)",
   397 		this,
   398 		client,
   399 		time);
   400 #endif
   401 	if (m_bCancelling)
   402 	{
   403 		return false;
   404 	}
   405 
   406 	return g_RadioMenuStyle.DoClientMenu(client, this, m_pHandler, time);
   407 }
   408 
   409 void CRadioMenu::VoteDisplay(int client, unsigned int maxTime)
   410 {
   411 #if defined MENU_DEBUG
   412 	g_Logger.LogMessage("[SM_MENU] CRadioMenu::VoteDisplay(%p) (client %d) (time %d)",
   413 		this,
   414 		client,
   415 		maxTime);
   416 #endif
   417 	if (m_bCancelling)
   418 	{
   419 		return;
   420 	}
   421 
   422 	g_RadioMenuStyle.DoClientMenu(client, this, m_pVoteHandler, maxTime);
   423 }
   424 
   425 void CRadioMenu::Cancel_Finally()
   426 {
   427 	g_RadioMenuStyle.CancelMenu(this);
   428 }
   429 
   430 const char *g_RadioNumTable[11] = 
   431 {
   432 	"0. ", "1. ", "2. ", "3. ", "4. ", "5. ", "6. ", "7. ", "8. ", "9. ", "0. "
   433 };