core/MenuStyle_Radio.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Tue Jan 22 23:18:27 2013 -0500 (2013-01-22)
changeset 3749 4dc3d723c490
parent 3743 a98686a77974
child 3855 d8ba5eddf543
permissions -rw-r--r--
Triggering build against new mac libprotobuf.
dvander@780
     1
/**
dvander@780
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@780
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@780
    28
 *
dvander@780
    29
 * Version: $Id$
dvander@780
    30
 */
dvander@780
    31
dvander@780
    32
#include "MenuStyle_Radio.h"
dvander@780
    33
#include "sm_stringutil.h"
dvander@780
    34
#include "UserMessages.h"
dvander@3010
    35
#include <IGameConfigs.h>
dvander@846
    36
#include "PlayerManager.h"
dvander@970
    37
#if defined MENU_DEBUG
dvander@970
    38
#include "Logger.h"
dvander@970
    39
#endif
dvander@3010
    40
#include "logic_bridge.h"
dvander@780
    41
skamonkey@3743
    42
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
    43
#include <google/protobuf/descriptor.h>
skamonkey@3743
    44
#endif
skamonkey@3743
    45
skamonkey@3743
    46
#if SOURCE_ENGINE == SE_CSGO
skamonkey@3743
    47
#include <game/shared/csgo/protobuf/cstrike15_usermessages.pb.h>
skamonkey@3743
    48
#endif
skamonkey@3743
    49
dvander@780
    50
extern const char *g_RadioNumTable[];
dvander@780
    51
CRadioStyle g_RadioMenuStyle;
dvander@780
    52
int g_ShowMenuId = -1;
dvander@785
    53
bool g_bRadioInit = false;
dvander@1695
    54
unsigned int g_RadioMenuTimeout = 0;
dvander@780
    55
skamonkey@3570
    56
// back, next, exit
skamonkey@3570
    57
#define MAX_PAGINATION_OPTIONS 3
skamonkey@3570
    58
skamonkey@3570
    59
#define MAX_MENUSLOT_KEYS 10
skamonkey@3570
    60
skamonkey@3570
    61
static unsigned int s_RadioMaxPageItems = MAX_MENUSLOT_KEYS;
skamonkey@3570
    62
skamonkey@3570
    63
dvander@1695
    64
CRadioStyle::CRadioStyle()
dvander@780
    65
{
dvander@1695
    66
	m_players = new CRadioMenuPlayer[256+1];
dvander@1695
    67
	for (size_t i = 0; i < 256+1; i++)
dvander@1695
    68
	{
dvander@1695
    69
		m_players[i].Radio_SetIndex(i);
dvander@1695
    70
	}
dvander@780
    71
}
dvander@780
    72
dvander@846
    73
void CRadioStyle::OnSourceModAllInitialized()
dvander@846
    74
{
dvander@846
    75
	g_Players.AddClientListener(this);
dvander@846
    76
}
dvander@846
    77
dvander@785
    78
void CRadioStyle::OnSourceModLevelChange(const char *mapName)
dvander@780
    79
{
dvander@785
    80
	if (g_bRadioInit)
dvander@785
    81
	{
dvander@785
    82
		return;
dvander@785
    83
	}
dvander@785
    84
dvander@785
    85
	g_bRadioInit = true;
dvander@780
    86
	const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
dvander@780
    87
	if (!msg || msg[0] == '\0')
dvander@780
    88
	{
dvander@780
    89
		return;
dvander@780
    90
	}
dvander@780
    91
dvander@780
    92
	g_ShowMenuId = g_UserMsgs.GetMessageIndex(msg);
dvander@780
    93
dvander@780
    94
	if (!IsSupported())
dvander@780
    95
	{
dvander@780
    96
		return;
dvander@780
    97
	}
dvander@780
    98
dvander@1695
    99
	const char *val = g_pGameConf->GetKeyValue("RadioMenuTimeout");
dvander@1695
   100
	if (val != NULL)
dvander@1695
   101
	{
dvander@1695
   102
		g_RadioMenuTimeout = atoi(val);
dvander@1695
   103
	}
dvander@1695
   104
	else
dvander@1695
   105
	{
dvander@1695
   106
		g_RadioMenuTimeout = 0;
dvander@1695
   107
	}
dvander@1695
   108
skamonkey@3570
   109
	const char *items = g_pGameConf->GetKeyValue("RadioMenuMaxPageItems");
skamonkey@3570
   110
	if (items != NULL)
skamonkey@3570
   111
	{
skamonkey@3570
   112
		int value = atoi(items);
skamonkey@3570
   113
skamonkey@3570
   114
		// Only override the mostly-safe default if it's a sane value
skamonkey@3570
   115
		if (value > MAX_PAGINATION_OPTIONS && value <= MAX_MENUSLOT_KEYS)
skamonkey@3570
   116
		{
skamonkey@3570
   117
			s_RadioMaxPageItems = value;
skamonkey@3570
   118
		}
skamonkey@3570
   119
	}
skamonkey@3570
   120
dvander@780
   121
	g_Menus.AddStyle(this);
dvander@780
   122
	g_Menus.SetDefaultStyle(this);
dvander@780
   123
dvander@780
   124
	g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
dvander@780
   125
}
dvander@780
   126
dvander@780
   127
void CRadioStyle::OnSourceModShutdown()
dvander@780
   128
{
dvander@846
   129
	g_Players.RemoveClientListener(this);
dvander@780
   130
	g_UserMsgs.UnhookUserMessage(g_ShowMenuId, this, false);
dvander@790
   131
dvander@790
   132
	while (!m_FreeDisplays.empty())
dvander@790
   133
	{
dvander@790
   134
		delete m_FreeDisplays.front();
dvander@790
   135
		m_FreeDisplays.pop();
dvander@790
   136
	}
dvander@780
   137
}
dvander@780
   138
dvander@780
   139
bool CRadioStyle::IsSupported()
dvander@780
   140
{
dvander@780
   141
	return (g_ShowMenuId != -1);
dvander@780
   142
}
dvander@780
   143
faluco@1541
   144
bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
dvander@780
   145
{
faluco@1541
   146
	if (strcmp(cmdname, "menuselect") == 0)
dvander@780
   147
	{
dvander@780
   148
		if (!m_players[client].bInMenu)
dvander@780
   149
		{
dvander@1838
   150
			m_players[client].bInExternMenu = false;
dvander@780
   151
			return false;
dvander@780
   152
		}
dvander@785
   153
faluco@1541
   154
		int arg = atoi(cmd.Arg(1));
dvander@780
   155
		ClientPressedKey(client, arg);
dvander@785
   156
		return true;
dvander@780
   157
	}
dvander@780
   158
dvander@780
   159
	return false;
dvander@780
   160
}
dvander@780
   161
dvander@780
   162
static unsigned int g_last_holdtime = 0;
dvander@780
   163
static unsigned int g_last_client_count = 0;
dvander@780
   164
static int g_last_clients[256];
dvander@780
   165
skamonkey@3743
   166
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   167
void CRadioStyle::OnUserMessage(int msg_id, protobuf::Message &msg, IRecipientFilter *pFilter)
skamonkey@3743
   168
#else
dvander@780
   169
void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
skamonkey@3743
   170
#endif
dvander@780
   171
{
dvander@780
   172
	int count = pFilter->GetRecipientCount();
skamonkey@3743
   173
skamonkey@3743
   174
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   175
	int c = ((CCSUsrMsg_ShowMenu &)msg).display_time();
skamonkey@3743
   176
#else
dvander@1838
   177
	bf_read br(bf->GetBasePointer(), 3);
dvander@780
   178
dvander@780
   179
	br.ReadWord();
dvander@780
   180
	int c = br.ReadChar();
skamonkey@3743
   181
#endif
dvander@780
   182
dvander@780
   183
	g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
dvander@780
   184
dvander@780
   185
	for (int i=0; i<count; i++)
dvander@780
   186
	{
dvander@780
   187
		g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
dvander@780
   188
	}
dvander@780
   189
}
dvander@780
   190
dvander@780
   191
void CRadioStyle::OnUserMessageSent(int msg_id)
dvander@780
   192
{
dvander@780
   193
	for (unsigned int i=0; i<g_last_client_count; i++)
dvander@780
   194
	{
dvander@780
   195
		int client = g_last_clients[i];
dvander@970
   196
#if defined MENU_DEBUG
dvander@970
   197
		g_Logger.LogMessage("[SM_MENU] CRadioStyle got ShowMenu (client %d) (bInMenu %d)",
dvander@970
   198
			client,
dvander@970
   199
			m_players[client].bInExternMenu);
dvander@970
   200
#endif
dvander@780
   201
		if (m_players[client].bInMenu)
dvander@780
   202
		{
dvander@1005
   203
			_CancelClientMenu(client, MenuCancel_Interrupted, true);
dvander@780
   204
		}
dvander@780
   205
		m_players[client].bInExternMenu = true;
dvander@780
   206
		m_players[client].menuHoldTime = g_last_holdtime;
dvander@780
   207
	}
dvander@780
   208
	g_last_client_count = 0;
dvander@780
   209
}
dvander@780
   210
dvander@787
   211
void CRadioStyle::SendDisplay(int client, IMenuPanel *display)
dvander@780
   212
{
dvander@780
   213
	CRadioDisplay *rDisplay = (CRadioDisplay *)display;
dvander@780
   214
	rDisplay->SendRawDisplay(client, m_players[client].menuHoldTime);
dvander@780
   215
}
dvander@780
   216
dvander@787
   217
IMenuPanel *CRadioStyle::CreatePanel()
dvander@780
   218
{
dvander@790
   219
	return g_RadioMenuStyle.MakeRadioDisplay();
dvander@780
   220
}
dvander@780
   221
dvander@790
   222
IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
dvander@780
   223
{
dvander@790
   224
	return new CRadioMenu(pHandler, pOwner);
dvander@780
   225
}
dvander@780
   226
dvander@780
   227
unsigned int CRadioStyle::GetMaxPageItems()
dvander@780
   228
{
skamonkey@3570
   229
	return s_RadioMaxPageItems;
dvander@780
   230
}
dvander@780
   231
dvander@780
   232
const char *CRadioStyle::GetStyleName()
dvander@780
   233
{
dvander@780
   234
	return "radio";
dvander@780
   235
}
dvander@780
   236
dvander@780
   237
CBaseMenuPlayer *CRadioStyle::GetMenuPlayer(int client)
dvander@780
   238
{
dvander@780
   239
	return &m_players[client];
dvander@780
   240
}
dvander@780
   241
dvander@790
   242
CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
dvander@790
   243
{
dvander@790
   244
	CRadioDisplay *display;
dvander@790
   245
	if (m_FreeDisplays.empty())
dvander@790
   246
	{
dvander@790
   247
		display = new CRadioDisplay();
dvander@1705
   248
	}
dvander@1705
   249
	else
dvander@1705
   250
	{
dvander@790
   251
		display = m_FreeDisplays.front();
dvander@790
   252
		m_FreeDisplays.pop();
dvander@790
   253
		display->Reset();
dvander@790
   254
	}
dvander@790
   255
	return display;
dvander@790
   256
}
dvander@790
   257
dvander@1705
   258
IMenuPanel *CRadioStyle::MakeRadioDisplay(const char *str, int keys)
dvander@1705
   259
{
dvander@1705
   260
	CRadioDisplay *pPanel = MakeRadioDisplay(NULL);
dvander@1705
   261
dvander@1705
   262
	pPanel->DirectSet(str, keys);
dvander@1705
   263
dvander@1705
   264
	return pPanel;
dvander@1705
   265
}
dvander@1705
   266
dvander@790
   267
void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
dvander@790
   268
{
dvander@790
   269
	m_FreeDisplays.push(display);
dvander@790
   270
}
dvander@790
   271
dvander@1695
   272
CRadioMenuPlayer *CRadioStyle::GetRadioMenuPlayer(int client)
dvander@1695
   273
{
dvander@1695
   274
	return &m_players[client];
dvander@1695
   275
}
dvander@1695
   276
dvander@1695
   277
void CRadioStyle::ProcessWatchList()
dvander@1695
   278
{
dvander@1695
   279
	if (!g_RadioMenuTimeout)
dvander@1695
   280
	{
dvander@1695
   281
		BaseMenuStyle::ProcessWatchList();
dvander@1695
   282
		return;
dvander@1695
   283
	}
dvander@1695
   284
dvander@1695
   285
	BaseMenuStyle::ProcessWatchList();
dvander@1695
   286
dvander@1695
   287
	CRadioMenuPlayer *pPlayer;
dvander@1695
   288
	unsigned int max_clients = g_Players.GetMaxClients();
dvander@1695
   289
	for (unsigned int i = 1; i <= max_clients; i++)
dvander@1695
   290
	{
dvander@1695
   291
		pPlayer = GetRadioMenuPlayer(i);
dvander@1695
   292
		if (!pPlayer->bInMenu || pPlayer->bInExternMenu)
dvander@1695
   293
		{
dvander@1695
   294
			continue;
dvander@1695
   295
		}
dvander@1695
   296
		if (pPlayer->Radio_NeedsRefresh())
dvander@1695
   297
		{
dvander@1695
   298
			pPlayer->Radio_Refresh();
dvander@1695
   299
		}
dvander@1695
   300
	}
dvander@1695
   301
}
dvander@1695
   302
dvander@1766
   303
unsigned int CRadioStyle::GetApproxMemUsage()
dvander@1766
   304
{
dvander@1766
   305
	return sizeof(CRadioStyle) + (sizeof(CRadioMenuPlayer) * 257);
dvander@1766
   306
}
dvander@1766
   307
dvander@780
   308
CRadioDisplay::CRadioDisplay()
dvander@780
   309
{
dvander@780
   310
	Reset();
dvander@780
   311
}
dvander@780
   312
dvander@780
   313
CRadioDisplay::CRadioDisplay(CRadioMenu *menu)
dvander@780
   314
{
dvander@780
   315
	Reset();
dvander@780
   316
}
dvander@780
   317
dvander@780
   318
bool CRadioDisplay::DrawRawLine(const char *rawline)
dvander@780
   319
{
dvander@780
   320
	m_BufferText.append(rawline);
dvander@780
   321
	m_BufferText.append("\n");
dvander@780
   322
	return true;
dvander@780
   323
}
dvander@780
   324
dvander@780
   325
void CRadioDisplay::Reset()
dvander@780
   326
{
dvander@780
   327
	m_BufferText.assign("");
dvander@780
   328
	m_Title.assign("");
dvander@780
   329
	m_NextPos = 1;
dvander@785
   330
	keys = 0;
dvander@780
   331
}
dvander@780
   332
dvander@1705
   333
void CRadioDisplay::DirectSet(const char *str, int keymap)
dvander@1705
   334
{
dvander@1705
   335
	m_Title.clear();
dvander@1705
   336
	m_BufferText.assign(str);
dvander@1705
   337
	keys = keymap;
dvander@1705
   338
}
dvander@1705
   339
dvander@840
   340
unsigned int CRadioDisplay::GetCurrentKey()
dvander@840
   341
{
dvander@840
   342
	return m_NextPos;
dvander@840
   343
}
dvander@840
   344
dvander@840
   345
bool CRadioDisplay::SetCurrentKey(unsigned int key)
dvander@840
   346
{
skamonkey@3570
   347
	if (key < m_NextPos || m_NextPos > s_RadioMaxPageItems)
dvander@840
   348
	{
dvander@840
   349
		return false;
dvander@840
   350
	}
dvander@840
   351
dvander@840
   352
	m_NextPos = key;
dvander@840
   353
dvander@840
   354
	return true;
dvander@840
   355
}
dvander@840
   356
dvander@780
   357
bool CRadioDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
dvander@780
   358
{
dvander@780
   359
	return g_RadioMenuStyle.DoClientMenu(client, this, handler, time);
dvander@780
   360
}
dvander@780
   361
dvander@780
   362
bool CRadioDisplay::SetExtOption(MenuOption option, const void *valuePtr)
dvander@780
   363
{
dvander@780
   364
	return false;
dvander@780
   365
}
dvander@780
   366
dvander@780
   367
IMenuStyle *CRadioDisplay::GetParentStyle()
dvander@780
   368
{
dvander@780
   369
	return &g_RadioMenuStyle;
dvander@780
   370
}
dvander@780
   371
dvander@780
   372
void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
dvander@780
   373
{
dvander@780
   374
	if (m_Title.size() != 0 && onlyIfEmpty)
dvander@780
   375
	{
dvander@780
   376
		return;
dvander@780
   377
	}
dvander@780
   378
	m_Title.assign(text);
dvander@780
   379
}
dvander@780
   380
dvander@780
   381
unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
dvander@780
   382
{
skamonkey@3570
   383
	if (m_NextPos > s_RadioMaxPageItems || !CanDrawItem(item.style))
dvander@780
   384
	{
dvander@780
   385
		return 0;
dvander@780
   386
	}
dvander@780
   387
dvander@780
   388
	if (item.style & ITEMDRAW_RAWLINE)
dvander@780
   389
	{
dvander@780
   390
		if (item.style & ITEMDRAW_SPACER)
dvander@780
   391
		{
dvander@785
   392
			m_BufferText.append(" \n");
dvander@780
   393
		} else {
dvander@780
   394
			m_BufferText.append(item.display);
dvander@780
   395
			m_BufferText.append("\n");
dvander@780
   396
		}
dvander@780
   397
		return 0;
dvander@780
   398
	} else if (item.style & ITEMDRAW_SPACER) {
dvander@785
   399
		m_BufferText.append(" \n");
dvander@785
   400
		return m_NextPos++;
dvander@785
   401
	} else if (item.style & ITEMDRAW_NOTEXT) {
dvander@780
   402
		return m_NextPos++;
dvander@780
   403
	}
dvander@780
   404
dvander@780
   405
	if (item.style & ITEMDRAW_DISABLED)
dvander@780
   406
	{
dvander@780
   407
		m_BufferText.append(g_RadioNumTable[m_NextPos]);
dvander@780
   408
		m_BufferText.append(item.display);
dvander@780
   409
		m_BufferText.append("\n");
dvander@780
   410
	} else {
dvander@785
   411
		m_BufferText.append("->");
dvander@785
   412
		m_BufferText.append(g_RadioNumTable[m_NextPos]);
dvander@780
   413
		m_BufferText.append(item.display);
dvander@780
   414
		m_BufferText.append("\n");
dvander@780
   415
		keys |= (1<<(m_NextPos-1));
dvander@780
   416
	}
dvander@780
   417
dvander@780
   418
	return m_NextPos++;
dvander@780
   419
}
dvander@780
   420
dvander@780
   421
bool CRadioDisplay::CanDrawItem(unsigned int drawFlags)
dvander@780
   422
{
dvander@780
   423
	if ((drawFlags & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
dvander@780
   424
	{
dvander@780
   425
		return false;
dvander@780
   426
	}
dvander@780
   427
dvander@785
   428
	if ((drawFlags & ITEMDRAW_DISABLED) && (drawFlags & ITEMDRAW_CONTROL))
dvander@785
   429
	{
dvander@785
   430
		return false;
dvander@785
   431
	}
dvander@785
   432
dvander@780
   433
	return true;
dvander@780
   434
}
dvander@780
   435
dvander@780
   436
void CRadioDisplay::SendRawDisplay(int client, unsigned int time)
dvander@780
   437
{
dvander@1695
   438
	int _sel_keys = (keys == 0) ? (1<<9) : keys;
dvander@1695
   439
	CRadioMenuPlayer *pPlayer = g_RadioMenuStyle.GetRadioMenuPlayer(client);
dvander@1695
   440
	pPlayer->Radio_Init(_sel_keys, m_Title.c_str(), m_BufferText.c_str());
dvander@1695
   441
	pPlayer->Radio_Refresh();
dvander@1695
   442
}
dvander@780
   443
dvander@1695
   444
void CRadioMenuPlayer::Radio_SetIndex(unsigned int index)
dvander@1695
   445
{
dvander@1695
   446
	m_index = index;
dvander@1695
   447
}
dvander@1695
   448
dvander@1695
   449
bool CRadioMenuPlayer::Radio_NeedsRefresh()
dvander@1695
   450
{
dvander@1695
   451
	return (gpGlobals->curtime - display_last_refresh >= g_RadioMenuTimeout);
dvander@1695
   452
}
dvander@780
   453
dvander@1695
   454
void CRadioMenuPlayer::Radio_Init(int keys, const char *title, const char *text)
dvander@1695
   455
{
dvander@1705
   456
	if (title[0] != '\0')
dvander@1705
   457
	{
dvander@1705
   458
		display_len = UTIL_Format(display_pkt, 
dvander@1705
   459
			sizeof(display_pkt), 
dvander@1705
   460
			"%s\n%s", 
dvander@1705
   461
			title,
dvander@1705
   462
			text);
dvander@1705
   463
	}
dvander@1705
   464
	else
dvander@1705
   465
	{
dvander@1705
   466
		display_len = UTIL_Format(display_pkt, 
dvander@1705
   467
			sizeof(display_pkt), 
dvander@1705
   468
			"%s", 
dvander@1705
   469
			text);
dvander@1705
   470
	}
dvander@1695
   471
	display_keys = keys;
dvander@1695
   472
}
dvander@780
   473
dvander@1695
   474
void CRadioMenuPlayer::Radio_Refresh()
dvander@1695
   475
{
dvander@1695
   476
	cell_t players[1] = {m_index};
dvander@1695
   477
	char *ptr = display_pkt;
dvander@1695
   478
	char save = 0;
dvander@1695
   479
	size_t len = display_len;
dvander@1695
   480
	unsigned int time;
dvander@819
   481
dvander@1695
   482
	/* Compute the new time */
dvander@1695
   483
	if (menuHoldTime == 0)
dvander@1695
   484
	{
dvander@1695
   485
		time = 0;
dvander@1695
   486
	}
dvander@1695
   487
	else
dvander@1695
   488
	{
dvander@1695
   489
		time = menuHoldTime - (unsigned int)(gpGlobals->curtime - menuStartTime);
dvander@1695
   490
	}
dvander@1695
   491
skamonkey@3743
   492
#ifdef USE_PROTOBUF_USERMESSAGES
skamonkey@3743
   493
	// If or when we need to support multiple games per engine with this, we can switch to reflection
skamonkey@3743
   494
	// TODO: find what happens past 240 on CS:GO
skamonkey@3743
   495
	CCSUsrMsg_ShowMenu *msg = (CCSUsrMsg_ShowMenu *)g_UserMsgs.StartProtobufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
skamonkey@3743
   496
	msg->set_bits_valid_slots(display_keys);
skamonkey@3743
   497
	msg->set_display_time(time);
skamonkey@3743
   498
	msg->set_menu_string(ptr);
skamonkey@3743
   499
	g_UserMsgs.EndMessage();
skamonkey@3743
   500
#else
dvander@780
   501
	while (true)
dvander@780
   502
	{
dvander@780
   503
		if (len > 240)
dvander@780
   504
		{
dvander@780
   505
			save = ptr[240];
dvander@780
   506
			ptr[240] = '\0';
dvander@780
   507
		}
skamonkey@3743
   508
skamonkey@3743
   509
		bf_write *buffer = g_UserMsgs.StartBitBufMessage(g_ShowMenuId, players, 1, USERMSG_BLOCKHOOKS);
dvander@1695
   510
		buffer->WriteWord(display_keys);
dvander@780
   511
		buffer->WriteChar(time ? time : -1);
dvander@780
   512
		buffer->WriteByte( (len > 240) ? 1 : 0 );
dvander@780
   513
		buffer->WriteString(ptr);
dvander@780
   514
		g_UserMsgs.EndMessage();
dvander@780
   515
		if (len > 240)
dvander@780
   516
		{
dvander@780
   517
			ptr[240] = save;
dvander@780
   518
			ptr = &ptr[240];
dvander@780
   519
			len -= 240;
dvander@1695
   520
		}
dvander@1695
   521
		else
dvander@1695
   522
		{
dvander@780
   523
			break;
dvander@780
   524
		}
dvander@780
   525
	}
skamonkey@3743
   526
#endif
dvander@1695
   527
dvander@1695
   528
	display_last_refresh = gpGlobals->curtime;
dvander@780
   529
}
dvander@780
   530
dvander@1361
   531
int CRadioDisplay::GetAmountRemaining()
dvander@1361
   532
{
dvander@1361
   533
	size_t amt = m_Title.size() + 1 + m_BufferText.size();
dvander@1361
   534
	if (amt >= 511)
dvander@1361
   535
	{
dvander@1361
   536
		return 0;
dvander@1361
   537
	}
dvander@1361
   538
	return (int)(511 - amt);
dvander@1361
   539
}
dvander@1361
   540
dvander@780
   541
void CRadioDisplay::DeleteThis()
dvander@780
   542
{
dvander@780
   543
	delete this;
dvander@780
   544
}
dvander@780
   545
dvander@819
   546
bool CRadioDisplay::SetSelectableKeys(unsigned int keymap)
dvander@819
   547
{
dvander@819
   548
	keys = (signed)keymap;
dvander@820
   549
	return true;
dvander@819
   550
}
dvander@819
   551
dvander@1766
   552
unsigned int CRadioDisplay::GetApproxMemUsage()
dvander@1766
   553
{
dvander@1766
   554
	return sizeof(CRadioDisplay)
dvander@1766
   555
		+ m_BufferText.size()
dvander@1766
   556
		+ m_Title.size();
dvander@1766
   557
}
dvander@1766
   558
dvander@790
   559
CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) : 
dvander@790
   560
CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
dvander@780
   561
{
skamonkey@3570
   562
	m_Pagination = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
dvander@780
   563
}
dvander@780
   564
dvander@780
   565
bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
dvander@780
   566
{
dvander@780
   567
	return false;
dvander@780
   568
}
dvander@780
   569
dvander@787
   570
IMenuPanel *CRadioMenu::CreatePanel()
dvander@780
   571
{
dvander@790
   572
	return g_RadioMenuStyle.MakeRadioDisplay(this);
dvander@780
   573
}
dvander@780
   574
dvander@1269
   575
bool CRadioMenu::Display(int client, unsigned int time, IMenuHandler *alt_handler)
dvander@780
   576
{
dvander@1474
   577
	return DisplayAtItem(client, time, 0, alt_handler);
dvander@1474
   578
}
dvander@1474
   579
dvander@1474
   580
bool CRadioMenu::DisplayAtItem(int client,
dvander@1474
   581
							   unsigned int time,
dvander@1474
   582
							   unsigned int start_item,
dvander@1474
   583
							   IMenuHandler *alt_handler)
dvander@1474
   584
{
dvander@970
   585
#if defined MENU_DEBUG
dvander@970
   586
	g_Logger.LogMessage("[SM_MENU] CRadioMenu::Display(%p) (client %d) (time %d)",
dvander@970
   587
		this,
dvander@970
   588
		client,
dvander@970
   589
		time);
dvander@970
   590
#endif
dvander@877
   591
	if (m_bCancelling)
dvander@877
   592
	{
dvander@877
   593
		return false;
dvander@877
   594
	}
dvander@877
   595
dvander@1474
   596
	return g_RadioMenuStyle.DoClientMenu(client,
dvander@1474
   597
		this,
dvander@1474
   598
		start_item,
dvander@1474
   599
		alt_handler ? alt_handler : m_pHandler, 
dvander@1474
   600
		time);
dvander@877
   601
}
dvander@877
   602
skamonkey@3570
   603
bool CRadioMenu::SetPagination(unsigned int itemsPerPage)
skamonkey@3570
   604
{
skamonkey@3570
   605
	const unsigned int maxPerPage = s_RadioMaxPageItems - MAX_PAGINATION_OPTIONS;
skamonkey@3570
   606
	if (itemsPerPage > maxPerPage)
skamonkey@3570
   607
	{
skamonkey@3570
   608
		return false;
skamonkey@3570
   609
	}
skamonkey@3570
   610
skamonkey@3570
   611
	return CBaseMenu::SetPagination(itemsPerPage);
skamonkey@3570
   612
}
skamonkey@3570
   613
dvander@780
   614
void CRadioMenu::Cancel_Finally()
dvander@780
   615
{
dvander@780
   616
	g_RadioMenuStyle.CancelMenu(this);
dvander@780
   617
}
dvander@780
   618
dvander@1766
   619
unsigned int CRadioMenu::GetApproxMemUsage()
dvander@1766
   620
{
dvander@1766
   621
	return sizeof(CRadioMenu) + GetBaseMemUsage();
dvander@1766
   622
}
dvander@1766
   623
dvander@780
   624
const char *g_RadioNumTable[11] = 
dvander@780
   625
{
dvander@785
   626
	"0. ", "1. ", "2. ", "3. ", "4. ", "5. ", "6. ", "7. ", "8. ", "9. ", "0. "
dvander@780
   627
};