atcprintf() is now fully re-entrant, meaning translations can be used from inside translations
3 * =============================================================================
5 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
6 * =============================================================================
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.
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
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/>.
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>.
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
41 extern const char *g_RadioNumTable[];
42 CRadioStyle g_RadioMenuStyle;
43 int g_ShowMenuId = -1;
44 bool g_bRadioInit = false;
46 CRadioStyle::CRadioStyle() : m_players(new CBaseMenuPlayer[256+1])
50 void CRadioStyle::OnSourceModAllInitialized()
52 g_Players.AddClientListener(this);
55 void CRadioStyle::OnSourceModLevelChange(const char *mapName)
63 const char *msg = g_pGameConf->GetKeyValue("HudRadioMenuMsg");
64 if (!msg || msg[0] == '\0')
69 g_ShowMenuId = g_UserMsgs.GetMessageIndex(msg);
76 g_Menus.AddStyle(this);
77 g_Menus.SetDefaultStyle(this);
79 g_UserMsgs.HookUserMessage(g_ShowMenuId, this, false);
82 void CRadioStyle::OnSourceModShutdown()
84 g_Players.RemoveClientListener(this);
85 g_UserMsgs.UnhookUserMessage(g_ShowMenuId, this, false);
87 while (!m_FreeDisplays.empty())
89 delete m_FreeDisplays.front();
94 bool CRadioStyle::IsSupported()
96 return (g_ShowMenuId != -1);
99 bool CRadioStyle::OnClientCommand(int client, const char *cmdname, const CCommand &cmd)
101 if (strcmp(cmdname, "menuselect") == 0)
103 if (!m_players[client].bInMenu)
108 int arg = atoi(cmd.Arg(1));
109 ClientPressedKey(client, arg);
116 static unsigned int g_last_holdtime = 0;
117 static unsigned int g_last_client_count = 0;
118 static int g_last_clients[256];
120 void CRadioStyle::OnUserMessage(int msg_id, bf_write *bf, IRecipientFilter *pFilter)
122 int count = pFilter->GetRecipientCount();
123 bf_read br(bf->GetBasePointer(), 2);
126 int c = br.ReadChar();
128 g_last_holdtime = (c == -1) ? 0 : (unsigned)c;
130 for (int i=0; i<count; i++)
132 g_last_clients[g_last_client_count++] = pFilter->GetRecipientIndex(i);
136 void CRadioStyle::OnUserMessageSent(int msg_id)
138 for (unsigned int i=0; i<g_last_client_count; i++)
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)",
144 m_players[client].bInExternMenu);
146 if (m_players[client].bInMenu)
148 _CancelClientMenu(client, MenuCancel_Interrupted, true);
150 m_players[client].bInExternMenu = true;
151 m_players[client].menuHoldTime = g_last_holdtime;
153 g_last_client_count = 0;
156 void CRadioStyle::SendDisplay(int client, IMenuPanel *display)
158 CRadioDisplay *rDisplay = (CRadioDisplay *)display;
159 rDisplay->SendRawDisplay(client, m_players[client].menuHoldTime);
162 IMenuPanel *CRadioStyle::CreatePanel()
164 return g_RadioMenuStyle.MakeRadioDisplay();
167 IBaseMenu *CRadioStyle::CreateMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner)
169 return new CRadioMenu(pHandler, pOwner);
172 unsigned int CRadioStyle::GetMaxPageItems()
177 const char *CRadioStyle::GetStyleName()
182 CBaseMenuPlayer *CRadioStyle::GetMenuPlayer(int client)
184 return &m_players[client];
187 CRadioDisplay *CRadioStyle::MakeRadioDisplay(CRadioMenu *menu)
189 CRadioDisplay *display;
190 if (m_FreeDisplays.empty())
192 display = new CRadioDisplay();
194 display = m_FreeDisplays.front();
195 m_FreeDisplays.pop();
201 void CRadioStyle::FreeRadioDisplay(CRadioDisplay *display)
203 m_FreeDisplays.push(display);
206 CRadioDisplay::CRadioDisplay()
211 CRadioDisplay::CRadioDisplay(CRadioMenu *menu)
216 bool CRadioDisplay::DrawRawLine(const char *rawline)
218 m_BufferText.append(rawline);
219 m_BufferText.append("\n");
223 void CRadioDisplay::Reset()
225 m_BufferText.assign("");
231 unsigned int CRadioDisplay::GetCurrentKey()
236 bool CRadioDisplay::SetCurrentKey(unsigned int key)
238 if (key < m_NextPos || m_NextPos > 10)
248 bool CRadioDisplay::SendDisplay(int client, IMenuHandler *handler, unsigned int time)
250 return g_RadioMenuStyle.DoClientMenu(client, this, handler, time);
253 bool CRadioDisplay::SetExtOption(MenuOption option, const void *valuePtr)
258 IMenuStyle *CRadioDisplay::GetParentStyle()
260 return &g_RadioMenuStyle;
263 void CRadioDisplay::DrawTitle(const char *text, bool onlyIfEmpty/* =false */)
265 if (m_Title.size() != 0 && onlyIfEmpty)
269 m_Title.assign(text);
272 unsigned int CRadioDisplay::DrawItem(const ItemDrawInfo &item)
274 if (m_NextPos > 10 || !CanDrawItem(item.style))
279 if (item.style & ITEMDRAW_RAWLINE)
281 if (item.style & ITEMDRAW_SPACER)
283 m_BufferText.append(" \n");
285 m_BufferText.append(item.display);
286 m_BufferText.append("\n");
289 } else if (item.style & ITEMDRAW_SPACER) {
290 m_BufferText.append(" \n");
292 } else if (item.style & ITEMDRAW_NOTEXT) {
296 if (item.style & ITEMDRAW_DISABLED)
298 m_BufferText.append(g_RadioNumTable[m_NextPos]);
299 m_BufferText.append(item.display);
300 m_BufferText.append("\n");
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));
312 bool CRadioDisplay::CanDrawItem(unsigned int drawFlags)
314 if ((drawFlags & ITEMDRAW_IGNORE) == ITEMDRAW_IGNORE)
319 if ((drawFlags & ITEMDRAW_DISABLED) && (drawFlags & ITEMDRAW_CONTROL))
327 void CRadioDisplay::SendRawDisplay(int client, unsigned int time)
332 len = UTIL_Format(buffer, sizeof(buffer), "%s\n%s", m_Title.c_str(), m_BufferText.c_str());
334 cell_t players[1] = {client};
336 int _sel_keys = (keys == 0) ? (1<<9) : keys;
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();
364 int CRadioDisplay::GetAmountRemaining()
366 size_t amt = m_Title.size() + 1 + m_BufferText.size();
371 return (int)(511 - amt);
374 void CRadioDisplay::DeleteThis()
379 bool CRadioDisplay::SetSelectableKeys(unsigned int keymap)
381 keys = (signed)keymap;
385 CRadioMenu::CRadioMenu(IMenuHandler *pHandler, IdentityToken_t *pOwner) :
386 CBaseMenu(pHandler, &g_RadioMenuStyle, pOwner)
390 bool CRadioMenu::SetExtOption(MenuOption option, const void *valuePtr)
395 IMenuPanel *CRadioMenu::CreatePanel()
397 return g_RadioMenuStyle.MakeRadioDisplay(this);
400 bool CRadioMenu::Display(int client, unsigned int time, IMenuHandler *alt_handler)
402 return DisplayAtItem(client, time, 0, alt_handler);
405 bool CRadioMenu::DisplayAtItem(int client,
407 unsigned int start_item,
408 IMenuHandler *alt_handler)
410 #if defined MENU_DEBUG
411 g_Logger.LogMessage("[SM_MENU] CRadioMenu::Display(%p) (client %d) (time %d)",
421 return g_RadioMenuStyle.DoClientMenu(client,
424 alt_handler ? alt_handler : m_pHandler,
428 void CRadioMenu::Cancel_Finally()
430 g_RadioMenuStyle.CancelMenu(this);
433 const char *g_RadioNumTable[11] =
435 "0. ", "1. ", "2. ", "3. ", "4. ", "5. ", "6. ", "7. ", "8. ", "9. ", "0. "