summaryrefslogtreecommitdiff
path: root/game/client/tf/vgui/tf_lobby_container_frame.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/vgui/tf_lobby_container_frame.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/client/tf/vgui/tf_lobby_container_frame.cpp')
-rw-r--r--game/client/tf/vgui/tf_lobby_container_frame.cpp630
1 files changed, 630 insertions, 0 deletions
diff --git a/game/client/tf/vgui/tf_lobby_container_frame.cpp b/game/client/tf/vgui/tf_lobby_container_frame.cpp
new file mode 100644
index 0000000..b8d0e48
--- /dev/null
+++ b/game/client/tf/vgui/tf_lobby_container_frame.cpp
@@ -0,0 +1,630 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#include "cbase.h"
+
+#include "ienginevgui.h"
+#include "vgui/IVGui.h"
+#include "vgui/IInput.h"
+#include "vgui_controls/MenuItem.h"
+#include "vgui_controls/PropertySheet.h"
+
+#include "tf_party.h"
+#include "tf_lobbypanel.h"
+#include "tf_pvp_rank_panel.h"
+
+#include "tf_lobby_container_frame.h"
+#include "tf_controls.h"
+
+#include "tf_item_inventory.h"
+#include "tf_lobbypanel.h"
+#include "tf_hud_mainmenuoverride.h"
+#include "tf_matchmaking_dashboard.h"
+#include "tf_ping_panel.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+bool BIsPartyLeader()
+{
+ CTFParty *pParty = GTFGCClientSystem()->GetParty();
+ return ( pParty == NULL || pParty->GetLeader() == steamapicontext->SteamUser()->GetSteamID() );
+}
+
+bool BIsPartyInUIState()
+{
+ if ( !GCClientSystem()->BConnectedtoGC() )
+ return false;
+ CTFParty *pParty = GTFGCClientSystem()->GetParty();
+ return ( pParty == NULL || pParty->GetState() == CSOTFParty_State_UI );
+}
+
+CSteamID SteamIDFromDecimalString( const char *pszUint64InDecimal )
+{
+ uint64 ulSteamID = 0;
+ if ( sscanf( pszUint64InDecimal, "%llu", &ulSteamID ) )
+ {
+ return CSteamID( ulSteamID );
+ }
+ else
+ {
+ Assert( false );
+ return CSteamID();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CBaseLobbyContainerFrame::CBaseLobbyContainerFrame( const char* pszPanelName )
+ : vgui::PropertyDialog( NULL, pszPanelName )
+ , m_bNextButtonEnabled( false )
+ , m_pContextMenu( NULL )
+{
+ vgui::VPANEL gameuiPanel = enginevgui->GetPanel( PANEL_GAMEUIDLL );
+ SetParent( gameuiPanel );
+
+ SetMoveable( false );
+ SetSizeable( false );
+
+ vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFileEx( enginevgui->GetPanel( PANEL_CLIENTDLL ), "resource/ClientScheme.res", "ClientScheme");
+ SetScheme(scheme);
+ SetProportional( true );
+
+ ListenForGameEvent( "gameui_hidden" );
+
+ ListenForGameEvent( "lobby_updated" );
+ ListenForGameEvent( "party_updated" );
+ ListenForGameEvent( "client_beginconnect" );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CBaseLobbyContainerFrame::~CBaseLobbyContainerFrame( void )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::ApplySchemeSettings( vgui::IScheme *pScheme )
+{
+ BaseClass::ApplySchemeSettings( pScheme );
+
+ // load control settings...
+ LoadControlSettings( GetResFile() );
+
+ m_pStartPartyButton = dynamic_cast<vgui::Button *>(FindChildByName( "StartPartyButton", true )); Assert( m_pStartPartyButton );
+ m_pBackButton = dynamic_cast<vgui::Button *>( FindChildByName( "BackButton", true ) ); Assert( m_pBackButton );
+ m_pNextButton = dynamic_cast<vgui::Button *>( FindChildByName( "NextButton", true ) ); Assert( m_pNextButton );
+
+ SetOKButtonVisible(false);
+ SetCancelButtonVisible(false);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::ShowPanel(bool bShow)
+{
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
+
+ // Keep the MM dashboard on top of us
+ bShow ? GetMMDashboardParentManager()->PushModalFullscreenPopup( this )
+ : GetMMDashboardParentManager()->PopModalFullscreenPopup( this );
+
+ m_pContents->SetControlVisible( "PartyActiveGroupBox", false );
+
+ // Make sure we're signed on
+ if ( bShow )
+ {
+ if ( GetPropertySheet()->GetActivePage() != m_pContents )
+ {
+ GetPropertySheet()->SetActivePage( m_pContents );
+ }
+ else
+ {
+ // VGUI doesn't tell the starting active page that it's active, so we post a pageshow to it
+ vgui::ivgui()->PostMessage( m_pContents->GetVPanel(), new KeyValues("PageShow"), GetPropertySheet()->GetVPanel() );
+ }
+
+ Activate();
+
+ // I don't know why, I don't want to know why, I shouldn't
+ // have to wonder why, but for whatever reason this stupid
+ // panel isn't laying out correctly unless we do this terribleness
+ InvalidateLayout( true );
+ m_pContents->InvalidateLayout( true, true );
+
+ GTFGCClientSystem()->SetLocalPlayerSquadSurplus( false );
+ WriteControls();
+ m_pContents->UpdateControls();
+
+ Panel* pPvPRankPanel = FindChildByName( "RankPanel", true );
+ if ( pPvPRankPanel )
+ {
+ pPvPRankPanel->OnCommand( "update_base_state" );
+ pPvPRankPanel->OnCommand( "begin_xp_lerp" );
+ }
+ }
+ else
+ {
+ if ( m_hPingPanel )
+ {
+ m_hPingPanel->MarkForDeletion();
+ }
+ }
+
+ OnCommand( "leave_party" );
+
+ SetVisible( bShow );
+ m_pContents->SetVisible( bShow );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::SetNextButtonEnabled( bool bValue )
+{
+ m_bNextButtonEnabled = bValue;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::OnThink()
+{
+ BaseClass::OnThink();
+
+ // Check if we don't want to be here, then get out!
+ if ( GTFGCClientSystem()->GetMatchmakingUIState() == eMatchmakingUIState_Inactive )
+ {
+ Msg( "Hiding LobbyContainerFrame" );
+ ShowPanel(false);
+ return;
+ }
+
+ WriteControls();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::FireGameEvent( IGameEvent *event )
+{
+ if ( GTFGCClientSystem()->GetSearchMode() != GetHandledMode() )
+ return;
+
+ const char *pszEventname = event->GetName();
+ if ( !Q_stricmp( pszEventname, "lobby_updated" ) || !Q_stricmp( pszEventname, "party_updated" ) )
+ {
+ WriteControls();
+ return;
+ }
+
+ // Bail when we connect to any server
+ if ( !Q_stricmp( pszEventname, "client_beginconnect" ) )
+ {
+ ShowPanel( false );
+ return;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::StartSearch( void )
+{
+ // Is anyone banned from matchmaking?
+ RTime32 rtimeExpire = 0;
+ if ( m_pContents->IsAnyoneBanned( rtimeExpire ) )
+ {
+ CRTime timeExpire( rtimeExpire );
+ timeExpire.SetToGMT( false );
+ char out_buf[k_RTimeRenderBufferSize];
+ wchar_t wszExpire[512];
+ wchar_t wszLocalized[512];
+ g_pVGuiLocalize->ConvertANSIToUnicode( timeExpire.Render( out_buf ), wszExpire, sizeof( wszExpire ) );
+ g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#TF_Matchmaking_Banned" ), 1, wszExpire );
+ ShowMessageBox( "#TF_Matchmaking_Title", wszLocalized, "#GameUI_OK" );
+ return;
+ }
+
+ if ( VerifyPartyAuthorization() )
+ {
+ GTFGCClientSystem()->RequestSelectWizardStep( TF_Matchmaking_WizardStep_SEARCHING );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::OnCommand( const char *command )
+{
+ if ( FStrEq( command, "options" ) )
+ {
+ OpenOptionsContextMenu();
+ }
+ else if ( FStrEq( command, "back" ) )
+ {
+ if ( !GCClientSystem()->BConnectedtoGC() || !BIsPartyLeader() )
+ {
+ // TODO: Remove this when we have the dashboard everywhere.
+ // Well...this entire panel should be gone.
+ GTFGCClientSystem()->EndMatchmaking();
+ // And hide us
+ ShowPanel( false );
+ return;
+ }
+
+ HandleBackPressed();
+ }
+ else if ( FStrEq( command, "leave_party" ) )
+ {
+ m_pStartPartyButton->SetVisible( true );
+ SetControlVisible( "PlayWithFriendsExplanation", true );
+ m_pContents->SetControlVisible( "PartyActiveGroupBox", false );
+ }
+ else if ( FStrEq( command, "start_party" ) )
+ {
+ m_pStartPartyButton->SetVisible( false );
+ SetControlVisible( "PlayWithFriendsExplanation", false );
+ m_pContents->SetControlVisible( "PartyActiveGroupBox", true );
+
+ Assert( steamapicontext );
+
+ IGameEvent *pEvent = gameeventmanager->CreateEvent( "mm_lobby_member_join" );
+ if ( pEvent )
+ {
+ pEvent->SetString( "steamid", CFmtStr( "%llu", steamapicontext->SteamUser()->GetSteamID().ConvertToUint64() ) );
+ pEvent->SetInt( "solo", 1 );
+ gameeventmanager->FireEventClientSide( pEvent );
+ }
+ }
+ else
+ {
+
+ // What other commands are there?
+ Assert( false );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::PerformLayout( void )
+{
+ if ( GetVParent() )
+ {
+ int w,h;
+ vgui::ipanel()->GetSize( GetVParent(), w, h );
+ SetBounds(0,0,w,h);
+ }
+
+ BaseClass::PerformLayout();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+static void LeaveSearch( bool bConfirmed, void *pContext )
+{
+ if ( bConfirmed )
+ {
+ switch ( GTFGCClientSystem()->GetSearchMode() )
+ {
+ case TF_Matchmaking_MVM:
+ GTFGCClientSystem()->RequestSelectWizardStep( TF_Matchmaking_WizardStep_MVM_CHALLENGE );
+ break;
+
+ case TF_Matchmaking_LADDER:
+ GTFGCClientSystem()->RequestSelectWizardStep( TF_Matchmaking_WizardStep_LADDER );
+ break;
+
+ default:
+ AssertMsg1( false, "Unknown search mode %d", (int)GTFGCClientSystem()->GetSearchMode() );
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::OnKeyCodeTyped(vgui::KeyCode code)
+{
+ if ( code == KEY_ESCAPE )
+ {
+ if ( m_pContents->IsPartyActiveGroupBoxVisible() )
+ {
+ ShowConfirmDialog( "#TF_MM_LeaveParty_Title", "#TF_MM_LeaveParty_Confirm",
+ "#TF_Coach_Yes", "#TF_Coach_No",
+ &CBaseLobbyContainerFrame::LeaveLobbyPanel );
+ return;
+ }
+ else if ( GTFGCClientSystem()->GetWizardStep() == TF_Matchmaking_WizardStep_SEARCHING )
+ {
+ ShowConfirmDialog( "#TF_MM_LeaveQueue_Title", "#TF_MM_LeaveQueue_Confirm",
+ "#TF_Coach_Yes", "#TF_Coach_No",
+ &LeaveSearch );
+ return;
+ }
+
+ OnCommand( "back" );
+ return;
+ }
+
+ BaseClass::OnKeyCodeTyped( code );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::OnKeyCodePressed(vgui::KeyCode code)
+{
+ ButtonCode_t nButtonCode = GetBaseButtonCode( code );
+
+ if ( nButtonCode == KEY_XBUTTON_B || nButtonCode == STEAMCONTROLLER_B || nButtonCode == STEAMCONTROLLER_START )
+ {
+ OnCommand( "back" );
+ return;
+ }
+ else if ( nButtonCode == KEY_XBUTTON_X )
+ {
+ m_pContents->ToggleJoinLateCheckButton();
+ }
+
+ BaseClass::OnKeyCodePressed( code );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::WriteControls()
+{
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
+
+ if ( !IsVisible() )
+ return;
+
+ // Make sure we want to be in matchmaking. (If we don't, the frame should hide us pretty quickly.)
+ // We might get an event or something right at the transition point occasionally when the UI should
+ // not be visible
+ if ( GTFGCClientSystem()->GetMatchmakingUIState() == eMatchmakingUIState_Inactive )
+ {
+ return;
+ }
+
+ bool bNoGC = false;
+ if ( !GCClientSystem()->BConnectedtoGC() ||
+ GTFGCClientSystem()->BHaveLiveMatch() ||
+ ( GTFGCClientSystem()->GetParty() && GTFGCClientSystem()->GetParty()->BOffline() ) )
+ {
+ bNoGC = true;
+ }
+
+ SetControlVisible( "PlayWithFriendsExplanation", !bNoGC && ShouldShowPartyButton(), true );
+ SetControlVisible( "RankPanel", !bNoGC, true );
+ SetControlVisible( "NoGCGroupBox", bNoGC, true );
+
+ GetPropertySheet()->SetTabWidth( -1 );
+
+ // Check if we already have a party, then make sure and show it
+ if ( !m_pStartPartyButton->IsVisible() && m_pContents->NumPlayersInParty() > 1 )
+ {
+ m_pContents->SetControlVisible( "PartyActiveGroupBox", true );
+ }
+
+ // Show/hide start party button as appropriate
+ bool bShowPartyButton = ShouldShowPartyButton();
+
+ m_pStartPartyButton->SetVisible( bShowPartyButton && !bNoGC );
+
+ // Check for matchmaking bans and display time remaining if we're banned
+ if ( steamapicontext == NULL || steamapicontext->SteamUser() == NULL )
+ return;
+
+ CEconGameAccountClient *pGameAccountClient = NULL;
+ if ( InventoryManager() && TFInventoryManager()->GetLocalTFInventory() && TFInventoryManager()->GetLocalTFInventory()->GetSOC() )
+ {
+ pGameAccountClient = TFInventoryManager()->GetLocalTFInventory()->GetSOC()->GetSingleton<CEconGameAccountClient>();
+ }
+
+ const IMatchGroupDescription *pMatchDesc = GetMatchGroupDescription( m_pContents->GetMatchGroup() );
+ EMMPenaltyPool ePenaltyPool = pMatchDesc ? pMatchDesc->m_params.m_ePenaltyPool : eMMPenaltyPool_Invalid;
+
+ CRTime timeExpire = CRTime::RTime32TimeCur();
+ int nDuration = -1;
+ bool bBanned = false;
+
+ if ( pGameAccountClient && ePenaltyPool != eMMPenaltyPool_Invalid )
+ {
+ switch ( ePenaltyPool )
+ {
+ case eMMPenaltyPool_Casual:
+ timeExpire = pGameAccountClient->Obj().matchmaking_casual_ban_expiration();
+ nDuration = pGameAccountClient->Obj().matchmaking_casual_ban_last_duration();
+ bBanned = timeExpire > CRTime::RTime32TimeCur();
+ break;
+ case eMMPenaltyPool_Ranked:
+ timeExpire = pGameAccountClient->Obj().matchmaking_ranked_ban_expiration();
+ nDuration = pGameAccountClient->Obj().matchmaking_ranked_ban_last_duration();
+ bBanned = timeExpire > CRTime::RTime32TimeCur();
+ break;
+ default: Assert( false );
+ }
+
+ SetControlVisible( "MatchmakingBanPanel", bBanned );
+
+ if ( bBanned )
+ {
+ CExLabel *pBanLabel = FindControl<CExLabel>( "MatchmakingBanDurationLabel", true );
+
+ if ( pBanLabel )
+ {
+ timeExpire.SetToGMT( false );
+
+ CRTime rtNow = CRTime::RTime32TimeCur();
+
+ int nSecondsRemaining = timeExpire.GetRTime32() - rtNow.GetRTime32();
+
+ if ( nSecondsRemaining >= 0 )
+ {
+
+ const int nDaysForLongBan = 2;
+
+ int nDaysRemaining = nSecondsRemaining / 86400;
+ int nHoursRemaining = nSecondsRemaining / 3600;
+ int nMinutesRemaining = ( nSecondsRemaining % 3600 ) / 60;
+
+ int nDurationDays = nDuration / 86400;
+ int nDurationHours = nDuration / 3600;
+ int nDurationMinutes = ( nDuration % 3600 ) / 60;
+
+ // Want the remainder hours if we're going to display 'days' remaining
+ if ( nDurationDays >= nDaysForLongBan )
+ {
+ nDurationHours = ( nDuration % ( 86400 * nDurationDays ) ) / 3600;
+
+ if ( nDaysRemaining >= nDaysForLongBan )
+ {
+ nHoursRemaining = ( nSecondsRemaining % ( 86400 * nDaysRemaining ) ) / 3600;
+ }
+ }
+
+ wchar_t wszDaysRemaining[16];
+ wchar_t wszHoursRemaining[16];
+ wchar_t wszMinutesRemaining[16];
+ wchar_t wszDurationDays[16];
+ wchar_t wszDurationHours[16];
+ wchar_t wszDurationMinutes[16];
+
+ _snwprintf( wszDaysRemaining, ARRAYSIZE( wszDaysRemaining ), L"%d", nDaysRemaining );
+ _snwprintf( wszHoursRemaining, ARRAYSIZE( wszHoursRemaining ), L"%d", nHoursRemaining );
+ _snwprintf( wszMinutesRemaining, ARRAYSIZE( wszMinutesRemaining ), L"%d", nMinutesRemaining );
+ _snwprintf( wszDurationDays, ARRAYSIZE( wszDurationDays ), L"%d", nDurationDays );
+ _snwprintf( wszDurationHours, ARRAYSIZE( wszDurationHours ), L"%d", nDurationHours );
+ _snwprintf( wszDurationMinutes, ARRAYSIZE( wszDurationMinutes ), L"%d", nDurationMinutes );
+
+ wchar_t wszLocalized[512];
+
+ // Short ban (less than "nDaysForLongBan" days and thus less than that remaining)
+ if ( nDurationDays < nDaysForLongBan )
+ {
+ // Less than an hour ban
+ if ( nDurationHours < 1 )
+ {
+ g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#TF_Matchmaking_Ban_Duration_Remaining_Short" ), 2, wszDurationMinutes, wszMinutesRemaining );
+ }
+ else
+ {
+ g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#TF_Matchmaking_Ban_Duration_Remaining" ), 4, wszDurationHours, wszDurationMinutes, wszHoursRemaining, wszMinutesRemaining );
+ }
+ }
+ // Long ban (at least "nDaysForLongBan" days) but less than that remaining
+ else if ( nDaysRemaining < nDaysForLongBan )
+ {
+ g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "#TF_Matchmaking_Ban_Duration_Remaining_Long_Penalty_Short_Duration" ), 4, wszDurationDays, wszDurationHours, wszHoursRemaining, wszMinutesRemaining );
+ }
+ // Long ban and at least that long remaining)
+ else
+ {
+ g_pVGuiLocalize->ConstructString_safe( wszLocalized, g_pVGuiLocalize->Find( "TF_Matchmaking_Ban_Duration_Remaining_Long_Penalty" ), 4, wszDurationDays, wszDurationHours, wszDaysRemaining, wszHoursRemaining );
+ }
+ pBanLabel->SetText( wszLocalized );
+ }
+ else
+ {
+ pBanLabel->SetText( "#TF_Matchmaking_Ban_Duration_Remaining_Shortly" );
+ }
+ }
+ }
+ }
+
+ m_pNextButton->SetEnabled( m_bNextButtonEnabled && !bBanned && !bNoGC );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Handle cases not handled by our derived classes
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::HandleBackPressed()
+{
+ // We dont know how or why we got here. Failsafe and just leave.
+ if( GTFGCClientSystem()->GetSearchMode() != GetHandledMode() )
+ {
+ Msg( "Lobby handles mode %d, but search mode is %d. Ending matchmaking", (int)( GetHandledMode() ), (int)( GTFGCClientSystem()->GetSearchMode() ) );
+ }
+
+ GTFGCClientSystem()->EndMatchmaking();
+ ShowPanel( false );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CBaseLobbyContainerFrame::ShouldShowPartyButton() const
+{
+ return !m_pContents->IsPartyActiveGroupBoxVisible() &&
+ GTFGCClientSystem()->GetWizardStep() != TF_Matchmaking_WizardStep_SEARCHING &&
+ GCClientSystem()->BConnectedtoGC() &&
+ BIsPartyLeader();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::OpenOptionsContextMenu()
+{
+ if ( m_pContextMenu )
+ delete m_pContextMenu;
+
+ m_pContextMenu = new Menu( this, "ContextMenu" );
+ MenuBuilder contextMenuBuilder( m_pContextMenu, this );
+ const char *pszContextMenuBorder = "NotificationDefault";
+ const char *pszContextMenuFont = "HudFontMediumSecondary";
+ m_pContextMenu->SetBorder( scheme()->GetIScheme( GetScheme() )->GetBorder( pszContextMenuBorder ) );
+ m_pContextMenu->SetFont( scheme()->GetIScheme( GetScheme() )->GetFont( pszContextMenuFont ) );
+
+ contextMenuBuilder.AddMenuItem( "#TF_LobbyContainer_Ping", new KeyValues( "Context_Ping" ), "ping" );
+ contextMenuBuilder.AddMenuItem( "#TF_LobbyContainer_Help", "show_explanations", "help" );
+
+ m_pContextMenu->SetVisible(true);
+ m_pContextMenu->AddActionSignalTarget(this);
+
+ m_pContextMenu->MakeReadyForUse();
+
+ Panel* pOptionsButton = FindChildByName( "OptionsButton" );
+
+ if ( !pOptionsButton )
+ {
+ // Position to the cursor's position
+ int nX, nY;
+ g_pVGuiInput->GetCursorPosition( nX, nY );
+ m_pContextMenu->SetPos( nX - 1, nY - 1 );
+ }
+ else
+ {
+ int nOptionsX = pOptionsButton->GetXPos();
+ int nX = Min( nOptionsX, GetWide() - m_pContextMenu->GetWide() );
+ int nY = pOptionsButton->GetYPos() + pOptionsButton->GetTall();
+ m_pContextMenu->SetPos( nX - 1, nY - 1 );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CBaseLobbyContainerFrame::OpenPingOptions()
+{
+ // just create a new one. panel will destroy itself on close.
+ m_hPingPanel = new CTFPingPanel( this, "PingPanel", m_pContents->GetMatchGroup() );
+}