diff options
Diffstat (limited to 'game/client/tf/vgui/tf_match_summary.cpp')
| -rw-r--r-- | game/client/tf/vgui/tf_match_summary.cpp | 1481 |
1 files changed, 1481 insertions, 0 deletions
diff --git a/game/client/tf/vgui/tf_match_summary.cpp b/game/client/tf/vgui/tf_match_summary.cpp new file mode 100644 index 0000000..4f5e4be --- /dev/null +++ b/game/client/tf/vgui/tf_match_summary.cpp @@ -0,0 +1,1481 @@ + +//========= 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 <vgui_controls/Label.h> +#include <vgui_controls/ImagePanel.h> +#include <vgui/ILocalize.h> +#include <vgui/ISurface.h> +#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<CTFBadgePanel*> &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 ); +} |