2010-11-20 10:37:14 +00:00
|
|
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <base/math.h>
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2011-03-23 12:06:35 +00:00
|
|
|
#include <engine/config.h>
|
2010-08-09 12:14:15 +00:00
|
|
|
#include <engine/demo.h>
|
2011-03-23 12:06:35 +00:00
|
|
|
#include <engine/friends.h>
|
2017-09-09 15:04:19 +00:00
|
|
|
#include <engine/ghost.h>
|
2011-04-06 18:18:31 +00:00
|
|
|
#include <engine/graphics.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/serverbrowser.h>
|
|
|
|
#include <engine/textrender.h>
|
|
|
|
#include <engine/shared/config.h>
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/generated/protocol.h>
|
|
|
|
#include <game/generated/client_data.h>
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/localization.h>
|
2014-02-19 13:49:08 +00:00
|
|
|
#include <game/client/components/countryflags.h>
|
2011-03-22 21:41:27 +00:00
|
|
|
#include <game/client/animstate.h>
|
|
|
|
#include <game/client/gameclient.h>
|
|
|
|
#include <game/client/render.h>
|
|
|
|
#include <game/client/ui.h>
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "menus.h"
|
|
|
|
#include "motd.h"
|
|
|
|
#include "voting.h"
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2011-04-09 06:41:31 +00:00
|
|
|
#include <base/tl/string.h>
|
2011-02-04 17:25:04 +00:00
|
|
|
#include <engine/keys.h>
|
|
|
|
#include <engine/storage.h>
|
|
|
|
#include "ghost.h"
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CMenus::RenderGame(CUIRect MainView)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2011-04-06 18:18:31 +00:00
|
|
|
CUIRect Button, ButtonBar;
|
|
|
|
MainView.HSplitTop(45.0f, &ButtonBar, &MainView);
|
2019-03-24 22:15:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&ButtonBar, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-22 21:41:27 +00:00
|
|
|
// button bar
|
|
|
|
ButtonBar.HSplitTop(10.0f, 0, &ButtonBar);
|
|
|
|
ButtonBar.HSplitTop(25.0f, &ButtonBar, 0);
|
|
|
|
ButtonBar.VMargin(10.0f, &ButtonBar);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-22 21:41:27 +00:00
|
|
|
ButtonBar.VSplitRight(120.0f, &ButtonBar, &Button);
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_DisconnectButton = 0;
|
|
|
|
if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button))
|
2014-07-08 18:21:19 +00:00
|
|
|
{
|
2019-03-29 13:56:02 +00:00
|
|
|
if(Client()->GetCurrentRaceTime() / 60 >= g_Config.m_ClConfirmDisconnectTime && g_Config.m_ClConfirmDisconnectTime >= 0)
|
2019-03-25 19:02:50 +00:00
|
|
|
{
|
2014-07-10 14:50:59 +00:00
|
|
|
m_Popup = POPUP_DISCONNECT;
|
2019-03-25 19:02:50 +00:00
|
|
|
}
|
2014-07-10 14:50:59 +00:00
|
|
|
else
|
2019-03-25 19:02:50 +00:00
|
|
|
{
|
2014-07-10 14:50:59 +00:00
|
|
|
Client()->Disconnect();
|
2019-03-25 19:02:50 +00:00
|
|
|
}
|
2014-07-08 18:21:19 +00:00
|
|
|
}
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2015-04-19 12:24:20 +00:00
|
|
|
static int s_SpectateButton = 0;
|
2015-05-28 21:11:01 +00:00
|
|
|
static int s_JoinRedButton = 0;
|
|
|
|
static int s_JoinBlueButton = 0;
|
2015-04-19 12:40:05 +00:00
|
|
|
bool DummyConnecting = m_pClient->Client()->DummyConnecting();
|
2015-04-19 12:24:20 +00:00
|
|
|
|
2011-03-04 16:08:10 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pGameInfoObj)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2014-05-03 22:11:11 +00:00
|
|
|
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
|
2011-03-22 21:41:27 +00:00
|
|
|
ButtonBar.VSplitLeft(120.0f, &Button, &ButtonBar);
|
2015-04-19 12:40:05 +00:00
|
|
|
if(!DummyConnecting && DoButton_Menu(&s_SpectateButton, Localize("Spectate"), 0, &Button))
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2014-07-08 00:00:13 +00:00
|
|
|
if(g_Config.m_ClDummy == 0 || m_pClient->Client()->DummyConnected())
|
|
|
|
{
|
|
|
|
m_pClient->SendSwitchTeam(TEAM_SPECTATORS);
|
|
|
|
SetActive(false);
|
|
|
|
}
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-04 16:08:10 +00:00
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags & GAMEFLAG_TEAMS)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_RED)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2014-05-03 22:11:11 +00:00
|
|
|
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
|
2011-03-22 21:41:27 +00:00
|
|
|
ButtonBar.VSplitLeft(120.0f, &Button, &ButtonBar);
|
2015-05-28 21:11:01 +00:00
|
|
|
if(!DummyConnecting && DoButton_Menu(&s_JoinRedButton, Localize("Join red"), 0, &Button))
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
m_pClient->SendSwitchTeam(TEAM_RED);
|
2010-05-29 07:25:38 +00:00
|
|
|
SetActive(false);
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-03 11:50:38 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_BLUE)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2014-05-03 22:11:11 +00:00
|
|
|
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
|
2011-03-22 21:41:27 +00:00
|
|
|
ButtonBar.VSplitLeft(120.0f, &Button, &ButtonBar);
|
2015-05-28 21:11:01 +00:00
|
|
|
if(!DummyConnecting && DoButton_Menu(&s_JoinBlueButton, Localize("Join blue"), 0, &Button))
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2011-01-03 11:50:38 +00:00
|
|
|
m_pClient->SendSwitchTeam(TEAM_BLUE);
|
2010-05-29 07:25:38 +00:00
|
|
|
SetActive(false);
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_pClient->m_Snap.m_pLocalInfo->m_Team != 0)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2014-05-03 22:11:11 +00:00
|
|
|
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
|
2011-03-22 21:41:27 +00:00
|
|
|
ButtonBar.VSplitLeft(120.0f, &Button, &ButtonBar);
|
2015-04-19 12:40:05 +00:00
|
|
|
if(!DummyConnecting && DoButton_Menu(&s_SpectateButton, Localize("Join game"), 0, &Button))
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_pClient->SendSwitchTeam(0);
|
|
|
|
SetActive(false);
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-08-09 12:14:15 +00:00
|
|
|
|
2014-05-03 22:11:11 +00:00
|
|
|
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
|
2011-03-22 21:41:27 +00:00
|
|
|
ButtonBar.VSplitLeft(150.0f, &Button, &ButtonBar);
|
2010-08-09 12:14:15 +00:00
|
|
|
|
|
|
|
static int s_DemoButton = 0;
|
2014-10-16 15:42:13 +00:00
|
|
|
bool Recording = DemoRecorder(RECORDER_MANUAL)->IsRecording();
|
2020-06-26 16:17:20 +00:00
|
|
|
if(DoButton_Menu(&s_DemoButton, Recording ? Localize("Stop record") : Localize("Record demo"), 0, &Button))
|
2010-08-09 12:14:15 +00:00
|
|
|
{
|
|
|
|
if(!Recording)
|
2015-08-22 15:36:47 +00:00
|
|
|
Client()->DemoRecorder_Start(Client()->GetCurrentMap(), true, RECORDER_MANUAL);
|
2010-08-09 12:14:15 +00:00
|
|
|
else
|
2014-10-16 15:42:13 +00:00
|
|
|
Client()->DemoRecorder_Stop(RECORDER_MANUAL);
|
2010-08-09 12:14:15 +00:00
|
|
|
}
|
2014-04-26 18:29:42 +00:00
|
|
|
|
2014-05-03 22:11:11 +00:00
|
|
|
ButtonBar.VSplitLeft(5.0f, 0, &ButtonBar);
|
2014-04-26 18:29:42 +00:00
|
|
|
ButtonBar.VSplitLeft(170.0f, &Button, &ButtonBar);
|
|
|
|
|
|
|
|
static int s_DummyButton = 0;
|
2015-04-19 12:40:05 +00:00
|
|
|
if(DummyConnecting)
|
|
|
|
{
|
|
|
|
DoButton_Menu(&s_DummyButton, Localize("Connecting dummy"), 1, &Button);
|
|
|
|
}
|
2020-06-26 09:13:55 +00:00
|
|
|
else if(DoButton_Menu(&s_DummyButton, Client()->DummyConnected() ? Localize("Disconnect Dummy") : Localize("Connect Dummy"), 0, &Button))
|
2014-04-26 18:29:42 +00:00
|
|
|
{
|
|
|
|
if(!Client()->DummyConnected())
|
|
|
|
{
|
2014-04-28 13:19:57 +00:00
|
|
|
Client()->DummyConnect();
|
2014-04-26 18:29:42 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-03-29 13:56:02 +00:00
|
|
|
if(Client()->GetCurrentRaceTime() / 60 >= g_Config.m_ClConfirmDisconnectTime && g_Config.m_ClConfirmDisconnectTime >= 0)
|
2019-03-25 19:02:50 +00:00
|
|
|
{
|
2019-03-30 15:59:25 +00:00
|
|
|
m_Popup = POPUP_DISCONNECT_DUMMY;
|
2019-03-25 19:02:50 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Client()->DummyDisconnect(0);
|
|
|
|
}
|
2014-04-26 18:29:42 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-06 18:18:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMenus::RenderPlayers(CUIRect MainView)
|
|
|
|
{
|
2014-02-19 13:49:08 +00:00
|
|
|
CUIRect Button, Button2, ButtonBar, Options, Player;
|
2019-03-24 22:15:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
|
2011-03-22 21:41:27 +00:00
|
|
|
|
|
|
|
// player options
|
|
|
|
MainView.Margin(10.0f, &Options);
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&Options, ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
|
2011-03-22 21:41:27 +00:00
|
|
|
Options.Margin(10.0f, &Options);
|
|
|
|
Options.HSplitTop(50.0f, &Button, &Options);
|
|
|
|
UI()->DoLabelScaled(&Button, Localize("Player options"), 34.0f, -1);
|
|
|
|
|
2011-04-06 18:18:31 +00:00
|
|
|
// headline
|
|
|
|
Options.HSplitTop(34.0f, &ButtonBar, &Options);
|
2020-06-27 20:58:28 +00:00
|
|
|
ButtonBar.VSplitRight(231.0f, &Player, &ButtonBar);
|
2011-04-06 18:18:31 +00:00
|
|
|
UI()->DoLabelScaled(&Player, Localize("Player"), 24.0f, -1);
|
|
|
|
|
|
|
|
ButtonBar.HMargin(1.0f, &ButtonBar);
|
|
|
|
float Width = ButtonBar.h*2.0f;
|
|
|
|
ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GUIICONS].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
|
|
|
RenderTools()->SelectSprite(SPRITE_GUIICON_MUTE);
|
|
|
|
IGraphics::CQuadItem QuadItem(Button.x, Button.y, Button.w, Button.h);
|
|
|
|
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
|
2020-06-27 20:39:54 +00:00
|
|
|
ButtonBar.VSplitLeft(20.0f, 0, &ButtonBar);
|
2020-06-26 22:06:07 +00:00
|
|
|
ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GUIICONS].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
|
|
|
RenderTools()->SelectSprite(SPRITE_GUIICON_EMOTICON_MUTE);
|
|
|
|
QuadItem = IGraphics::CQuadItem(Button.x, Button.y, Button.w, Button.h);
|
|
|
|
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
|
2011-04-06 18:18:31 +00:00
|
|
|
ButtonBar.VSplitLeft(20.0f, 0, &ButtonBar);
|
|
|
|
ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GUIICONS].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
|
|
|
RenderTools()->SelectSprite(SPRITE_GUIICON_FRIEND);
|
|
|
|
QuadItem = IGraphics::CQuadItem(Button.x, Button.y, Button.w, Button.h);
|
|
|
|
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
|
2013-12-31 21:14:59 +00:00
|
|
|
int TotalPlayers = 0;
|
|
|
|
|
2014-01-10 12:55:31 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; ++i)
|
2013-12-31 21:14:59 +00:00
|
|
|
{
|
2014-09-23 07:52:18 +00:00
|
|
|
if(!m_pClient->m_Snap.m_paInfoByName[i])
|
2013-12-31 21:14:59 +00:00
|
|
|
continue;
|
|
|
|
|
2014-09-23 07:52:18 +00:00
|
|
|
int Index = m_pClient->m_Snap.m_paInfoByName[i]->m_ClientID;
|
2013-12-31 21:14:59 +00:00
|
|
|
|
|
|
|
if(Index == m_pClient->m_Snap.m_LocalClientID)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
TotalPlayers++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int s_VoteList = 0;
|
|
|
|
static float s_ScrollValue = 0;
|
|
|
|
CUIRect List = Options;
|
|
|
|
//List.HSplitTop(28.0f, 0, &List);
|
|
|
|
UiDoListboxStart(&s_VoteList, &List, 24.0f, "", "", TotalPlayers, 1, -1, s_ScrollValue);
|
|
|
|
|
2011-04-06 18:18:31 +00:00
|
|
|
// options
|
2020-06-26 22:06:07 +00:00
|
|
|
static int s_aPlayerIDs[MAX_CLIENTS][3] = {{0}};
|
2013-12-31 21:14:59 +00:00
|
|
|
|
2011-04-06 18:18:31 +00:00
|
|
|
for(int i = 0, Count = 0; i < MAX_CLIENTS; ++i)
|
2011-03-22 21:41:27 +00:00
|
|
|
{
|
2014-09-23 00:10:59 +00:00
|
|
|
if(!m_pClient->m_Snap.m_paInfoByName[i])
|
2011-08-04 21:43:39 +00:00
|
|
|
continue;
|
|
|
|
|
2014-09-23 00:10:59 +00:00
|
|
|
int Index = m_pClient->m_Snap.m_paInfoByName[i]->m_ClientID;
|
2013-12-31 21:14:59 +00:00
|
|
|
|
2011-08-04 21:43:39 +00:00
|
|
|
if(Index == m_pClient->m_Snap.m_LocalClientID)
|
2011-03-22 21:41:27 +00:00
|
|
|
continue;
|
|
|
|
|
2014-02-02 20:06:05 +00:00
|
|
|
CListboxItem Item = UiDoListboxNextItem(&m_pClient->m_aClients[Index]);
|
|
|
|
|
2013-12-31 21:14:59 +00:00
|
|
|
Count++;
|
|
|
|
|
|
|
|
if(!Item.m_Visible)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if(Count%2 == 1)
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&Item.m_Rect, ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 10.0f);
|
2014-02-19 13:49:08 +00:00
|
|
|
Item.m_Rect.VSplitRight(300.0f, &Player, &Item.m_Rect);
|
2011-03-22 21:41:27 +00:00
|
|
|
|
|
|
|
// player info
|
2011-03-28 19:10:37 +00:00
|
|
|
Player.VSplitLeft(28.0f, &Button, &Player);
|
2011-08-04 21:43:39 +00:00
|
|
|
CTeeRenderInfo Info = m_pClient->m_aClients[Index].m_RenderInfo;
|
2011-03-22 21:41:27 +00:00
|
|
|
Info.m_Size = Button.h;
|
|
|
|
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1.0f, 0.0f), vec2(Button.x+Button.h/2, Button.y+Button.h/2));
|
|
|
|
|
|
|
|
Player.HSplitTop(1.5f, 0, &Player);
|
|
|
|
Player.VSplitMid(&Player, &Button);
|
2014-02-19 13:49:08 +00:00
|
|
|
Item.m_Rect.VSplitRight(200.0f, &Button2, &Item.m_Rect);
|
2011-03-22 21:41:27 +00:00
|
|
|
CTextCursor Cursor;
|
2018-04-04 00:40:30 +00:00
|
|
|
TextRender()->SetCursor(&Cursor, Player.x, Player.y + (Player.h - 14.f) / 2.f, 14.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
2011-03-22 21:41:27 +00:00
|
|
|
Cursor.m_LineWidth = Player.w;
|
2011-08-04 21:43:39 +00:00
|
|
|
TextRender()->TextEx(&Cursor, m_pClient->m_aClients[Index].m_aName, -1);
|
2011-03-22 21:41:27 +00:00
|
|
|
|
2018-04-04 00:40:30 +00:00
|
|
|
TextRender()->SetCursor(&Cursor, Button.x,Button.y + (Button.h - 14.f) / 2.f, 14.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
2011-03-22 21:41:27 +00:00
|
|
|
Cursor.m_LineWidth = Button.w;
|
2011-08-04 21:43:39 +00:00
|
|
|
TextRender()->TextEx(&Cursor, m_pClient->m_aClients[Index].m_aClan, -1);
|
2011-03-22 21:41:27 +00:00
|
|
|
|
2014-02-19 13:49:08 +00:00
|
|
|
//TextRender()->SetCursor(&Cursor, Button2.x,Button2.y, 14.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
|
|
|
//Cursor.m_LineWidth = Button.w;
|
2019-04-26 21:47:34 +00:00
|
|
|
ColorRGBA Color(1.0f, 1.0f, 1.0f, 0.5f);
|
2014-02-19 13:49:08 +00:00
|
|
|
m_pClient->m_pCountryFlags->Render(m_pClient->m_aClients[Index].m_Country, &Color,
|
|
|
|
Button2.x, Button2.y + Button2.h/2.0f - 0.75*Button2.h/2.0f, 1.5f*Button2.h, 0.75f*Button2.h);
|
|
|
|
|
2020-06-26 22:06:07 +00:00
|
|
|
// ignore chat button
|
2014-02-02 20:06:05 +00:00
|
|
|
Item.m_Rect.HMargin(2.0f, &Item.m_Rect);
|
|
|
|
Item.m_Rect.VSplitLeft(Width, &Button, &Item.m_Rect);
|
2011-04-06 18:18:31 +00:00
|
|
|
Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button);
|
|
|
|
Button.VSplitLeft(Button.h, &Button, 0);
|
2013-11-14 15:23:15 +00:00
|
|
|
if(g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[Index].m_Friend)
|
2012-01-10 22:03:23 +00:00
|
|
|
DoButton_Toggle(&s_aPlayerIDs[Index][0], 1, &Button, false);
|
|
|
|
else
|
|
|
|
if(DoButton_Toggle(&s_aPlayerIDs[Index][0], m_pClient->m_aClients[Index].m_ChatIgnore, &Button, true))
|
|
|
|
m_pClient->m_aClients[Index].m_ChatIgnore ^= 1;
|
2011-03-23 12:06:35 +00:00
|
|
|
|
2020-06-26 22:06:07 +00:00
|
|
|
// ignore emoticon button
|
|
|
|
Item.m_Rect.VSplitLeft(20.0f, &Button, &Item.m_Rect);
|
|
|
|
Item.m_Rect.VSplitLeft(Width, &Button, &Item.m_Rect);
|
|
|
|
Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button);
|
|
|
|
Button.VSplitLeft(Button.h, &Button, 0);
|
|
|
|
if(g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[Index].m_Friend)
|
|
|
|
DoButton_Toggle(&s_aPlayerIDs[Index][1], 1, &Button, false);
|
|
|
|
else
|
|
|
|
if(DoButton_Toggle(&s_aPlayerIDs[Index][1], m_pClient->m_aClients[Index].m_EmoticonIgnore, &Button, true))
|
|
|
|
m_pClient->m_aClients[Index].m_EmoticonIgnore ^= 1;
|
|
|
|
|
2011-03-23 12:06:35 +00:00
|
|
|
// friend button
|
2014-02-02 20:06:05 +00:00
|
|
|
Item.m_Rect.VSplitLeft(20.0f, &Button, &Item.m_Rect);
|
|
|
|
Item.m_Rect.VSplitLeft(Width, &Button, &Item.m_Rect);
|
2011-04-06 18:18:31 +00:00
|
|
|
Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button);
|
|
|
|
Button.VSplitLeft(Button.h, &Button, 0);
|
2020-06-26 22:06:07 +00:00
|
|
|
if(DoButton_Toggle(&s_aPlayerIDs[Index][2], m_pClient->m_aClients[Index].m_Friend, &Button, true))
|
2011-05-04 23:43:27 +00:00
|
|
|
{
|
2011-08-04 21:43:39 +00:00
|
|
|
if(m_pClient->m_aClients[Index].m_Friend)
|
|
|
|
m_pClient->Friends()->RemoveFriend(m_pClient->m_aClients[Index].m_aName, m_pClient->m_aClients[Index].m_aClan);
|
2011-04-06 18:18:31 +00:00
|
|
|
else
|
2011-08-04 21:43:39 +00:00
|
|
|
m_pClient->Friends()->AddFriend(m_pClient->m_aClients[Index].m_aName, m_pClient->m_aClients[Index].m_aClan);
|
2011-05-04 23:43:27 +00:00
|
|
|
}
|
2011-03-22 21:41:27 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2014-01-10 12:55:31 +00:00
|
|
|
UiDoListboxEnd(&s_ScrollValue, 0);
|
2008-09-29 11:34:49 +00:00
|
|
|
/*
|
2009-10-27 14:38:53 +00:00
|
|
|
CUIRect bars;
|
|
|
|
votearea.HSplitTop(10.0f, 0, &votearea);
|
|
|
|
votearea.HSplitTop(25.0f + 10.0f*3 + 25.0f, &votearea, &bars);
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2011-02-11 06:00:12 +00:00
|
|
|
RenderTools()->DrawUIRect(&votearea, color_tabbar_active, CUI::CORNER_ALL, 10.0f);
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
votearea.VMargin(20.0f, &votearea);
|
|
|
|
votearea.HMargin(10.0f, &votearea);
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2009-10-27 14:38:53 +00:00
|
|
|
votearea.HSplitBottom(35.0f, &votearea, &bars);
|
2008-09-29 11:34:49 +00:00
|
|
|
|
|
|
|
if(gameclient.voting->is_voting())
|
|
|
|
{
|
|
|
|
// do yes button
|
2009-10-27 14:38:53 +00:00
|
|
|
votearea.VSplitLeft(50.0f, &button, &votearea);
|
2008-09-29 11:34:49 +00:00
|
|
|
static int yes_button = 0;
|
2009-10-27 14:38:53 +00:00
|
|
|
if(UI()->DoButton(&yes_button, "Yes", 0, &button, ui_draw_menu_button, 0))
|
2008-09-29 11:34:49 +00:00
|
|
|
gameclient.voting->vote(1);
|
|
|
|
|
|
|
|
// do no button
|
2009-10-27 14:38:53 +00:00
|
|
|
votearea.VSplitLeft(5.0f, 0, &votearea);
|
|
|
|
votearea.VSplitLeft(50.0f, &button, &votearea);
|
2008-09-29 11:34:49 +00:00
|
|
|
static int no_button = 0;
|
2009-10-27 14:38:53 +00:00
|
|
|
if(UI()->DoButton(&no_button, "No", 0, &button, ui_draw_menu_button, 0))
|
2008-09-29 11:34:49 +00:00
|
|
|
gameclient.voting->vote(-1);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
// do time left
|
2009-10-27 14:38:53 +00:00
|
|
|
votearea.VSplitRight(50.0f, &votearea, &button);
|
2008-09-29 11:34:49 +00:00
|
|
|
char buf[256];
|
|
|
|
str_format(buf, sizeof(buf), "%d", gameclient.voting->seconds_left());
|
2009-10-27 14:38:53 +00:00
|
|
|
UI()->DoLabel(&button, buf, 24.0f, 0);
|
2008-09-29 11:34:49 +00:00
|
|
|
|
|
|
|
// do description and command
|
2009-10-27 14:38:53 +00:00
|
|
|
votearea.VSplitLeft(5.0f, 0, &votearea);
|
|
|
|
UI()->DoLabel(&votearea, gameclient.voting->vote_description(), 14.0f, -1);
|
|
|
|
votearea.HSplitTop(16.0f, 0, &votearea);
|
|
|
|
UI()->DoLabel(&votearea, gameclient.voting->vote_command(), 10.0f, -1);
|
2008-09-29 11:34:49 +00:00
|
|
|
|
|
|
|
// do bars
|
2009-10-27 14:38:53 +00:00
|
|
|
bars.HSplitTop(10.0f, 0, &bars);
|
|
|
|
bars.HMargin(5.0f, &bars);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
gameclient.voting->render_bars(bars, true);
|
|
|
|
|
2011-04-13 18:37:12 +00:00
|
|
|
}
|
2008-09-29 11:34:49 +00:00
|
|
|
else
|
|
|
|
{
|
2009-10-27 14:38:53 +00:00
|
|
|
UI()->DoLabel(&votearea, "No vote in progress", 18.0f, -1);
|
2008-09-29 11:34:49 +00:00
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CMenus::RenderServerInfo(CUIRect MainView)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2011-03-13 10:14:35 +00:00
|
|
|
if(!m_pClient->m_Snap.m_pLocalInfo)
|
|
|
|
return;
|
|
|
|
|
2008-10-17 21:16:23 +00:00
|
|
|
// fetch server info
|
2010-05-29 07:25:38 +00:00
|
|
|
CServerInfo CurrentServerInfo;
|
|
|
|
Client()->GetServerInfo(&CurrentServerInfo);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
// render background
|
2019-03-24 22:15:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CUIRect View, ServerInfo, GameInfo, Motd;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
float x = 0.0f;
|
|
|
|
float y = 0.0f;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
char aBuf[1024];
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
// set view to use for all sub-modules
|
2010-05-29 07:25:38 +00:00
|
|
|
MainView.Margin(10.0f, &View);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// serverinfo
|
2010-12-14 00:20:47 +00:00
|
|
|
View.HSplitTop(View.h/2/UI()->Scale()-5.0f, &ServerInfo, &Motd);
|
|
|
|
ServerInfo.VSplitLeft(View.w/2/UI()->Scale()-5.0f, &ServerInfo, &GameInfo);
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&ServerInfo, ColorRGBA(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
ServerInfo.Margin(5.0f, &ServerInfo);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
x = 5.0f;
|
|
|
|
y = 0.0f;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 32, Localize("Server info"), 250);
|
2008-09-29 11:34:49 +00:00
|
|
|
y += 32.0f+5.0f;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
mem_zero(aBuf, sizeof(aBuf));
|
2008-09-29 11:34:49 +00:00
|
|
|
str_format(
|
2010-05-29 07:25:38 +00:00
|
|
|
aBuf,
|
|
|
|
sizeof(aBuf),
|
2008-09-29 11:34:49 +00:00
|
|
|
"%s\n\n"
|
2009-06-15 07:34:25 +00:00
|
|
|
"%s: %s\n"
|
|
|
|
"%s: %d\n"
|
|
|
|
"%s: %s\n"
|
|
|
|
"%s: %s\n",
|
2010-05-29 07:25:38 +00:00
|
|
|
CurrentServerInfo.m_aName,
|
2013-12-18 03:11:26 +00:00
|
|
|
Localize("Address"), CurrentServerInfo.m_aAddress,
|
2010-05-29 07:25:38 +00:00
|
|
|
Localize("Ping"), m_pClient->m_Snap.m_pLocalInfo->m_Latency,
|
|
|
|
Localize("Version"), CurrentServerInfo.m_aVersion,
|
|
|
|
Localize("Password"), CurrentServerInfo.m_Flags &1 ? Localize("Yes") : Localize("No")
|
2008-09-29 11:34:49 +00:00
|
|
|
);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
TextRender()->Text(0, ServerInfo.x+x, ServerInfo.y+y, 20, aBuf, 250);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CUIRect Button;
|
|
|
|
int IsFavorite = ServerBrowser()->IsFavorite(CurrentServerInfo.m_NetAddr);
|
|
|
|
ServerInfo.HSplitBottom(20.0f, &ServerInfo, &Button);
|
|
|
|
static int s_AddFavButton = 0;
|
|
|
|
if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), IsFavorite, &Button))
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(IsFavorite)
|
|
|
|
ServerBrowser()->RemoveFavorite(CurrentServerInfo.m_NetAddr);
|
2008-09-29 11:34:49 +00:00
|
|
|
else
|
2010-05-29 07:25:38 +00:00
|
|
|
ServerBrowser()->AddFavorite(CurrentServerInfo.m_NetAddr);
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// gameinfo
|
|
|
|
GameInfo.VSplitLeft(10.0f, 0x0, &GameInfo);
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&GameInfo, ColorRGBA(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
GameInfo.Margin(5.0f, &GameInfo);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
x = 5.0f;
|
|
|
|
y = 0.0f;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 32, Localize("Game info"), 250);
|
2008-09-29 11:34:49 +00:00
|
|
|
y += 32.0f+5.0f;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-04 16:08:10 +00:00
|
|
|
if(m_pClient->m_Snap.m_pGameInfoObj)
|
|
|
|
{
|
|
|
|
mem_zero(aBuf, sizeof(aBuf));
|
|
|
|
str_format(
|
|
|
|
aBuf,
|
|
|
|
sizeof(aBuf),
|
|
|
|
"\n\n"
|
|
|
|
"%s: %s\n"
|
|
|
|
"%s: %s\n"
|
|
|
|
"%s: %d\n"
|
|
|
|
"%s: %d\n"
|
|
|
|
"\n"
|
|
|
|
"%s: %d/%d\n",
|
|
|
|
Localize("Game type"), CurrentServerInfo.m_aGameType,
|
|
|
|
Localize("Map"), CurrentServerInfo.m_aMap,
|
|
|
|
Localize("Score limit"), m_pClient->m_Snap.m_pGameInfoObj->m_ScoreLimit,
|
|
|
|
Localize("Time limit"), m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit,
|
2011-03-20 14:33:49 +00:00
|
|
|
Localize("Players"), m_pClient->m_Snap.m_NumPlayers, CurrentServerInfo.m_MaxClients
|
2011-03-04 16:08:10 +00:00
|
|
|
);
|
|
|
|
TextRender()->Text(0, GameInfo.x+x, GameInfo.y+y, 20, aBuf, 250);
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// motd
|
|
|
|
Motd.HSplitTop(10.0f, 0, &Motd);
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&Motd, ColorRGBA(1,1,1,0.25f), CUI::CORNER_ALL, 10.0f);
|
2010-05-29 07:25:38 +00:00
|
|
|
Motd.Margin(5.0f, &Motd);
|
2008-09-29 11:34:49 +00:00
|
|
|
y = 0.0f;
|
|
|
|
x = 5.0f;
|
2010-05-29 07:25:38 +00:00
|
|
|
TextRender()->Text(0, Motd.x+x, Motd.y+y, 32, Localize("MOTD"), -1);
|
2008-09-29 11:34:49 +00:00
|
|
|
y += 32.0f+5.0f;
|
2010-05-29 07:25:38 +00:00
|
|
|
TextRender()->Text(0, Motd.x+x, Motd.y+y, 16, m_pClient->m_pMotd->m_aServerMotd, (int)Motd.w);
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
|
2016-04-27 18:04:31 +00:00
|
|
|
bool CMenus::RenderServerControlServer(CUIRect MainView)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_VoteList = 0;
|
|
|
|
static float s_ScrollValue = 0;
|
|
|
|
CUIRect List = MainView;
|
2015-04-02 23:27:07 +00:00
|
|
|
int Total = m_pClient->m_pVoting->m_NumVoteOptions;
|
2015-04-18 22:31:45 +00:00
|
|
|
int NumVoteOptions = 0;
|
2015-04-02 23:27:07 +00:00
|
|
|
int aIndices[MAX_VOTE_OPTIONS];
|
2015-03-14 14:32:04 +00:00
|
|
|
static int s_CurVoteOption = 0;
|
2015-07-25 16:43:54 +00:00
|
|
|
int TotalShown = 0;
|
|
|
|
|
|
|
|
for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext)
|
|
|
|
{
|
|
|
|
if(m_aFilterString[0] != '\0' && !str_find_nocase(pOption->m_aDescription, m_aFilterString))
|
|
|
|
continue;
|
|
|
|
TotalShown++;
|
|
|
|
}
|
2015-03-14 10:05:08 +00:00
|
|
|
|
2015-07-25 16:43:54 +00:00
|
|
|
UiDoListboxStart(&s_VoteList, &List, 24.0f, "", "", TotalShown, 1, s_CurVoteOption, s_ScrollValue);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2015-03-14 14:32:04 +00:00
|
|
|
int i = -1;
|
2011-03-26 16:44:34 +00:00
|
|
|
for(CVoteOptionClient *pOption = m_pClient->m_pVoting->m_pFirst; pOption; pOption = pOption->m_pNext)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2015-03-14 14:32:04 +00:00
|
|
|
i++;
|
2015-03-15 16:08:39 +00:00
|
|
|
if(m_aFilterString[0] != '\0' && !str_find_nocase(pOption->m_aDescription, m_aFilterString))
|
2015-03-13 15:44:05 +00:00
|
|
|
continue;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CListboxItem Item = UiDoListboxNextItem(pOption);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Item.m_Visible)
|
2011-03-25 09:26:59 +00:00
|
|
|
UI()->DoLabelScaled(&Item.m_Rect, pOption->m_aDescription, 16.0f, -1);
|
2015-03-14 10:05:08 +00:00
|
|
|
|
2015-03-14 14:32:04 +00:00
|
|
|
if(NumVoteOptions < Total)
|
|
|
|
aIndices[NumVoteOptions] = i;
|
|
|
|
NumVoteOptions++;
|
2008-10-06 18:05:01 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2016-04-27 18:04:31 +00:00
|
|
|
bool Call;
|
|
|
|
s_CurVoteOption = UiDoListboxEnd(&s_ScrollValue, &Call);
|
2015-03-14 14:32:04 +00:00
|
|
|
if(s_CurVoteOption < Total)
|
|
|
|
m_CallvoteSelectedOption = aIndices[s_CurVoteOption];
|
2016-04-27 18:04:31 +00:00
|
|
|
return Call;
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
|
2016-04-27 18:04:31 +00:00
|
|
|
bool CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-31 15:36:20 +00:00
|
|
|
int NumOptions = 0;
|
2010-05-31 20:05:45 +00:00
|
|
|
int Selected = -1;
|
|
|
|
static int aPlayerIDs[MAX_CLIENTS];
|
2010-05-31 15:36:20 +00:00
|
|
|
for(int i = 0; i < MAX_CLIENTS; i++)
|
|
|
|
{
|
2014-09-23 06:03:26 +00:00
|
|
|
if(!m_pClient->m_Snap.m_paInfoByName[i])
|
2010-05-31 15:36:20 +00:00
|
|
|
continue;
|
2011-08-11 08:59:14 +00:00
|
|
|
|
2014-09-23 06:03:26 +00:00
|
|
|
int Index = m_pClient->m_Snap.m_paInfoByName[i]->m_ClientID;
|
|
|
|
if(Index == m_pClient->m_Snap.m_LocalClientID || (FilterSpectators && m_pClient->m_Snap.m_paInfoByName[i]->m_Team == TEAM_SPECTATORS))
|
2010-05-31 15:36:20 +00:00
|
|
|
continue;
|
2015-03-14 10:05:08 +00:00
|
|
|
|
|
|
|
if(!str_find_nocase(m_pClient->m_aClients[Index].m_aName, m_aFilterString))
|
|
|
|
continue;
|
|
|
|
|
2011-08-04 21:43:39 +00:00
|
|
|
if(m_CallvoteSelectedPlayer == Index)
|
2010-05-31 20:05:45 +00:00
|
|
|
Selected = NumOptions;
|
2011-08-04 21:43:39 +00:00
|
|
|
aPlayerIDs[NumOptions++] = Index;
|
2010-05-31 15:36:20 +00:00
|
|
|
}
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2010-05-31 15:36:20 +00:00
|
|
|
static int s_VoteList = 0;
|
|
|
|
static float s_ScrollValue = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
CUIRect List = MainView;
|
2011-04-08 22:03:56 +00:00
|
|
|
UiDoListboxStart(&s_VoteList, &List, 24.0f, "", "", NumOptions, 1, Selected, s_ScrollValue);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-31 20:05:45 +00:00
|
|
|
for(int i = 0; i < NumOptions; i++)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-31 20:05:45 +00:00
|
|
|
CListboxItem Item = UiDoListboxNextItem(&aPlayerIDs[i]);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-31 15:36:20 +00:00
|
|
|
if(Item.m_Visible)
|
|
|
|
{
|
2010-05-31 20:05:45 +00:00
|
|
|
CTeeRenderInfo Info = m_pClient->m_aClients[aPlayerIDs[i]].m_RenderInfo;
|
2010-05-31 15:36:20 +00:00
|
|
|
Info.m_Size = Item.m_Rect.h;
|
|
|
|
Item.m_Rect.HSplitTop(5.0f, 0, &Item.m_Rect); // some margin from the top
|
|
|
|
RenderTools()->RenderTee(CAnimState::GetIdle(), &Info, EMOTE_NORMAL, vec2(1,0), vec2(Item.m_Rect.x+Item.m_Rect.h/2, Item.m_Rect.y+Item.m_Rect.h/2));
|
|
|
|
Item.m_Rect.x +=Info.m_Size;
|
2010-12-14 00:20:47 +00:00
|
|
|
UI()->DoLabelScaled(&Item.m_Rect, m_pClient->m_aClients[aPlayerIDs[i]].m_aName, 16.0f, -1);
|
2010-05-31 15:36:20 +00:00
|
|
|
}
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2016-04-27 18:04:31 +00:00
|
|
|
bool Call;
|
|
|
|
Selected = UiDoListboxEnd(&s_ScrollValue, &Call);
|
2010-05-31 20:05:45 +00:00
|
|
|
m_CallvoteSelectedPlayer = Selected != -1 ? aPlayerIDs[Selected] : -1;
|
2016-04-27 18:04:31 +00:00
|
|
|
return Call;
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CMenus::RenderServerControl(CUIRect MainView)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_ControlPage = 0;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-09-29 11:34:49 +00:00
|
|
|
// render background
|
2011-04-06 09:41:40 +00:00
|
|
|
CUIRect Bottom, Extended, TabBar, Button;
|
2011-04-08 22:03:56 +00:00
|
|
|
MainView.HSplitTop(20.0f, &Bottom, &MainView);
|
2019-03-24 22:15:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&Bottom, ms_ColorTabbarActive, 0, 10.0f);
|
2011-04-08 22:03:56 +00:00
|
|
|
MainView.HSplitTop(20.0f, &TabBar, &MainView);
|
|
|
|
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
|
2011-04-06 09:41:40 +00:00
|
|
|
MainView.Margin(10.0f, &MainView);
|
|
|
|
MainView.HSplitBottom(90.0f, &MainView, &Extended);
|
|
|
|
|
|
|
|
// tab bar
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2011-04-06 09:41:40 +00:00
|
|
|
TabBar.VSplitLeft(TabBar.w/3, &Button, &TabBar);
|
|
|
|
static int s_Button0 = 0;
|
2011-04-08 22:03:56 +00:00
|
|
|
if(DoButton_MenuTab(&s_Button0, Localize("Change settings"), s_ControlPage == 0, &Button, 0))
|
2011-04-06 09:41:40 +00:00
|
|
|
s_ControlPage = 0;
|
|
|
|
|
|
|
|
TabBar.VSplitMid(&Button, &TabBar);
|
|
|
|
static int s_Button1 = 0;
|
|
|
|
if(DoButton_MenuTab(&s_Button1, Localize("Kick player"), s_ControlPage == 1, &Button, 0))
|
|
|
|
s_ControlPage = 1;
|
|
|
|
|
|
|
|
static int s_Button2 = 0;
|
2011-04-08 22:03:56 +00:00
|
|
|
if(DoButton_MenuTab(&s_Button2, Localize("Move player to spectators"), s_ControlPage == 2, &TabBar, 0))
|
2011-04-06 09:41:40 +00:00
|
|
|
s_ControlPage = 2;
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
2011-03-31 13:43:12 +00:00
|
|
|
|
|
|
|
// render page
|
2010-05-29 07:25:38 +00:00
|
|
|
MainView.HSplitBottom(ms_ButtonHeight + 5*2, &MainView, &Bottom);
|
|
|
|
Bottom.HMargin(5.0f, &Bottom);
|
2011-03-31 13:43:12 +00:00
|
|
|
|
2016-04-27 18:04:31 +00:00
|
|
|
bool Call = false;
|
2010-05-29 07:25:38 +00:00
|
|
|
if(s_ControlPage == 0)
|
2016-04-27 18:04:31 +00:00
|
|
|
Call = RenderServerControlServer(MainView);
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(s_ControlPage == 1)
|
2016-04-27 18:04:31 +00:00
|
|
|
Call = RenderServerControlKick(MainView, false);
|
2011-03-26 15:56:59 +00:00
|
|
|
else if(s_ControlPage == 2)
|
2016-04-27 18:04:31 +00:00
|
|
|
Call = RenderServerControlKick(MainView, true);
|
2008-09-29 11:34:49 +00:00
|
|
|
|
2011-03-31 13:43:12 +00:00
|
|
|
// vote menu
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2018-09-20 05:43:05 +00:00
|
|
|
CUIRect Button, QuickSearch;
|
2015-03-13 15:15:05 +00:00
|
|
|
|
|
|
|
// render quick search
|
|
|
|
{
|
|
|
|
Bottom.VSplitLeft(240.0f, &QuickSearch, &Bottom);
|
|
|
|
QuickSearch.HSplitTop(5.0f, 0, &QuickSearch);
|
2018-03-13 20:59:07 +00:00
|
|
|
const char *pSearchLabel = "\xEE\xA2\xB6";
|
|
|
|
TextRender()->SetCurFont(TextRender()->GetFont(TEXT_FONT_ICON_FONT));
|
2019-01-06 05:42:57 +00:00
|
|
|
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
|
2015-03-13 15:15:05 +00:00
|
|
|
UI()->DoLabelScaled(&QuickSearch, pSearchLabel, 14.0f, -1);
|
2020-07-15 19:10:13 +00:00
|
|
|
float wSearch = TextRender()->TextWidth(0, 14.0f, pSearchLabel, -1, -1.0f);
|
2018-03-13 20:59:07 +00:00
|
|
|
TextRender()->SetRenderFlags(0);
|
|
|
|
TextRender()->SetCurFont(NULL);
|
2015-03-13 15:15:05 +00:00
|
|
|
QuickSearch.VSplitLeft(wSearch, 0, &QuickSearch);
|
|
|
|
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
|
2018-09-20 05:43:05 +00:00
|
|
|
static int s_ClearButton = 0;
|
2015-03-13 15:15:05 +00:00
|
|
|
static float Offset = 0.0f;
|
2015-03-13 15:44:05 +00:00
|
|
|
//static char aFilterString[25];
|
2017-07-24 16:05:19 +00:00
|
|
|
if(Input()->KeyPress(KEY_F) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
|
|
|
|
UI()->SetActiveItem(&m_aFilterString);
|
2018-09-20 05:43:05 +00:00
|
|
|
if(DoClearableEditBox(&m_aFilterString, &s_ClearButton, &QuickSearch, m_aFilterString, sizeof(m_aFilterString), 14.0f, &Offset, false, CUI::CORNER_ALL, Localize("Search")))
|
2015-03-13 15:15:05 +00:00
|
|
|
{
|
2018-09-20 05:43:05 +00:00
|
|
|
// TODO: Implement here
|
2015-03-13 15:15:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Bottom.VSplitRight(120.0f, &Bottom, &Button);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_CallVoteButton = 0;
|
2016-04-27 18:04:31 +00:00
|
|
|
if(DoButton_Menu(&s_CallVoteButton, Localize("Call vote"), 0, &Button) || Call)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(s_ControlPage == 0)
|
2016-04-27 18:04:31 +00:00
|
|
|
{
|
2011-03-25 09:26:59 +00:00
|
|
|
m_pClient->m_pVoting->CallvoteOption(m_CallvoteSelectedOption, m_aCallvoteReason);
|
2017-07-25 17:08:16 +00:00
|
|
|
if(g_Config.m_UiCloseWindowAfterChangingSetting)
|
|
|
|
SetActive(false);
|
2016-04-27 18:04:31 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(s_ControlPage == 1)
|
|
|
|
{
|
|
|
|
if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS &&
|
|
|
|
m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer])
|
|
|
|
{
|
2010-10-09 18:34:17 +00:00
|
|
|
m_pClient->m_pVoting->CallvoteKick(m_CallvoteSelectedPlayer, m_aCallvoteReason);
|
2010-05-29 07:25:38 +00:00
|
|
|
SetActive(false);
|
|
|
|
}
|
|
|
|
}
|
2011-03-26 15:56:59 +00:00
|
|
|
else if(s_ControlPage == 2)
|
|
|
|
{
|
|
|
|
if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS &&
|
|
|
|
m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer])
|
|
|
|
{
|
|
|
|
m_pClient->m_pVoting->CallvoteSpectate(m_CallvoteSelectedPlayer, m_aCallvoteReason);
|
|
|
|
SetActive(false);
|
|
|
|
}
|
|
|
|
}
|
2011-03-25 11:06:45 +00:00
|
|
|
m_aCallvoteReason[0] = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-10-09 18:34:17 +00:00
|
|
|
// render kick reason
|
2011-03-25 09:26:59 +00:00
|
|
|
CUIRect Reason;
|
|
|
|
Bottom.VSplitRight(40.0f, &Bottom, 0);
|
|
|
|
Bottom.VSplitRight(160.0f, &Bottom, &Reason);
|
|
|
|
Reason.HSplitTop(5.0f, 0, &Reason);
|
|
|
|
const char *pLabel = Localize("Reason:");
|
|
|
|
UI()->DoLabelScaled(&Reason, pLabel, 14.0f, -1);
|
2020-07-15 19:10:13 +00:00
|
|
|
float w = TextRender()->TextWidth(0, 14.0f, pLabel, -1, -1.0f);
|
2011-03-25 09:26:59 +00:00
|
|
|
Reason.VSplitLeft(w+10.0f, 0, &Reason);
|
|
|
|
static float s_Offset = 0.0f;
|
2017-07-24 16:05:19 +00:00
|
|
|
if(Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
|
|
|
|
UI()->SetActiveItem(&m_aCallvoteReason);
|
2011-03-25 09:26:59 +00:00
|
|
|
DoEditBox(&m_aCallvoteReason, &Reason, m_aCallvoteReason, sizeof(m_aCallvoteReason), 14.0f, &s_Offset, false, CUI::CORNER_ALL);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-26 17:43:43 +00:00
|
|
|
// extended features (only available when authed in rcon)
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Client()->RconAuthed())
|
|
|
|
{
|
2011-03-26 17:43:43 +00:00
|
|
|
// background
|
|
|
|
Extended.Margin(10.0f, &Extended);
|
|
|
|
Extended.HSplitTop(20.0f, &Bottom, &Extended);
|
|
|
|
Extended.HSplitTop(5.0f, 0, &Extended);
|
|
|
|
|
|
|
|
// force vote
|
|
|
|
Bottom.VSplitLeft(5.0f, 0, &Bottom);
|
2010-05-29 07:25:38 +00:00
|
|
|
Bottom.VSplitLeft(120.0f, &Button, &Bottom);
|
|
|
|
static int s_ForceVoteButton = 0;
|
|
|
|
if(DoButton_Menu(&s_ForceVoteButton, Localize("Force vote"), 0, &Button))
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(s_ControlPage == 0)
|
2011-03-25 11:06:45 +00:00
|
|
|
m_pClient->m_pVoting->CallvoteOption(m_CallvoteSelectedOption, m_aCallvoteReason, true);
|
2010-05-29 07:25:38 +00:00
|
|
|
else if(s_ControlPage == 1)
|
|
|
|
{
|
|
|
|
if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS &&
|
|
|
|
m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer])
|
|
|
|
{
|
2011-03-25 11:06:45 +00:00
|
|
|
m_pClient->m_pVoting->CallvoteKick(m_CallvoteSelectedPlayer, m_aCallvoteReason, true);
|
2010-05-29 07:25:38 +00:00
|
|
|
SetActive(false);
|
|
|
|
}
|
|
|
|
}
|
2011-03-26 15:56:59 +00:00
|
|
|
else if(s_ControlPage == 2)
|
2008-09-29 11:34:49 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_CallvoteSelectedPlayer >= 0 && m_CallvoteSelectedPlayer < MAX_CLIENTS &&
|
|
|
|
m_pClient->m_Snap.m_paPlayerInfos[m_CallvoteSelectedPlayer])
|
|
|
|
{
|
2011-03-26 15:56:59 +00:00
|
|
|
m_pClient->m_pVoting->CallvoteSpectate(m_CallvoteSelectedPlayer, m_aCallvoteReason, true);
|
2010-05-29 07:25:38 +00:00
|
|
|
SetActive(false);
|
|
|
|
}
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
2011-03-25 11:06:45 +00:00
|
|
|
m_aCallvoteReason[0] = 0;
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
2011-03-26 17:43:43 +00:00
|
|
|
|
|
|
|
if(s_ControlPage == 0)
|
|
|
|
{
|
|
|
|
// remove vote
|
|
|
|
Bottom.VSplitRight(10.0f, &Bottom, 0);
|
|
|
|
Bottom.VSplitRight(120.0f, 0, &Button);
|
|
|
|
static int s_RemoveVoteButton = 0;
|
|
|
|
if(DoButton_Menu(&s_RemoveVoteButton, Localize("Remove"), 0, &Button))
|
|
|
|
m_pClient->m_pVoting->RemovevoteOption(m_CallvoteSelectedOption);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2011-03-26 17:43:43 +00:00
|
|
|
|
|
|
|
// add vote
|
|
|
|
Extended.HSplitTop(20.0f, &Bottom, &Extended);
|
|
|
|
Bottom.VSplitLeft(5.0f, 0, &Bottom);
|
|
|
|
Bottom.VSplitLeft(250.0f, &Button, &Bottom);
|
|
|
|
UI()->DoLabelScaled(&Button, Localize("Vote description:"), 14.0f, -1);
|
|
|
|
|
|
|
|
Bottom.VSplitLeft(20.0f, 0, &Button);
|
|
|
|
UI()->DoLabelScaled(&Button, Localize("Vote command:"), 14.0f, -1);
|
|
|
|
|
|
|
|
static char s_aVoteDescription[64] = {0};
|
|
|
|
static char s_aVoteCommand[512] = {0};
|
|
|
|
Extended.HSplitTop(20.0f, &Bottom, &Extended);
|
|
|
|
Bottom.VSplitRight(10.0f, &Bottom, 0);
|
|
|
|
Bottom.VSplitRight(120.0f, &Bottom, &Button);
|
|
|
|
static int s_AddVoteButton = 0;
|
|
|
|
if(DoButton_Menu(&s_AddVoteButton, Localize("Add"), 0, &Button))
|
2011-04-05 18:06:41 +00:00
|
|
|
if(s_aVoteDescription[0] != 0 && s_aVoteCommand[0] != 0)
|
|
|
|
m_pClient->m_pVoting->AddvoteOption(s_aVoteDescription, s_aVoteCommand);
|
2011-03-26 17:43:43 +00:00
|
|
|
|
|
|
|
Bottom.VSplitLeft(5.0f, 0, &Bottom);
|
|
|
|
Bottom.VSplitLeft(250.0f, &Button, &Bottom);
|
|
|
|
static float s_OffsetDesc = 0.0f;
|
|
|
|
DoEditBox(&s_aVoteDescription, &Button, s_aVoteDescription, sizeof(s_aVoteDescription), 14.0f, &s_OffsetDesc, false, CUI::CORNER_ALL);
|
|
|
|
|
2011-04-13 18:37:12 +00:00
|
|
|
Bottom.VMargin(20.0f, &Button);
|
2011-03-26 17:43:43 +00:00
|
|
|
static float s_OffsetCmd = 0.0f;
|
|
|
|
DoEditBox(&s_aVoteCommand, &Button, s_aVoteCommand, sizeof(s_aVoteCommand), 14.0f, &s_OffsetCmd, false, CUI::CORNER_ALL);
|
2008-09-29 11:34:49 +00:00
|
|
|
}
|
|
|
|
}
|
2011-03-31 13:43:12 +00:00
|
|
|
}
|
2011-02-23 07:33:21 +00:00
|
|
|
}
|
|
|
|
|
2016-04-27 18:14:03 +00:00
|
|
|
void CMenus::RenderInGameNetwork(CUIRect MainView)
|
2010-10-29 22:44:52 +00:00
|
|
|
{
|
|
|
|
CUIRect Box = MainView;
|
|
|
|
CUIRect Button;
|
|
|
|
|
2015-10-04 16:54:13 +00:00
|
|
|
int Page = g_Config.m_UiPage;
|
2010-10-29 22:44:52 +00:00
|
|
|
int NewPage = -1;
|
|
|
|
|
2019-03-24 22:15:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
|
2010-10-29 22:44:52 +00:00
|
|
|
|
|
|
|
Box.HSplitTop(5.0f, &MainView, &MainView);
|
|
|
|
Box.HSplitTop(24.0f, &Box, &MainView);
|
|
|
|
|
|
|
|
Box.VSplitLeft(100.0f, &Button, &Box);
|
|
|
|
static int s_InternetButton=0;
|
2019-03-26 16:38:46 +00:00
|
|
|
if(DoButton_MenuTab(&s_InternetButton, Localize("Internet"), Page==PAGE_INTERNET, &Button, 0))
|
2010-10-29 22:44:52 +00:00
|
|
|
{
|
2018-03-13 20:59:07 +00:00
|
|
|
if(Page != PAGE_INTERNET)
|
2015-10-04 16:54:13 +00:00
|
|
|
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
|
2010-10-29 22:44:52 +00:00
|
|
|
NewPage = PAGE_INTERNET;
|
|
|
|
}
|
|
|
|
|
|
|
|
Box.VSplitLeft(80.0f, &Button, &Box);
|
|
|
|
static int s_LanButton=0;
|
2015-10-04 16:54:13 +00:00
|
|
|
if(DoButton_MenuTab(&s_LanButton, Localize("LAN"), Page==PAGE_LAN, &Button, 0))
|
2010-10-29 22:44:52 +00:00
|
|
|
{
|
2018-03-13 20:59:07 +00:00
|
|
|
if(Page != PAGE_LAN)
|
2015-10-04 16:54:13 +00:00
|
|
|
ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN);
|
2010-10-29 22:44:52 +00:00
|
|
|
NewPage = PAGE_LAN;
|
|
|
|
}
|
|
|
|
|
|
|
|
Box.VSplitLeft(110.0f, &Button, &Box);
|
|
|
|
static int s_FavoritesButton=0;
|
2015-10-04 16:54:13 +00:00
|
|
|
if(DoButton_MenuTab(&s_FavoritesButton, Localize("Favorites"), Page==PAGE_FAVORITES, &Button, 0))
|
2010-10-29 22:44:52 +00:00
|
|
|
{
|
2018-03-13 20:59:07 +00:00
|
|
|
if(Page != PAGE_FAVORITES)
|
2015-10-04 16:54:13 +00:00
|
|
|
ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
|
2019-03-24 22:15:38 +00:00
|
|
|
NewPage = PAGE_FAVORITES;
|
2010-10-29 22:44:52 +00:00
|
|
|
}
|
|
|
|
|
2014-09-20 11:41:20 +00:00
|
|
|
Box.VSplitLeft(110.0f, &Button, &Box);
|
|
|
|
static int s_DDNetButton=0;
|
2019-03-24 22:15:38 +00:00
|
|
|
if(DoButton_MenuTab(&s_DDNetButton, "DDNet", Page==PAGE_DDNET, &Button, 0) || Page < PAGE_INTERNET || Page > PAGE_KOG)
|
2014-09-20 11:41:20 +00:00
|
|
|
{
|
2018-03-13 20:59:07 +00:00
|
|
|
if(Page != PAGE_DDNET)
|
2017-09-03 16:17:21 +00:00
|
|
|
{
|
|
|
|
Client()->RequestDDNetInfo();
|
2015-10-04 16:54:13 +00:00
|
|
|
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
|
2017-09-03 16:17:21 +00:00
|
|
|
}
|
2019-03-24 22:15:38 +00:00
|
|
|
NewPage = PAGE_DDNET;
|
|
|
|
}
|
|
|
|
|
|
|
|
Box.VSplitLeft(110.0f, &Button, &Box);
|
|
|
|
static int s_KoGButton=0;
|
|
|
|
if(DoButton_MenuTab(&s_KoGButton, "KoG", Page==PAGE_KOG, &Button, CUI::CORNER_BR))
|
|
|
|
{
|
|
|
|
if(Page != PAGE_KOG)
|
|
|
|
{
|
|
|
|
Client()->RequestDDNetInfo();
|
|
|
|
ServerBrowser()->Refresh(IServerBrowser::TYPE_KOG);
|
|
|
|
}
|
|
|
|
NewPage = PAGE_KOG;
|
2014-09-20 11:41:20 +00:00
|
|
|
}
|
|
|
|
|
2010-10-29 22:44:52 +00:00
|
|
|
if(NewPage != -1)
|
|
|
|
{
|
|
|
|
if(Client()->State() != IClient::STATE_OFFLINE)
|
|
|
|
g_Config.m_UiPage = NewPage;
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderServerbrowser(MainView);
|
|
|
|
return;
|
|
|
|
}
|
2011-02-04 17:25:04 +00:00
|
|
|
|
|
|
|
// ghost stuff
|
2011-04-09 06:41:31 +00:00
|
|
|
int CMenus::GhostlistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser)
|
2011-02-04 17:25:04 +00:00
|
|
|
{
|
|
|
|
CMenus *pSelf = (CMenus *)pUser;
|
2017-09-28 17:13:20 +00:00
|
|
|
const char *pMap = pSelf->Client()->GetCurrentMap();
|
2018-07-25 08:29:05 +00:00
|
|
|
if(IsDir || !str_endswith(pName, ".gho") || !str_startswith(pName, pMap))
|
2011-04-09 06:41:31 +00:00
|
|
|
return 0;
|
|
|
|
|
2017-09-09 15:04:19 +00:00
|
|
|
char aFilename[256];
|
2017-09-29 21:15:47 +00:00
|
|
|
str_format(aFilename, sizeof(aFilename), "%s/%s", pSelf->m_pClient->m_pGhost->GetGhostDir(), pName);
|
2017-09-09 15:04:19 +00:00
|
|
|
|
|
|
|
CGhostHeader Header;
|
2017-10-28 12:23:24 +00:00
|
|
|
if(!pSelf->m_pClient->m_pGhost->GhostLoader()->GetGhostInfo(aFilename, &Header, pMap, pSelf->Client()->GetMapCrc()))
|
2011-04-09 06:41:31 +00:00
|
|
|
return 0;
|
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
CGhostItem Item;
|
2017-09-09 15:04:19 +00:00
|
|
|
str_copy(Item.m_aFilename, aFilename, sizeof(Item.m_aFilename));
|
2011-02-04 17:25:04 +00:00
|
|
|
str_copy(Item.m_aPlayer, Header.m_aOwner, sizeof(Item.m_aPlayer));
|
2017-10-28 12:23:24 +00:00
|
|
|
Item.m_Time = Header.GetTime();
|
2017-09-09 15:04:19 +00:00
|
|
|
if(Item.m_Time > 0)
|
2017-09-09 16:25:32 +00:00
|
|
|
pSelf->m_lGhosts.add(Item);
|
2011-04-09 06:41:31 +00:00
|
|
|
return 0;
|
2011-02-04 17:25:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CMenus::GhostlistPopulate()
|
|
|
|
{
|
2017-09-09 16:25:32 +00:00
|
|
|
CGhostItem *pOwnGhost = 0;
|
2011-02-04 17:25:04 +00:00
|
|
|
m_lGhosts.clear();
|
2017-09-29 21:15:47 +00:00
|
|
|
Storage()->ListDirectory(IStorage::TYPE_ALL, m_pClient->m_pGhost->GetGhostDir(), GhostlistFetchCallback, this);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
for(int i = 0; i < m_lGhosts.size(); i++)
|
|
|
|
{
|
2017-09-09 16:25:32 +00:00
|
|
|
if(str_comp(m_lGhosts[i].m_aPlayer, g_Config.m_PlayerName) == 0 && (!pOwnGhost || m_lGhosts[i] < *pOwnGhost))
|
|
|
|
pOwnGhost = &m_lGhosts[i];
|
2011-02-04 17:25:04 +00:00
|
|
|
}
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2017-09-09 16:25:32 +00:00
|
|
|
if(pOwnGhost)
|
2011-02-04 17:25:04 +00:00
|
|
|
{
|
2017-09-09 16:25:32 +00:00
|
|
|
pOwnGhost->m_Own = true;
|
|
|
|
pOwnGhost->m_Slot = m_pClient->m_pGhost->Load(pOwnGhost->m_aFilename);
|
2011-02-04 17:25:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-09 16:25:32 +00:00
|
|
|
CMenus::CGhostItem *CMenus::GetOwnGhost()
|
|
|
|
{
|
|
|
|
for(int i = 0; i < m_lGhosts.size(); i++)
|
|
|
|
if(m_lGhosts[i].m_Own)
|
|
|
|
return &m_lGhosts[i];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-09-10 01:48:22 +00:00
|
|
|
void CMenus::UpdateOwnGhost(CGhostItem Item)
|
|
|
|
{
|
|
|
|
int Own = -1;
|
|
|
|
for(int i = 0; i < m_lGhosts.size(); i++)
|
|
|
|
if(m_lGhosts[i].m_Own)
|
|
|
|
Own = i;
|
|
|
|
|
|
|
|
if(Own != -1)
|
|
|
|
{
|
|
|
|
m_lGhosts[Own].m_Slot = -1;
|
|
|
|
m_lGhosts[Own].m_Own = false;
|
|
|
|
if(Item.HasFile() || !m_lGhosts[Own].HasFile())
|
|
|
|
DeleteGhostItem(Own);
|
|
|
|
}
|
|
|
|
|
|
|
|
Item.m_Own = true;
|
|
|
|
m_lGhosts.add(Item);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMenus::DeleteGhostItem(int Index)
|
|
|
|
{
|
|
|
|
if(m_lGhosts[Index].HasFile())
|
|
|
|
Storage()->RemoveFile(m_lGhosts[Index].m_aFilename, IStorage::TYPE_SAVE);
|
|
|
|
m_lGhosts.remove_index(Index);
|
|
|
|
}
|
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
void CMenus::RenderGhost(CUIRect MainView)
|
|
|
|
{
|
|
|
|
// render background
|
2019-03-24 22:15:38 +00:00
|
|
|
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
MainView.HSplitTop(10.0f, 0, &MainView);
|
|
|
|
MainView.HSplitBottom(5.0f, &MainView, 0);
|
|
|
|
MainView.VSplitLeft(5.0f, 0, &MainView);
|
|
|
|
MainView.VSplitRight(5.0f, &MainView, 0);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
CUIRect Headers, Status;
|
|
|
|
CUIRect View = MainView;
|
|
|
|
|
|
|
|
View.HSplitTop(17.0f, &Headers, &View);
|
|
|
|
View.HSplitBottom(28.0f, &View, &Status);
|
|
|
|
|
|
|
|
// split of the scrollbar
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&Headers, ColorRGBA(1,1,1,0.25f), CUI::CORNER_T, 5.0f);
|
2011-02-04 17:25:04 +00:00
|
|
|
Headers.VSplitRight(20.0f, &Headers, 0);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
struct CColumn
|
|
|
|
{
|
|
|
|
int m_Id;
|
|
|
|
CLocConstString m_Caption;
|
|
|
|
float m_Width;
|
|
|
|
CUIRect m_Rect;
|
|
|
|
CUIRect m_Spacer;
|
|
|
|
};
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
COL_ACTIVE=0,
|
|
|
|
COL_NAME,
|
|
|
|
COL_TIME,
|
|
|
|
};
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
static CColumn s_aCols[] = {
|
|
|
|
{-1, " ", 2.0f, {0}, {0}},
|
|
|
|
{COL_ACTIVE, " ", 30.0f, {0}, {0}},
|
2017-09-25 19:36:25 +00:00
|
|
|
{COL_NAME, "Name", 300.0f, {0}, {0}},
|
|
|
|
{COL_TIME, "Time", 200.0f, {0}, {0}},
|
2011-02-04 17:25:04 +00:00
|
|
|
};
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
int NumCols = sizeof(s_aCols)/sizeof(CColumn);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
// do layout
|
|
|
|
for(int i = 0; i < NumCols; i++)
|
|
|
|
{
|
|
|
|
Headers.VSplitLeft(s_aCols[i].m_Width, &s_aCols[i].m_Rect, &Headers);
|
|
|
|
|
|
|
|
if(i+1 < NumCols)
|
|
|
|
Headers.VSplitLeft(2, &s_aCols[i].m_Spacer, &Headers);
|
|
|
|
}
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
// do headers
|
|
|
|
for(int i = 0; i < NumCols; i++)
|
|
|
|
DoButton_GridHeader(s_aCols[i].m_Caption, s_aCols[i].m_Caption, 0, &s_aCols[i].m_Rect);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&View, ColorRGBA(0,0,0,0.15f), 0, 0);
|
2011-02-04 17:25:04 +00:00
|
|
|
|
|
|
|
CUIRect Scroll;
|
|
|
|
View.VSplitRight(15, &View, &Scroll);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
int NumGhosts = m_lGhosts.size();
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
int Num = (int)(View.h/s_aCols[0].m_Rect.h) + 1;
|
|
|
|
static int s_ScrollBar = 0;
|
|
|
|
static float s_ScrollValue = 0;
|
|
|
|
|
|
|
|
Scroll.HMargin(5.0f, &Scroll);
|
|
|
|
s_ScrollValue = DoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
|
|
|
|
|
|
|
|
int ScrollNum = NumGhosts-Num+1;
|
|
|
|
if(ScrollNum > 0)
|
|
|
|
{
|
2016-04-30 18:11:26 +00:00
|
|
|
if(Input()->KeyPress(KEY_MOUSE_WHEEL_UP))
|
2011-02-04 17:25:04 +00:00
|
|
|
s_ScrollValue -= 1.0f/ScrollNum;
|
2016-04-30 18:11:26 +00:00
|
|
|
if(Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN))
|
2011-02-04 17:25:04 +00:00
|
|
|
s_ScrollValue += 1.0f/ScrollNum;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ScrollNum = 0;
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
static int s_SelectedIndex = 0;
|
|
|
|
for(int i = 0; i < m_NumInputEvents; i++)
|
|
|
|
{
|
|
|
|
int NewIndex = -1;
|
|
|
|
if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS)
|
|
|
|
{
|
|
|
|
if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = s_SelectedIndex + 1;
|
|
|
|
if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = s_SelectedIndex - 1;
|
|
|
|
}
|
|
|
|
if(NewIndex > -1 && NewIndex < NumGhosts)
|
|
|
|
{
|
|
|
|
//scroll
|
|
|
|
float IndexY = View.y - s_ScrollValue*ScrollNum*s_aCols[0].m_Rect.h + NewIndex*s_aCols[0].m_Rect.h;
|
|
|
|
int Scroll = View.y > IndexY ? -1 : View.y+View.h < IndexY+s_aCols[0].m_Rect.h ? 1 : 0;
|
|
|
|
if(Scroll)
|
|
|
|
{
|
|
|
|
if(Scroll < 0)
|
|
|
|
{
|
|
|
|
int NumScrolls = (View.y-IndexY+s_aCols[0].m_Rect.h-1.0f)/s_aCols[0].m_Rect.h;
|
|
|
|
s_ScrollValue -= (1.0f/ScrollNum)*NumScrolls;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int NumScrolls = (IndexY+s_aCols[0].m_Rect.h-(View.y+View.h)+s_aCols[0].m_Rect.h-1.0f)/s_aCols[0].m_Rect.h;
|
|
|
|
s_ScrollValue += (1.0f/ScrollNum)*NumScrolls;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
s_SelectedIndex = NewIndex;
|
|
|
|
}
|
|
|
|
}
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
if(s_ScrollValue < 0) s_ScrollValue = 0;
|
|
|
|
if(s_ScrollValue > 1) s_ScrollValue = 1;
|
|
|
|
|
|
|
|
// set clipping
|
|
|
|
UI()->ClipEnable(&View);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
CUIRect OriginalView = View;
|
|
|
|
View.y -= s_ScrollValue*ScrollNum*s_aCols[0].m_Rect.h;
|
|
|
|
|
2011-02-11 06:00:12 +00:00
|
|
|
int NewSelected = -1;
|
|
|
|
|
2018-03-13 20:59:07 +00:00
|
|
|
for(int i = 0; i < NumGhosts; i++)
|
2011-02-04 17:25:04 +00:00
|
|
|
{
|
|
|
|
const CGhostItem *pItem = &m_lGhosts[i];
|
|
|
|
CUIRect Row;
|
|
|
|
CUIRect SelectHitBox;
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
View.HSplitTop(17.0f, &Row, &View);
|
|
|
|
SelectHitBox = Row;
|
|
|
|
|
|
|
|
// make sure that only those in view can be selected
|
|
|
|
if(Row.y+Row.h > OriginalView.y && Row.y < OriginalView.y+OriginalView.h)
|
|
|
|
{
|
|
|
|
if(i == s_SelectedIndex)
|
|
|
|
{
|
|
|
|
CUIRect r = Row;
|
|
|
|
r.Margin(1.5f, &r);
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&r, ColorRGBA(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f);
|
2011-02-04 17:25:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// clip the selection
|
|
|
|
if(SelectHitBox.y < OriginalView.y) // top
|
|
|
|
{
|
|
|
|
SelectHitBox.h -= OriginalView.y-SelectHitBox.y;
|
|
|
|
SelectHitBox.y = OriginalView.y;
|
|
|
|
}
|
|
|
|
else if(SelectHitBox.y+SelectHitBox.h > OriginalView.y+OriginalView.h) // bottom
|
|
|
|
SelectHitBox.h = OriginalView.y+OriginalView.h-SelectHitBox.y;
|
|
|
|
|
|
|
|
if(UI()->DoButtonLogic(pItem, "", 0, &SelectHitBox))
|
|
|
|
{
|
2011-02-11 06:00:12 +00:00
|
|
|
NewSelected = i;
|
2011-02-04 17:25:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-26 12:06:32 +00:00
|
|
|
ColorRGBA rgb = ColorRGBA(1.0f, 1.0f, 1.0f);
|
2017-09-09 18:19:44 +00:00
|
|
|
if(pItem->m_Own)
|
2019-04-26 12:06:32 +00:00
|
|
|
rgb = color_cast<ColorRGBA>(ColorHSLA(0.33f, 1.0f, 0.75f));
|
2017-09-10 01:48:22 +00:00
|
|
|
|
2019-12-02 09:18:50 +00:00
|
|
|
TextRender()->TextColor(rgb.WithAlpha(pItem->HasFile() ? 1.0f : 0.5f));
|
2017-09-09 18:19:44 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
for(int c = 0; c < NumCols; c++)
|
|
|
|
{
|
|
|
|
CUIRect Button;
|
|
|
|
Button.x = s_aCols[c].m_Rect.x;
|
|
|
|
Button.y = Row.y;
|
|
|
|
Button.h = Row.h;
|
|
|
|
Button.w = s_aCols[c].m_Rect.w;
|
|
|
|
|
|
|
|
int Id = s_aCols[c].m_Id;
|
|
|
|
|
|
|
|
if(Id == COL_ACTIVE)
|
|
|
|
{
|
2017-09-09 16:25:32 +00:00
|
|
|
if(pItem->Active())
|
2011-02-04 17:25:04 +00:00
|
|
|
{
|
|
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id);
|
|
|
|
Graphics()->QuadsBegin();
|
|
|
|
RenderTools()->SelectSprite(SPRITE_OOP + 7);
|
|
|
|
IGraphics::CQuadItem QuadItem(Button.x+Button.w/2, Button.y+Button.h/2, 20.0f, 20.0f);
|
|
|
|
Graphics()->QuadsDraw(&QuadItem, 1);
|
|
|
|
|
|
|
|
Graphics()->QuadsEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(Id == COL_NAME)
|
|
|
|
{
|
|
|
|
CTextCursor Cursor;
|
2018-03-13 20:59:07 +00:00
|
|
|
TextRender()->SetCursor(&Cursor, Button.x, Button.y + (Button.h - 12.0f * UI()->Scale()) / 2.f, 12.0f * UI()->Scale(), TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
2011-02-04 17:25:04 +00:00
|
|
|
Cursor.m_LineWidth = Button.w;
|
|
|
|
|
2017-09-09 18:19:44 +00:00
|
|
|
TextRender()->TextEx(&Cursor, pItem->m_aPlayer, -1);
|
2011-02-04 17:25:04 +00:00
|
|
|
}
|
|
|
|
else if(Id == COL_TIME)
|
|
|
|
{
|
|
|
|
CTextCursor Cursor;
|
2018-03-13 20:59:07 +00:00
|
|
|
TextRender()->SetCursor(&Cursor, Button.x, Button.y + (Button.h - 12.0f * UI()->Scale()) / 2.f, 12.0f * UI()->Scale(), TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
|
2011-02-04 17:25:04 +00:00
|
|
|
Cursor.m_LineWidth = Button.w;
|
|
|
|
|
|
|
|
char aBuf[64];
|
2017-08-30 23:59:22 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "%02d:%02d.%03d", pItem->m_Time / (60 * 1000), (pItem->m_Time / 1000) % 60, pItem->m_Time % 1000);
|
2011-02-04 17:25:04 +00:00
|
|
|
TextRender()->TextEx(&Cursor, aBuf, -1);
|
|
|
|
}
|
|
|
|
}
|
2017-09-09 18:19:44 +00:00
|
|
|
|
|
|
|
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
|
2011-02-04 17:25:04 +00:00
|
|
|
}
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2017-09-09 16:25:32 +00:00
|
|
|
UI()->ClipDisable();
|
|
|
|
|
2011-02-11 06:00:12 +00:00
|
|
|
if(NewSelected != -1)
|
|
|
|
s_SelectedIndex = NewSelected;
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2019-04-26 21:47:34 +00:00
|
|
|
RenderTools()->DrawUIRect(&Status, ColorRGBA(1,1,1,0.25f), CUI::CORNER_B, 5.0f);
|
2011-02-04 17:25:04 +00:00
|
|
|
Status.Margin(5.0f, &Status);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2011-02-04 17:25:04 +00:00
|
|
|
CUIRect Button;
|
2017-09-17 22:57:21 +00:00
|
|
|
Status.VSplitLeft(120.0f, &Button, &Status);
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2017-09-10 02:09:38 +00:00
|
|
|
static int s_ReloadButton = 0;
|
2017-09-17 22:57:21 +00:00
|
|
|
if(DoButton_Menu(&s_ReloadButton, Localize("Reload"), 0, &Button))
|
|
|
|
{
|
|
|
|
m_pClient->m_pGhost->UnloadAll();
|
|
|
|
GhostlistPopulate();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(s_SelectedIndex >= m_lGhosts.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
CGhostItem *pGhost = &m_lGhosts[s_SelectedIndex];
|
2011-04-09 06:41:31 +00:00
|
|
|
|
2017-09-10 02:57:03 +00:00
|
|
|
CGhostItem *pOwnGhost = GetOwnGhost();
|
|
|
|
int ReservedSlots = !pGhost->m_Own && !(pOwnGhost && pOwnGhost->Active());
|
2017-10-28 12:23:24 +00:00
|
|
|
if(pGhost->HasFile() && (pGhost->Active() || m_pClient->m_pGhost->FreeSlots() > ReservedSlots))
|
2011-02-04 17:25:04 +00:00
|
|
|
{
|
2017-09-10 01:48:22 +00:00
|
|
|
Status.VSplitRight(120.0f, &Status, &Button);
|
|
|
|
|
2017-09-17 22:57:21 +00:00
|
|
|
static int s_GhostButton = 0;
|
2017-09-10 01:48:22 +00:00
|
|
|
const char *pText = pGhost->Active() ? Localize("Deactivate") : Localize("Activate");
|
|
|
|
if(DoButton_Menu(&s_GhostButton, pText, 0, &Button) || (NewSelected != -1 && Input()->MouseDoubleClick()))
|
2017-09-09 16:25:32 +00:00
|
|
|
{
|
2017-09-10 01:48:22 +00:00
|
|
|
if(pGhost->Active())
|
|
|
|
{
|
|
|
|
m_pClient->m_pGhost->Unload(pGhost->m_Slot);
|
|
|
|
pGhost->m_Slot = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
pGhost->m_Slot = m_pClient->m_pGhost->Load(pGhost->m_aFilename);
|
2017-09-09 16:25:32 +00:00
|
|
|
}
|
2017-09-10 01:48:22 +00:00
|
|
|
|
|
|
|
Status.VSplitRight(5.0f, &Status, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status.VSplitRight(120.0f, &Status, &Button);
|
|
|
|
|
2017-09-17 22:57:21 +00:00
|
|
|
static int s_DeleteButton = 0;
|
2017-09-10 01:48:22 +00:00
|
|
|
if(DoButton_Menu(&s_DeleteButton, Localize("Delete"), 0, &Button))
|
|
|
|
{
|
|
|
|
if(pGhost->Active())
|
|
|
|
m_pClient->m_pGhost->Unload(pGhost->m_Slot);
|
|
|
|
DeleteGhostItem(s_SelectedIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
Status.VSplitRight(5.0f, &Status, 0);
|
|
|
|
|
|
|
|
bool Recording = m_pClient->m_pGhost->GhostRecorder()->IsRecording();
|
|
|
|
if(!pGhost->HasFile() && !Recording && pGhost->Active())
|
|
|
|
{
|
2017-09-17 22:57:21 +00:00
|
|
|
static int s_SaveButton = 0;
|
2017-09-10 01:48:22 +00:00
|
|
|
Status.VSplitRight(120.0f, &Status, &Button);
|
|
|
|
if(DoButton_Menu(&s_SaveButton, Localize("Save"), 0, &Button))
|
|
|
|
m_pClient->m_pGhost->SaveGhost(pGhost);
|
2011-02-04 17:25:04 +00:00
|
|
|
}
|
|
|
|
}
|