diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/vgui/tf_lobbypanel_comp.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf/vgui/tf_lobbypanel_comp.cpp')
| -rw-r--r-- | game/client/tf/vgui/tf_lobbypanel_comp.cpp | 826 |
1 files changed, 826 insertions, 0 deletions
diff --git a/game/client/tf/vgui/tf_lobbypanel_comp.cpp b/game/client/tf/vgui/tf_lobbypanel_comp.cpp new file mode 100644 index 0000000..73577af --- /dev/null +++ b/game/client/tf/vgui/tf_lobbypanel_comp.cpp @@ -0,0 +1,826 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// +#include "cbase.h" + +#include "tf_party.h" +#include "vgui_controls/PropertySheet.h" +#include "vgui_controls/ScrollableEditablePanel.h" + +#include "tf_lobbypanel_comp.h" +#include "tf_lobby_container_frame_comp.h" + +#include "vgui/ISystem.h" + +#include "tf_streams.h" +#include "tf_badge_panel.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +ConVar tf_mm_ladder_ui_last_rating_change( "tf_mm_ladder_ui_last_rating_change", "0", FCVAR_HIDDEN | FCVAR_ARCHIVE, "Track last match skillrating change for UI." ); +ConVar tf_mm_ladder_ui_last_rating_time( "tf_mm_ladder_ui_last_rating_time", "-1", FCVAR_HIDDEN | FCVAR_ARCHIVE, "Track last match skillrating change time for UI." ); + +class CLobbyPanel_Comp; + +#include "iclientmode.h" +#include <vgui_controls/AnimationController.h> + +class CMatchHistoryEntryPanel : public CExpandablePanel +{ +public: + DECLARE_CLASS_SIMPLE( CMatchHistoryEntryPanel, CExpandablePanel ); + CMatchHistoryEntryPanel( Panel* pParent, const char *pszPanelname ) + : BaseClass( pParent, pszPanelname ) + {} + + virtual void ApplySchemeSettings( IScheme *pScheme ) OVERRIDE + { + BaseClass::ApplySchemeSettings( pScheme ); + + LoadControlSettings( "resource/ui/MatchHistoryEntryPanel.res" ); + } + + void SetMatchData( const CSOTFMatchResultPlayerStats& stats ) + { + EditablePanel* pContainer = FindControl< EditablePanel >( "Container" ); + if ( !pContainer ) + return; + + // Match date + CRTime matchdate( stats.endtime() ); + char rtime_buf[k_RTimeRenderBufferSize]; + matchdate.Render( rtime_buf ); + pContainer->SetDialogVariable( "match_date", rtime_buf ); + + // Map name + const MapDef_t* pMapDef = GetItemSchema()->GetMasterMapDefByIndex( stats.map_index() ); + const char* pszMapToken = "#TF_Map_Unknown"; + if ( pMapDef ) + { + pszMapToken = pMapDef->pszMapNameLocKey; + } + pContainer->SetDialogVariable( "map_name", g_pVGuiLocalize->Find( pszMapToken ) ); + + // KD ratio + float flKDRatio = stats.kills(); + if ( stats.deaths() > 0 ) + { + flKDRatio /= (float)stats.deaths(); + } + pContainer->SetDialogVariable( "kd_ratio", CFmtStr( "%.1f", flKDRatio ) ); + + pContainer->SetControlVisible( "WinLabel", stats.display_rating_change() > 0 ); + pContainer->SetControlVisible( "LossLabel", stats.display_rating_change() < 0 ); + + EditablePanel* pStatsContainer = FindControl< EditablePanel >( "SlidingStatsContainer", true ); + if ( pStatsContainer ) + { + pStatsContainer->SetDialogVariable( "stat_kills", LocalizeNumberWithToken( "TF_Competitive_Kills", stats.kills() ) ); + pStatsContainer->SetDialogVariable( "stat_deaths", LocalizeNumberWithToken( "TF_Competitive_Deaths", stats.deaths() ) ); + pStatsContainer->SetDialogVariable( "stat_damage", LocalizeNumberWithToken( "TF_Competitive_Damage", stats.damage() ) ); + pStatsContainer->SetDialogVariable( "stat_healing", LocalizeNumberWithToken( "TF_Competitive_Healing", stats.healing() ) ); + pStatsContainer->SetDialogVariable( "stat_support", LocalizeNumberWithToken( "TF_Competitive_Support", stats.support() ) ); + pStatsContainer->SetDialogVariable( "stat_score", LocalizeNumberWithToken( "TF_Competitive_Score", stats.score() ) ); + + ScalableImagePanel* pMapImage = pStatsContainer->FindControl< ScalableImagePanel >( "BGImage", true ); + if ( pMapImage && pMapDef ) + { + char imagename[ 512 ]; + Q_snprintf( imagename, sizeof( imagename ), "..\\vgui\\maps\\menu_thumb_%s", pMapDef->pszMapName ); + pMapImage->SetImage( imagename ); + } + + // Lambdas, wherefore art thou... + SetupClassIcon( pStatsContainer, "scout", TF_CLASS_SCOUT, stats ); + SetupClassIcon( pStatsContainer, "soldier", TF_CLASS_SOLDIER, stats ); + SetupClassIcon( pStatsContainer, "pyro", TF_CLASS_PYRO, stats ); + SetupClassIcon( pStatsContainer, "demo", TF_CLASS_DEMOMAN, stats ); + SetupClassIcon( pStatsContainer, "heavy", TF_CLASS_HEAVYWEAPONS, stats ); + SetupClassIcon( pStatsContainer, "engineer", TF_CLASS_ENGINEER, stats ); + SetupClassIcon( pStatsContainer, "medic", TF_CLASS_MEDIC, stats ); + SetupClassIcon( pStatsContainer, "sniper", TF_CLASS_SNIPER, stats ); + SetupClassIcon( pStatsContainer, "spy", TF_CLASS_SPY, stats ); + + SetupMedalForStat( pStatsContainer, stats.kills_medal(), "kills" ); + SetupMedalForStat( pStatsContainer, stats.damage_medal(), "damage" ); + SetupMedalForStat( pStatsContainer, stats.healing_medal(), "healing" ); + SetupMedalForStat( pStatsContainer, stats.support_medal(), "support" ); + SetupMedalForStat( pStatsContainer, stats.score_medal(), "score" ); + } + } +private: + + void SetupMedalForStat( EditablePanel* pParent, int nStat, const char* pszStatName ) + { + ScalableImagePanel* pMedalImage = pParent->FindControl< ScalableImagePanel >( CFmtStr( "%sMedal", pszStatName ) ); + if ( pMedalImage ) + { + if ( nStat != StatMedal_None ) + { + pMedalImage->SetImage( g_pszCompetitiveMedalImages[ nStat ] ); + } + pMedalImage->SetVisible( nStat != StatMedal_None ); + } + } + + void SetupClassIcon( EditablePanel* pParent, const char* pszClassName, int nBit, const CSOTFMatchResultPlayerStats& stats ) + { + ScalableImagePanel* pClassIcon = pParent->FindControl< ScalableImagePanel >( CFmtStr( "%sIcon", pszClassName ), true ); + if( pClassIcon ) + { + pClassIcon->SetImage( stats.classes_played() & (1<<nBit) ? CFmtStr( "class_icons/filter_%s_on", pszClassName ) : CFmtStr( "class_icons/filter_%s", pszClassName ) ); + } + } +}; + +DECLARE_BUILD_FACTORY( CMatchHistoryEntryPanel ); + +extern Color s_colorChallengeHeader; + +DECLARE_BUILD_FACTORY( CLadderLobbyLeaderboard ); +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CLadderLobbyLeaderboard::CLadderLobbyLeaderboard( Panel *pParent, const char *pszPanelName ) + : CTFLeaderboardPanel( pParent, pszPanelName ) +{ + m_pScoreList = new vgui::EditablePanel( this, "ScoreList" ); + m_pScoreListScroller = new vgui::ScrollableEditablePanel( this, m_pScoreList, "ScoreListScroller" ); + m_pScoreListScroller->AddActionSignalTarget( this ); + + m_pszLeaderboardName = "tf2_ladder_6v6"; + + for ( int i = 0; i < 100; ++i ) + { + vgui::EditablePanel *pEntryUI = new vgui::EditablePanel( m_pScoreList, "LeaderboardEntry" ); + m_vecLeaderboardEntries.AddToTail( pEntryUI ); + } + + m_pToolTip = new CTFTextToolTip( this ); + m_pToolTipEmbeddedPanel = new vgui::EditablePanel( this, "TooltipPanel" ); + m_pToolTipEmbeddedPanel->SetKeyBoardInputEnabled( false ); + m_pToolTipEmbeddedPanel->SetMouseInputEnabled( false ); + m_pToolTip->SetEmbeddedPanel( m_pToolTipEmbeddedPanel ); + m_pToolTip->SetTooltipDelay( 0 ); + + m_bIsDataValid = false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLadderLobbyLeaderboard::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + LoadControlSettings( "Resource/UI/econ/LobbyLeaderboard.res" ); + + FOR_EACH_VEC( m_vecLeaderboardEntries, i ) + { + m_vecLeaderboardEntries[i]->ApplySchemeSettings( pScheme ); + m_vecLeaderboardEntries[i]->LoadControlSettings( "Resource/UI/LeaderboardEntryRank.res" ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLadderLobbyLeaderboard::PerformLayout() +{ + BaseClass::PerformLayout(); + + UpdateLeaderboards(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLadderLobbyLeaderboard::OnCommand( const char *command ) +{ + if ( Q_strnicmp( command, "stream", 6 ) == 0 ) + { + vgui::system()->ShellExecute( "open", command + 7 ); + return; + } + else if ( FStrEq( "global", command ) ) + { + if ( m_bGlobal != true ) + { + m_bGlobal = true; + UpdateLeaderboards(); + } + + return; + } + else if ( FStrEq( "local", command ) ) + { + if ( m_bGlobal == true ) + { + m_bGlobal = false; + UpdateLeaderboards(); + } + } + + BaseClass::OnCommand( command ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CLadderLobbyLeaderboard::GetLeaderboardData( CUtlVector< LeaderboardEntry_t* >& scores ) +{ + CUtlVector< LeaderboardEntry_t* > vecLadderScores; + if ( Leaderboards_GetLadderLeaderboard( vecLadderScores, m_pszLeaderboardName, m_bGlobal ) ) + { + scores.AddVectorToTail( vecLadderScores ); + return true; + } + + return false; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CLadderLobbyLeaderboard::UpdateLeaderboards() +{ + CUtlVector< LeaderboardEntry_t* > scores; + m_bIsDataValid = GetLeaderboardData( scores ); + if ( !m_bIsDataValid ) + return false; + + int nScoreListHeight = scores.Count() * m_yEntryStep; + int nScrollerWidth, nScrollerHeight; + m_pScoreListScroller->GetSize( nScrollerWidth, nScrollerHeight ); + + m_pScoreList->SetSize( nScrollerWidth, Max( nScoreListHeight, nScrollerHeight ) ); + + m_pScoreList->InvalidateLayout( true ); + m_pScoreListScroller->InvalidateLayout( true ); + m_pScoreListScroller->GetScrollbar()->InvalidateLayout( true ); + static int nScrollWidth = m_pScoreListScroller->GetScrollbar()->GetWide(); + m_pScoreListScroller->GetScrollbar()->SetWide( nScrollWidth>>1 ); + if ( m_pScoreListScroller->GetScrollbar()->GetButton( 0 ) && + m_pScoreListScroller->GetScrollbar()->GetButton( 1 ) ) + { + m_pScoreListScroller->GetScrollbar()->GetButton( 0 )->SetVisible( false ); + m_pScoreListScroller->GetScrollbar()->GetButton( 1 )->SetVisible( false ); + } + + FOR_EACH_VEC( m_vecLeaderboardEntries, i ) + { + EditablePanel *pContainer = dynamic_cast< EditablePanel* >( m_vecLeaderboardEntries[i] ); + if ( !pContainer ) + continue; + + Color colorToUse = i % 2 == 1 ? m_OddTextColor : m_EvenTextColor; + + bool bIsEntryVisible = i < scores.Count(); + pContainer->SetVisible( bIsEntryVisible ); + pContainer->SetPos( 0, i * m_yEntryStep ); + if ( bIsEntryVisible ) + { + const LeaderboardEntry_t *pLeaderboardEntry = scores[i]; + const CSteamID &steamID = pLeaderboardEntry->m_steamIDUser; + +#ifdef TWITCH_LEADERBOARD + TwitchTvAccountInfo_t *pTwitchInfo = StreamManager()->GetTwitchTvAccountInfo( steamID.ConvertToUint64() ); + ETwitchTvState_t twitchState = pTwitchInfo ? pTwitchInfo->m_eTwitchTvState : k_ETwitchTvState_Error; + // still waiting for twitch info to load + if ( twitchState <= k_ETwitchTvState_Loading ) + return false; +#endif // TWITCH_LEADERBOARD + + bool bIsLocalPlayer = steamapicontext && steamapicontext->SteamUser() && steamapicontext->SteamUser()->GetSteamID() == steamID; + pContainer->SetDialogVariable( "position", m_bGlobal ? CFmtStr( "%d.", pLeaderboardEntry->m_nGlobalRank ) : "" ); + pContainer->SetDialogVariable( "username", InventoryManager()->PersonaName_Get( steamID.GetAccountID() ) ); + + CExLabel *pNameText = dynamic_cast< CExLabel* >( pContainer->FindChildByName( "UserName" ) ); + if ( pNameText ) + { + pNameText->SetColorStr( bIsLocalPlayer ? m_LocalPlayerTextColor : colorToUse ); + } + + CAvatarImagePanel *pAvatar = dynamic_cast< CAvatarImagePanel* >( pContainer->FindChildByName( "AvatarImage" ) ); + if ( pAvatar ) + { + pAvatar->SetShouldDrawFriendIcon( false ); + pAvatar->SetPlayer( steamID, k_EAvatarSize32x32 ); + } + + CTFBadgePanel *pRankImage = dynamic_cast< CTFBadgePanel* >( pContainer->FindChildByName( "RankImage" ) ); + if ( pRankImage ) + { + const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( k_nMatchGroup_Ladder_6v6 ); + const LevelInfo_t& levelInfo = pMatchDesc->m_pProgressionDesc->GetLevelForExperience( pLeaderboardEntry->m_nScore ); + pRankImage->SetupBadge( pMatchDesc->m_pProgressionDesc, levelInfo ); + + wchar_t wszOutString[ 128 ]; + char szLocalized[512]; + wchar_t wszCount[ 16 ]; + _snwprintf( wszCount, ARRAYSIZE( wszCount ), L"%d", levelInfo.m_nLevelNum ); + const wchar_t *wpszFormat = g_pVGuiLocalize->Find( pMatchDesc->m_pProgressionDesc->m_pszLevelToken ); + g_pVGuiLocalize->ConstructString_safe( wszOutString, wpszFormat, 2, wszCount, g_pVGuiLocalize->Find( levelInfo.m_pszLevelTitle ) ); + g_pVGuiLocalize->ConvertUnicodeToANSI( wszOutString, szLocalized, sizeof( szLocalized ) ); + + pRankImage->SetMouseInputEnabled( true ); + pRankImage->SetVisible( true ); + pRankImage->SetTooltip( m_pToolTip, szLocalized ); + } + + CExImageButton *pStreamImage = dynamic_cast< CExImageButton* >( pContainer->FindChildByName( "StreamImageButton" ) ); + if ( pStreamImage ) + { +#ifdef TWITCH_LEADERBOARD + if ( twitchState == k_ETwitchTvState_Linked ) + { + pStreamImage->SetVisible( true ); + pStreamImage->SetCommand( CFmtStr( "stream %s", pTwitchInfo->m_sTwitchTvChannel.String() ) ); + } + else +#endif // TWITCH_LEADERBOARD + { + pStreamImage->SetVisible( false ); + pStreamImage->SetCommand( "" ); + } + } + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLadderLobbyLeaderboard::SetLeaderboard( const char *pszLeaderboardName, bool bGlobal ) +{ + m_pszLeaderboardName = pszLeaderboardName; + m_bGlobal = bGlobal; + + UpdateLeaderboards(); +} + +static void GetPlayerNameForSteamID( wchar_t *wCharPlayerName, int nBufSizeBytes, const CSteamID &steamID ) +{ + const char *pszName = steamapicontext->SteamFriends()->GetFriendPersonaName( steamID ); + V_UTF8ToUnicode( pszName, wCharPlayerName, nBufSizeBytes ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CLobbyPanel_Comp::CLobbyPanel_Comp( vgui::Panel *pParent, CBaseLobbyContainerFrame* pLobbyContainer ) + : CBaseLobbyPanel( pParent, pLobbyContainer ) + , m_pCompetitiveModeLeaderboard( NULL ) + , m_pMatchHistoryScroller( NULL ) + , m_eMatchSortMethod( SORT_BY_DATE ) + , m_bDescendingMatchHistorySort( true ) +{ + // Comp + m_fontMedalsCount = 0; + + m_flCompetitiveRankProgress = -1.f; + m_flCompetitiveRankPrevProgress = -1.f; + m_flRefreshPlayerListTime = -1.f; + m_bCompetitiveRankChangePlayedSound = false; + m_bMatchHistoryLoaded = false; + m_bMatchDataForLocalPlayerDirty = true; + + ListenForGameEvent( "gc_new_session" ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CLobbyPanel_Comp::~CLobbyPanel_Comp() +{ + delete m_pImageList; + m_pImageList = NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::OnCommand( const char *command ) +{ + + if ( FStrEq( command, "medals_help" ) ) + { + CExplanationPopup *pPopup = dynamic_cast< CExplanationPopup* >( GetParent()->FindChildByName( "MedalsHelp" ) ); + if ( pPopup ) + { + pPopup->Popup(); + } + return; + } + else if ( FStrEq( command, "show_leaderboards" ) ) + { + if ( m_pCompetitiveModeLeaderboard ) + { + m_pCompetitiveModeLeaderboard->SetVisible( true ); + } + + SetControlVisible( "MatchHistoryCategories", false, true ); + SetControlVisible( "MatchHistoryContainer", false, true ); + + return; + } + else if ( FStrEq( command, "show_match_history" ) ) + { + m_bMatchDataForLocalPlayerDirty = true; + + if ( m_pCompetitiveModeLeaderboard ) + { + m_pCompetitiveModeLeaderboard->SetVisible( false ); + } + + SetControlVisible( "MatchHistoryCategories", true, true ); + SetControlVisible( "MatchHistoryContainer", true, true ); + + return; + } + else if ( !Q_strncmp( "sort", command, 4 ) ) + { + EMatchHistorySortMethods_t eNewMethod = (EMatchHistorySortMethods_t)atoi( command + 4 ); + + if ( eNewMethod == m_eMatchSortMethod ) + { + m_bDescendingMatchHistorySort = !m_bDescendingMatchHistorySort; + } + else + { + m_eMatchSortMethod = eNewMethod; + m_bDescendingMatchHistorySort = true; + } + + m_bMatchDataForLocalPlayerDirty = true; + + return; + } + + BaseClass::OnCommand( command ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CLobbyPanel_Comp::ShouldShowLateJoin() const +{ + return false; // For now +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::ApplyChatUserSettings( const CBaseLobbyPanel::LobbyPlayerInfo &player, KeyValues *pKV ) const +{ + pKV->SetInt( "has_ticket", 0 ); + pKV->SetInt( "squad_surplus", 0 ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::WriteGameSettingsControls() +{ + BaseClass::WriteGameSettingsControls(); + + // 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; + } + + ++m_iWritingPanel; + + m_pContainer->SetNextButtonEnabled( true ); + + SetControlVisible( "ScrollableContainer", GTFGCClientSystem()->GetWizardStep()== TF_Matchmaking_WizardStep_LADDER ); + + --m_iWritingPanel; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CLobbyPanel_Comp::GetMedalCountForStat( EMatchGroup unLadderType, RankStatType_t nStatType, int nMedalLevel ) +{ + CSOTFLadderData *pData = GetLocalPlayerLadderData( unLadderType ); + if ( !pData ) + return 0; + + switch ( nStatType ) + { + case RankStat_Score: + if ( nMedalLevel == StatMedal_Bronze ) + { + return pData->Obj().score_bronze(); + } + else if ( nMedalLevel == StatMedal_Silver ) + { + return pData->Obj().score_silver(); + } + else if ( nMedalLevel == StatMedal_Gold ) + { + return pData->Obj().score_gold(); + } + break; + case RankStat_Kills: + if ( nMedalLevel == StatMedal_Bronze ) + { + return pData->Obj().kills_bronze(); + } + else if ( nMedalLevel == StatMedal_Silver ) + { + return pData->Obj().kills_silver(); + } + else if ( nMedalLevel == StatMedal_Gold ) + { + return pData->Obj().kills_gold(); + } + break; + case RankStat_Damage: + if ( nMedalLevel == StatMedal_Bronze ) + { + return pData->Obj().damage_bronze(); + } + else if ( nMedalLevel == StatMedal_Silver ) + { + return pData->Obj().damage_silver(); + } + else if ( nMedalLevel == StatMedal_Gold ) + { + return pData->Obj().damage_gold(); + } + break; + case RankStat_Healing: + if ( nMedalLevel == StatMedal_Bronze ) + { + return pData->Obj().healing_bronze(); + } + else if ( nMedalLevel == StatMedal_Silver ) + { + return pData->Obj().healing_silver(); + } + else if ( nMedalLevel == StatMedal_Gold ) + { + return pData->Obj().healing_gold(); + } + break; + case RankStat_Support: + if ( nMedalLevel == StatMedal_Bronze ) + { + return pData->Obj().support_bronze(); + } + else if ( nMedalLevel == StatMedal_Silver ) + { + return pData->Obj().support_silver(); + } + else if ( nMedalLevel == StatMedal_Gold ) + { + return pData->Obj().support_gold(); + } + break; + case RankStat_Deaths: + // Not supported + break; + default: + Assert( 0 ); + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::OnThink() +{ + BaseClass::OnThink(); + + if ( m_bMatchDataForLocalPlayerDirty ) + { + UpdateMatchDataForLocalPlayer(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::FireGameEvent( IGameEvent *event ) +{ + const char *pszEventname = event->GetName(); + if ( !Q_stricmp( pszEventname, "gc_new_session" ) ) + { + // This is loaded on demand by the GC - if we have a new session, we need to re-request + if ( m_bMatchHistoryLoaded ) + { + m_bMatchHistoryLoaded = false; + m_bMatchDataForLocalPlayerDirty = true; + } + } + + BaseClass::FireGameEvent( event ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +EMatchGroup CLobbyPanel_Comp::GetMatchGroup( void ) const +{ + return k_nMatchGroup_Ladder_6v6; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::SOCreated( const CSteamID & steamIDOwner, const CSharedObject *pObject, ESOCacheEvent eEvent ) +{ + if ( pObject->GetTypeID() != CSOTFMatchResultPlayerInfo::k_nTypeID ) + return; + + m_bMatchDataForLocalPlayerDirty = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::SOUpdated( const CSteamID & steamIDOwner, const CSharedObject *pObject, ESOCacheEvent eEvent ) +{ + if ( pObject->GetTypeID() != CSOTFMatchResultPlayerInfo::k_nTypeID ) + return; + + m_bMatchDataForLocalPlayerDirty = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::PerformLayout() +{ + BaseClass::PerformLayout(); + + m_bMatchDataForLocalPlayerDirty = true; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CLobbyPanel_Comp::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + EditablePanel* pPlaylistBGPanel = FindControl< EditablePanel >( "PlaylistBGPanel", true ); + m_pCompetitiveModeLeaderboard = pPlaylistBGPanel->FindControl< CLadderLobbyLeaderboard >( "Leaderboard", true ); + + m_pMatchHistoryScroller = pPlaylistBGPanel->FindControl< CScrollableList >( "MatchHistoryContainer" ); + + int nAvatarWidth = ( ( m_iAvatarWidth * 5 / 4 ) + 1 ); + int nExtraWidth = ( m_pChatPlayerList->GetWide() - ( 2 * nAvatarWidth ) - m_iPlayerNameWidth - m_iBannedWidth - m_iHasPassWidth ); + + m_pChatPlayerList->AddColumnToSection( 0, "avatar", "#TF_Players", vgui::SectionedListPanel::COLUMN_IMAGE, nAvatarWidth ); + m_pChatPlayerList->AddColumnToSection( 0, "name", "", 0, m_iPlayerNameWidth + nExtraWidth ); + m_pChatPlayerList->AddColumnToSection( 0, "is_banned", "", vgui::SectionedListPanel::COLUMN_IMAGE | vgui::SectionedListPanel::COLUMN_CENTER, m_iBannedWidth ); + m_pChatPlayerList->AddColumnToSection( 0, "has_competitive_access", "", vgui::SectionedListPanel::COLUMN_IMAGE | vgui::SectionedListPanel::COLUMN_CENTER, m_iHasPassWidth ); + m_pChatPlayerList->AddColumnToSection( 0, "rank", "", vgui::SectionedListPanel::COLUMN_IMAGE | vgui::SectionedListPanel::COLUMN_CENTER, nAvatarWidth ); + m_pChatPlayerList->SetDrawHeaders( false ); + m_fontMedalsCount = pScheme->GetFont( "HudFontSmallestBold", true ); +} + +static int SortResult( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ) +{ + return a->display_rating_change() < b->display_rating_change(); +} + +static int SortDate( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ) +{ + return a->endtime() < b->endtime(); +} + +static int SortMap( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ) +{ + const MapDef_t* pMapDef = GetItemSchema()->GetMasterMapDefByIndex( a->map_index() ); + const wchar_t* pszAMapName = g_pVGuiLocalize->Find( pMapDef ? pMapDef->pszMapNameLocKey : "#TF_Map_Unknown" ); + + pMapDef = GetItemSchema()->GetMasterMapDefByIndex( b->map_index() ); + const wchar_t* pszBMapName = g_pVGuiLocalize->Find( pMapDef ? pMapDef->pszMapNameLocKey : "#TF_Map_Unknown" ); + + return wcscoll( pszAMapName, pszBMapName ); +} + +static int SortKDR( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ) +{ + float flAKDRatio = a->kills(); + if ( a->deaths() > 0 ) + { + flAKDRatio /= (float)a->deaths(); + } + + float flBKDRatio = b->kills(); + if ( b->deaths() > 0 ) + { + flBKDRatio /= (float)b->deaths(); + } + + return ( flBKDRatio - flAKDRatio ) * 1000.f; +} + +void CLobbyPanel_Comp::UpdateMatchDataForLocalPlayer() +{ + m_bMatchDataForLocalPlayerDirty = false; + + CUtlVector < CSOTFMatchResultPlayerStats > vecMatches; + GetLocalPlayerMatchHistory( GetMatchGroup(), vecMatches ); + + if ( !m_bMatchHistoryLoaded ) + { + GCSDK::CProtoBufMsg< CMsgGCMatchHistoryLoad > msg( k_EMsgGCMatchHistoryLoad ); + GCClientSystem()->BSendMessage( msg ); + + m_bMatchHistoryLoaded = true; + } + + if ( m_pMatchHistoryScroller ) + { + m_pMatchHistoryScroller->ClearAutoLayoutPanels(); + + typedef int (*MatchSortFunc)( const CSOTFMatchResultPlayerStats * a, const CSOTFMatchResultPlayerStats * b ); + + struct SortMethodData_t + { + MatchSortFunc m_pfnSort; + CExButton* m_pSortButton; + }; + + EditablePanel* pPlaylistBGPanel = FindControl< EditablePanel >( "PlaylistBGPanel", true ); + Assert( pPlaylistBGPanel ); + if ( !pPlaylistBGPanel ) + return; + + SortMethodData_t sortMethods[ NUM_SORT_METHODS ] = { { &SortResult, pPlaylistBGPanel->FindControl< CExButton >( "ResultButton", true ) } + , { &SortDate, pPlaylistBGPanel->FindControl< CExButton >( "DateButton", true ) } + , { &SortMap, pPlaylistBGPanel->FindControl< CExButton >( "MapButton", true ) } + , { &SortKDR, pPlaylistBGPanel->FindControl< CExButton >( "KDRButton", true ) } }; + + // Sort + vecMatches.Sort( sortMethods[ m_eMatchSortMethod ].m_pfnSort ); + + Label* pSortArrow = pPlaylistBGPanel->FindControl< Label >( "SortArrow", true ); + Assert( pSortArrow ); + if ( !pSortArrow ) + return; + + // Update controls + for( int i=0; i<ARRAYSIZE( sortMethods ); ++i ) + { + if( sortMethods[ i ].m_pSortButton ) + { + bool bSelected = i == m_eMatchSortMethod; + sortMethods[ i ].m_pSortButton->SetSelected( bSelected ); + + if ( bSelected ) + { + int nDummy, nX; + sortMethods[ i ].m_pSortButton->GetContentSize( nX, nDummy ); + // Move the sort arrow to the right edge of the selected panel + pSortArrow->SetPos( sortMethods[ i ].m_pSortButton->GetXPos() + nX , pSortArrow->GetYPos() ); + // Fixup the label to be an up or down arrow + pSortArrow->SetText( m_bDescendingMatchHistorySort ? L"6" : L"5" ); + } + } + } + + // Potentially go backwards + if ( m_bDescendingMatchHistorySort ) + { + FOR_EACH_VEC( vecMatches, i ) + { + CMatchHistoryEntryPanel* pMatchEntryPanel = new CMatchHistoryEntryPanel( m_pMatchHistoryScroller, "MatchEntry" ); + pMatchEntryPanel->MakeReadyForUse(); + pMatchEntryPanel->SetMatchData( vecMatches[ i ] ); + m_pMatchHistoryScroller->AddPanel( pMatchEntryPanel, 5 ); + } + } + else + { + FOR_EACH_VEC_BACK( vecMatches, i ) + { + CMatchHistoryEntryPanel* pMatchEntryPanel = new CMatchHistoryEntryPanel( m_pMatchHistoryScroller, "MatchEntry" ); + pMatchEntryPanel->MakeReadyForUse(); + pMatchEntryPanel->SetMatchData( vecMatches[ i ] ); + m_pMatchHistoryScroller->AddPanel( pMatchEntryPanel, 5 ); + } + } + + m_pMatchHistoryScroller->MakeReadyForUse(); + } +} |