//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include "hud.h" #include "tf_match_summary.h" #include "tf_hud_statpanel.h" #include "tf_spectatorgui.h" #include "vgui_controls/AnimationController.h" #include "iclientmode.h" #include "engine/IEngineSound.h" #include "c_tf_playerresource.h" #include "c_team.h" #include "tf_clientscoreboard.h" #include #include #include #include #include "vgui_avatarimage.h" #include "fmtstr.h" #include "teamplayroundbased_gamerules.h" #include "tf_gamerules.h" #include "tf_logic_halloween_2014.h" #include "tf_playermodelpanel.h" #include "tf_mapinfo.h" #include "c_tf_team.h" #include "tf_pvp_rank_panel.h" #include "tf_badge_panel.h" #include "tf_survey_questions.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" void AddSubKeyNamed( KeyValues *pKeys, const char *pszName ); extern ISoundEmitterSystemBase *soundemitterbase; #define MAX_PLAYER_MODELS 6 #define MS_STATE_TRANSITION_TO_STATS 17.0f #define MS_STATE_TRANSITION_TO_MEDALS 3.0f #define MS_STATE_TIME_BETWEEN_MEDALS 0.1f #define MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES 0.1f extern ConVar tf_scoreboard_alt_class_icons; DECLARE_BUILD_FACTORY( TFSectionedListPanel ); DECLARE_HUDELEMENT( CTFMatchSummary ); #ifdef STAGING_ONLY static void cc_tf_restart_match_summary() { CTFMatchSummary *pMatchSummary = GET_HUDELEMENT( CTFMatchSummary ); if (pMatchSummary) { pMatchSummary->InvalidateLayout(true, true); pMatchSummary->SetVisible( false ); pMatchSummary->SetVisible( true ); } } ConCommand tf_restart_match_summary("tf_restart_match_summary", cc_tf_restart_match_summary); #endif //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CTFMatchSummary::CTFMatchSummary( const char *pElementName ) : CHudElement( pElementName ) , EditablePanel( NULL, "MatchSummary" ) , m_bXPShown( false ) { vgui::Panel *pParent = g_pClientMode->GetViewport(); SetParent( pParent ); m_pMainStatsContainer = new EditablePanel( this, "MainStatsContainer" ); m_pDrawingPanel = new CDrawingPanel( this, "DrawingPanel" ); m_pStatsBgPanel = new EditablePanel( this, "StatsBgPanel" ); m_pTeamScoresPanel = new EditablePanel( m_pMainStatsContainer, "TeamScoresPanel" ); m_pParticlePanel = new CTFParticlePanel( m_pMainStatsContainer, "ParticlePanel" ); m_pStatsLabelPanel = new EditablePanel( m_pMainStatsContainer, "StatsLabelPanel" ); m_pBlueTeamPanel = new EditablePanel( m_pTeamScoresPanel, "BlueTeamPanel" ); m_pRedTeamPanel = new EditablePanel( m_pTeamScoresPanel, "RedTeamPanel" ); m_pPlayerListBlueParent = new EditablePanel( m_pBlueTeamPanel, "BluePlayerListParent" ); m_pPlayerListBlue = new TFSectionedListPanel( m_pPlayerListBlueParent, "BluePlayerList" ); m_pPlayerListRedParent = new EditablePanel( m_pRedTeamPanel, "RedPlayerListParent" ); m_pPlayerListRed = new TFSectionedListPanel( m_pPlayerListRedParent, "RedPlayerList" ); m_pBlueTeamScore = new CExLabel( m_pBlueTeamPanel, "BlueTeamScore", "" ); m_pBlueTeamScoreDropshadow = new CExLabel( m_pBlueTeamPanel, "BlueTeamScoreDropshadow", "" ); m_pBlueTeamScoreBG = new EditablePanel( m_pBlueTeamPanel, "BlueTeamScoreBG" ); m_pBluePlayerListBG = new EditablePanel( m_pBlueTeamPanel, "BluePlayerListBG" ); m_pRedTeamScore = new CExLabel( m_pRedTeamPanel, "RedTeamScore", "" ); m_pRedTeamScoreDropshadow = new CExLabel( m_pRedTeamPanel, "RedTeamScoreDropshadow", "" ); m_pRedTeamScoreBG = new EditablePanel( m_pRedTeamPanel, "RedTeamScoreBG" ); m_pRedPlayerListBG = new EditablePanel( m_pRedTeamPanel, "RedPlayerListBG" ); m_pBlueMedalsPanel = new EditablePanel( m_pTeamScoresPanel, "BlueMedals" ); m_pRedMedalsPanel = new EditablePanel( m_pTeamScoresPanel, "RedMedals" ); m_pRedTeamImage = new vgui::ImagePanel( m_pRedTeamPanel, "RedTeamImage" ); m_pBlueTeamImage = new vgui::ImagePanel( m_pBlueTeamPanel, "BlueTeamImage" ); m_pRedLeaderAvatarImage = new CAvatarImagePanel( m_pRedTeamPanel, "RedLeaderAvatar" ); m_pBlueLeaderAvatarImage = new CAvatarImagePanel( m_pBlueTeamPanel, "BlueLeaderAvatar" ); m_pRedLeaderAvatarBG = new EditablePanel( m_pRedTeamPanel, "RedLeaderAvatarBG" ); m_pBlueLeaderAvatarBG = new EditablePanel( m_pBlueTeamPanel, "BlueLeaderAvatarBG" ); m_pStatsAndMedals = new CExLabel( m_pStatsLabelPanel, "StatsAndMedals", "" ); m_pStatsAndMedalsShadow = new CExLabel( m_pStatsLabelPanel, "StatsAndMedalsShadow", "" ); m_pRedTeamName = new CExLabel( m_pRedTeamPanel, "RedTeamLabel", "" ); m_pBlueTeamName = new CExLabel( m_pBlueTeamPanel, "BlueTeamLabel", "" ); m_pRedTeamWinner = new CExLabel( m_pRedTeamPanel, "RedTeamWinner", "" ); m_pRedTeamWinnerDropshadow = new CExLabel( m_pRedTeamPanel, "RedTeamWinnerDropshadow", "" ); m_pBlueTeamWinner = new CExLabel( m_pBlueTeamPanel, "BlueTeamWinner", "" ); m_pBlueTeamWinnerDropshadow = new CExLabel( m_pBlueTeamPanel, "BlueTeamWinnerDropshadow", "" ); m_pImageList = NULL; m_mapAvatarsToImageList.SetLessFunc( DefLessFunc( CSteamID ) ); m_mapAvatarsToImageList.RemoveAll(); Q_memset( m_SkillRatings, 0, sizeof( m_SkillRatings ) ); m_iCurrentState = MS_STATE_INITIAL; m_flNextActionTime = -1; m_nMedalsToAward_Bronze_Blue = 0; m_nMedalsToAward_Silver_Blue = 0; m_nMedalsToAward_Gold_Blue = 0; m_nMedalsToAward_Bronze_Red = 0; m_nMedalsToAward_Silver_Red = 0; m_nMedalsToAward_Gold_Red = 0; m_nMedalsRevealed = 0; m_nNumMedalsThisUpdate = 0; m_bBlueGoldValueRevealed = false; m_bBlueSilverValueRevealed = false; m_bBlueBronzeValueRevealed = false; m_bRedGoldValueRevealed = false; m_bRedSilverValueRevealed = false; m_bRedBronzeValueRevealed = false; m_bPlayerAbandoned = false; m_flMedalSoundTime = -1.f; m_bLargeMatchGroup = false; Q_memset( m_iImageClass, NULL, sizeof( m_iImageClass ) ); Q_memset( m_iImageClassAlt, NULL, sizeof( m_iImageClassAlt ) ); ListenForGameEvent( "competitive_victory" ); ListenForGameEvent( "competitive_stats_update" ); ListenForGameEvent( "player_abandoned_match" ); ListenForGameEvent( "client_disconnect" ); ListenForGameEvent( "show_match_summary" ); vgui::ivgui()->AddTickSignal( GetVPanel(), 50 ); } //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- CTFMatchSummary::~CTFMatchSummary() { if ( NULL != m_pImageList ) { delete m_pImageList; m_pImageList = NULL; } } //----------------------------------------------------------------------------- // Purpose: Applies scheme settings //----------------------------------------------------------------------------- void CTFMatchSummary::ApplySchemeSettings( vgui::IScheme *pScheme ) { BaseClass::ApplySchemeSettings( pScheme ); m_bLargeMatchGroup = false; KeyValues *pConditions = NULL; if ( TFGameRules() ) { const IMatchGroupDescription* pMatch = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() ); if ( pMatch ) { if ( pMatch->m_params.m_pmm_match_group_size->GetInt() > 12 ) { pConditions = new KeyValues( "conditions" ); AddSubKeyNamed( pConditions, "if_large" ); m_bLargeMatchGroup = true; } } } LoadControlSettings( "resource/UI/HudMatchSummary.res", NULL, NULL, pConditions ); if ( pConditions ) { pConditions->deleteThis(); } if ( m_pDrawingPanel ) { m_pDrawingPanel->ClearAllLines(); m_pDrawingPanel->SetType( DRAWING_PANEL_TYPE_MATCH_SUMMARY ); m_pDrawingPanel->MakePopup(); } if ( m_pImageList ) delete m_pImageList; m_pImageList = new ImageList( false ); m_mapAvatarsToImageList.RemoveAll(); for ( int i = 1; i < (int)StatMedal_Max; i++ ) { m_iImageMedals[i] = m_pImageList->AddImage( scheme()->GetImage( g_pszCompetitiveMedalImages[i], true ) ); } for ( int i = 1; i < SCOREBOARD_CLASS_ICONS; i++ ) { m_iImageClass[i] = m_pImageList->AddImage( scheme()->GetImage( g_pszClassIcons[i], true ) ); m_iImageClassAlt[i] = m_pImageList->AddImage( scheme()->GetImage( g_pszClassIconsAlt[i], true ) ); } int iCurrentCount = m_pImageList->GetImageCount(); // resize the images to our resolution for ( int i = 0; i < iCurrentCount; i++ ) { int wide = 13, tall = 13; m_pImageList->GetImage( i )->SetSize( scheme()->GetProportionalScaledValueEx( GetScheme(), wide ), scheme()->GetProportionalScaledValueEx( GetScheme(), tall ) ); } // resize the images to our resolution for ( int i = iCurrentCount; i < m_pImageList->GetImageCount(); i++ ) { int wide = 26, tall = 26; m_pImageList->GetImage( i )->SetSize( scheme()->GetProportionalScaledValueEx( GetScheme(), wide ), scheme()->GetProportionalScaledValueEx( GetScheme(), tall ) ); } SetPaintBackgroundEnabled( false ); m_pTeamScoresPanel->SetPaintBackgroundEnabled( false ); m_pPlayerListBlueParent->SetPaintBackgroundEnabled( false ); m_pPlayerListRedParent->SetPaintBackgroundEnabled( false ); m_pPlayerListBlue->SetPaintBackgroundEnabled( false ); m_pPlayerListRed->SetPaintBackgroundEnabled( false ); m_pPlayerListBlue->SetImageList( m_pImageList, false ); m_pPlayerListBlue->SetVisible( true ); m_pPlayerListRed->SetImageList( m_pImageList, false ); m_pPlayerListRed->SetVisible( true ); InitPlayerList( m_pPlayerListBlue, TF_TEAM_BLUE ); InitPlayerList( m_pPlayerListRed, TF_TEAM_RED ); m_hFont = pScheme->GetFont( "ScoreboardVerySmall", true ); m_iCurrentState = MS_STATE_INITIAL; m_flNextActionTime = -1; RecalculateMedalCounts(); m_nMedalsRevealed = 0; m_bBlueGoldValueRevealed = false; m_bBlueSilverValueRevealed = false; m_bBlueBronzeValueRevealed = false; m_bRedGoldValueRevealed = false; m_bRedSilverValueRevealed = false; m_bRedBronzeValueRevealed = false; m_flMedalSoundTime = -1.f; m_flDrawingPanelTime = -1.f; m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_gold", "?" ); m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_silver", "?" ); m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_bronze", "?" ); m_pRedMedalsPanel->SetDialogVariable( "redteammedals_gold", "?" ); m_pRedMedalsPanel->SetDialogVariable( "redteammedals_silver", "?" ); m_pRedMedalsPanel->SetDialogVariable( "redteammedals_bronze", "?" ); Update(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::PerformLayout() { BaseClass::PerformLayout(); EditablePanel* pStatsContainer = FindControl< EditablePanel >( "MainStatsContainer" ); if ( pStatsContainer && m_bLargeMatchGroup ) { pStatsContainer->SetPos( pStatsContainer->GetXPos(), m_iAnimStatsContainer12v12YPos ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CTFMatchSummary::ShouldDraw( void ) { return IsVisible(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::SetVisible( bool state ) { int iRenderGroup = gHUD.LookupRenderGroupIndexByName( "mid" ); if ( state ) { gHUD.LockRenderGroup( iRenderGroup ); InvalidateLayout( true, true ); m_iCurrentState = MS_STATE_INITIAL; m_flDrawingPanelTime = gpGlobals->curtime + 4.5f; CPvPRankPanel* pPvPRankPanel = FindControl< CPvPRankPanel >( "RankPanel" ); if ( pPvPRankPanel ) { pPvPRankPanel->SetMatchGroup( TFGameRules()->GetCurrentMatchGroup() ); } g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "CompetitiveGame_LowerChatWindow", false ); } else { gHUD.UnlockRenderGroup( iRenderGroup ); } BaseClass::SetVisible( state ); } //----------------------------------------------------------------------------- // Purpose: Used for sorting players //----------------------------------------------------------------------------- bool CTFMatchSummary::TFPlayerSortFunc( vgui::SectionedListPanel *list, int itemID1, int itemID2 ) { KeyValues *it1 = list->GetItemData( itemID1 ); KeyValues *it2 = list->GetItemData( itemID2 ); Assert( it1 && it2 ); // first compare score int v1 = it1->GetInt( "score" ); int v2 = it2->GetInt( "score" ); if ( v1 > v2 ) return true; else if ( v1 < v2 ) return false; // if score is the same, use player index to get deterministic sort int iPlayerIndex1 = it1->GetInt( "playerIndex" ); int iPlayerIndex2 = it2->GetInt( "playerIndex" ); return ( iPlayerIndex1 > iPlayerIndex2 ); } //----------------------------------------------------------------------------- // Purpose: Inits the player list in a list panel //----------------------------------------------------------------------------- void CTFMatchSummary::InitPlayerList( TFSectionedListPanel *pPlayerList, int nTeam ) { float flAspectRatio = engine->GetScreenAspectRatio(); bool bStandard = flAspectRatio < 1.6f; pPlayerList->SetVerticalScrollbar( false ); pPlayerList->RemoveAll(); pPlayerList->RemoveAllSections(); pPlayerList->AddSection( 0, "Players", TFPlayerSortFunc ); pPlayerList->SetSectionAlwaysVisible( 0, true ); pPlayerList->SetSectionDrawDividerBar( 0, false ); pPlayerList->SetBorder( NULL ); pPlayerList->SetMouseInputEnabled( false ); pPlayerList->SetClickable( false ); pPlayerList->AddColumnToSection( 0, "medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_CENTER, pPlayerList->m_iMedalWidth ); pPlayerList->AddColumnToSection( 0, "avatar", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAvatarWidth ); pPlayerList->AddColumnToSection( 0, "spacer", "", 0, pPlayerList->m_iSpacerWidth ); pPlayerList->AddColumnToSection( 0, "name", "", 0, pPlayerList->m_iNameWidth ); pPlayerList->AddColumnToSection( 0, "class", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iClassWidth ); pPlayerList->AddColumnToSection( 0, "score", bStandard ? "#TF_Comp_Scoreboard_Score_Standard" : "#TF_Comp_Scoreboard_Score", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth ); pPlayerList->AddColumnToSection( 0, "score_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth ); pPlayerList->AddColumnToSection( 0, "kills", bStandard ? "#TF_Comp_Scoreboard_Kills_Standard" : "#TF_Comp_Scoreboard_Kills", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth ); pPlayerList->AddColumnToSection( 0, "kills_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth ); pPlayerList->AddColumnToSection( 0, "damage", bStandard ? "#TF_Comp_Scoreboard_Damage_Standard" : "#TF_Comp_Scoreboard_Damage", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth ); pPlayerList->AddColumnToSection( 0, "damage_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth ); pPlayerList->AddColumnToSection( 0, "healing", bStandard ? "#TF_Comp_Scoreboard_Healing_Standard" : "#TF_Comp_Scoreboard_Healing", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth ); pPlayerList->AddColumnToSection( 0, "healing_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth ); pPlayerList->AddColumnToSection( 0, "support", bStandard ? "#TF_Comp_Scoreboard_Support_Standard" : "#TF_Comp_Scoreboard_Support", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth ); pPlayerList->AddColumnToSection( 0, "support_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::Update( void ) { UpdateTeamInfo(); UpdatePlayerList(); UpdateBadgePanels( m_pRedBadgePanels, m_pPlayerListRed ); UpdateBadgePanels( m_pBlueBadgePanels, m_pPlayerListBlue ); } //----------------------------------------------------------------------------- // Purpose: Updates information about teams //----------------------------------------------------------------------------- void CTFMatchSummary::UpdateTeamInfo() { bool bUseWinnerLabel = false; if ( GetGlobalTFTeam( TF_TEAM_RED ) && GetGlobalTFTeam( TF_TEAM_BLUE ) ) { if ( GetGlobalTFTeam( TF_TEAM_RED )->Get_Score() == GetGlobalTFTeam( TF_TEAM_BLUE )->Get_Score() ) { bUseWinnerLabel = true; } } int nWinningTeam = TEAM_INVALID; if ( TFGameRules() ) { nWinningTeam = TFGameRules()->GetWinningTeam(); } for ( int teamIndex = TF_TEAM_RED; teamIndex <= TF_TEAM_BLUE; teamIndex++ ) { C_TFTeam *team = GetGlobalTFTeam( teamIndex ); if ( team ) { // choose dialog variables to set depending on team const char *pDialogVarTeamName = ""; const char *pDialogVarTeamScore = ""; const char *pDialogVarWinner = ""; vgui::EditablePanel *pOwner = NULL; switch ( teamIndex ) { case TF_TEAM_RED: pDialogVarTeamName = "redteamname"; pDialogVarTeamScore = "redteamscore"; pDialogVarWinner = "redteamwinner"; pOwner = m_pRedTeamPanel; break; case TF_TEAM_BLUE: pDialogVarTeamName = "blueteamname"; pDialogVarTeamScore = "blueteamscore"; pDialogVarWinner = "blueteamwinner"; pOwner = m_pBlueTeamPanel; break; default: Assert( false ); break; } if ( !pOwner ) return; // set the team name pOwner->SetDialogVariable( pDialogVarTeamName, team->Get_Localized_Name() ); if ( bUseWinnerLabel ) { const char *pszLabel = ""; if ( teamIndex == nWinningTeam ) { if ( team->GetNumPlayers() > 1 ) { pszLabel = "#TF_Winners"; } else { pszLabel = "#TF_Winner"; } } pOwner->SetDialogVariable( pDialogVarTeamScore, "" ); pOwner->SetDialogVariable( pDialogVarWinner, g_pVGuiLocalize->Find( pszLabel ) ); } else { pOwner->SetDialogVariable( pDialogVarTeamScore, team->Get_Score() ); pOwner->SetDialogVariable( pDialogVarWinner, "" ); } } } bool bShowAvatars = g_TF_PR && g_TF_PR->HasPremadeParties(); if ( bShowAvatars ) { m_pRedLeaderAvatarImage->SetPlayer( GetSteamIDForPlayerIndex( g_TF_PR->GetPartyLeaderRedTeamIndex() ), k_EAvatarSize64x64 ); m_pRedLeaderAvatarImage->SetShouldDrawFriendIcon( false ); m_pBlueLeaderAvatarImage->SetPlayer( GetSteamIDForPlayerIndex( g_TF_PR->GetPartyLeaderBlueTeamIndex() ), k_EAvatarSize64x64 ); m_pBlueLeaderAvatarImage->SetShouldDrawFriendIcon( false ); } m_pRedLeaderAvatarImage->SetVisible( bShowAvatars ); m_pRedLeaderAvatarBG->SetVisible( bShowAvatars ); m_pRedTeamName->SetVisible( bShowAvatars ); m_pRedTeamImage->SetVisible( !bShowAvatars ); m_pBlueLeaderAvatarImage->SetVisible( bShowAvatars ); m_pBlueLeaderAvatarBG->SetVisible( bShowAvatars ); m_pBlueTeamName->SetVisible( bShowAvatars ); m_pBlueTeamImage->SetVisible( !bShowAvatars ); } //----------------------------------------------------------------------------- // Purpose: Returns the last medal (column) added so we can display some effects //----------------------------------------------------------------------------- matchsummary_columns_t CTFMatchSummary::InternalAddMedalKeyValues( int iIndex, StatMedal_t eMedal, KeyValues *pKeyValues, int nTotalMedals /*= -1*/ ) { int nMedal = (int)eMedal; matchsummary_columns_t retVal = MS_COLUMN_INVALID; if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) ) { if ( m_SkillRatings[iIndex].nScoreRank == nMedal ) { pKeyValues->SetInt( "score_medal", m_iImageMedals[nMedal] ); if ( nTotalMedals >= 0 ) { m_nNumMedalsThisUpdate++; } if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) ) { retVal = MS_COLUMN_SCORE_MEDAL; } } } if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) ) { if ( m_SkillRatings[iIndex].nKillsRank == nMedal ) { pKeyValues->SetInt( "kills_medal", m_iImageMedals[nMedal] ); if ( nTotalMedals >= 0 ) { m_nNumMedalsThisUpdate++; } if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) ) { retVal = MS_COLUMN_KILLS_MEDAL; } } } if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) ) { if ( m_SkillRatings[iIndex].nDamageRank == nMedal ) { pKeyValues->SetInt( "damage_medal", m_iImageMedals[nMedal] ); if ( nTotalMedals >= 0 ) { m_nNumMedalsThisUpdate++; } if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) ) { retVal = MS_COLUMN_DAMAGE_MEDAL; } } } if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) ) { if ( m_SkillRatings[iIndex].nHealingRank == nMedal ) { pKeyValues->SetInt( "healing_medal", m_iImageMedals[nMedal] ); if ( nTotalMedals >= 0 ) { m_nNumMedalsThisUpdate++; } if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) ) { retVal = MS_COLUMN_HEALING_MEDAL; } } } if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) ) { if ( m_SkillRatings[iIndex].nSupportRank == nMedal ) { pKeyValues->SetInt( "support_medal", m_iImageMedals[nMedal] ); if ( nTotalMedals >= 0 ) { m_nNumMedalsThisUpdate++; } if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) ) { retVal = MS_COLUMN_SUPPORT_MEDAL; } } } return retVal; } //----------------------------------------------------------------------------- // Purpose: Updates the player list //----------------------------------------------------------------------------- void CTFMatchSummary::UpdatePlayerList() { m_pPlayerListRed->RemoveAll(); m_pPlayerListRed->ClearAllColorOverrideForCell(); m_pPlayerListBlue->RemoveAll(); m_pPlayerListBlue->ClearAllColorOverrideForCell(); if ( !g_TF_PR ) return; m_nNumMedalsThisUpdate = 0; for ( int playerIndex = 1; playerIndex <= MAX_PLAYERS; playerIndex++ ) { if ( g_PR->IsConnected( playerIndex ) || g_PR->IsValid( playerIndex ) ) { TFSectionedListPanel *pPlayerList = NULL; int nTeam = g_PR->GetTeam( playerIndex ); switch ( nTeam ) { case TF_TEAM_BLUE: pPlayerList = m_pPlayerListBlue; break; case TF_TEAM_RED: pPlayerList = m_pPlayerListRed; break; } if ( null == pPlayerList ) continue; KeyValues *pKeyValues = new KeyValues( "data" ); pKeyValues->SetInt( "playerIndex", playerIndex ); // this is just a placeholder in the sectioned list panel pKeyValues->SetInt( "medal", 0 ); pKeyValues->SetString( "name", g_TF_PR->GetPlayerName( playerIndex ) ); pKeyValues->SetInt( "score", g_TF_PR->GetTotalScore( playerIndex ) ); int iClass = g_TF_PR->GetPlayerClass( playerIndex ); if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass <= TF_LAST_NORMAL_CLASS ) { pKeyValues->SetInt( "class", tf_scoreboard_alt_class_icons.GetBool() ? m_iImageClassAlt[iClass] : m_iImageClass[iClass] ); } else { pKeyValues->SetInt( "class", 0 ); } pKeyValues->SetInt( "kills", g_TF_PR->GetPlayerScore( playerIndex ) ); pKeyValues->SetInt( "damage", g_TF_PR->GetDamage( playerIndex ) ); pKeyValues->SetInt( "healing", g_TF_PR->GetHealing( playerIndex ) ); int nSupport = g_TF_PR->GetDamageAssist( playerIndex ) + g_TF_PR->GetHealingAssist( playerIndex ) + g_TF_PR->GetDamageBlocked( playerIndex ) + ( g_TF_PR->GetBonusPoints( playerIndex ) * 25 ); pKeyValues->SetInt( "support", nSupport ); matchsummary_columns_t eParticleColumn = MS_COLUMN_INVALID; StatMedal_t eParticleMedal = StatMedal_None; if ( m_iCurrentState == MS_STATE_GOLD_MEDALS ) { // we can add the bronze and silver since we've already processed those InternalAddMedalKeyValues( playerIndex, StatMedal_Bronze, pKeyValues ); InternalAddMedalKeyValues( playerIndex, StatMedal_Silver, pKeyValues ); eParticleColumn = InternalAddMedalKeyValues( playerIndex, StatMedal_Gold, pKeyValues, m_nMedalsRevealed ); eParticleMedal = StatMedal_Gold; } else if ( m_iCurrentState == MS_STATE_SILVER_MEDALS ) { // we can add the bronze since we've already processed those InternalAddMedalKeyValues( playerIndex, StatMedal_Bronze, pKeyValues ); eParticleColumn = InternalAddMedalKeyValues( playerIndex, StatMedal_Silver, pKeyValues, m_nMedalsRevealed ); eParticleMedal = StatMedal_Silver; } else if ( m_iCurrentState == MS_STATE_BRONZE_MEDALS ) { eParticleColumn = InternalAddMedalKeyValues( playerIndex, StatMedal_Bronze, pKeyValues, m_nMedalsRevealed ); eParticleMedal = StatMedal_Bronze; } UpdatePlayerAvatar( playerIndex, pKeyValues ); int itemID = pPlayerList->AddItem( 0, pKeyValues ); pPlayerList->SetItemFgColor( itemID, g_PR->GetTeamColor( nTeam ) ); // Green background for rematch folks pPlayerList->SetItemBgColor( itemID, Color( 80, 80, 80, 80 ) ); pPlayerList->SetItemBgHorizFillInset( itemID, pPlayerList->m_iHorizFillInset ); pPlayerList->SetItemFont( itemID, m_hFont ); // This highlights the local player in grey if ( playerIndex == GetLocalPlayerIndex() ) { pPlayerList->SetSelectedItem( itemID ); } // loop through and setup our medal color overrides KeyValues *pKey = pKeyValues->FindKey( "score_medal" ); if ( pKey && pKey->GetInt() ) { int nMedal = pKey->GetInt(); pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_SCORE, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal ); } pKey = pKeyValues->FindKey( "kills_medal" ); if ( pKey && pKey->GetInt() ) { int nMedal = pKey->GetInt(); pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_KILLS, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal ); } pKey = pKeyValues->FindKey( "damage_medal" ); if ( pKey && pKey->GetInt() ) { int nMedal = pKey->GetInt(); pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_DAMAGE, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal ); } pKey = pKeyValues->FindKey( "healing_medal" ); if ( pKey && pKey->GetInt() ) { int nMedal = pKey->GetInt(); pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_HEALING, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal ); } pKey = pKeyValues->FindKey( "support_medal" ); if ( pKey && pKey->GetInt() ) { int nMedal = pKey->GetInt(); pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_SUPPORT, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal ); } pKeyValues->deleteThis(); if ( ( eParticleColumn > MS_COLUMN_INVALID ) && ( eParticleMedal > StatMedal_None ) ) { int nPanelXPos, nPanelYPos, nPanelWide, nPanelTall; pPlayerList->GetMaxCellBounds( itemID, eParticleColumn, nPanelXPos, nPanelYPos, nPanelWide, nPanelTall ); FireMedalEffects( pPlayerList, nPanelXPos, nPanelYPos, nPanelWide, nPanelTall, eParticleMedal ); } } } m_pPlayerListRed->SetSectionFgColor( 0, g_PR->GetTeamColor( TF_TEAM_RED ) ); m_pPlayerListBlue->SetSectionFgColor( 0, g_PR->GetTeamColor( TF_TEAM_BLUE ) ); // force the lists to PerformLayout() now so we can update our rank images after we return m_pPlayerListRed->InvalidateLayout( true ); m_pPlayerListBlue->InvalidateLayout( true ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::FireMedalEffects( Panel *pPanel, int nPanelXPos, int nPanelYPos, int nPanelWide, int nPanelTall, StatMedal_t eParticleMedal ) { if ( !pPanel ) return; int nPanelCenterX = nPanelXPos + ( nPanelWide / 2 ); int nPanelCenterY = nPanelYPos + ( nPanelTall / 2 ); int iItemAbsX, iItemAbsY; vgui::ipanel()->GetAbsPos( pPanel->GetParent()->GetVPanel(), iItemAbsX, iItemAbsY ); int x = iItemAbsX + nPanelCenterX; int y = iItemAbsY + nPanelCenterY; const char *pszSoundEffect = "MatchMaking.None"; const char *pszParticleEffect = "mvm_loot_smoke"; if ( eParticleMedal == StatMedal_Bronze ) { pszSoundEffect = "MatchMaking.Bronze"; pszParticleEffect = "mvm_loot_explosion"; } else if ( eParticleMedal == StatMedal_Silver ) { pszSoundEffect = "MatchMaking.Silver"; pszParticleEffect = "mvm_loot_explosion"; } else if ( eParticleMedal == StatMedal_Gold ) { pszSoundEffect = "MatchMaking.Gold"; pszParticleEffect = "mvm_pow_gold_seq_firework_mid"; } m_pParticlePanel->FireParticleEffect( pszParticleEffect, x, y, 0.2f, false ); C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); if ( pLocalPlayer ) { pLocalPlayer->EmitSound( pszSoundEffect ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::UpdateBadgePanels( CUtlVector &pBadgePanels, TFSectionedListPanel *pPlayerList ) { if ( !TFGameRules() ) return; const IMatchGroupDescription *pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() ); const IProgressionDesc *pProgressionDesc = pMatchDesc ? pMatchDesc->m_pProgressionDesc : NULL; if ( pProgressionDesc ) { if ( pPlayerList ) { int iNumPanels = 0; int parentTall = pPlayerList->GetTall(); CTFBadgePanel *pPanel = NULL; for ( int i = 0; i < pPlayerList->GetItemCount(); i++ ) { KeyValues *pKeyValues = pPlayerList->GetItemData( i ); if ( !pKeyValues ) continue; const CSteamID steamID = GetSteamIDForPlayerIndex( pKeyValues->GetInt( "playerIndex" ) ); #ifdef STAGING_ONLY if ( steamID.IsValid() || tf_test_match_summary.GetBool() ) #else if ( steamID.IsValid() ) #endif // STAGING_ONLY { if ( iNumPanels >= pBadgePanels.Count() ) { pPanel = new CTFBadgePanel( m_pMainStatsContainer, "BadgePanel" ); pPanel->MakeReadyForUse(); pPanel->SetVisible( true ); pPanel->SetZPos( 9999 ); pBadgePanels.AddToTail( pPanel ); } else { pPanel = pBadgePanels[iNumPanels]; } int x, y, wide, tall; pPlayerList->GetMaxCellBounds( i, 0, x, y, wide, tall ); if ( y + tall > parentTall ) continue; if ( !pPanel->IsVisible() ) { pPanel->SetVisible( true ); } int xParent = 0, yParent = 0; if ( pPlayerList->GetParent() ) { pPlayerList->GetParent()->GetPos( xParent, yParent ); } int xGrandParent = 0, yGrandParent = 0; if ( pPlayerList->GetParent()->GetParent() ) { pPlayerList->GetParent()->GetParent()->GetPos( xGrandParent, yGrandParent ); } int nPanelXPos, nPanelYPos, nPanelWide, nPanelTall; pPanel->GetBounds( nPanelXPos, nPanelYPos, nPanelWide, nPanelTall ); if ( ( nPanelXPos != xGrandParent + xParent + x ) || ( nPanelYPos != yGrandParent + yParent + y ) || ( nPanelWide != wide ) || ( nPanelTall != tall ) ) { pPanel->SetBounds( xGrandParent + xParent + x, yGrandParent + yParent + y, wide, tall ); pPanel->InvalidateLayout( true, true ); } pPanel->SetupBadge( pProgressionDesc, steamID ); iNumPanels++; } } // hide any unused images for ( int i = iNumPanels; i < pBadgePanels.Count(); i++ ) { if ( pBadgePanels[i]->IsVisible() ) { pBadgePanels[i]->SetVisible( false ); } } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::UpdatePlayerAvatar( int playerIndex, KeyValues *kv ) { if ( !g_PR ) return; uint32 iAccountID = g_PR->GetAccountID( playerIndex ); if ( iAccountID > 0 ) { // Update their avatar if ( kv && steamapicontext->SteamFriends() && steamapicontext->SteamUtils() ) { CSteamID steamIDForPlayer( iAccountID, 1, GetUniverse(), k_EAccountTypeIndividual ); // See if we already have that avatar in our list int iMapIndex = m_mapAvatarsToImageList.Find( steamIDForPlayer ); int iImageIndex; if ( iMapIndex == m_mapAvatarsToImageList.InvalidIndex() ) { CAvatarImage *pImage = new CAvatarImage(); pImage->SetAvatarSteamID( steamIDForPlayer ); pImage->SetAvatarSize( 32, 32 ); // Deliberately non scaling iImageIndex = m_pImageList->AddImage( pImage ); m_mapAvatarsToImageList.Insert( steamIDForPlayer, iImageIndex ); } else { iImageIndex = m_mapAvatarsToImageList[iMapIndex]; } kv->SetInt( "avatar", iImageIndex ); CAvatarImage *pAvIm = (CAvatarImage *)m_pImageList->GetImage( iImageIndex ); pAvIm->UpdateFriendStatus(); } } } //----------------------------------------------------------------------------- // Purpose: Event handler //----------------------------------------------------------------------------- void CTFMatchSummary::FireGameEvent( IGameEvent *event ) { const char *type = event->GetName(); if ( FStrEq( type, "competitive_victory" ) ) { Q_memset( m_SkillRatings, 0, sizeof( m_SkillRatings ) ); Leaderboards_LadderRefresh(); } else if ( FStrEq( type, "competitive_stats_update" ) ) { int iIndex = event->GetInt( "index" ); Assert( iIndex > 0 && iIndex <= MAX_PLAYERS ); if ( iIndex > 0 && iIndex <= MAX_PLAYERS ) { m_SkillRatings[iIndex].unRating = event->GetInt( "rating" ); // Rank m_SkillRatings[iIndex].nDelta = event->GetInt( "delta" ); m_SkillRatings[iIndex].nScoreRank = event->GetInt( "score_rank" ); // Medal for Score (Gold, Silver, Bronze, or nothing) m_SkillRatings[iIndex].nKillsRank = event->GetInt( "kills_rank" ); // Medal for Kills m_SkillRatings[iIndex].nDamageRank = event->GetInt( "damage_rank" ); // Medal for Damage m_SkillRatings[iIndex].nHealingRank = event->GetInt( "healing_rank" ); // Medal for Healing m_SkillRatings[iIndex].nSupportRank = event->GetInt( "support_rank" ); // Medal for Rank RecalculateMedalCounts(); } } else if ( FStrEq( type, "player_abandoned_match" ) ) { m_bPlayerAbandoned = true; } else if ( FStrEq( type, "client_disconnect" ) ) { m_bPlayerAbandoned = false; } else if ( FStrEq( type, "show_match_summary" ) ) { SetVisible( true ); if ( m_pPlayerListRedParent->GetParent() ) { int nRedBadgeOffset = m_pPlayerListRedParent->GetParent()->GetXPos(); FOR_EACH_VEC( m_pRedBadgePanels, i ) { g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedBadgePanels[i], "xpos", m_pRedBadgePanels[i]->GetXPos() - nRedBadgeOffset, 0.25, 0.25, vgui::AnimationController::INTERPOLATOR_ACCEL ); } } if ( m_pPlayerListBlueParent->GetParent() ) { int nBlueBadgeOffset = m_pPlayerListBlueParent->GetParent()->GetXPos(); FOR_EACH_VEC( m_pBlueBadgePanels, i ) { g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueBadgePanels[i], "xpos", m_pBlueBadgePanels[i]->GetXPos() - nBlueBadgeOffset, 0.25, 0.25, vgui::AnimationController::INTERPOLATOR_ACCEL ); } } g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pTeamScoresPanel, "HudMatchSummary_SlideInPanels", false ); } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::InternalUpdateMedalCountForType( int iTeam, StatMedal_t eMedal ) { switch ( eMedal ) { case StatMedal_Bronze: if ( iTeam == TF_TEAM_RED ) { m_nMedalsToAward_Bronze_Red++; } else if ( iTeam == TF_TEAM_BLUE ) { m_nMedalsToAward_Bronze_Blue++; } break; case StatMedal_Silver: if ( iTeam == TF_TEAM_RED ) { m_nMedalsToAward_Silver_Red++; } else if ( iTeam == TF_TEAM_BLUE ) { m_nMedalsToAward_Silver_Blue++; } break; case StatMedal_Gold: if ( iTeam == TF_TEAM_RED ) { m_nMedalsToAward_Gold_Red++; } else if ( iTeam == TF_TEAM_BLUE ) { m_nMedalsToAward_Gold_Blue++; } break; case StatMedal_None: default: break; } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::RecalculateMedalCounts() { m_nMedalsToAward_Bronze_Blue = 0; m_nMedalsToAward_Silver_Blue = 0; m_nMedalsToAward_Gold_Blue = 0; m_nMedalsToAward_Bronze_Red = 0; m_nMedalsToAward_Silver_Red = 0; m_nMedalsToAward_Gold_Red = 0; if ( !g_PR ) return; for ( int playerIndex = 1; playerIndex <= MAX_PLAYERS; playerIndex++ ) { if ( g_PR->IsConnected( playerIndex ) || g_PR->IsValid( playerIndex ) ) { int nTeam = g_PR->GetTeam( playerIndex ); if ( nTeam >= FIRST_GAME_TEAM ) { InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nScoreRank ) ); InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nKillsRank ) ); InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nDamageRank ) ); InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nHealingRank ) ); InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nSupportRank ) ); } } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::OnTick() { BaseClass::OnTick(); C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); if ( !IsVisible() || !pLocalPlayer ) return; const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() ); if ( !pMatchDesc ) return; if ( pMatchDesc->m_params.m_bAllowDrawingAtMatchSummary && m_pDrawingPanel && ( m_flDrawingPanelTime > 0 ) && ( m_flDrawingPanelTime < gpGlobals->curtime ) ) { m_pDrawingPanel->SetVisible( true ); m_pDrawingPanel->SetKeyBoardInputEnabled( false ); m_flDrawingPanelTime = -1.f; if ( pLocalPlayer ) { pLocalPlayer->EmitSound( "Announcer.SummaryScreenWinners" ); } } int nMedalsToAward_Bronze_Total = m_nMedalsToAward_Bronze_Blue + m_nMedalsToAward_Bronze_Red; int nMedalsToAward_Silver_Total = m_nMedalsToAward_Silver_Blue + m_nMedalsToAward_Silver_Red; int nMedalsToAward_Gold_Total = m_nMedalsToAward_Gold_Blue + m_nMedalsToAward_Gold_Red; bool bShowPerformanceMedals = ShowPerformanceMedals(); bool bMapHasMatchSummaryStage = ( TFGameRules() && TFGameRules()->MapHasMatchSummaryStage() ); #ifdef STAGING_ONLY bool bUseMatchSummaryStage = tf_test_match_summary.GetBool() || ( pMatchDesc && pMatchDesc->m_params.m_bUseMatchSummaryStage ); #else bool bUseMatchSummaryStage = ( pMatchDesc && pMatchDesc->m_params.m_bUseMatchSummaryStage ); #endif switch ( m_iCurrentState ) { case MS_STATE_INITIAL: { bool bUseStage = ( bMapHasMatchSummaryStage && bUseMatchSummaryStage ); if ( GTFGCClientSystem()->GetSurveyRequest().has_match_id() ) { Panel* pSurveyPanel = CreateSurveyQuestionPanel( this, GTFGCClientSystem()->GetSurveyRequest() ); pSurveyPanel->MakePopup(); } m_iCurrentState = MS_STATE_DRAWING; m_flNextActionTime = bUseStage ? gpGlobals->curtime + MS_STATE_TRANSITION_TO_STATS : gpGlobals->curtime + 2.f; m_bXPShown = false; if ( !bUseStage ) { // if we're not using the stage we'll just show the doors and then skip to stats with no drawing if ( m_pDrawingPanel ) { m_pDrawingPanel->SetVisible( false ); } } break; } case MS_STATE_DRAWING: { if ( gpGlobals->curtime > m_flNextActionTime ) { if ( m_pDrawingPanel ) { m_pDrawingPanel->SetVisible( false ); } if ( m_pStatsBgPanel ) { m_pStatsBgPanel->SetVisible( true ); } if ( m_pStatsLabelPanel ) { m_pStatsLabelPanel->SetVisible( true ); } g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pStatsLabelPanel, "ypos", m_bLargeMatchGroup ? m_iAnimStatsLabelPanel12v12YPos : m_iAnimStatsLabelPanel6v6YPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueMedalsPanel, "ypos", m_iAnimBlueMedalsYPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedMedalsPanel, "ypos", m_iAnimRedMedalsYPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamName, "ypos", m_bLargeMatchGroup ? m_iAnimBlueTeamLabel12v12YPos : m_iAnimBlueTeamLabel6v6YPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamName, "ypos", m_bLargeMatchGroup ? m_iAnimRedTeamLabel12v12YPos : m_iAnimRedTeamLabel6v6YPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pPlayerListBlueParent, "wide", m_iAnimBluePlayerListParent, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamScore, "wide", m_iAnimBlueTeamScore, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamScoreDropshadow, "wide", m_iAnimBlueTeamScoreDropshadow, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamScoreBG, "wide", m_iAnimBlueTeamScoreBG, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBluePlayerListBG, "wide", m_iAnimBluePlayerListBG, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScore, "wide", m_iAnimRedTeamScoreWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScore, "xpos", m_iAnimRedTeamScoreXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScoreDropshadow, "wide", m_iAnimRedTeamScoreDropshadowWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScoreDropshadow, "xpos", m_iAnimRedTeamScoreDropshadowXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScoreBG, "wide", m_iAnimRedTeamScoreBGWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScoreBG, "xpos", m_iAnimRedTeamScoreBGXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pPlayerListRedParent, "wide", m_iAnimRedPlayerListParentWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pPlayerListRedParent, "xpos", m_iAnimRedPlayerListParentXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedPlayerListBG, "wide", m_iAnimRedPlayerListBGWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedPlayerListBG, "xpos", m_iAnimRedPlayerListBGXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamWinner, "wide", m_iAnimBlueTeamScore, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamWinnerDropshadow, "wide", m_iAnimBlueTeamScoreDropshadow, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamWinner, "wide", m_iAnimRedTeamScoreWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamWinner, "xpos", m_iAnimRedTeamScoreXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamWinnerDropshadow, "wide", m_iAnimRedTeamScoreDropshadowWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamWinnerDropshadow, "xpos", m_iAnimRedTeamScoreDropshadowXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); int nRedBadgeOffset = m_pPlayerListRedParent->GetXPos() - m_iAnimRedPlayerListParentXPos; FOR_EACH_VEC( m_pRedBadgePanels, i ) { g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedBadgePanels[i], "xpos", m_pRedBadgePanels[i]->GetXPos() - nRedBadgeOffset, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL ); } float flDelay = MS_STATE_TRANSITION_TO_MEDALS; if ( pLocalPlayer ) { if ( bShowPerformanceMedals ) { const char *pszEntryName = UTIL_GetRandomSoundFromEntry( "Announcer.CompSummaryScreenOutlierQuestion" ); if ( pszEntryName && pszEntryName[0] ) { flDelay = enginesound->GetSoundDuration( pszEntryName ); pLocalPlayer->EmitSound( pszEntryName ); } } pLocalPlayer->EmitSound( "MatchMaking.ScoreboardPanelSlide" ); } m_iCurrentState = MS_STATE_STATS; m_flNextActionTime = gpGlobals->curtime + flDelay; m_pRedMedalsPanel->SetVisible( bShowPerformanceMedals ); m_pBlueMedalsPanel->SetVisible( bShowPerformanceMedals ); m_pStatsAndMedals->SetText( bShowPerformanceMedals ? g_pVGuiLocalize->Find( "#TF_CompSummary_StatsAndMedals" ) : L"" ); m_pStatsAndMedalsShadow->SetText( bShowPerformanceMedals ? g_pVGuiLocalize->Find( "#TF_CompSummary_StatsAndMedals" ) : L"" ); } break; } case MS_STATE_STATS: { if ( gpGlobals->curtime > m_flNextActionTime ) { m_iCurrentState = bShowPerformanceMedals ? MS_STATE_BRONZE_MEDALS : MS_STATE_FINAL; m_nMedalsRevealed = 0; m_flNextActionTime = -1; } break; } case MS_STATE_BRONZE_MEDALS: { if ( gpGlobals->curtime > m_flNextActionTime ) { if ( !m_bBlueBronzeValueRevealed && !m_bRedBronzeValueRevealed ) { m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_bronze", m_nMedalsToAward_Bronze_Blue ); m_bBlueBronzeValueRevealed = true; Panel *pChild = m_pBlueMedalsPanel->FindChildByName( "BlueBronzeMedalValue" ); if ( pChild ) { int nXPos, nYPos, nWide, nTall; pChild->GetBounds( nXPos, nYPos, nWide, nTall ); FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Bronze_Blue > 0 ) ? StatMedal_Bronze : StatMedal_None ); } m_pRedMedalsPanel->SetDialogVariable( "redteammedals_bronze", m_nMedalsToAward_Bronze_Red ); m_bRedBronzeValueRevealed = true; pChild = m_pRedMedalsPanel->FindChildByName( "RedBronzeMedalValue" ); if ( pChild ) { int nXPos, nYPos, nWide, nTall; pChild->GetBounds( nXPos, nYPos, nWide, nTall ); FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Bronze_Red > 0 ) ? StatMedal_Bronze : StatMedal_None ); } m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES; } else { if ( ( nMedalsToAward_Bronze_Total > 0 ) && ( m_nMedalsRevealed < nMedalsToAward_Bronze_Total ) ) { Update(); m_nMedalsRevealed++; m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS; } else { m_iCurrentState = MS_STATE_SILVER_MEDALS; m_nMedalsRevealed = 0; m_flNextActionTime = MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES; } } } break; } case MS_STATE_SILVER_MEDALS: { if ( gpGlobals->curtime > m_flNextActionTime ) { if ( !m_bBlueSilverValueRevealed && !m_bRedSilverValueRevealed ) { m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_silver", m_nMedalsToAward_Silver_Blue ); m_bBlueSilverValueRevealed = true; Panel *pChild = m_pBlueMedalsPanel->FindChildByName( "BlueSilverMedalValue" ); if ( pChild ) { int nXPos, nYPos, nWide, nTall; pChild->GetBounds( nXPos, nYPos, nWide, nTall ); FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Silver_Blue > 0 ) ? StatMedal_Silver : StatMedal_None ); } m_pRedMedalsPanel->SetDialogVariable( "redteammedals_silver", m_nMedalsToAward_Silver_Red ); m_bRedSilverValueRevealed = true; pChild = m_pRedMedalsPanel->FindChildByName( "RedSilverMedalValue" ); if ( pChild ) { int nXPos, nYPos, nWide, nTall; pChild->GetBounds( nXPos, nYPos, nWide, nTall ); FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Silver_Red > 0 ) ? StatMedal_Silver : StatMedal_None ); } m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES; } else { if ( ( nMedalsToAward_Silver_Total > 0 ) && ( m_nMedalsRevealed < nMedalsToAward_Silver_Total ) ) { Update(); m_nMedalsRevealed++; m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS; } else { m_iCurrentState = MS_STATE_GOLD_MEDALS; m_nMedalsRevealed = 0; m_flNextActionTime = MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES; } } } break; } case MS_STATE_GOLD_MEDALS: { if ( gpGlobals->curtime > m_flNextActionTime ) { if ( !m_bBlueGoldValueRevealed && !m_bRedGoldValueRevealed ) { m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_gold", m_nMedalsToAward_Gold_Blue ); m_bBlueGoldValueRevealed = true; Panel *pChild = m_pBlueMedalsPanel->FindChildByName( "BlueGoldMedalValue" ); if ( pChild ) { int nXPos, nYPos, nWide, nTall; pChild->GetBounds( nXPos, nYPos, nWide, nTall ); FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Gold_Blue > 0 ) ? StatMedal_Gold : StatMedal_None ); } m_pRedMedalsPanel->SetDialogVariable( "redteammedals_gold", m_nMedalsToAward_Gold_Red ); m_bRedGoldValueRevealed = true; pChild = m_pRedMedalsPanel->FindChildByName( "RedGoldMedalValue" ); if ( pChild ) { int nXPos, nYPos, nWide, nTall; pChild->GetBounds( nXPos, nYPos, nWide, nTall ); FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Gold_Red > 0 ) ? StatMedal_Gold : StatMedal_None ); } m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES; } else { if ( ( nMedalsToAward_Gold_Total > 0 ) && ( m_nMedalsRevealed < nMedalsToAward_Gold_Total ) ) { Update(); m_nMedalsRevealed++; m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS; } else { m_iCurrentState = MS_STATE_FINAL; m_nMedalsRevealed = 0; m_flNextActionTime = -1; if ( pLocalPlayer ) { const char *pszSoundScriptEntry = "Announcer.CompSummaryScreenOutlierNo"; if ( nMedalsToAward_Bronze_Total || nMedalsToAward_Silver_Total || nMedalsToAward_Gold_Total ) { pszSoundScriptEntry = "Announcer.CompSummaryScreenOutlierYes"; } const char *pszSoundName = UTIL_GetRandomSoundFromEntry( pszSoundScriptEntry ); m_flMedalSoundTime = gpGlobals->curtime + enginesound->GetSoundDuration( pszSoundName ) + 0.5f; pLocalPlayer->EmitSound( pszSoundName ); IGameEvent *event = gameeventmanager->CreateEvent( "ds_screenshot" ); if ( event ) { event->SetFloat( "delay", 0.5f ); gameeventmanager->FireEventClientSide( event ); } } } } } break; } default: case MS_STATE_FINAL: { bool bMedalSoundTimeComplete = ( m_flMedalSoundTime > 0 ) && ( m_flMedalSoundTime < gpGlobals->curtime ); if ( !m_bXPShown /*&& ( !bShowMedals || bMedalSoundTimeComplete ) */) { g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "CompetitiveGame_ShowPvPRankPanel", false ); m_bXPShown = true; } if ( bShowPerformanceMedals ) { if ( bMedalSoundTimeComplete ) { m_flMedalSoundTime = -1.f; int iLocalPlayerIndex = GetLocalPlayerIndex(); if ( ( m_SkillRatings[iLocalPlayerIndex].nScoreRank != StatMedal_None ) || ( m_SkillRatings[iLocalPlayerIndex].nKillsRank != StatMedal_None ) || ( m_SkillRatings[iLocalPlayerIndex].nDamageRank != StatMedal_None ) || ( m_SkillRatings[iLocalPlayerIndex].nHealingRank != StatMedal_None ) || ( m_SkillRatings[iLocalPlayerIndex].nSupportRank != StatMedal_None ) ) { if ( pLocalPlayer ) { int iClass = RandomInt( TF_CLASS_SCOUT, TF_CLASS_ENGINEER ); if ( pLocalPlayer->GetPlayerClass() && ( pLocalPlayer->GetPlayerClass()->GetClassIndex() > TF_CLASS_UNDEFINED ) ) { iClass = pLocalPlayer->GetPlayerClass()->GetClassIndex(); } pLocalPlayer->EmitSound( VarArgs( "%s.CompSummaryScreenOutlier", g_aPlayerClassNames_NonLocalized[iClass] ) ); } } } } break; } } } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMatchSummary::LevelInit( void ) { SetVisible( false ); } void CTFMatchSummary::LevelShutdown( void ) { SetVisible( false ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CTFMatchSummary::ShowPerformanceMedals( void ) { bool bDistributePerformanceMedals = false; const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() ); if ( pMatchDesc ) { bDistributePerformanceMedals = pMatchDesc->m_params.m_bDistributePerformanceMedals; } return ( bDistributePerformanceMedals && !m_bPlayerAbandoned ); }