mirror of
https://github.com/nillerusr/source-engine.git
synced 2025-12-01 05:30:48 +00:00
2535 lines
71 KiB
C++
2535 lines
71 KiB
C++
//========= Copyright © 1996-2008, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=====================================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "VFoundGames.h"
|
|
#include "VGenericPanelList.h"
|
|
#include "EngineInterface.h"
|
|
#include "VFooterPanel.h"
|
|
#include "VHybridButton.h"
|
|
#include "VDropDownMenu.h"
|
|
#include "VFlyoutMenu.h"
|
|
#include "UIGameData.h"
|
|
#include "vdownloadcampaign.h"
|
|
#include "gameui_util.h"
|
|
|
|
#include "vgui/ISurface.h"
|
|
#include "vgui/IBorder.h"
|
|
#include "vgui_controls/Label.h"
|
|
#include "vgui_controls/Button.h"
|
|
#include "vgui_controls/ImagePanel.h"
|
|
#include "vgui/ILocalize.h"
|
|
#include "VGenericConfirmation.h"
|
|
#include "VGameSettings.h"
|
|
#include "vgetlegacydata.h"
|
|
#include "cdll_util.h"
|
|
#include "nb_header_footer.h"
|
|
#include "nb_button.h"
|
|
#include "fmtstr.h"
|
|
#include "smartptr.h"
|
|
#include "missionchooser/iasw_mission_chooser.h"
|
|
#include "missionchooser/iasw_mission_chooser_source.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
using namespace vgui;
|
|
using namespace BaseModUI;
|
|
|
|
ConVar ui_foundgames_spinner_time( "ui_foundgames_spinner_time", "1", FCVAR_DEVELOPMENTONLY );
|
|
ConVar ui_foundgames_update_time( "ui_foundgames_update_time", "1", FCVAR_DEVELOPMENTONLY );
|
|
ConVar ui_foundgames_fake_content( "ui_foundgames_fake_content", "0", FCVAR_DEVELOPMENTONLY );
|
|
ConVar ui_foundgames_fake_count( "ui_foundgames_fake_count", "0", FCVAR_DEVELOPMENTONLY );
|
|
|
|
void Demo_DisableButton( Button *pButton );
|
|
|
|
const char *COM_GetModDirectory();
|
|
|
|
static bool IsUserLIVEEnabled( int nUserID )
|
|
{
|
|
#ifdef _X360
|
|
return ( eXUserSigninState_SignedInToLive == XUserGetSigninState( nUserID ) );
|
|
#endif // _X360
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool AnyUserConnectedToLIVE()
|
|
{
|
|
#ifdef _X360
|
|
for ( uint idx = 0; idx < XBX_GetNumGameUsers(); ++ idx )
|
|
{
|
|
if ( IsUserLIVEEnabled( XBX_GetUserId( idx ) ) )
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
static char const * NoTeamGameMode( char const * szGameMode )
|
|
{
|
|
if ( char const *szNoTeamMode = StringAfterPrefix( szGameMode, "team" ) )
|
|
return szNoTeamMode;
|
|
else
|
|
return szGameMode;
|
|
}
|
|
|
|
bool BaseModUI::FoundGameListItem::Info::IsJoinable() const
|
|
{
|
|
return mbInGame && mIsJoinable;
|
|
}
|
|
|
|
bool BaseModUI::FoundGameListItem::Info::IsDLC() const
|
|
{
|
|
if ( IsX360() )
|
|
return mbDLC;
|
|
|
|
return false;
|
|
}
|
|
|
|
char const * BaseModUI::FoundGameListItem::Info::IsOtherTitle() const
|
|
{
|
|
if ( mchOtherTitle[0] )
|
|
return mchOtherTitle;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool BaseModUI::FoundGameListItem::Info::IsDownloadable() const
|
|
{
|
|
if ( IsX360() )
|
|
return false;
|
|
|
|
if ( mbInGame && mpGameDetails )
|
|
{
|
|
IASW_Mission_Chooser_Source *pSource = missionchooser ? missionchooser->LocalMissionSource() : NULL;
|
|
if ( pSource )
|
|
{
|
|
const char *szMissionName = mpGameDetails->GetString( "game/mission", "" );
|
|
KeyValues *pMissionKeys = pSource->GetMissionDetails( szMissionName );
|
|
char const *szWebsite = mpGameDetails->GetString( "game/missioninfo/website", NULL );
|
|
if ( ( !pMissionKeys || Q_stricmp( pMissionKeys->GetString( "version", "" ),
|
|
mpGameDetails->GetString( "game/missioninfo/version", "" ) ) )
|
|
&& ( szWebsite && *szWebsite ) )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
const char * BaseModUI::FoundGameListItem::Info::GetJoinButtonHint() const
|
|
{
|
|
if ( IsOtherTitle() )
|
|
{
|
|
return "#L4D360UI_FoundGames_Join_Modded";
|
|
}
|
|
if ( IsDLC() || IsDownloadable() )
|
|
{
|
|
return "#L4D360UI_FoundGames_Join_Download";
|
|
}
|
|
|
|
if ( IsJoinable() )
|
|
{
|
|
return "#L4D360UI_FoundGames_Join_Success";
|
|
}
|
|
|
|
int numSlots = mpGameDetails->GetInt( "members/numSlots", 0 );
|
|
int numPlayers = mpGameDetails->GetInt( "members/numPlayers", 0 );
|
|
|
|
if ( numSlots <= 0 )
|
|
return "#L4D360UI_FoundGames_Join_Fail_Not_In_Joinable";
|
|
|
|
if ( numPlayers >= numSlots )
|
|
return "#L4D360UI_FoundGames_Join_Fail_No_Slots";
|
|
|
|
if ( !Q_stricmp( "private", mpGameDetails->GetString( "system/access", "" ) ) )
|
|
return "#L4D360UI_FoundGames_Join_Fail_Private_Game";
|
|
|
|
return "#L4D360UI_FoundGames_Join_Fail_Not_In_Joinable";
|
|
}
|
|
|
|
const char * BaseModUI::FoundGameListItem::Info::GetNonJoinableShortHint() const
|
|
{
|
|
int numSlots = mpGameDetails->GetInt( "members/numSlots", 0 );
|
|
int numPlayers = mpGameDetails->GetInt( "members/numPlayers", 0 );
|
|
|
|
if ( !numSlots )
|
|
return ""; //#L4D360UI_Lobby_NotInJoinableGame";
|
|
|
|
if ( numPlayers >= numSlots )
|
|
return "#L4D360UI_WaitScreen_GameFull";
|
|
|
|
if ( !Q_stricmp( "private", mpGameDetails->GetString( "system/access", "" ) ) )
|
|
return "#L4D360UI_WaitScreen_GamePrivate";
|
|
|
|
return "";
|
|
}
|
|
|
|
//=============================================================================
|
|
//
|
|
//=============================================================================
|
|
FoundGameListItem::FoundGameListItem( vgui::Panel *parent, const char *panelName ):
|
|
BaseClass( parent, panelName ),
|
|
m_pListCtrlr( ( GenericPanelList * ) parent )
|
|
{
|
|
m_pImgPing = NULL;
|
|
m_pLblPing = NULL;
|
|
m_pLblPlayerGamerTag = NULL;
|
|
m_pLblDifficulty = NULL;
|
|
m_pLblSwarmState = NULL;
|
|
m_pLblPlayers = NULL;
|
|
m_pLblNotJoinable = NULL;
|
|
|
|
SetProportional( true );
|
|
|
|
SetGameIndex( m_FullInfo );
|
|
|
|
SetPaintBackgroundEnabled( true );
|
|
|
|
m_sweep = 0;
|
|
m_bSelected = false;
|
|
m_bHasMouseover = false;
|
|
|
|
CBaseModFrame::AddFrameListener( this );
|
|
}
|
|
|
|
//=============================================================================
|
|
FoundGameListItem::~FoundGameListItem()
|
|
{
|
|
if ( m_FullInfo.mpGameDetails )
|
|
m_FullInfo.mpGameDetails->deleteThis();
|
|
m_FullInfo.mpGameDetails = NULL;
|
|
|
|
CBaseModFrame::RemoveFrameListener( this );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::SetAvatarXUID( XUID xuid )
|
|
{
|
|
if ( IsPC() )
|
|
{
|
|
vgui::ImagePanel *imgAvatar = dynamic_cast< vgui::ImagePanel* >( FindChildByName( "PnlGamerPic" ) );
|
|
vgui::ImagePanel *pnlModPic = dynamic_cast< vgui::ImagePanel* >( FindChildByName( "PnlModPic" ) );
|
|
|
|
if ( GetFullInfo().mInfoType == FGT_PUBLICGAME && pnlModPic )
|
|
{
|
|
SetControlVisible( "ImgAvatarBG", false );
|
|
|
|
// TODO: Show wrench icon for custom missions/campaigns
|
|
/*
|
|
char const *szCampaign = GetFullInfo().mpGameDetails->GetString( "game/campaign", "" );
|
|
KeyValues *pCampaignInfo = ( szCampaign && *szCampaign ) ? g_pMatchExtSwarm->GetAllMissions()->FindKey( szCampaign ) : NULL;
|
|
if ( pCampaignInfo )
|
|
{
|
|
if ( pCampaignInfo->GetInt( "builtin" ) )
|
|
{
|
|
//pnlModPic->SetImage( "icon_l4d" );
|
|
pnlModPic->SetVisible( false );
|
|
}
|
|
else
|
|
{
|
|
pnlModPic->SetImage( "icon_modwrench" );
|
|
pnlModPic->SetVisible( true );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pnlModPic->SetImage( "icon_download" );
|
|
pnlModPic->SetVisible( true );
|
|
}
|
|
*/
|
|
|
|
|
|
imgAvatar->SetVisible( false );
|
|
}
|
|
else if ( imgAvatar )
|
|
{
|
|
if ( xuid != 0 )
|
|
{
|
|
IImage *pImage = NULL;
|
|
|
|
if ( m_FullInfo.mInfoType == FoundGameListItem::FGT_PLAYER )
|
|
pImage = CUIGameData::Get()->GetAvatarImage( xuid );
|
|
|
|
if ( pImage )
|
|
{
|
|
imgAvatar->SetImage( pImage );
|
|
}
|
|
else
|
|
{
|
|
imgAvatar->SetImage( "icon_lobby" );
|
|
}
|
|
|
|
SetControlVisible( "ImgAvatarBG", ( pImage != NULL ) );
|
|
}
|
|
else
|
|
{
|
|
imgAvatar->SetImage( "icon_lobby" );
|
|
SetControlVisible( "ImgAvatarBG", false );
|
|
}
|
|
|
|
imgAvatar->SetVisible( true );
|
|
pnlModPic->SetVisible( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FoundGameListItem::SetSweep( bool sweep )
|
|
{
|
|
m_sweep = sweep;
|
|
}
|
|
|
|
bool FoundGameListItem::IsSweep() const
|
|
{
|
|
return m_sweep;
|
|
}
|
|
|
|
void FoundGameListItem::SetGameIndex( const Info& fi )
|
|
{
|
|
if ( m_FullInfo.mpGameDetails != fi.mpGameDetails )
|
|
{
|
|
if ( m_FullInfo.mpGameDetails )
|
|
m_FullInfo.mpGameDetails->deleteThis();
|
|
|
|
m_FullInfo = fi;
|
|
m_FullInfo.mpGameDetails = fi.mpGameDetails ? fi.mpGameDetails->MakeCopy() : NULL;
|
|
}
|
|
else
|
|
{
|
|
m_FullInfo = fi;
|
|
}
|
|
|
|
SetAvatarXUID( fi.mFriendXUID );
|
|
SetGamerTag( fi.Name );
|
|
|
|
SetGamePing( fi.mPing );
|
|
|
|
if ( fi.miPing > 0 )
|
|
{
|
|
SetControlString( "LblPing", VarArgs( "%d", fi.miPing ) );
|
|
}
|
|
|
|
if ( IsPC() )
|
|
SetControlVisible( "ImgPingSmall", ( fi.miPing > 0 ) );
|
|
|
|
if ( fi.IsDLC() )
|
|
{
|
|
if( m_pLblNotJoinable )
|
|
{
|
|
m_pLblNotJoinable->SetText( "#L4D2360_FoundGames_DLC" );
|
|
}
|
|
|
|
SetGamePlayerCount( 0, 0 );
|
|
SetGameDifficulty( "" );
|
|
SetSwarmState( "" );
|
|
}
|
|
else if ( char const *szOtherTitle = fi.IsOtherTitle() )
|
|
{
|
|
if( m_pLblNotJoinable )
|
|
{
|
|
wchar_t convertedString[64];
|
|
g_pVGuiLocalize->ConvertANSIToUnicode( szOtherTitle, convertedString, sizeof( convertedString ) );
|
|
wchar_t finalString[128];
|
|
g_pVGuiLocalize->ConstructString( finalString, sizeof( finalString ), g_pVGuiLocalize->Find( "#L4D360UI_Not_Joinable_Mod" ), 1, convertedString );
|
|
|
|
m_pLblNotJoinable->SetText( finalString );
|
|
}
|
|
|
|
SetGamePlayerCount( 0, 0 );
|
|
SetGameDifficulty( "" );
|
|
SetSwarmState( "" );
|
|
}
|
|
else if ( fi.IsJoinable() || fi.IsDownloadable() )
|
|
{
|
|
int numSlots = fi.mpGameDetails->GetInt( "members/numSlots", 0 );
|
|
int numPlayers = fi.mpGameDetails->GetInt( "members/numPlayers", 0 );
|
|
|
|
SetGamePlayerCount( numPlayers , numSlots );
|
|
|
|
char const *szMode = fi.mpGameDetails->GetString( "game/mode", "campaign" );
|
|
|
|
if ( !Q_stricmp( "finale", fi.mpGameDetails->GetString( "game/state", "" ) ) )
|
|
{
|
|
// Display it as in finale, hide the playercount, but it's still joinable if they really want to.
|
|
SetGameDifficulty( "#L4D360UI_WaitScreen_GameInFinale" );
|
|
SetGamePlayerCount( 0, 0 );
|
|
}
|
|
else if( !GameModeHasDifficulty( szMode ) )
|
|
{
|
|
SetGameDifficulty( CFmtStr( "#L4D360UI_Mode_%s", szMode ) );
|
|
}
|
|
else
|
|
{
|
|
char const *szDiff = fi.mpGameDetails->GetString( "game/difficulty", "normal" );
|
|
char chDiffBuffer[64];
|
|
Q_snprintf( chDiffBuffer, sizeof( chDiffBuffer ), "#L4D360UI_Difficulty_%s_%s", szDiff, szMode );
|
|
SetGameDifficulty( chDiffBuffer );
|
|
}
|
|
|
|
char const *szDiff = fi.mpGameDetails->GetString( "game/swarmstate", "ingame" );
|
|
Msg( "Adding a server to the list:\n" );
|
|
KeyValuesDumpAsDevMsg( fi.mpGameDetails );
|
|
if ( !Q_stricmp( szDiff, "ingame" ) )
|
|
{
|
|
SetSwarmState( "#L4D360UI_ingame" );
|
|
}
|
|
else
|
|
{
|
|
SetSwarmState( "#L4D360UI_briefing" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( m_pLblNotJoinable )
|
|
{
|
|
char const *szHint = fi.GetNonJoinableShortHint();
|
|
if ( !szHint || !*szHint )
|
|
szHint = "#L4D360UI_Lobby_NotInJoinableGame";
|
|
|
|
m_pLblNotJoinable->SetText( szHint );
|
|
}
|
|
|
|
SetGamePlayerCount( 0, 0 );
|
|
SetGameDifficulty( "" );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
const FoundGameListItem::Info& FoundGameListItem::GetFullInfo()
|
|
{
|
|
return m_FullInfo;
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::SetGamerTag( char const* gamerTag )
|
|
{
|
|
if( m_pLblPlayerGamerTag )
|
|
{
|
|
m_pLblPlayerGamerTag->SetText( gamerTag ? gamerTag : "" );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::SetGamePing( Info::GAME_PING ping )
|
|
{
|
|
if( m_pImgPing )
|
|
{
|
|
switch( ping )
|
|
{
|
|
case Info::GP_LOW:
|
|
m_pImgPing->SetImage( "icon_con_high" );
|
|
break;
|
|
|
|
case Info::GP_MEDIUM:
|
|
m_pImgPing->SetImage( "icon_con_medium" );
|
|
break;
|
|
|
|
case Info::GP_HIGH:
|
|
m_pImgPing->SetImage( "icon_con_low" );
|
|
break;
|
|
|
|
case Info::GP_SYSTEMLINK:
|
|
m_pImgPing->SetImage( "icon_lan" );
|
|
break;
|
|
|
|
case Info::GP_NONE:
|
|
m_pImgPing->SetImage( "" );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::SetGameDifficulty( const char *difficultyName )
|
|
{
|
|
if( m_pLblDifficulty )
|
|
{
|
|
m_pLblDifficulty->SetText( difficultyName ? difficultyName : "" );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::SetSwarmState( const char *szSwarmStateText )
|
|
{
|
|
if( m_pLblSwarmState )
|
|
{
|
|
m_pLblSwarmState->SetText( szSwarmStateText ? szSwarmStateText : "" );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::SetGamePlayerCount( int current, int max )
|
|
{
|
|
if( m_pLblPlayers )
|
|
{
|
|
if ( GetFullInfo().mInfoType == FGT_PUBLICGAME )
|
|
{
|
|
max = GetFullInfo().mpGameDetails->GetInt( "rollup/game", 0 ) +
|
|
GetFullInfo().mpGameDetails->GetInt( "rollup/lobby", 0 );
|
|
|
|
wchar_t finalString[256] = L"";
|
|
|
|
const wchar_t *countText = NULL;
|
|
|
|
extern ConVar ui_public_lobby_filter_status;
|
|
if ( !Q_stricmp( ui_public_lobby_filter_status.GetString(), "lobby" ) )
|
|
{
|
|
countText = ( max == 1 ) ?
|
|
g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_LobbyCount_1" ) :
|
|
g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_LobbyCount" );
|
|
}
|
|
else
|
|
{
|
|
countText = ( max == 1 ) ?
|
|
g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_GameCount_1" ) :
|
|
g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_GameCount" );
|
|
}
|
|
|
|
if( countText )
|
|
{
|
|
wchar_t convertedString[256];
|
|
V_snwprintf( convertedString, ARRAYSIZE( convertedString ), L"%d", max );
|
|
g_pVGuiLocalize->ConstructString( finalString, sizeof( finalString ), countText, 1, convertedString );
|
|
}
|
|
|
|
m_pLblPlayers->SetText( finalString );
|
|
}
|
|
else if( current >= 0 && max != 0 )
|
|
{
|
|
char countText[256];
|
|
V_snprintf( countText, 256, "%d/%d", current, max );
|
|
m_pLblPlayers->SetText( countText );
|
|
}
|
|
else
|
|
{
|
|
m_pLblPlayers->SetText( "" );
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::DrawListItemLabel( vgui::Label* label, bool bSmallFont, bool bEastAligned /* = false */ )
|
|
{
|
|
int panelWide, panelTall;
|
|
GetSize( panelWide, panelTall );
|
|
|
|
if ( label )
|
|
{
|
|
bool bHasFocus = HasFocus() || HasMouseover() || IsSelected();
|
|
|
|
Color col( 100, 100, 100, 255 );
|
|
if ( bHasFocus )
|
|
{
|
|
col.SetColor( 255, 255, 255, 255 );
|
|
}
|
|
|
|
int x, y;
|
|
wchar_t szUnicode[512];
|
|
|
|
label->GetText( szUnicode, sizeof( szUnicode ) );
|
|
label->GetPos( x, y );
|
|
|
|
HFont drawFont = ( bSmallFont ) ? ( m_hSmallTextFont ) : ( m_hTextFont );
|
|
HFont blurFont = ( bSmallFont ) ? ( m_hSmallTextBlurFont ) : ( m_hTextBlurFont );
|
|
|
|
int len = V_wcslen( szUnicode );
|
|
int textWide, textTall;
|
|
surface()->GetTextSize( drawFont, szUnicode, textWide, textTall ); // this is just ballpark numbers as they don't count & characters
|
|
|
|
// If we drew labels properly I wouldn't be here on a saturday writing code like this:
|
|
// Cannot ask surface about whole text size as it will skip & characters that can be
|
|
// in player names
|
|
int labelWide = label->GetWide();
|
|
if ( labelWide > 0 )
|
|
{
|
|
textWide = 0;
|
|
HFont wideFont = bHasFocus ? blurFont : drawFont;
|
|
for ( int i=0;i<len;i++ )
|
|
{
|
|
textWide += surface()->GetCharacterWidth( wideFont, szUnicode[i] );
|
|
|
|
if ( textWide > labelWide )
|
|
{
|
|
int dotWide = surface()->GetCharacterWidth( wideFont, '.' );
|
|
for ( int k = 3; k -- > 0; )
|
|
{
|
|
if ( i > k )
|
|
{
|
|
textWide += dotWide - surface()->GetCharacterWidth( wideFont, szUnicode[i-k-1] );
|
|
szUnicode[i-k-1] = '.';
|
|
}
|
|
}
|
|
|
|
szUnicode[i] = 0;
|
|
len = i;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// vertical center
|
|
y = ( panelTall - textTall ) / 2;
|
|
|
|
if ( bEastAligned )
|
|
{
|
|
x += labelWide - textWide;
|
|
}
|
|
|
|
vgui::surface()->DrawSetTextFont( drawFont );
|
|
vgui::surface()->DrawSetTextPos( x, y );
|
|
vgui::surface()->DrawSetTextColor( col );
|
|
vgui::surface()->DrawPrintText( szUnicode, len );
|
|
|
|
if ( bHasFocus )
|
|
{
|
|
// draw glow
|
|
int alpha = 60.0f + 30.0f * sin( Plat_FloatTime() * 4.0f );
|
|
vgui::surface()->DrawSetTextColor( Color( 255, 255, 255, alpha ) );
|
|
vgui::surface()->DrawSetTextFont( blurFont );
|
|
vgui::surface()->DrawSetTextPos( x, y );
|
|
vgui::surface()->DrawPrintText( szUnicode, len );
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::PaintBackground()
|
|
{
|
|
if ( !m_pListCtrlr->IsPanelItemVisible( this ) )
|
|
return;
|
|
|
|
// if we're hilighted, background
|
|
if ( IsSelected() )
|
|
{
|
|
int y;
|
|
int x;
|
|
GetPos( x, y );
|
|
int tall = GetTall() * 0.9;
|
|
y = ( GetTall() - tall ) / 2;
|
|
int wide = GetWide();
|
|
|
|
// draw border lines
|
|
surface()->DrawSetColor( Color( 65, 74, 96, 255 ) );
|
|
surface()->DrawFilledRectFade( x, y, x + 0.5f * wide, y+2, 0, 255, true );
|
|
surface()->DrawFilledRectFade( x + 0.5f * wide, y, x + wide, y+2, 255, 0, true );
|
|
surface()->DrawFilledRectFade( x, y+tall-2, x + 0.5f * wide, y+tall, 0, 255, true );
|
|
surface()->DrawFilledRectFade( x + 0.5f * wide, y+tall-2, x + wide, y+tall, 255, 0, true );
|
|
|
|
int blotchWide = GetWide();
|
|
int blotchX = 0;
|
|
surface()->DrawFilledRectFade( blotchX, y, blotchX + 0.25f * blotchWide, y+tall, 0, 150, true );
|
|
surface()->DrawFilledRectFade( blotchX + 0.25f * blotchWide, y, blotchX + blotchWide, y+tall, 150, 0, true );
|
|
}
|
|
|
|
DrawListItemLabel( m_pLblPing, true, !IsPC() );
|
|
|
|
DrawListItemLabel( m_pLblPlayerGamerTag, true );
|
|
|
|
// Depending on the game info different labels get rendered in the list
|
|
const Info &fi = m_FullInfo;
|
|
|
|
if ( fi.IsDLC() || fi.IsOtherTitle() )
|
|
{
|
|
DrawListItemLabel( m_pLblNotJoinable, true );
|
|
}
|
|
else if ( fi.IsJoinable() || fi.IsDownloadable() )
|
|
{
|
|
DrawListItemLabel( m_pLblDifficulty, true );
|
|
DrawListItemLabel( m_pLblPlayers, true );
|
|
DrawListItemLabel( m_pLblSwarmState, true );
|
|
}
|
|
else
|
|
{
|
|
DrawListItemLabel( m_pLblNotJoinable, true );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::CmdJoinGame()
|
|
{
|
|
if ( !m_FullInfo.IsJoinable() || !m_FullInfo.mpfnJoinGame )
|
|
{
|
|
const char *szShortHint = m_FullInfo.GetNonJoinableShortHint();
|
|
|
|
if ( m_FullInfo.IsDLC() )
|
|
szShortHint = "#L4D2360_FoundGames_DLC_Msg";
|
|
|
|
if ( char const *szOtherTitle = m_FullInfo.IsOtherTitle() )
|
|
{
|
|
szShortHint = "#L4D2360_JoinError_OtherTitle_Modded"; // waitscreen needs a static str ptr
|
|
}
|
|
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_DENY );
|
|
|
|
CBaseModFrame *pWaitScreen = CBaseModPanel::GetSingleton().GetWindow( WT_GENERICWAITSCREEN );
|
|
if ( pWaitScreen )
|
|
// Do not show a second waitscreen that can potentially lead to focus loss
|
|
// when a waitscreen will assume that another waitscreen is the caller.
|
|
return;
|
|
|
|
if ( szShortHint && *szShortHint )
|
|
{
|
|
CUIGameData::Get()->OpenWaitScreen( szShortHint );
|
|
CUIGameData::Get()->CloseWaitScreen( NULL, NULL );
|
|
}
|
|
return;
|
|
}
|
|
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_ACCEPT );
|
|
|
|
(*m_FullInfo.mpfnJoinGame)( m_FullInfo );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::CmdViewGamercard()
|
|
{
|
|
#ifdef _X360
|
|
int iUserSlot = CBaseModPanel::GetSingleton().GetLastActiveUserId();
|
|
int iUserId = XBX_GetUserId( iUserSlot );
|
|
|
|
// Warn a player who tries to access a gamer card without multiplayer priviledges that they may not do so
|
|
if ( IsUserLIVEEnabled( iUserId ) == false )
|
|
{
|
|
bool bReplacementFound = false;
|
|
for ( unsigned int i = 0; i < XBX_GetNumGameUsers(); ++ i )
|
|
{
|
|
if ( IsUserLIVEEnabled( XBX_GetUserId( i ) ) )
|
|
{
|
|
// Swap with the first player that CAN make this request
|
|
iUserId = XBX_GetUserId( i );
|
|
bReplacementFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// No valid user there to call from, so just reject the call
|
|
if ( bReplacementFound == false )
|
|
return;
|
|
}
|
|
|
|
if( FGT_PLAYER == m_FullInfo.mInfoType )
|
|
{
|
|
XUID xuidView = m_FullInfo.mpGameDetails->GetUint64( "player/xuidOnline", 0ull );
|
|
if ( !xuidView )
|
|
xuidView = m_FullInfo.mpGameDetails->GetUint64( "player/xuid", 0ull );
|
|
if ( !xuidView )
|
|
xuidView = m_FullInfo.mFriendXUID;
|
|
|
|
if ( xuidView )
|
|
{
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_ACCEPT );
|
|
XShowGamerCardUI( iUserId, xuidView );
|
|
}
|
|
}
|
|
#endif // _X360
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::OnKeyCodePressed( KeyCode code )
|
|
{
|
|
int iUserSlot = GetJoystickForCode( code );
|
|
CBaseModPanel::GetSingleton().SetLastActiveUserId( iUserSlot );
|
|
|
|
switch( GetBaseButtonCode( code ) )
|
|
{
|
|
case KEY_XBUTTON_A:
|
|
case KEY_ENTER:
|
|
CmdJoinGame();
|
|
break;
|
|
case KEY_XBUTTON_Y:
|
|
CmdViewGamercard();
|
|
break;
|
|
|
|
case KEY_XSTICK1_RIGHT:
|
|
case KEY_XSTICK2_RIGHT:
|
|
case KEY_XBUTTON_RIGHT:
|
|
case KEY_RIGHT:
|
|
if( m_pListCtrlr->NavigateRight() )
|
|
{
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_FOCUS );
|
|
NavigateFrom();
|
|
}
|
|
break;
|
|
|
|
case KEY_XSTICK1_LEFT:
|
|
case KEY_XSTICK2_LEFT:
|
|
case KEY_XBUTTON_LEFT:
|
|
case KEY_LEFT:
|
|
if( m_pListCtrlr->NavigateLeft() )
|
|
{
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_FOCUS );
|
|
NavigateFrom();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
BaseClass::OnKeyCodePressed( code );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void FoundGameListItem::OnKeyCodeTyped( vgui::KeyCode code )
|
|
{
|
|
switch( code )
|
|
{
|
|
case KEY_TAB:
|
|
if( m_pListCtrlr->NavigateDown() )
|
|
{
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_FOCUS );
|
|
NavigateFrom();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
BaseClass::OnKeyCodePressed( code );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::OnMousePressed( vgui::MouseCode code )
|
|
{
|
|
FlyoutMenu::CloseActiveMenu();
|
|
switch ( code )
|
|
{
|
|
case MOUSE_LEFT:
|
|
m_pListCtrlr->SelectPanelItemByPanel( this );
|
|
break;
|
|
}
|
|
BaseClass::OnMousePressed( code );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::OnMouseDoublePressed(MouseCode code)
|
|
{
|
|
/*
|
|
switch ( code )
|
|
{
|
|
case MOUSE_LEFT:
|
|
// act as though the 360 "A" button got pressed
|
|
OnKeyCodePressed( ButtonCodeToJoystickButtonCode( KEY_XBUTTON_A, CBaseModPanel::GetSingleton().GetLastActiveUserId() ) );
|
|
break;
|
|
}
|
|
*/
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::ApplySettings( KeyValues *inResourceData )
|
|
{
|
|
BaseClass::ApplySettings( inResourceData );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::ApplySchemeSettings( IScheme *pScheme )
|
|
{
|
|
BaseClass::ApplySchemeSettings( pScheme );
|
|
|
|
LoadControlSettings( CFmtStr( "Resource/UI/BaseModUI/%s.res", GetName() ) );
|
|
|
|
//////////////////////////////////////////////////////
|
|
// !!!!! THE ENABLED STATES CONTROL VISIBILITY !!!! //
|
|
//////////////////////////////////////////////////////
|
|
// We paint the controls ourselves to achieve the new look, so they must be non-visible to allow that
|
|
// Toggle the enabled to make them draw/notdraw
|
|
|
|
m_pImgPing = dynamic_cast< vgui::ImagePanel * > ( FindChildByName( "ImgPing" ) );
|
|
if ( m_pImgPing )
|
|
{
|
|
m_pImgPing->SetVisible( false );
|
|
}
|
|
|
|
m_pLblPing = dynamic_cast< vgui::Label * > ( FindChildByName( "LblPing" ) );
|
|
if ( m_pLblPing )
|
|
{
|
|
m_pLblPing->SetVisible( false );
|
|
}
|
|
|
|
m_pLblPlayerGamerTag = dynamic_cast< vgui::Label * > ( FindChildByName( "LblGamerTag" ) );
|
|
if ( m_pLblPlayerGamerTag )
|
|
{
|
|
m_pLblPlayerGamerTag->SetVisible( false );
|
|
}
|
|
m_pLblDifficulty = dynamic_cast< vgui::Label * > ( FindChildByName( "LblDifficulty" ) );
|
|
if ( m_pLblDifficulty )
|
|
{
|
|
m_pLblDifficulty->SetVisible( false );
|
|
}
|
|
m_pLblSwarmState = dynamic_cast< vgui::Label * > ( FindChildByName( "LblSwarmState" ) );
|
|
if ( m_pLblSwarmState )
|
|
{
|
|
m_pLblSwarmState->SetVisible( false );
|
|
}
|
|
m_pLblPlayers = dynamic_cast< vgui::Label * > ( FindChildByName( "LblNumPlayers" ) );
|
|
if ( m_pLblPlayers )
|
|
{
|
|
m_pLblPlayers->SetVisible( false );
|
|
}
|
|
|
|
m_pLblNotJoinable = dynamic_cast< vgui::Label * > ( FindChildByName( "LblNotJoinable" ) );
|
|
if ( m_pLblNotJoinable )
|
|
{
|
|
m_pLblNotJoinable->SetVisible( false );
|
|
}
|
|
|
|
m_hTextFont = pScheme->GetFont( "Default", true );
|
|
m_hTextBlurFont = pScheme->GetFont( "DefaultBlur", true );
|
|
|
|
m_hSmallTextFont = pScheme->GetFont( "DefaultMedium", true );
|
|
m_hSmallTextBlurFont = pScheme->GetFont( "DefaultMediumBlur", true );
|
|
|
|
// Parse our own info again now that we have controls
|
|
SetGameIndex( m_FullInfo );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::PerformLayout()
|
|
{
|
|
BaseClass::PerformLayout();
|
|
|
|
// set all our children (image panel and labels) to not accept mouse input so they
|
|
// don't eat any mouse input and it all goes to us
|
|
for ( int i = 0; i < GetChildCount(); i++ )
|
|
{
|
|
Panel *panel = GetChild( i );
|
|
Assert( panel );
|
|
panel->SetMouseInputEnabled( false );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGameListItem::OnCursorEntered()
|
|
{
|
|
if( GetParent() )
|
|
{
|
|
GetParent()->NavigateToChild( this );
|
|
}
|
|
else
|
|
{
|
|
NavigateTo();
|
|
}
|
|
}
|
|
|
|
void FoundGameListItem::NavigateTo( void )
|
|
{
|
|
#ifdef _X360
|
|
m_pListCtrlr->SelectPanelItemByPanel( this );
|
|
#else
|
|
SetHasMouseover( true );
|
|
RequestFocus();
|
|
#endif
|
|
BaseClass::NavigateTo();
|
|
}
|
|
|
|
void FoundGameListItem::NavigateFrom( void )
|
|
{
|
|
SetHasMouseover( false );
|
|
BaseClass::NavigateFrom();
|
|
#ifdef _X360
|
|
OnClose();
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef _X360
|
|
void FoundGames::NavigateTo()
|
|
{
|
|
BaseClass::NavigateTo();
|
|
|
|
m_GplGames->NavigateTo();
|
|
}
|
|
#endif
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
//=============================================================================
|
|
|
|
//=============================================================================
|
|
FoundGames::FoundGames( Panel *parent, const char *panelName ):
|
|
BaseClass( parent, panelName, true, true, false ),
|
|
m_flSearchStartedTime( 0.0f ), m_flSearchEndTime( 0.0f ),
|
|
m_pDataSettings( NULL ),
|
|
m_pPreviousSelectedItem( NULL ),
|
|
m_flScheduledUpdateGameDetails( 0.0f )
|
|
{
|
|
SetProportional( true );
|
|
SetPaintBackgroundEnabled( true );
|
|
|
|
m_pHeaderFooter = new CNB_Header_Footer( this, "HeaderFooter" );
|
|
m_pHeaderFooter->SetTitle( "" );
|
|
m_pHeaderFooter->SetHeaderEnabled( false );
|
|
m_pHeaderFooter->SetFooterEnabled( true );
|
|
m_pHeaderFooter->SetGradientBarEnabled( true );
|
|
m_pHeaderFooter->SetGradientBarPos( 80, 315 );
|
|
|
|
m_pTitle = new vgui::Label( this, "Title", "" );
|
|
|
|
|
|
m_GplGames = new GenericPanelList( this, "GplGames", GenericPanelList::ISM_PERITEM );
|
|
m_GplGames->SetPaintBackgroundEnabled( true );
|
|
|
|
m_LastEngineSpinnerTime = 0.0f;
|
|
m_CurrentSpinnerValue = 0;
|
|
|
|
SetLowerGarnishEnabled( true );
|
|
|
|
OnItemSelected( NULL );
|
|
|
|
SetDeleteSelfOnClose( true );
|
|
}
|
|
|
|
//=============================================================================
|
|
FoundGames::~FoundGames()
|
|
{
|
|
g_pMatchFramework->GetEventsSubscription()->Unsubscribe( this );
|
|
|
|
if ( m_pDataSettings )
|
|
m_pDataSettings->deleteThis();
|
|
m_pDataSettings = NULL;
|
|
|
|
delete m_GplGames;
|
|
|
|
RemoveFrameListener( this );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::Activate()
|
|
{
|
|
BaseClass::Activate();
|
|
|
|
AddFrameListener( this );
|
|
|
|
UpdateGameDetails();
|
|
m_GplGames->NavigateTo();
|
|
|
|
UpdateFooterButtons();
|
|
|
|
if ( BaseModHybridButton *pWndCreateGame = dynamic_cast< BaseModHybridButton * >( FindChildByName( "DrpCreateGame" ) ) )
|
|
{
|
|
pWndCreateGame->SetVisible( CanCreateGame() );
|
|
pWndCreateGame->SetText( CFmtStr( "#L4D360UI_FoudGames_CreateNew_%s", "campaign" ) );
|
|
}
|
|
if ( CNB_Button *pWndCreateGame = dynamic_cast< CNB_Button * >( FindChildByName( "BtnCreateNewGame" ) ) )
|
|
{
|
|
pWndCreateGame->SetVisible( CanCreateGame() );
|
|
pWndCreateGame->SetText( CFmtStr( "#L4D360UI_FoudGames_CreateNew_%s", "campaign" ) );
|
|
}
|
|
|
|
if ( Panel *pLabelX = FindChildByName( "LblPressX" ) )
|
|
pLabelX->SetVisible( CanCreateGame() );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::OnCommand( const char *command )
|
|
{
|
|
if( V_strcmp( command, "Back" ) == 0 )
|
|
{
|
|
// Act as though 360 B button was pressed
|
|
OnKeyCodePressed( ButtonCodeToJoystickButtonCode( KEY_XBUTTON_B, CBaseModPanel::GetSingleton().GetLastActiveUserId() ) );
|
|
}
|
|
else if( V_strcmp( command, "CreateGame" ) == 0 )
|
|
{
|
|
if ( !CanCreateGame() )
|
|
{
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_INVALID );
|
|
return;
|
|
}
|
|
|
|
KeyValues *pSettings = KeyValues::FromString(
|
|
"settings",
|
|
" system { "
|
|
" network LIVE "
|
|
" access friends "
|
|
" } "
|
|
" game { "
|
|
" mode = "
|
|
" campaign = "
|
|
" mission = "
|
|
" } "
|
|
" options { "
|
|
" action create "
|
|
" } "
|
|
);
|
|
KeyValues::AutoDelete autodelete( pSettings );
|
|
|
|
char const *szGameMode = "campaign";
|
|
pSettings->SetString( "game/mode", szGameMode );
|
|
pSettings->SetString( "game/campaign", "jacob" );
|
|
pSettings->SetString( "game/mission", "asi-jac1-landingbay_01" );
|
|
|
|
if ( !CUIGameData::Get()->SignedInToLive() )
|
|
{
|
|
pSettings->SetString( "system/network", "lan" );
|
|
pSettings->SetString( "system/access", "public" );
|
|
}
|
|
|
|
if ( StringHasPrefix( szGameMode, "team" ) )
|
|
{
|
|
pSettings->SetString( "system/netflag", "teamlobby" );
|
|
}
|
|
else if ( !Q_stricmp( "custommatch", m_pDataSettings->GetString( "options/action", "" ) ) )
|
|
{
|
|
pSettings->SetString( "system/access", "public" );
|
|
}
|
|
|
|
// TCR: We need to respect the default difficulty
|
|
pSettings->SetString( "game/difficulty", GameModeGetDefaultDifficulty( szGameMode ) );
|
|
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_ACCEPT );
|
|
CBaseModPanel::GetSingleton().CloseAllWindows();
|
|
CBaseModPanel::GetSingleton().OpenWindow( WT_GAMESETTINGS, NULL, true, pSettings );
|
|
}
|
|
else if ( V_strcmp( command, "JoinSelected" ) == 0 )
|
|
{
|
|
FoundGameListItem *pSelectedItem = static_cast< FoundGameListItem * >( m_GplGames->GetSelectedPanelItem() );
|
|
if ( pSelectedItem )
|
|
{
|
|
PostMessage( pSelectedItem, new KeyValues( "JoinGame" ) );
|
|
}
|
|
}
|
|
else if ( !V_strcmp( command, "DownloadSelected" ) || !V_strcmp( command, "Website" ) )
|
|
{
|
|
FoundGameListItem *pSelectedItem = static_cast< FoundGameListItem * >( m_GplGames->GetSelectedPanelItem() );
|
|
if ( pSelectedItem )
|
|
{
|
|
// Open the download window
|
|
KeyValues *pSelectedDetails = pSelectedItem->GetFullInfo().mpGameDetails;
|
|
if ( pSelectedDetails )
|
|
{
|
|
pSelectedDetails->SetString( "game/missioninfo/from", "Join" );
|
|
pSelectedDetails->SetString( "game/missioninfo/action", command );
|
|
}
|
|
CBaseModPanel::GetSingleton().OpenWindow( WT_DOWNLOADCAMPAIGN, this, true, pSelectedDetails );
|
|
}
|
|
}
|
|
else if ( V_strcmp( command, "PlayerDropDown" ) == 0 )
|
|
{
|
|
DropDownMenu *pDrpPlayer = dynamic_cast< DropDownMenu * > ( FindChildByName( "DrpSelectedPlayerName" ) );
|
|
if ( pDrpPlayer )
|
|
{
|
|
BaseModHybridButton *pBtnPlayerGamerTag = dynamic_cast< BaseModHybridButton * > ( pDrpPlayer->FindChildByName( "BtnSelectedPlayerName" ) );
|
|
if ( pBtnPlayerGamerTag )
|
|
{
|
|
int x, y;
|
|
pBtnPlayerGamerTag->GetPos( x, y );
|
|
int tall = pBtnPlayerGamerTag->GetTall();
|
|
pBtnPlayerGamerTag->LocalToScreen( x, y );
|
|
OpenPlayerFlyout( pBtnPlayerGamerTag, m_SelectedGamePlayerID, x, y + tall + 1 );
|
|
}
|
|
}
|
|
}
|
|
else if ( V_strcmp( command, "#L4D360UI_SendMessage" ) == 0 )
|
|
{
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_ACCEPT );
|
|
char steamCmd[64];
|
|
Q_snprintf( steamCmd, sizeof( steamCmd ), "chat/%llu", m_SelectedGamePlayerID );
|
|
CUIGameData::Get()->ExecuteOverlayCommand( steamCmd );
|
|
}
|
|
else if ( V_strcmp( command, "#L4D360UI_ViewSteamID" ) == 0 )
|
|
{
|
|
CBaseModPanel::GetSingleton().PlayUISound( UISOUND_ACCEPT );
|
|
char steamCmd[64];
|
|
Q_snprintf( steamCmd, sizeof( steamCmd ), "steamid/%llu", m_SelectedGamePlayerID );
|
|
CUIGameData::Get()->ExecuteOverlayCommand( steamCmd );
|
|
}
|
|
}
|
|
|
|
void FoundGames::OnEvent( KeyValues *pEvent )
|
|
{
|
|
char const *szName = pEvent->GetName();
|
|
|
|
if ( !Q_stricmp( "OnMatchPlayerMgrUpdate", szName ) )
|
|
{
|
|
char const *szUpdate = pEvent->GetString( "update", "" );
|
|
if ( !Q_stricmp( "searchstarted", szUpdate ) )
|
|
{
|
|
m_flSearchStartedTime = Plat_FloatTime();
|
|
m_flSearchEndTime = m_flSearchStartedTime + ui_foundgames_spinner_time.GetFloat();
|
|
OnThink();
|
|
}
|
|
else if ( !Q_stricmp( "searchfinished", szUpdate ) )
|
|
{
|
|
m_flSearchStartedTime = 0.0f;
|
|
UpdateGameDetails();
|
|
}
|
|
else if ( !Q_stricmp( "friend", szUpdate ) )
|
|
{
|
|
// Friend's game details have been updated
|
|
if ( !m_flScheduledUpdateGameDetails )
|
|
m_flScheduledUpdateGameDetails = Plat_FloatTime();
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::OpenPlayerFlyout( BaseModHybridButton *button, uint64 playerId, int x, int y )
|
|
{
|
|
#ifdef NO_STEAM
|
|
Error( "FoundGames::OpenPlayerFlyout does not exist on the Xbox 360." );
|
|
#else
|
|
if ( playerId == 0 )
|
|
return;
|
|
|
|
FlyoutMenu *flyout = NULL;
|
|
|
|
CSteamID objSteamId( playerId );
|
|
if ( !objSteamId.IsValid() )
|
|
return;
|
|
|
|
if ( !Q_stricmp( "groupserver", m_pDataSettings->GetString( "options/action" ) ) && objSteamId.BClanAccount() )
|
|
{
|
|
flyout = dynamic_cast< FlyoutMenu * >( FindChildByName( "FlmPlayerFlyout_SteamGroup" ) );
|
|
}
|
|
else if ( steamapicontext->SteamFriends()->GetFriendRelationship( playerId ) == k_EFriendRelationshipFriend )
|
|
{
|
|
flyout = dynamic_cast< FlyoutMenu * >( FindChildByName( "FlmPlayerFlyout" ) );
|
|
}
|
|
else
|
|
{
|
|
flyout = dynamic_cast< FlyoutMenu * >( FindChildByName( "FlmPlayerFlyout_NotFriend" ) );
|
|
}
|
|
|
|
if ( flyout )
|
|
{
|
|
// If one is open for this player, close it
|
|
if ( playerId == m_flyoutPlayerId && flyout->IsVisible() )
|
|
{
|
|
flyout->CloseMenu( button );
|
|
return;
|
|
}
|
|
|
|
int wndX, wndY;
|
|
GetPos( wndX, wndY );
|
|
|
|
m_flyoutPlayerId = playerId;
|
|
flyout->OpenMenu( button );
|
|
flyout->SetPos( x, y - wndY );
|
|
flyout->SetOriginalTall( 0 );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
void FoundGames::OnKeyCodePressed( KeyCode code )
|
|
{
|
|
int iUserSlot = GetJoystickForCode( code );
|
|
CBaseModPanel::GetSingleton().SetLastActiveUserId( iUserSlot );
|
|
|
|
switch( GetBaseButtonCode( code ) )
|
|
{
|
|
case KEY_XBUTTON_X:
|
|
OnCommand( "CreateGame" );
|
|
break;
|
|
|
|
default:
|
|
BaseClass::OnKeyCodePressed( code );
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool FoundGames::CanCreateGame()
|
|
{
|
|
//char const *szGameMode = m_pDataSettings->GetString( "game/mode", NULL );
|
|
bool bGroupServerList = !Q_stricmp( "groupserver", m_pDataSettings->GetString( "options/action", "" ) );
|
|
|
|
//return ( szGameMode && *szGameMode && !bGroupServerList );
|
|
return !bGroupServerList;
|
|
}
|
|
|
|
void FoundGames::UpdateTitle()
|
|
{
|
|
if ( const char *gameMode = m_pDataSettings->GetString( "game/mode", NULL ) )
|
|
{
|
|
gameMode = NoTeamGameMode( gameMode );
|
|
m_pTitle->SetText( CFmtStr( "#L4D360UI_FoundFriendGames_Title_%s", gameMode ) );
|
|
//BaseClass::DrawDialogBackground( CFmtStr( "#L4D360UI_FoundFriendGames_Title_%s", gameMode ), NULL, "#L4D360UI_FoundGames_Description", NULL, NULL );
|
|
}
|
|
else
|
|
{
|
|
m_pTitle->SetText( CFmtStr( "#L4D360UI_FoundGames_AllGames" ) );
|
|
//BaseClass::DrawDialogBackground( "#L4D360UI_FoundGames_AllGames", NULL, "#L4D360UI_FoundGames_Description", NULL, NULL );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::OnThink()
|
|
{
|
|
BaseClass::OnThink();
|
|
|
|
UpdateTitle();
|
|
|
|
if ( m_flScheduledUpdateGameDetails && m_flScheduledUpdateGameDetails + ui_foundgames_update_time.GetFloat() < Plat_FloatTime() )
|
|
{
|
|
UpdateGameDetails();
|
|
}
|
|
|
|
vgui::ImagePanel *pStillSearchingTag = dynamic_cast< vgui::ImagePanel* >( FindChildByName( "SearchingIcon" ) );
|
|
if ( pStillSearchingTag )
|
|
{
|
|
vgui::Label* label = dynamic_cast< vgui::Label* >( FindChildByName( "LblSearching" ) );
|
|
if ( label )
|
|
{
|
|
label->SetVisible( m_GplGames->GetPanelItemCount() == 0 );
|
|
}
|
|
|
|
// If we're searching (or haven't reached the top of the spinner) animate the spinner
|
|
if ( m_flSearchStartedTime > 0.0f || Plat_FloatTime() < m_flSearchEndTime ||
|
|
( m_CurrentSpinnerValue % pStillSearchingTag->GetNumFrames() != 1 ) )
|
|
{
|
|
// clock the anim at 10hz
|
|
float time = Plat_FloatTime();
|
|
if ( ( m_LastEngineSpinnerTime + 0.1f ) < time )
|
|
{
|
|
m_LastEngineSpinnerTime = time;
|
|
pStillSearchingTag->SetFrame( m_CurrentSpinnerValue++ );
|
|
}
|
|
|
|
pStillSearchingTag->SetAlpha( 255 );
|
|
|
|
if ( label )
|
|
label->SetText( "#L4D360UI_FoundGames_Searching" );
|
|
}
|
|
else
|
|
{
|
|
// Fade
|
|
pStillSearchingTag->SetAlpha( 0 );
|
|
|
|
if ( label )
|
|
{
|
|
bool bGroupServer = !Q_stricmp( "groupserver", m_pDataSettings->GetString( "options/action", "" ) );
|
|
char const *szGameMode = m_pDataSettings->GetString( "game/mode", "" );
|
|
szGameMode = NoTeamGameMode( szGameMode );
|
|
|
|
if ( bGroupServer && szGameMode && *szGameMode )
|
|
label->SetText( CFmtStr( "#L4D360UI_FoundGames_NoGamesFound_%s", szGameMode ) );
|
|
else
|
|
label->SetText( "#L4D360UI_FoundGames_NoGamesFound" );
|
|
}
|
|
}
|
|
|
|
if ( m_GplGames->GetPanelItemCount() > 0 && label )
|
|
{
|
|
if ( char const *szNonSearchingCaptionText = GetListHeaderText() )
|
|
{
|
|
label->SetText( szNonSearchingCaptionText );
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateFooterButtons();
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::PaintBackground()
|
|
{
|
|
/*
|
|
if ( const char *gameMode = m_pDataSettings->GetString( "game/mode", NULL ) )
|
|
{
|
|
gameMode = NoTeamGameMode( gameMode );
|
|
BaseClass::DrawDialogBackground( CFmtStr( "#L4D360UI_FoundFriendGames_Title_%s", gameMode ), NULL, "#L4D360UI_FoundGames_Description", NULL, NULL );
|
|
}
|
|
else
|
|
{
|
|
BaseClass::DrawDialogBackground( "#L4D360UI_FoundGames_AllGames", NULL, "#L4D360UI_FoundGames_Description", NULL, NULL );
|
|
}
|
|
*/
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::LoadLayout()
|
|
{
|
|
BaseClass::LoadLayout();
|
|
|
|
// Re-trigger selection to update game details
|
|
OnItemSelected( "" );
|
|
}
|
|
|
|
void FoundGames::UpdateFooterButtons()
|
|
{
|
|
#ifdef _X360
|
|
CBaseModFooterPanel *footer = BaseModUI::CBaseModPanel::GetSingleton().GetFooterPanel();
|
|
if( footer )
|
|
{
|
|
bool bNotSelectingListItem = true;
|
|
bool bShouldShowGamerCard = false;
|
|
|
|
for( int slotCount = 0; slotCount < m_GplGames->GetPanelItemCount(); ++slotCount )
|
|
{
|
|
FoundGameListItem *listItem = static_cast< FoundGameListItem * >( m_GplGames->GetPanelItem( slotCount ) );
|
|
if ( listItem && listItem->HasFocus() &&
|
|
FoundGameListItem::FGT_PLAYER == listItem->GetFullInfo().mInfoType )
|
|
{
|
|
bNotSelectingListItem = false;
|
|
|
|
if ( listItem->GetFullInfo().mPing != FoundGameListItem::Info::GP_SYSTEMLINK ||
|
|
listItem->GetFullInfo().mpGameDetails->GetUint64( "player/xuidOnline", 0ull ) )
|
|
{
|
|
bShouldShowGamerCard = AnyUserConnectedToLIVE();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
footer->SetButtons( FB_ABUTTON | FB_BBUTTON | ( bShouldShowGamerCard ? FB_YBUTTON : FB_NONE ), FF_ABY_ONLY, false );
|
|
footer->SetButtonText( FB_BBUTTON, bNotSelectingListItem ? "#L4D360UI_Cancel" : "#L4D360UI_Back" );
|
|
footer->SetButtonText( FB_ABUTTON, "#L4D360UI_Select" );
|
|
footer->SetButtonText( FB_YBUTTON, "#L4D360UI_ViewGamerCard" );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
struct DifficultyToStringItem
|
|
{
|
|
const char* m_difficultyStr;
|
|
int m_difficultyNum;
|
|
};
|
|
|
|
void FoundGames::SetFoundDesiredText( bool bFoundGame )
|
|
{
|
|
vgui::Label* label = dynamic_cast< vgui::Label* >( FindChildByName( "LblNoGamesFound" ) );
|
|
if( label )
|
|
{
|
|
char const *szGameMode = m_pDataSettings->GetString( "game/mode", NULL );
|
|
if ( !szGameMode )
|
|
{
|
|
label->SetVisible( false );
|
|
}
|
|
else
|
|
{
|
|
label->SetVisible( !bFoundGame && m_GplGames->GetPanelItemCount() > 0 );
|
|
|
|
szGameMode = NoTeamGameMode( szGameMode );
|
|
label->SetText( CFmtStr( "#L4D360UI_FoundGames_NoGamesFound_%s", szGameMode ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FoundGames::AddGameFromDetails( const FoundGameListItem::Info &fi )
|
|
{
|
|
if ( !fi.Name[0] )
|
|
return false;
|
|
|
|
// See if already in list
|
|
FoundGameListItem* game = NULL;
|
|
|
|
for( int j = 0; j < m_GplGames->GetPanelItemCount(); ++j )
|
|
{
|
|
FoundGameListItem *item = dynamic_cast< FoundGameListItem* >( m_GplGames->GetPanelItem( j ) );
|
|
if ( !item )
|
|
continue;
|
|
|
|
if ( IsADuplicateServer( item, fi ) )
|
|
{
|
|
game = item;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !game )
|
|
{
|
|
char const *szItemTemplateName = "FoundGameListItem";
|
|
if ( fi.mInfoType == FoundGameListItem::FGT_PUBLICGAME )
|
|
szItemTemplateName = "FoundGameListItemPublic";
|
|
game = m_GplGames->AddPanelItem< FoundGameListItem >( szItemTemplateName );
|
|
}
|
|
else if ( !game->IsSweep() )
|
|
{
|
|
// Game has already been updated with a valid campaign or versus info
|
|
return false;
|
|
}
|
|
|
|
game->SetSweep( false ); // No need to remove
|
|
|
|
// Make a copy
|
|
FoundGameListItem::Info fiCopy = fi;
|
|
|
|
static CGameUIConVarRef cl_names_debug( "cl_names_debug" );
|
|
if ( cl_names_debug.GetInt() )
|
|
Q_strncpy( fiCopy.Name, "WWWWWWWWWWWWWWW", sizeof( fiCopy.Name ) );
|
|
|
|
// fix up ping - friends games do not contain useful ping info
|
|
if ( fi.mPing != FoundGameListItem::Info::GP_SYSTEMLINK )
|
|
{
|
|
fiCopy.mPing = FoundGameListItem::Info::GP_NONE;
|
|
}
|
|
|
|
game->SetGameIndex( fiCopy );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool FoundGames::IsADuplicateServer( FoundGameListItem *item, FoundGameListItem::Info const &fi )
|
|
{
|
|
FoundGameListItem::Info const &ii = item->GetFullInfo();
|
|
|
|
if ( IsX360() )
|
|
{
|
|
if( ii.mFriendXUID == fi.mFriendXUID ||
|
|
ii.mpGameDetails->GetUint64( "player/xuidOnline", 0ull ) == fi.mFriendXUID ||
|
|
fi.mpGameDetails->GetUint64( "player/xuidOnline", 0ull ) == ii.mFriendXUID )
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if ( fi.mFriendXUID && ii.mFriendXUID == fi.mFriendXUID)
|
|
return true;
|
|
|
|
uint64 xuidOnline = fi.mpGameDetails->GetUint64( "player/xuidOnline", 0ull );
|
|
if ( xuidOnline && ii.mpGameDetails->GetUint64( "player/xuidOnline", 0ull ) == xuidOnline )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void FoundGames::SetDetailsPanelVisible( bool bIsVisible )
|
|
{
|
|
SetControlVisible( "LblCampaign", bIsVisible );
|
|
SetControlVisible( "LblChapter", bIsVisible );
|
|
SetControlVisible( "LblPlayerAccess", bIsVisible );
|
|
SetControlVisible( "LblPlayerAccessText", bIsVisible );
|
|
SetControlVisible( "LblGameDifficulty", bIsVisible );
|
|
SetControlVisible( "LblGameDifficultyText", bIsVisible );
|
|
SetControlVisible( "LblNumPlayers", bIsVisible );
|
|
SetControlVisible( "LblNumPlayersText", bIsVisible );
|
|
SetControlVisible( "LblViewingGames", bIsVisible );
|
|
SetControlVisible( "LblGameStatus", bIsVisible );
|
|
if ( IsX360() )
|
|
{
|
|
SetControlVisible( "LblGameStatus2", bIsVisible );
|
|
}
|
|
SetControlVisible( "LblSelectedPlayerName", bIsVisible );
|
|
SetControlVisible( "ImgSelectedAvatar", bIsVisible );
|
|
|
|
if ( !bIsVisible )
|
|
{
|
|
SetControlVisible( "ImgLevelImage", bIsVisible );
|
|
SetControlVisible( "ImgFrame", bIsVisible );
|
|
SetControlVisible( "BtnDownloadSelected", bIsVisible );
|
|
SetControlVisible( "LblNewVersion", bIsVisible );
|
|
SetControlVisible( "BtnJoinSelected", bIsVisible );
|
|
SetControlVisible( "ImgAvatarBG", bIsVisible );
|
|
SetControlVisible( "DrpSelectedPlayerName", bIsVisible );
|
|
SetControlVisible( "IconForwardArrow", bIsVisible );
|
|
}
|
|
}
|
|
|
|
char const *s_sort_pchGameModePrefer = NULL;
|
|
static int __cdecl FoundFriendsSortFunc( vgui::Panel* const *a, vgui::Panel* const *b)
|
|
{
|
|
FoundGameListItem *fA = dynamic_cast< FoundGameListItem* >(*a);
|
|
FoundGameListItem *fB = dynamic_cast< FoundGameListItem* >(*b);
|
|
|
|
const BaseModUI::FoundGameListItem::Info &ia = fA->GetFullInfo();
|
|
const BaseModUI::FoundGameListItem::Info &ib = fB->GetFullInfo();
|
|
|
|
// If this is just global lister then always sort by gamertags
|
|
// Servers sort by ping first
|
|
const FoundGameListItem::Type_t eServer = FoundGameListItem::FGT_SERVER;
|
|
if ( ia.mInfoType == eServer && ib.mInfoType == eServer && ia.miPing != ib.miPing )
|
|
{
|
|
return ( ia.miPing < ib.miPing ? -1 : 1 );
|
|
}
|
|
|
|
if ( !s_sort_pchGameModePrefer )
|
|
{
|
|
// Players sort by gamertags
|
|
if ( int iResult = Q_stricmp( ia.Name, ib.Name ) )
|
|
return iResult;
|
|
else if ( int iResult2 = Q_strcmp( ia.Name, ib.Name ) )
|
|
return iResult2;
|
|
}
|
|
|
|
// Ingame first
|
|
if ( ia.mbInGame != ib.mbInGame )
|
|
{
|
|
return ( ia.mbInGame ? -1 : 1 );
|
|
}
|
|
|
|
// Not joinable games
|
|
if ( ia.mIsJoinable != ib.mIsJoinable )
|
|
{
|
|
return ( ia.mIsJoinable ? -1 : 1 );
|
|
}
|
|
|
|
// Private games
|
|
bool aPrivate = !Q_stricmp( "private", ia.mpGameDetails->GetString( "system/access", "" ) );
|
|
bool bPrivate = !Q_stricmp( "private", ib.mpGameDetails->GetString( "system/access", "" ) );
|
|
if ( aPrivate != bPrivate )
|
|
{
|
|
return aPrivate ? 1 : -1;
|
|
}
|
|
|
|
// Games in finale, etc.
|
|
bool aFinale = !Q_stricmp( "finale", ia.mpGameDetails->GetString( "game/state", "" ) );
|
|
bool bFinale = !Q_stricmp( "finale", ib.mpGameDetails->GetString( "game/state", "" ) );
|
|
if ( aFinale != bFinale )
|
|
{
|
|
return aFinale ? 1 : -1;
|
|
}
|
|
|
|
// Full games
|
|
int numASlots = ia.mpGameDetails->GetInt( "members/numSlots", 0 );
|
|
int numAPlayers = ia.mpGameDetails->GetInt( "members/numPlayers", 0 );
|
|
|
|
int numBSlots = ib.mpGameDetails->GetInt( "members/numSlots", 0 );
|
|
int numBPlayers = ib.mpGameDetails->GetInt( "members/numPlayers", 0 );
|
|
|
|
bool aFull = ( numASlots == numAPlayers );
|
|
bool bFull = ( numBSlots == numBPlayers );
|
|
if ( aFull != bFull )
|
|
{
|
|
return aFull ? 1 : -1;
|
|
}
|
|
|
|
// Then campaign vs. versus
|
|
char const *aGameMode = ia.mpGameDetails->GetString( "game/mode", "" );
|
|
char const *bGameMode = ib.mpGameDetails->GetString( "game/mode", "" );
|
|
if ( s_sort_pchGameModePrefer )
|
|
{
|
|
aGameMode = NoTeamGameMode( aGameMode );
|
|
bGameMode = NoTeamGameMode( bGameMode );
|
|
|
|
char const *szFilter = NoTeamGameMode( s_sort_pchGameModePrefer );
|
|
|
|
bool aPreferGameMode = !Q_stricmp( aGameMode, szFilter );
|
|
bool bPreferGameMode = !Q_stricmp( bGameMode, szFilter );
|
|
|
|
if ( aPreferGameMode != bPreferGameMode )
|
|
{
|
|
return aPreferGameMode ? -1 : 1;
|
|
}
|
|
}
|
|
if ( int iCmp = Q_stricmp( aGameMode, bGameMode ) )
|
|
{
|
|
return iCmp;
|
|
}
|
|
|
|
// System Link first
|
|
bool aLan = !Q_stricmp( ia.mpGameDetails->GetString( "system/network", "" ), "lan" );
|
|
bool bLan = !Q_stricmp( ib.mpGameDetails->GetString( "system/network", "" ), "lan" );
|
|
if ( aLan != bLan )
|
|
{
|
|
return aLan ? -1 : 1;
|
|
}
|
|
|
|
// Better numeric (ms) ping first
|
|
if ( ia.miPing != ib.miPing )
|
|
{
|
|
return ( ia.miPing < ib.miPing ? -1 : 1 );
|
|
}
|
|
|
|
// Better enum ping first
|
|
if ( ia.mPing != ib.mPing )
|
|
{
|
|
return ( ia.mPing > ib.mPing ? -1 : 1 );
|
|
}
|
|
|
|
// And as last resort by gamertags
|
|
return Q_stricmp( ia.Name, ib.Name );
|
|
}
|
|
|
|
static void HandleJoinPlayerSession( FoundGameListItem::Info const &fi )
|
|
{
|
|
if ( fi.mInfoType != FoundGameListItem::FGT_PLAYER )
|
|
return;
|
|
|
|
IPlayerFriend *item = g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->GetFriendByXUID( fi.mFriendXUID );
|
|
if ( item )
|
|
item->Join();
|
|
}
|
|
|
|
void FoundGames::StartSearching()
|
|
{
|
|
g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->EnableFriendsUpdate( true );
|
|
}
|
|
|
|
void FoundGames::AddServersToList()
|
|
{
|
|
IPlayerManager *mgr = g_pMatchFramework->GetMatchSystem()->GetPlayerManager();
|
|
|
|
int numItems = mgr->GetNumFriends();
|
|
for( int i = 0; i < numItems; ++i )
|
|
{
|
|
IPlayerFriend *item = mgr->GetFriendByIndex( i );
|
|
KeyValues *pGameDetails = item->GetGameDetails();
|
|
|
|
FoundGameListItem::Info fi;
|
|
|
|
fi.mInfoType = FoundGameListItem::FGT_PLAYER;
|
|
Q_strncpy( fi.Name, item->GetName(), sizeof( fi.Name ) );
|
|
|
|
fi.mIsJoinable = false;
|
|
|
|
fi.mbInGame = item->IsJoinable();
|
|
|
|
fi.mPing = fi.GP_HIGH;
|
|
if ( !Q_stricmp( "lan", pGameDetails->GetString( "system/network", "" ) ) )
|
|
fi.mPing = fi.GP_SYSTEMLINK;
|
|
|
|
fi.miPing = pGameDetails->GetInt( "system/ping", 0 );
|
|
|
|
fi.mpGameDetails = pGameDetails;
|
|
fi.mFriendXUID = item->GetXUID();
|
|
|
|
// On X360 check against our registered missions
|
|
KeyValues *pMissionMapInfo = NULL; pMissionMapInfo;
|
|
|
|
const char *szModDir = pGameDetails->GetString( "game/dir", "swarm" );
|
|
if ( Q_stricmp( szModDir, COM_GetModDirectory() ) )
|
|
{
|
|
Q_snprintf( fi.mchOtherTitle, sizeof( fi.mchOtherTitle ), szModDir );
|
|
}
|
|
|
|
//
|
|
// Check if this is actually a non-joinable game
|
|
//
|
|
int numSlots = fi.mpGameDetails->GetInt( "members/numSlots", 0 );
|
|
if ( fi.IsDLC() || fi.IsOtherTitle() )
|
|
{
|
|
fi.mIsJoinable = false;
|
|
}
|
|
else if ( fi.mbInGame && numSlots > 0 )
|
|
{
|
|
if ( !fi.IsDownloadable() )
|
|
{
|
|
char const *szHint = fi.GetNonJoinableShortHint();
|
|
if ( !*szHint )
|
|
{
|
|
fi.mIsJoinable = true;
|
|
fi.mpfnJoinGame = HandleJoinPlayerSession;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fi.mIsJoinable = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This is the case when we technically already know the session ID,
|
|
// but the query to determine session details is still in progress
|
|
// and actually may fail due to firewalls/NATs, so we fake the details
|
|
// as if we do not know that the friend is in game yet.
|
|
fi.mIsJoinable = false;
|
|
fi.mbInGame = false;
|
|
}
|
|
|
|
AddGameFromDetails( fi );
|
|
}
|
|
}
|
|
|
|
void FoundGames::AddFakeServersToList()
|
|
{
|
|
KeyValues *pDetails = KeyValues::FromString( "FakeContent",
|
|
" system { "
|
|
" network LIVE "
|
|
" access public "
|
|
" } "
|
|
" game { "
|
|
" mode campaign "
|
|
" campaign jacob "
|
|
" difficulty normal "
|
|
" state lobby "
|
|
" } "
|
|
" members { "
|
|
" numMachines #int#0 "
|
|
" numPlayers #int#1 "
|
|
" numSlots #int#4 "
|
|
" } "
|
|
);
|
|
KeyValues::AutoDelete autodelete_pDetails( pDetails );
|
|
|
|
for ( int k = 0; k < ui_foundgames_fake_count.GetInt(); ++ k )
|
|
{
|
|
int n = k + ui_foundgames_fake_content.GetInt();
|
|
|
|
FoundGameListItem::Info fi;
|
|
fi.mInfoType = FoundGameListItem::FGT_PLAYER;
|
|
|
|
Q_snprintf( fi.Name, ARRAYSIZE( fi.Name ), "Fake Content #%02d", n );
|
|
fi.mIsJoinable = true;
|
|
fi.mbInGame = true;
|
|
fi.mPing = fi.GP_HIGH;
|
|
fi.miPing = 0;
|
|
|
|
fi.mFriendXUID = ( 0xFFFFFFFFull << 32ull ) | ( n << 8 );
|
|
|
|
fi.mpGameDetails = pDetails;
|
|
|
|
fi.mpGameDetails->SetInt( "members/numPlayers", 1 + n%3 );
|
|
fi.mpGameDetails->SetString( "game/mission", "asi-jac2-deima" );
|
|
|
|
char const *szGameModes[] = { "campaign", "single_mission" };
|
|
fi.mpGameDetails->SetString( "game/mode", szGameModes[ n % ARRAYSIZE( szGameModes ) ] );
|
|
|
|
AddGameFromDetails( fi );
|
|
}
|
|
}
|
|
|
|
void FoundGames::SortListItems()
|
|
{
|
|
s_sort_pchGameModePrefer = m_pDataSettings->GetString( "game/mode", NULL );
|
|
m_GplGames->SortPanelItems( FoundFriendsSortFunc );
|
|
}
|
|
|
|
void FoundGames::UpdateGameDetails()
|
|
{
|
|
m_flScheduledUpdateGameDetails = 0.0f;
|
|
bool bEmpty = !m_GplGames->GetPanelItemCount();
|
|
|
|
// Mark all as stale
|
|
for( int i = 0; i < m_GplGames->GetPanelItemCount(); ++i )
|
|
{
|
|
FoundGameListItem *game = dynamic_cast< FoundGameListItem* >( m_GplGames->GetPanelItem( i ) );
|
|
if( game )
|
|
{
|
|
game->SetSweep( true );
|
|
}
|
|
}
|
|
|
|
if ( ui_foundgames_fake_content.GetBool() )
|
|
AddFakeServersToList();
|
|
else
|
|
AddServersToList();
|
|
|
|
// Remove stale games, it's a vector, so removing an item puts the next item into the current index
|
|
for ( int i = 0; i < m_GplGames->GetPanelItemCount(); /* */ )
|
|
{
|
|
FoundGameListItem *game = dynamic_cast< FoundGameListItem* >( m_GplGames->GetPanelItem( i ) );
|
|
if( game && game->IsSweep() )
|
|
{
|
|
m_GplGames->RemovePanelItem( static_cast<unsigned short>( i ) );
|
|
continue;
|
|
}
|
|
++i;
|
|
}
|
|
|
|
//
|
|
// Sort the list
|
|
//
|
|
SortListItems();
|
|
|
|
//
|
|
// Update whether we found the game we were looking for
|
|
//
|
|
if ( m_GplGames->GetPanelItemCount() == 0 )
|
|
{
|
|
SetDetailsPanelVisible(false);
|
|
SetFoundDesiredText( false );
|
|
}
|
|
else
|
|
{
|
|
bool foundDesiredGame = false;
|
|
if ( FoundGameListItem *item = dynamic_cast< FoundGameListItem* >( m_GplGames->GetPanelItem( 0 ) ) )
|
|
{
|
|
const FoundGameListItem::Info &fullInfo = item->GetFullInfo();
|
|
|
|
char const *szListPreferredMode = m_pDataSettings->GetString( "game/mode", "campaign" );
|
|
szListPreferredMode = NoTeamGameMode( szListPreferredMode );
|
|
|
|
char const *szGameItemMode = fullInfo.mpGameDetails->GetString( "game/mode", "" );
|
|
szGameItemMode = NoTeamGameMode( szGameItemMode );
|
|
|
|
// just need a game in progress. Not filtering by game mode yet.
|
|
foundDesiredGame = fullInfo.mbInGame; // && !Q_stricmp( szListPreferredMode, szGameItemMode );
|
|
}
|
|
SetFoundDesiredText( foundDesiredGame );
|
|
}
|
|
|
|
// Handle adding new item to empty result list
|
|
if ( bEmpty )
|
|
m_GplGames->SelectPanelItem( 0, GenericPanelList::SD_DOWN, true, false );
|
|
|
|
// Re-trigger selection to update game details
|
|
OnItemSelected( "" );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::OnItemSelected( const char* panelName )
|
|
{
|
|
if ( !m_bLayoutLoaded )
|
|
return;
|
|
|
|
FoundGameListItem* gameListItem = static_cast<FoundGameListItem*>( m_GplGames->GetSelectedPanelItem() );
|
|
|
|
bool bChangedSelection = ( gameListItem != m_pPreviousSelectedItem );
|
|
m_pPreviousSelectedItem = gameListItem;
|
|
|
|
#if !defined( _X360 )
|
|
|
|
// Set active state
|
|
for ( int i = 0; i < m_GplGames->GetPanelItemCount(); /* */ )
|
|
{
|
|
FoundGameListItem *pItem = dynamic_cast< FoundGameListItem* >( m_GplGames->GetPanelItem( i ) );
|
|
|
|
if ( pItem )
|
|
{
|
|
pItem->SetSelected( pItem == gameListItem );
|
|
}
|
|
++i;
|
|
}
|
|
|
|
#endif
|
|
|
|
const char* campaignName = "#L4D360UI_CampaignName_Unknown";
|
|
|
|
const char* chapterName = "#L4D360UI_LevelName_Unknown";
|
|
|
|
char chDifficultyBuffer[64] = {0};
|
|
const char* currentDifficulty = "#L4D360UI_Unknown";
|
|
|
|
const char* currentSurvivorAccess = "#L4D360UI_Unknown";
|
|
char chImageBuffer[64] = {0};
|
|
const char* chapterImage = "swarm/MissionPics/UnknownMissionPic";
|
|
|
|
const char *szDownloadAuthor = NULL;
|
|
const char *szDownloadWebsite = "";
|
|
bool bDownloadableCampaign = false;
|
|
|
|
const int stringSize = 256;
|
|
char playerCountText[ stringSize ] = "";
|
|
|
|
enum DetailsDisplayType_t { DETAILS_NONE, DETAILS_PRESENCE, DETAILS_INGAME };
|
|
DetailsDisplayType_t eDetails = DETAILS_INGAME;
|
|
|
|
vgui::Label *lblChapter = dynamic_cast< vgui::Label* >( FindChildByName( "LblChapter" ) );
|
|
vgui::Label *lblGameStatus = dynamic_cast< vgui::Label* >( FindChildByName( "LblGameStatus" ) );
|
|
vgui::Label *lblGameStatus2 = NULL;
|
|
if ( IsX360() )
|
|
{
|
|
lblGameStatus2 = dynamic_cast< vgui::Label* >( FindChildByName( "LblGameStatus2" ) );
|
|
}
|
|
vgui::Label* lblGameDifficulty = dynamic_cast< vgui::Label* >( FindChildByName( "LblGameDifficulty" ) );
|
|
|
|
CNB_Button *joinButton = dynamic_cast< CNB_Button* >( FindChildByName( "BtnJoinSelected" ) );
|
|
BaseModUI::BaseModHybridButton *downloadButton = dynamic_cast< BaseModUI::BaseModHybridButton* >( FindChildByName( "BtnDownloadSelected" ) );
|
|
vgui::Label *downloadVersionLabel = dynamic_cast< vgui::Label* >( FindChildByName( "LblNewVersion" ) );
|
|
vgui::ImagePanel *imgAvatar = dynamic_cast< vgui::ImagePanel* >( FindChildByName( "ImgSelectedAvatar" ) );
|
|
DropDownMenu *pDrpPlayer = dynamic_cast< DropDownMenu * > ( FindChildByName( "DrpSelectedPlayerName" ) );
|
|
int bBuiltIn = 0;
|
|
|
|
if( gameListItem )
|
|
{
|
|
if( lblGameStatus )
|
|
{
|
|
lblGameStatus->SetText( "" );
|
|
}
|
|
|
|
if ( lblGameStatus2 )
|
|
{
|
|
lblGameStatus2->SetText( "" );
|
|
}
|
|
|
|
const FoundGameListItem::Info &fi = gameListItem->GetFullInfo();
|
|
|
|
if ( !Q_stricmp( "noplayerinfo", m_pDataSettings->GetString( "UI/display", "" ) ) )
|
|
{
|
|
if ( imgAvatar )
|
|
imgAvatar->SetVisible( false );
|
|
|
|
if ( pDrpPlayer )
|
|
pDrpPlayer->SetVisible( false );
|
|
}
|
|
else
|
|
{
|
|
if ( bChangedSelection )
|
|
{
|
|
DropDownMenu *pDrpPlayer = dynamic_cast< DropDownMenu * > ( FindChildByName( "DrpSelectedPlayerName" ) );
|
|
if ( pDrpPlayer )
|
|
{
|
|
pDrpPlayer->SetVisible( true );
|
|
|
|
BaseModHybridButton *pBtnPlayerGamerTag = dynamic_cast< BaseModHybridButton * > ( pDrpPlayer->FindChildByName( "BtnSelectedPlayerName" ) );
|
|
if ( pBtnPlayerGamerTag )
|
|
{
|
|
pBtnPlayerGamerTag->SetText( fi.Name );
|
|
|
|
FlyoutMenu *flyout = dynamic_cast< FlyoutMenu * >( FindChildByName( "FlmPlayerFlyout" ) );
|
|
if ( flyout && flyout->IsVisible() )
|
|
{
|
|
flyout->CloseMenu( pBtnPlayerGamerTag );
|
|
}
|
|
|
|
flyout = dynamic_cast< FlyoutMenu * >( FindChildByName( "FlmPlayerFlyout_NotFriend" ) );
|
|
if ( flyout && flyout->IsVisible() )
|
|
{
|
|
flyout->CloseMenu( pBtnPlayerGamerTag );
|
|
}
|
|
|
|
pBtnPlayerGamerTag->SetShowDropDownIndicator( fi.mInfoType == FoundGameListItem::FGT_PLAYER );
|
|
}
|
|
}
|
|
}
|
|
|
|
m_SelectedGamePlayerID = fi.mFriendXUID;
|
|
|
|
if ( imgAvatar )
|
|
{
|
|
IImage *pImage = NULL;
|
|
|
|
if ( fi.mInfoType == FoundGameListItem::FGT_PLAYER )
|
|
pImage = CUIGameData::Get()->GetAvatarImage( fi.mFriendXUID );
|
|
|
|
if ( pImage )
|
|
{
|
|
imgAvatar->SetImage( "" ); // must be cleared - setting an IImage doesn't reset this.
|
|
imgAvatar->SetImage( pImage );
|
|
SetControlVisible( "ImgAvatarBG", true );
|
|
}
|
|
else if ( fi.mPing == FoundGameListItem::Info::GP_SYSTEMLINK || fi.mInfoType == FoundGameListItem::FGT_SERVER )
|
|
{
|
|
imgAvatar->SetImage( "icon_lan" );
|
|
SetControlVisible( "ImgAvatarBG", false );
|
|
}
|
|
else
|
|
{
|
|
imgAvatar->SetImage( "icon_lobby" ); // must be cleared - setting an IImage doesn't reset this.
|
|
SetControlVisible( "ImgAvatarBG", false );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fi.IsDLC() )
|
|
{
|
|
currentDifficulty = NULL;
|
|
currentSurvivorAccess = NULL;
|
|
// TODO:
|
|
//chapterImage = "maps/addon";
|
|
if ( lblGameStatus )
|
|
lblGameStatus->SetText( "" );
|
|
}
|
|
else if ( char const *szOtherTitle = fi.IsOtherTitle() )
|
|
{
|
|
campaignName = "";
|
|
chapterName = "";
|
|
|
|
currentDifficulty = NULL;
|
|
currentSurvivorAccess = NULL;
|
|
Q_snprintf( chImageBuffer, sizeof( chImageBuffer ), "swarm/MissionPics/addonMissionPic" );
|
|
chapterImage = chImageBuffer;
|
|
if ( lblGameStatus )
|
|
lblGameStatus->SetText( "" );
|
|
}
|
|
else if( fi.mbInGame )
|
|
{
|
|
chapterName = "";
|
|
IASW_Mission_Chooser_Source *pSource = missionchooser ? missionchooser->LocalMissionSource() : NULL;
|
|
const char *szDetailsMissionName = fi.mpGameDetails->GetString( "game/mission", "" );
|
|
KeyValues *pMissionKeys = NULL;
|
|
if ( pSource && szDetailsMissionName && szDetailsMissionName[0] )
|
|
{
|
|
pMissionKeys = pSource->GetMissionDetails( szDetailsMissionName );
|
|
}
|
|
|
|
if ( pMissionKeys )
|
|
{
|
|
if ( pMissionKeys->GetString( "image", NULL ) )
|
|
{
|
|
chapterImage = pMissionKeys->GetString( "image" );
|
|
}
|
|
campaignName = pMissionKeys->GetString( "displaytitle" );
|
|
szDownloadAuthor = pMissionKeys->GetString( "author", szDownloadAuthor );
|
|
szDownloadWebsite = pMissionKeys->GetString( "website", szDownloadWebsite );
|
|
}
|
|
else
|
|
{
|
|
campaignName = fi.mpGameDetails->GetString( "game/missioninfo/displaytitle", "#L4D360UI_CampaignName_Unknown" );
|
|
bDownloadableCampaign = true;
|
|
}
|
|
|
|
campaignName = fi.mpGameDetails->GetString( "game/missioninfo/displaytitle", campaignName );
|
|
szDownloadAuthor = fi.mpGameDetails->GetString( "game/missioninfo/author", szDownloadAuthor );
|
|
szDownloadWebsite = fi.mpGameDetails->GetString( "game/missioninfo/website", szDownloadWebsite );
|
|
bBuiltIn = fi.mpGameDetails->GetInt( "game/missioninfo/builtin", 0 );
|
|
|
|
if ( bBuiltIn )
|
|
szDownloadWebsite = ""; // no website access for builtin campaigns
|
|
|
|
char const *szGameMode = fi.mpGameDetails->GetString( "game/mode", "" );
|
|
if( !GameModeHasDifficulty( szGameMode ) )
|
|
{
|
|
Q_snprintf( chDifficultyBuffer, sizeof( chDifficultyBuffer ), "#L4D360UI_Mode_%s", szGameMode );
|
|
currentDifficulty = chDifficultyBuffer;
|
|
}
|
|
else
|
|
{
|
|
currentDifficulty = fi.mpGameDetails->GetString( "game/difficulty", "normal" );
|
|
Q_snprintf( chDifficultyBuffer, sizeof( chDifficultyBuffer ), "#L4D360UI_Difficulty_%s_%s", currentDifficulty, szGameMode );
|
|
currentDifficulty = chDifficultyBuffer;
|
|
}
|
|
|
|
char const *szAccess = fi.mpGameDetails->GetString( "system/access", "public" );
|
|
|
|
if ( !Q_stricmp( "private", szAccess ) )
|
|
currentSurvivorAccess = "#L4D360UI_Access_Invite";
|
|
else if ( !Q_stricmp( "friends", szAccess ) )
|
|
currentSurvivorAccess = "#L4D360UI_Access_Friends";
|
|
else
|
|
currentSurvivorAccess = "#L4D360UI_Access_Public";
|
|
|
|
int numSlots = fi.mpGameDetails->GetInt( "members/numSlots", 0 );
|
|
int numPlayers = fi.mpGameDetails->GetInt( "members/numPlayers", 0 );
|
|
if ( !numSlots )
|
|
Q_snprintf( playerCountText, stringSize, "1" );
|
|
else
|
|
Q_snprintf( playerCountText, stringSize, "%d/%d", numPlayers, numSlots );
|
|
|
|
if ( !Q_stricmp( "offline", fi.mpGameDetails->GetString( "system/network" ) ) )
|
|
{
|
|
playerCountText[0] = 0;
|
|
currentSurvivorAccess = ( numPlayers > 1 ) ? "#L4D360UI_Mode_offline_SS" : "#L4D360UI_Mode_offline_SP";
|
|
}
|
|
|
|
if ( lblGameStatus && ( fi.mInfoType == FoundGameListItem::FGT_PUBLICGAME ) )
|
|
{
|
|
int numLobbies = fi.mpGameDetails->GetInt( "rollup/lobby", 0 );
|
|
int numGames = fi.mpGameDetails->GetInt( "rollup/game", 0 );
|
|
|
|
wchar_t finalString[256] = L"";
|
|
wchar_t lobbyString[256] = L"";
|
|
wchar_t gamesString[256] = L"";
|
|
wchar_t numInLobbies[13], numInGame[13];
|
|
V_snwprintf( numInLobbies, ARRAYSIZE( numInLobbies ), L"%d", numLobbies );
|
|
V_snwprintf( numInGame, ARRAYSIZE( numInGame ), L"%d", numGames );
|
|
|
|
// Lobbies
|
|
const wchar_t *countText = NULL;
|
|
countText = ( numLobbies == 1 ) ?
|
|
g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_LobbyCount_1" ) :
|
|
g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_LobbyCount" );
|
|
if ( countText )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( lobbyString, sizeof( lobbyString ), countText, 1, numInLobbies );
|
|
}
|
|
|
|
// Games in Progress
|
|
countText = ( numGames == 1 ) ?
|
|
g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_GameCountInProgress_1" ) :
|
|
g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_GameCountInProgress" );
|
|
if ( countText )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( gamesString, sizeof( gamesString ), countText, 1, numInGame );
|
|
}
|
|
|
|
if ( IsX360() )
|
|
{
|
|
// Split games and lobbies into two lines
|
|
lblGameStatus->SetText( lobbyString );
|
|
if ( lblGameStatus2 )
|
|
{
|
|
lblGameStatus2->SetText( gamesString );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// merge games and lobbies
|
|
const wchar_t *statusText = g_pVGuiLocalize->Find( "#L4D360UI_FoundPublicGames_Status" );
|
|
if ( statusText )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( finalString, sizeof( finalString ), statusText, 2, lobbyString, gamesString );
|
|
}
|
|
lblGameStatus->SetText( finalString );
|
|
}
|
|
|
|
if ( numLobbies + numGames == 0 )
|
|
{
|
|
lblGameStatus->SetText( "#L4D360UI_FoundPublicGames_Status_None" );
|
|
|
|
if ( lblGameStatus2 )
|
|
{
|
|
lblGameStatus2->SetText( "" );
|
|
}
|
|
}
|
|
}
|
|
else if( lblGameStatus )
|
|
{
|
|
char const *szNetwork = fi.mpGameDetails->GetString( "system/network", "LIVE" );
|
|
|
|
char const *szGameState = fi.mpGameDetails->GetString( "game/state", "lobby" );
|
|
if ( !szGameState || !*szGameState )
|
|
szGameState = "game";
|
|
|
|
char chStatusTextBuffer[128];
|
|
Q_snprintf( chStatusTextBuffer, sizeof( chStatusTextBuffer ), "#L4D360UI_FoundGames_%sIn%s",
|
|
( !Q_stricmp( szNetwork, "lan" ) ) ? "Syslink" : "XboxLive",
|
|
szGameState );
|
|
lblGameStatus->SetText( chStatusTextBuffer );
|
|
}
|
|
}
|
|
|
|
if ( !fi.mbInGame || ( eDetails == DETAILS_PRESENCE ) )
|
|
{
|
|
// Friend not in game or in a private game, resort to presence only display
|
|
eDetails = DETAILS_PRESENCE;
|
|
|
|
// TODO?
|
|
//if ( !fi.IsOtherTitle() )
|
|
//chapterImage = "maps/any";
|
|
|
|
currentDifficulty = NULL;
|
|
currentSurvivorAccess = NULL;
|
|
|
|
chapterName = NULL; // NOT setting chapter name to "char-string"
|
|
campaignName = "";
|
|
|
|
// Tokenize rich presence string
|
|
wchar_t wszRichPresenceCopy[ MAX_RICHPRESENCE_SIZE ];
|
|
wcsncpy( wszRichPresenceCopy, fi.mpGameDetails->GetWString( "player/richpresence", L"" ), ARRAYSIZE( wszRichPresenceCopy ) );
|
|
wszRichPresenceCopy[ MAX_RICHPRESENCE_SIZE - 1 ] = 0;
|
|
wchar_t *pwzLine2 = wszRichPresenceCopy;
|
|
while ( *pwzLine2 != 0 && *pwzLine2 != L'\r' && *pwzLine2 != L'\n' )
|
|
++ pwzLine2;
|
|
while ( *pwzLine2 != 0 && ( *pwzLine2 == L'\r' || *pwzLine2 == L'\n' ) )
|
|
*( pwzLine2 ++ ) = 0;
|
|
|
|
if ( lblChapter )
|
|
{
|
|
lblChapter->SetText( wszRichPresenceCopy );
|
|
}
|
|
|
|
if ( lblGameDifficulty )
|
|
{
|
|
lblGameDifficulty->SetText( pwzLine2 );
|
|
}
|
|
}
|
|
|
|
if ( fi.IsDLC() || fi.IsOtherTitle() )
|
|
{
|
|
// Don't do anything below
|
|
}
|
|
else if ( fi.IsDownloadable() )
|
|
{
|
|
if ( joinButton )
|
|
{
|
|
joinButton->SetVisible( false );
|
|
SetControlVisible( "IconForwardArrow", false );
|
|
}
|
|
if ( downloadButton )
|
|
{
|
|
downloadButton->SetVisible( true );
|
|
downloadButton->SetEnabled( !!*szDownloadWebsite );
|
|
//downloadButton->SetHelpText( fi.GetJoinButtonHint(), true );
|
|
}
|
|
if ( downloadVersionLabel )
|
|
{
|
|
downloadVersionLabel->SetVisible( !bDownloadableCampaign );
|
|
}
|
|
}
|
|
else if ( joinButton )
|
|
{
|
|
if ( downloadButton )
|
|
{
|
|
downloadButton->SetVisible( false );
|
|
}
|
|
if ( downloadVersionLabel )
|
|
{
|
|
downloadVersionLabel->SetVisible( false );
|
|
}
|
|
|
|
bool bGameJoinable = fi.IsJoinable();
|
|
if ( !playerCountText[0] )
|
|
bGameJoinable = false; // single player games or offline
|
|
|
|
joinButton->SetVisible( true );
|
|
joinButton->SetEnabled( bGameJoinable );
|
|
//joinButton->SetHelpText( fi.GetJoinButtonHint(), bGameJoinable );
|
|
|
|
SetControlVisible( "IconForwardArrow", bGameJoinable );
|
|
}
|
|
else if ( !IsX360() )
|
|
{
|
|
eDetails = DETAILS_NONE;
|
|
|
|
if ( downloadButton )
|
|
{
|
|
downloadButton->SetVisible( false );
|
|
}
|
|
if ( downloadVersionLabel )
|
|
{
|
|
downloadVersionLabel->SetVisible( false );
|
|
}
|
|
if ( joinButton )
|
|
{
|
|
joinButton->SetVisible( false );
|
|
}
|
|
|
|
SetControlVisible( "IconForwardArrow", false );
|
|
}
|
|
}
|
|
|
|
vgui::Label *lblCampaign = dynamic_cast< vgui::Label* >( FindChildByName( "LblCampaign" ) );
|
|
if( lblCampaign )
|
|
{
|
|
lblCampaign->SetText( campaignName );
|
|
}
|
|
|
|
if( lblChapter && chapterName )
|
|
{
|
|
lblChapter->SetText( chapterName );
|
|
}
|
|
|
|
//
|
|
// Image
|
|
//
|
|
if ( chapterImage )
|
|
{
|
|
if( vgui::ImagePanel *imgLevelImage = dynamic_cast< vgui::ImagePanel* >( FindChildByName( "ImgLevelImage" ) ) )
|
|
imgLevelImage->SetImage( chapterImage );
|
|
|
|
SetControlVisible( "ImgLevelImage", true );
|
|
SetControlVisible( "ImgFrame", true );
|
|
}
|
|
else
|
|
{
|
|
SetControlVisible( "ImgLevelImage", false );
|
|
SetControlVisible( "ImgFrame", false );
|
|
}
|
|
|
|
wchar_t finalString[MAX_PATH] = L"";
|
|
wchar_t convertedString[MAX_PATH] = L"";
|
|
|
|
vgui::Label *lblAuthor = dynamic_cast< vgui::Label* >( FindChildByName( "LblAuthor" ) );
|
|
if( lblAuthor )
|
|
{
|
|
finalString[0] = 0;
|
|
if ( szDownloadAuthor && *szDownloadAuthor )
|
|
{
|
|
const wchar_t * authorFormat = g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_Author" );
|
|
g_pVGuiLocalize->ConvertANSIToUnicode( szDownloadAuthor, convertedString, sizeof( convertedString ) );
|
|
if ( authorFormat )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( finalString, sizeof( finalString ), authorFormat, 1, convertedString );
|
|
}
|
|
}
|
|
|
|
lblAuthor->SetText( finalString );
|
|
lblAuthor->SetVisible( finalString[0] != 0 );
|
|
|
|
|
|
//lblAuthor->SetText( "test" );
|
|
//lblAuthor->SetFgColor( Color( 255, 255, 255, 255 ) );
|
|
//lblAuthor->SetVisible( true );
|
|
|
|
//Msg( "author zpos = %d\n", lblAuthor->GetZPos() );
|
|
}
|
|
|
|
BaseModHybridButton *btnWebsite = dynamic_cast< BaseModHybridButton* >( FindChildByName( "BtnWebsite" ) );
|
|
if( btnWebsite )
|
|
{
|
|
finalString[0] = 0;
|
|
if ( *szDownloadWebsite )
|
|
{
|
|
const wchar_t * websiteFormat = g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_WebSite" );
|
|
g_pVGuiLocalize->ConvertANSIToUnicode( szDownloadWebsite, convertedString, sizeof( convertedString ) );
|
|
if ( websiteFormat )
|
|
{
|
|
g_pVGuiLocalize->ConstructString( finalString, sizeof( finalString ), websiteFormat, 1, convertedString );
|
|
}
|
|
}
|
|
|
|
btnWebsite->SetText( finalString );
|
|
btnWebsite->SetVisible( finalString[0] != 0 );
|
|
}
|
|
|
|
vgui::Label *lblAccess = dynamic_cast< vgui::Label* >( FindChildByName( "LblPlayerAccess" ) );
|
|
if( lblAccess )
|
|
{
|
|
lblAccess->SetText( currentSurvivorAccess ? currentSurvivorAccess : "" );
|
|
}
|
|
|
|
if( lblGameDifficulty && currentDifficulty )
|
|
{
|
|
lblGameDifficulty->SetText( currentDifficulty );
|
|
}
|
|
|
|
vgui::Label* lblNumPlayers = dynamic_cast< vgui::Label* >( FindChildByName( "LblNumPlayers" ) );
|
|
if( lblNumPlayers && ( eDetails == DETAILS_INGAME ) )
|
|
{
|
|
finalString[0] = 0;
|
|
const wchar_t * playersFormat = g_pVGuiLocalize->Find( "#L4D360UI_FoundGames_Players" );
|
|
if( playersFormat && playerCountText[0] )
|
|
{
|
|
g_pVGuiLocalize->ConvertANSIToUnicode( playerCountText, convertedString, sizeof( convertedString ) );
|
|
g_pVGuiLocalize->ConstructString( finalString, sizeof( finalString ), playersFormat, 1, convertedString );
|
|
}
|
|
|
|
lblNumPlayers->SetText( finalString );
|
|
}
|
|
else if( lblNumPlayers )
|
|
{
|
|
lblNumPlayers->SetText( "" );
|
|
}
|
|
|
|
vgui::Label *lblViewingGames = dynamic_cast< vgui::Label* >( FindChildByName( "LblViewingGames" ) );
|
|
if( lblViewingGames )
|
|
{
|
|
if( m_GplGames->GetPanelItemCount() )
|
|
{
|
|
char viewingGames[ 128 ];
|
|
int firstItem = m_GplGames->GetFirstVisibleItemNumber()+1;
|
|
int lastItem = m_GplGames->GetLastVisibleItemNumber()+1;
|
|
lastItem = MIN( lastItem, m_GplGames->GetPanelItemCount() );
|
|
Q_snprintf( viewingGames, 128, "%d-%d", firstItem, lastItem );
|
|
lblViewingGames->SetVisible( true );
|
|
lblViewingGames->SetText( viewingGames );
|
|
}
|
|
else
|
|
{
|
|
lblViewingGames->SetVisible( false );
|
|
}
|
|
}
|
|
|
|
if( !gameListItem )
|
|
{
|
|
eDetails = DETAILS_NONE;
|
|
}
|
|
|
|
#ifndef _X360
|
|
// Are we on the "Play Online" menus?
|
|
if ( CBaseModPanel::GetSingleton().GetWindow( WT_FOUNDPUBLICGAMES ) )
|
|
{
|
|
BaseModUI::BaseModHybridButton *m_pInstallSupportBtn = dynamic_cast< BaseModUI::BaseModHybridButton * >( FindChildByName( "BtnInstallSupport" ) );
|
|
vgui::Label *m_pSupportRequiredDetails = dynamic_cast< vgui::Label * >( FindChildByName( "LblSupportRequiredDetails" ) );
|
|
vgui::Label *lblInstalling = dynamic_cast< vgui::Label* >( FindChildByName( "LblInstalling" ) );
|
|
vgui::Label *lblInstallingDetails = dynamic_cast< vgui::Label* >( FindChildByName( "LblInstallingDetails" ) );
|
|
|
|
// If a SDK map is selected
|
|
if ( !bBuiltIn )
|
|
{
|
|
// If the Legacy SDK is NOT installed
|
|
if ( !GetLegacyData::IsInstalled() )
|
|
{
|
|
// If we are not already installing it
|
|
if ( !GetLegacyData::IsInstalling() )
|
|
{
|
|
// Hide all buttons and prompt the user to download the SDK
|
|
if ( joinButton && downloadButton && btnWebsite && m_pSupportRequiredDetails && m_pInstallSupportBtn )
|
|
{
|
|
joinButton->SetVisible( false );
|
|
downloadButton->SetVisible( false );
|
|
btnWebsite->SetVisible( false );
|
|
m_pSupportRequiredDetails->SetVisible( true );
|
|
m_pInstallSupportBtn->SetVisible( true );
|
|
}
|
|
|
|
SetControlVisible( "IconForwardArrow", false );
|
|
}
|
|
|
|
}
|
|
else // The SDK is installed or is installing
|
|
{
|
|
// Hide the SDK install prompt buttons
|
|
if ( m_pSupportRequiredDetails && m_pInstallSupportBtn )
|
|
{
|
|
m_pSupportRequiredDetails->SetVisible( false );
|
|
m_pInstallSupportBtn->SetVisible( false );
|
|
}
|
|
|
|
// If we are currently installing, display the install message
|
|
if ( GetLegacyData::IsInstalling() )
|
|
{
|
|
if ( lblInstalling && lblInstallingDetails )
|
|
{
|
|
lblInstalling->SetVisible( true );
|
|
lblInstallingDetails->SetVisible( true );
|
|
//joinButton->SetEnabled( false ); // comment in to force the Join Game button to only be active when the SDK is installed
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// A built-in map is selected. Hide any SDK install prompts
|
|
if ( lblInstalling && lblInstallingDetails && m_pSupportRequiredDetails && m_pInstallSupportBtn )
|
|
{
|
|
lblInstalling->SetVisible( false );
|
|
lblInstallingDetails->SetVisible( false );
|
|
m_pSupportRequiredDetails->SetVisible( false );
|
|
m_pInstallSupportBtn->SetVisible( false );
|
|
//joinButton->SetEnabled( true ); // comment in to force the Join Game button to only be active when the SDK is installed
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
SetDetailsPanelVisible( eDetails != DETAILS_NONE );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::ApplySchemeSettings( IScheme *pScheme )
|
|
{
|
|
BaseClass::ApplySchemeSettings( pScheme );
|
|
|
|
SetPaintBackgroundEnabled( true );
|
|
SetupAsDialogStyle();
|
|
|
|
m_pPreviousSelectedItem = NULL;
|
|
|
|
// Subscribe to the matchmaking events
|
|
g_pMatchFramework->GetEventsSubscription()->Subscribe( this );
|
|
|
|
Activate();
|
|
|
|
if( m_GplGames && m_ActiveControl != m_GplGames )
|
|
{
|
|
if ( m_ActiveControl )
|
|
m_ActiveControl->NavigateFrom();
|
|
|
|
m_GplGames->NavigateTo();
|
|
m_ActiveControl = m_GplGames;
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
FoundGameListItem* FoundGames::GetGameItem( int index )
|
|
{
|
|
FoundGameListItem *result = NULL;
|
|
if( index < m_GplGames->GetPanelItemCount() && index >= 0 )
|
|
{
|
|
result = dynamic_cast< FoundGameListItem* >( m_GplGames->GetPanelItem( index ) );
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::OnOpen()
|
|
{
|
|
SetVisible( true );
|
|
|
|
BaseClass::OnOpen();
|
|
|
|
m_GplGames->SetScrollBarVisible( IsPC() );
|
|
|
|
// trigger an explicit update
|
|
StartSearching();
|
|
UpdateGameDetails();
|
|
}
|
|
|
|
void FoundGames::SetDataSettings( KeyValues *pSettings )
|
|
{
|
|
if ( m_pDataSettings )
|
|
m_pDataSettings->deleteThis();
|
|
m_pDataSettings = pSettings ? pSettings->MakeCopy() : NULL;
|
|
|
|
BaseClass::SetDataSettings( pSettings );
|
|
}
|
|
|
|
//=============================================================================
|
|
void FoundGames::OnClose()
|
|
{
|
|
BaseClass::OnClose();
|
|
|
|
RemoveFrameListener( this );
|
|
}
|