Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1481 lines
54 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "hud.h"
  9. #include "tf_match_summary.h"
  10. #include "tf_hud_statpanel.h"
  11. #include "tf_spectatorgui.h"
  12. #include "vgui_controls/AnimationController.h"
  13. #include "iclientmode.h"
  14. #include "engine/IEngineSound.h"
  15. #include "c_tf_playerresource.h"
  16. #include "c_team.h"
  17. #include "tf_clientscoreboard.h"
  18. #include <vgui_controls/Label.h>
  19. #include <vgui_controls/ImagePanel.h>
  20. #include <vgui/ILocalize.h>
  21. #include <vgui/ISurface.h>
  22. #include "vgui_avatarimage.h"
  23. #include "fmtstr.h"
  24. #include "teamplayroundbased_gamerules.h"
  25. #include "tf_gamerules.h"
  26. #include "tf_logic_halloween_2014.h"
  27. #include "tf_playermodelpanel.h"
  28. #include "tf_mapinfo.h"
  29. #include "c_tf_team.h"
  30. #include "tf_pvp_rank_panel.h"
  31. #include "tf_badge_panel.h"
  32. #include "tf_survey_questions.h"
  33. // memdbgon must be the last include file in a .cpp file!!!
  34. #include "tier0/memdbgon.h"
  35. void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
  36. extern ISoundEmitterSystemBase *soundemitterbase;
  37. #define MAX_PLAYER_MODELS 6
  38. #define MS_STATE_TRANSITION_TO_STATS 17.0f
  39. #define MS_STATE_TRANSITION_TO_MEDALS 3.0f
  40. #define MS_STATE_TIME_BETWEEN_MEDALS 0.1f
  41. #define MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES 0.1f
  42. extern ConVar tf_scoreboard_alt_class_icons;
  43. DECLARE_BUILD_FACTORY( TFSectionedListPanel );
  44. DECLARE_HUDELEMENT( CTFMatchSummary );
  45. #ifdef STAGING_ONLY
  46. static void cc_tf_restart_match_summary()
  47. {
  48. CTFMatchSummary *pMatchSummary = GET_HUDELEMENT( CTFMatchSummary );
  49. if (pMatchSummary)
  50. {
  51. pMatchSummary->InvalidateLayout(true, true);
  52. pMatchSummary->SetVisible( false );
  53. pMatchSummary->SetVisible( true );
  54. }
  55. }
  56. ConCommand tf_restart_match_summary("tf_restart_match_summary", cc_tf_restart_match_summary);
  57. #endif
  58. //-----------------------------------------------------------------------------
  59. // Purpose: Constructor
  60. //-----------------------------------------------------------------------------
  61. CTFMatchSummary::CTFMatchSummary( const char *pElementName )
  62. : CHudElement( pElementName )
  63. , EditablePanel( NULL, "MatchSummary" )
  64. , m_bXPShown( false )
  65. {
  66. vgui::Panel *pParent = g_pClientMode->GetViewport();
  67. SetParent( pParent );
  68. m_pMainStatsContainer = new EditablePanel( this, "MainStatsContainer" );
  69. m_pDrawingPanel = new CDrawingPanel( this, "DrawingPanel" );
  70. m_pStatsBgPanel = new EditablePanel( this, "StatsBgPanel" );
  71. m_pTeamScoresPanel = new EditablePanel( m_pMainStatsContainer, "TeamScoresPanel" );
  72. m_pParticlePanel = new CTFParticlePanel( m_pMainStatsContainer, "ParticlePanel" );
  73. m_pStatsLabelPanel = new EditablePanel( m_pMainStatsContainer, "StatsLabelPanel" );
  74. m_pBlueTeamPanel = new EditablePanel( m_pTeamScoresPanel, "BlueTeamPanel" );
  75. m_pRedTeamPanel = new EditablePanel( m_pTeamScoresPanel, "RedTeamPanel" );
  76. m_pPlayerListBlueParent = new EditablePanel( m_pBlueTeamPanel, "BluePlayerListParent" );
  77. m_pPlayerListBlue = new TFSectionedListPanel( m_pPlayerListBlueParent, "BluePlayerList" );
  78. m_pPlayerListRedParent = new EditablePanel( m_pRedTeamPanel, "RedPlayerListParent" );
  79. m_pPlayerListRed = new TFSectionedListPanel( m_pPlayerListRedParent, "RedPlayerList" );
  80. m_pBlueTeamScore = new CExLabel( m_pBlueTeamPanel, "BlueTeamScore", "" );
  81. m_pBlueTeamScoreDropshadow = new CExLabel( m_pBlueTeamPanel, "BlueTeamScoreDropshadow", "" );
  82. m_pBlueTeamScoreBG = new EditablePanel( m_pBlueTeamPanel, "BlueTeamScoreBG" );
  83. m_pBluePlayerListBG = new EditablePanel( m_pBlueTeamPanel, "BluePlayerListBG" );
  84. m_pRedTeamScore = new CExLabel( m_pRedTeamPanel, "RedTeamScore", "" );
  85. m_pRedTeamScoreDropshadow = new CExLabel( m_pRedTeamPanel, "RedTeamScoreDropshadow", "" );
  86. m_pRedTeamScoreBG = new EditablePanel( m_pRedTeamPanel, "RedTeamScoreBG" );
  87. m_pRedPlayerListBG = new EditablePanel( m_pRedTeamPanel, "RedPlayerListBG" );
  88. m_pBlueMedalsPanel = new EditablePanel( m_pTeamScoresPanel, "BlueMedals" );
  89. m_pRedMedalsPanel = new EditablePanel( m_pTeamScoresPanel, "RedMedals" );
  90. m_pRedTeamImage = new vgui::ImagePanel( m_pRedTeamPanel, "RedTeamImage" );
  91. m_pBlueTeamImage = new vgui::ImagePanel( m_pBlueTeamPanel, "BlueTeamImage" );
  92. m_pRedLeaderAvatarImage = new CAvatarImagePanel( m_pRedTeamPanel, "RedLeaderAvatar" );
  93. m_pBlueLeaderAvatarImage = new CAvatarImagePanel( m_pBlueTeamPanel, "BlueLeaderAvatar" );
  94. m_pRedLeaderAvatarBG = new EditablePanel( m_pRedTeamPanel, "RedLeaderAvatarBG" );
  95. m_pBlueLeaderAvatarBG = new EditablePanel( m_pBlueTeamPanel, "BlueLeaderAvatarBG" );
  96. m_pStatsAndMedals = new CExLabel( m_pStatsLabelPanel, "StatsAndMedals", "" );
  97. m_pStatsAndMedalsShadow = new CExLabel( m_pStatsLabelPanel, "StatsAndMedalsShadow", "" );
  98. m_pRedTeamName = new CExLabel( m_pRedTeamPanel, "RedTeamLabel", "" );
  99. m_pBlueTeamName = new CExLabel( m_pBlueTeamPanel, "BlueTeamLabel", "" );
  100. m_pRedTeamWinner = new CExLabel( m_pRedTeamPanel, "RedTeamWinner", "" );
  101. m_pRedTeamWinnerDropshadow = new CExLabel( m_pRedTeamPanel, "RedTeamWinnerDropshadow", "" );
  102. m_pBlueTeamWinner = new CExLabel( m_pBlueTeamPanel, "BlueTeamWinner", "" );
  103. m_pBlueTeamWinnerDropshadow = new CExLabel( m_pBlueTeamPanel, "BlueTeamWinnerDropshadow", "" );
  104. m_pImageList = NULL;
  105. m_mapAvatarsToImageList.SetLessFunc( DefLessFunc( CSteamID ) );
  106. m_mapAvatarsToImageList.RemoveAll();
  107. Q_memset( m_SkillRatings, 0, sizeof( m_SkillRatings ) );
  108. m_iCurrentState = MS_STATE_INITIAL;
  109. m_flNextActionTime = -1;
  110. m_nMedalsToAward_Bronze_Blue = 0;
  111. m_nMedalsToAward_Silver_Blue = 0;
  112. m_nMedalsToAward_Gold_Blue = 0;
  113. m_nMedalsToAward_Bronze_Red = 0;
  114. m_nMedalsToAward_Silver_Red = 0;
  115. m_nMedalsToAward_Gold_Red = 0;
  116. m_nMedalsRevealed = 0;
  117. m_nNumMedalsThisUpdate = 0;
  118. m_bBlueGoldValueRevealed = false;
  119. m_bBlueSilverValueRevealed = false;
  120. m_bBlueBronzeValueRevealed = false;
  121. m_bRedGoldValueRevealed = false;
  122. m_bRedSilverValueRevealed = false;
  123. m_bRedBronzeValueRevealed = false;
  124. m_bPlayerAbandoned = false;
  125. m_flMedalSoundTime = -1.f;
  126. m_bLargeMatchGroup = false;
  127. Q_memset( m_iImageClass, NULL, sizeof( m_iImageClass ) );
  128. Q_memset( m_iImageClassAlt, NULL, sizeof( m_iImageClassAlt ) );
  129. ListenForGameEvent( "competitive_victory" );
  130. ListenForGameEvent( "competitive_stats_update" );
  131. ListenForGameEvent( "player_abandoned_match" );
  132. ListenForGameEvent( "client_disconnect" );
  133. ListenForGameEvent( "show_match_summary" );
  134. vgui::ivgui()->AddTickSignal( GetVPanel(), 50 );
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose: Constructor
  138. //-----------------------------------------------------------------------------
  139. CTFMatchSummary::~CTFMatchSummary()
  140. {
  141. if ( NULL != m_pImageList )
  142. {
  143. delete m_pImageList;
  144. m_pImageList = NULL;
  145. }
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Purpose: Applies scheme settings
  149. //-----------------------------------------------------------------------------
  150. void CTFMatchSummary::ApplySchemeSettings( vgui::IScheme *pScheme )
  151. {
  152. BaseClass::ApplySchemeSettings( pScheme );
  153. m_bLargeMatchGroup = false;
  154. KeyValues *pConditions = NULL;
  155. if ( TFGameRules() )
  156. {
  157. const IMatchGroupDescription* pMatch = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
  158. if ( pMatch )
  159. {
  160. if ( pMatch->m_params.m_pmm_match_group_size->GetInt() > 12 )
  161. {
  162. pConditions = new KeyValues( "conditions" );
  163. AddSubKeyNamed( pConditions, "if_large" );
  164. m_bLargeMatchGroup = true;
  165. }
  166. }
  167. }
  168. LoadControlSettings( "resource/UI/HudMatchSummary.res", NULL, NULL, pConditions );
  169. if ( pConditions )
  170. {
  171. pConditions->deleteThis();
  172. }
  173. if ( m_pDrawingPanel )
  174. {
  175. m_pDrawingPanel->ClearAllLines();
  176. m_pDrawingPanel->SetType( DRAWING_PANEL_TYPE_MATCH_SUMMARY );
  177. m_pDrawingPanel->MakePopup();
  178. }
  179. if ( m_pImageList )
  180. delete m_pImageList;
  181. m_pImageList = new ImageList( false );
  182. m_mapAvatarsToImageList.RemoveAll();
  183. for ( int i = 1; i < (int)StatMedal_Max; i++ )
  184. {
  185. m_iImageMedals[i] = m_pImageList->AddImage( scheme()->GetImage( g_pszCompetitiveMedalImages[i], true ) );
  186. }
  187. for ( int i = 1; i < SCOREBOARD_CLASS_ICONS; i++ )
  188. {
  189. m_iImageClass[i] = m_pImageList->AddImage( scheme()->GetImage( g_pszClassIcons[i], true ) );
  190. m_iImageClassAlt[i] = m_pImageList->AddImage( scheme()->GetImage( g_pszClassIconsAlt[i], true ) );
  191. }
  192. int iCurrentCount = m_pImageList->GetImageCount();
  193. // resize the images to our resolution
  194. for ( int i = 0; i < iCurrentCount; i++ )
  195. {
  196. int wide = 13, tall = 13;
  197. m_pImageList->GetImage( i )->SetSize( scheme()->GetProportionalScaledValueEx( GetScheme(), wide ), scheme()->GetProportionalScaledValueEx( GetScheme(), tall ) );
  198. }
  199. // resize the images to our resolution
  200. for ( int i = iCurrentCount; i < m_pImageList->GetImageCount(); i++ )
  201. {
  202. int wide = 26, tall = 26;
  203. m_pImageList->GetImage( i )->SetSize( scheme()->GetProportionalScaledValueEx( GetScheme(), wide ), scheme()->GetProportionalScaledValueEx( GetScheme(), tall ) );
  204. }
  205. SetPaintBackgroundEnabled( false );
  206. m_pTeamScoresPanel->SetPaintBackgroundEnabled( false );
  207. m_pPlayerListBlueParent->SetPaintBackgroundEnabled( false );
  208. m_pPlayerListRedParent->SetPaintBackgroundEnabled( false );
  209. m_pPlayerListBlue->SetPaintBackgroundEnabled( false );
  210. m_pPlayerListRed->SetPaintBackgroundEnabled( false );
  211. m_pPlayerListBlue->SetImageList( m_pImageList, false );
  212. m_pPlayerListBlue->SetVisible( true );
  213. m_pPlayerListRed->SetImageList( m_pImageList, false );
  214. m_pPlayerListRed->SetVisible( true );
  215. InitPlayerList( m_pPlayerListBlue, TF_TEAM_BLUE );
  216. InitPlayerList( m_pPlayerListRed, TF_TEAM_RED );
  217. m_hFont = pScheme->GetFont( "ScoreboardVerySmall", true );
  218. m_iCurrentState = MS_STATE_INITIAL;
  219. m_flNextActionTime = -1;
  220. RecalculateMedalCounts();
  221. m_nMedalsRevealed = 0;
  222. m_bBlueGoldValueRevealed = false;
  223. m_bBlueSilverValueRevealed = false;
  224. m_bBlueBronzeValueRevealed = false;
  225. m_bRedGoldValueRevealed = false;
  226. m_bRedSilverValueRevealed = false;
  227. m_bRedBronzeValueRevealed = false;
  228. m_flMedalSoundTime = -1.f;
  229. m_flDrawingPanelTime = -1.f;
  230. m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_gold", "?" );
  231. m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_silver", "?" );
  232. m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_bronze", "?" );
  233. m_pRedMedalsPanel->SetDialogVariable( "redteammedals_gold", "?" );
  234. m_pRedMedalsPanel->SetDialogVariable( "redteammedals_silver", "?" );
  235. m_pRedMedalsPanel->SetDialogVariable( "redteammedals_bronze", "?" );
  236. Update();
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Purpose:
  240. //-----------------------------------------------------------------------------
  241. void CTFMatchSummary::PerformLayout()
  242. {
  243. BaseClass::PerformLayout();
  244. EditablePanel* pStatsContainer = FindControl< EditablePanel >( "MainStatsContainer" );
  245. if ( pStatsContainer && m_bLargeMatchGroup )
  246. {
  247. pStatsContainer->SetPos( pStatsContainer->GetXPos(), m_iAnimStatsContainer12v12YPos );
  248. }
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Purpose:
  252. //-----------------------------------------------------------------------------
  253. bool CTFMatchSummary::ShouldDraw( void )
  254. {
  255. return IsVisible();
  256. }
  257. //-----------------------------------------------------------------------------
  258. // Purpose:
  259. //-----------------------------------------------------------------------------
  260. void CTFMatchSummary::SetVisible( bool state )
  261. {
  262. int iRenderGroup = gHUD.LookupRenderGroupIndexByName( "mid" );
  263. if ( state )
  264. {
  265. gHUD.LockRenderGroup( iRenderGroup );
  266. InvalidateLayout( true, true );
  267. m_iCurrentState = MS_STATE_INITIAL;
  268. m_flDrawingPanelTime = gpGlobals->curtime + 4.5f;
  269. CPvPRankPanel* pPvPRankPanel = FindControl< CPvPRankPanel >( "RankPanel" );
  270. if ( pPvPRankPanel )
  271. {
  272. pPvPRankPanel->SetMatchGroup( TFGameRules()->GetCurrentMatchGroup() );
  273. }
  274. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "CompetitiveGame_LowerChatWindow", false );
  275. }
  276. else
  277. {
  278. gHUD.UnlockRenderGroup( iRenderGroup );
  279. }
  280. BaseClass::SetVisible( state );
  281. }
  282. //-----------------------------------------------------------------------------
  283. // Purpose: Used for sorting players
  284. //-----------------------------------------------------------------------------
  285. bool CTFMatchSummary::TFPlayerSortFunc( vgui::SectionedListPanel *list, int itemID1, int itemID2 )
  286. {
  287. KeyValues *it1 = list->GetItemData( itemID1 );
  288. KeyValues *it2 = list->GetItemData( itemID2 );
  289. Assert( it1 && it2 );
  290. // first compare score
  291. int v1 = it1->GetInt( "score" );
  292. int v2 = it2->GetInt( "score" );
  293. if ( v1 > v2 )
  294. return true;
  295. else if ( v1 < v2 )
  296. return false;
  297. // if score is the same, use player index to get deterministic sort
  298. int iPlayerIndex1 = it1->GetInt( "playerIndex" );
  299. int iPlayerIndex2 = it2->GetInt( "playerIndex" );
  300. return ( iPlayerIndex1 > iPlayerIndex2 );
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Purpose: Inits the player list in a list panel
  304. //-----------------------------------------------------------------------------
  305. void CTFMatchSummary::InitPlayerList( TFSectionedListPanel *pPlayerList, int nTeam )
  306. {
  307. float flAspectRatio = engine->GetScreenAspectRatio();
  308. bool bStandard = flAspectRatio < 1.6f;
  309. pPlayerList->SetVerticalScrollbar( false );
  310. pPlayerList->RemoveAll();
  311. pPlayerList->RemoveAllSections();
  312. pPlayerList->AddSection( 0, "Players", TFPlayerSortFunc );
  313. pPlayerList->SetSectionAlwaysVisible( 0, true );
  314. pPlayerList->SetSectionDrawDividerBar( 0, false );
  315. pPlayerList->SetBorder( NULL );
  316. pPlayerList->SetMouseInputEnabled( false );
  317. pPlayerList->SetClickable( false );
  318. pPlayerList->AddColumnToSection( 0, "medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_CENTER, pPlayerList->m_iMedalWidth );
  319. pPlayerList->AddColumnToSection( 0, "avatar", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAvatarWidth );
  320. pPlayerList->AddColumnToSection( 0, "spacer", "", 0, pPlayerList->m_iSpacerWidth );
  321. pPlayerList->AddColumnToSection( 0, "name", "", 0, pPlayerList->m_iNameWidth );
  322. pPlayerList->AddColumnToSection( 0, "class", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iClassWidth );
  323. pPlayerList->AddColumnToSection( 0, "score", bStandard ? "#TF_Comp_Scoreboard_Score_Standard" : "#TF_Comp_Scoreboard_Score", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth );
  324. pPlayerList->AddColumnToSection( 0, "score_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth );
  325. pPlayerList->AddColumnToSection( 0, "kills", bStandard ? "#TF_Comp_Scoreboard_Kills_Standard" : "#TF_Comp_Scoreboard_Kills", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth );
  326. pPlayerList->AddColumnToSection( 0, "kills_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth );
  327. pPlayerList->AddColumnToSection( 0, "damage", bStandard ? "#TF_Comp_Scoreboard_Damage_Standard" : "#TF_Comp_Scoreboard_Damage", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth );
  328. pPlayerList->AddColumnToSection( 0, "damage_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth );
  329. pPlayerList->AddColumnToSection( 0, "healing", bStandard ? "#TF_Comp_Scoreboard_Healing_Standard" : "#TF_Comp_Scoreboard_Healing", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth );
  330. pPlayerList->AddColumnToSection( 0, "healing_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth );
  331. pPlayerList->AddColumnToSection( 0, "support", bStandard ? "#TF_Comp_Scoreboard_Support_Standard" : "#TF_Comp_Scoreboard_Support", SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iStatsWidth );
  332. pPlayerList->AddColumnToSection( 0, "support_medal", "", SectionedListPanel::COLUMN_IMAGE | SectionedListPanel::COLUMN_RIGHT, pPlayerList->m_iAwardWidth );
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Purpose:
  336. //-----------------------------------------------------------------------------
  337. void CTFMatchSummary::Update( void )
  338. {
  339. UpdateTeamInfo();
  340. UpdatePlayerList();
  341. UpdateBadgePanels( m_pRedBadgePanels, m_pPlayerListRed );
  342. UpdateBadgePanels( m_pBlueBadgePanels, m_pPlayerListBlue );
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Purpose: Updates information about teams
  346. //-----------------------------------------------------------------------------
  347. void CTFMatchSummary::UpdateTeamInfo()
  348. {
  349. bool bUseWinnerLabel = false;
  350. if ( GetGlobalTFTeam( TF_TEAM_RED ) && GetGlobalTFTeam( TF_TEAM_BLUE ) )
  351. {
  352. if ( GetGlobalTFTeam( TF_TEAM_RED )->Get_Score() == GetGlobalTFTeam( TF_TEAM_BLUE )->Get_Score() )
  353. {
  354. bUseWinnerLabel = true;
  355. }
  356. }
  357. int nWinningTeam = TEAM_INVALID;
  358. if ( TFGameRules() )
  359. {
  360. nWinningTeam = TFGameRules()->GetWinningTeam();
  361. }
  362. for ( int teamIndex = TF_TEAM_RED; teamIndex <= TF_TEAM_BLUE; teamIndex++ )
  363. {
  364. C_TFTeam *team = GetGlobalTFTeam( teamIndex );
  365. if ( team )
  366. {
  367. // choose dialog variables to set depending on team
  368. const char *pDialogVarTeamName = "";
  369. const char *pDialogVarTeamScore = "";
  370. const char *pDialogVarWinner = "";
  371. vgui::EditablePanel *pOwner = NULL;
  372. switch ( teamIndex )
  373. {
  374. case TF_TEAM_RED:
  375. pDialogVarTeamName = "redteamname";
  376. pDialogVarTeamScore = "redteamscore";
  377. pDialogVarWinner = "redteamwinner";
  378. pOwner = m_pRedTeamPanel;
  379. break;
  380. case TF_TEAM_BLUE:
  381. pDialogVarTeamName = "blueteamname";
  382. pDialogVarTeamScore = "blueteamscore";
  383. pDialogVarWinner = "blueteamwinner";
  384. pOwner = m_pBlueTeamPanel;
  385. break;
  386. default:
  387. Assert( false );
  388. break;
  389. }
  390. if ( !pOwner )
  391. return;
  392. // set the team name
  393. pOwner->SetDialogVariable( pDialogVarTeamName, team->Get_Localized_Name() );
  394. if ( bUseWinnerLabel )
  395. {
  396. const char *pszLabel = "";
  397. if ( teamIndex == nWinningTeam )
  398. {
  399. if ( team->GetNumPlayers() > 1 )
  400. {
  401. pszLabel = "#TF_Winners";
  402. }
  403. else
  404. {
  405. pszLabel = "#TF_Winner";
  406. }
  407. }
  408. pOwner->SetDialogVariable( pDialogVarTeamScore, "" );
  409. pOwner->SetDialogVariable( pDialogVarWinner, g_pVGuiLocalize->Find( pszLabel ) );
  410. }
  411. else
  412. {
  413. pOwner->SetDialogVariable( pDialogVarTeamScore, team->Get_Score() );
  414. pOwner->SetDialogVariable( pDialogVarWinner, "" );
  415. }
  416. }
  417. }
  418. bool bShowAvatars = g_TF_PR && g_TF_PR->HasPremadeParties();
  419. if ( bShowAvatars )
  420. {
  421. m_pRedLeaderAvatarImage->SetPlayer( GetSteamIDForPlayerIndex( g_TF_PR->GetPartyLeaderRedTeamIndex() ), k_EAvatarSize64x64 );
  422. m_pRedLeaderAvatarImage->SetShouldDrawFriendIcon( false );
  423. m_pBlueLeaderAvatarImage->SetPlayer( GetSteamIDForPlayerIndex( g_TF_PR->GetPartyLeaderBlueTeamIndex() ), k_EAvatarSize64x64 );
  424. m_pBlueLeaderAvatarImage->SetShouldDrawFriendIcon( false );
  425. }
  426. m_pRedLeaderAvatarImage->SetVisible( bShowAvatars );
  427. m_pRedLeaderAvatarBG->SetVisible( bShowAvatars );
  428. m_pRedTeamName->SetVisible( bShowAvatars );
  429. m_pRedTeamImage->SetVisible( !bShowAvatars );
  430. m_pBlueLeaderAvatarImage->SetVisible( bShowAvatars );
  431. m_pBlueLeaderAvatarBG->SetVisible( bShowAvatars );
  432. m_pBlueTeamName->SetVisible( bShowAvatars );
  433. m_pBlueTeamImage->SetVisible( !bShowAvatars );
  434. }
  435. //-----------------------------------------------------------------------------
  436. // Purpose: Returns the last medal (column) added so we can display some effects
  437. //-----------------------------------------------------------------------------
  438. matchsummary_columns_t CTFMatchSummary::InternalAddMedalKeyValues( int iIndex, StatMedal_t eMedal, KeyValues *pKeyValues, int nTotalMedals /*= -1*/ )
  439. {
  440. int nMedal = (int)eMedal;
  441. matchsummary_columns_t retVal = MS_COLUMN_INVALID;
  442. if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) )
  443. {
  444. if ( m_SkillRatings[iIndex].nScoreRank == nMedal )
  445. {
  446. pKeyValues->SetInt( "score_medal", m_iImageMedals[nMedal] );
  447. if ( nTotalMedals >= 0 )
  448. {
  449. m_nNumMedalsThisUpdate++;
  450. }
  451. if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) )
  452. {
  453. retVal = MS_COLUMN_SCORE_MEDAL;
  454. }
  455. }
  456. }
  457. if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) )
  458. {
  459. if ( m_SkillRatings[iIndex].nKillsRank == nMedal )
  460. {
  461. pKeyValues->SetInt( "kills_medal", m_iImageMedals[nMedal] );
  462. if ( nTotalMedals >= 0 )
  463. {
  464. m_nNumMedalsThisUpdate++;
  465. }
  466. if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) )
  467. {
  468. retVal = MS_COLUMN_KILLS_MEDAL;
  469. }
  470. }
  471. }
  472. if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) )
  473. {
  474. if ( m_SkillRatings[iIndex].nDamageRank == nMedal )
  475. {
  476. pKeyValues->SetInt( "damage_medal", m_iImageMedals[nMedal] );
  477. if ( nTotalMedals >= 0 )
  478. {
  479. m_nNumMedalsThisUpdate++;
  480. }
  481. if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) )
  482. {
  483. retVal = MS_COLUMN_DAMAGE_MEDAL;
  484. }
  485. }
  486. }
  487. if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) )
  488. {
  489. if ( m_SkillRatings[iIndex].nHealingRank == nMedal )
  490. {
  491. pKeyValues->SetInt( "healing_medal", m_iImageMedals[nMedal] );
  492. if ( nTotalMedals >= 0 )
  493. {
  494. m_nNumMedalsThisUpdate++;
  495. }
  496. if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) )
  497. {
  498. retVal = MS_COLUMN_HEALING_MEDAL;
  499. }
  500. }
  501. }
  502. if ( ( nTotalMedals < 0 ) || ( m_nNumMedalsThisUpdate <= nTotalMedals ) )
  503. {
  504. if ( m_SkillRatings[iIndex].nSupportRank == nMedal )
  505. {
  506. pKeyValues->SetInt( "support_medal", m_iImageMedals[nMedal] );
  507. if ( nTotalMedals >= 0 )
  508. {
  509. m_nNumMedalsThisUpdate++;
  510. }
  511. if ( ( nTotalMedals >= 0 ) && ( m_nNumMedalsThisUpdate > nTotalMedals ) )
  512. {
  513. retVal = MS_COLUMN_SUPPORT_MEDAL;
  514. }
  515. }
  516. }
  517. return retVal;
  518. }
  519. //-----------------------------------------------------------------------------
  520. // Purpose: Updates the player list
  521. //-----------------------------------------------------------------------------
  522. void CTFMatchSummary::UpdatePlayerList()
  523. {
  524. m_pPlayerListRed->RemoveAll();
  525. m_pPlayerListRed->ClearAllColorOverrideForCell();
  526. m_pPlayerListBlue->RemoveAll();
  527. m_pPlayerListBlue->ClearAllColorOverrideForCell();
  528. if ( !g_TF_PR )
  529. return;
  530. m_nNumMedalsThisUpdate = 0;
  531. for ( int playerIndex = 1; playerIndex <= MAX_PLAYERS; playerIndex++ )
  532. {
  533. if ( g_PR->IsConnected( playerIndex ) || g_PR->IsValid( playerIndex ) )
  534. {
  535. TFSectionedListPanel *pPlayerList = NULL;
  536. int nTeam = g_PR->GetTeam( playerIndex );
  537. switch ( nTeam )
  538. {
  539. case TF_TEAM_BLUE:
  540. pPlayerList = m_pPlayerListBlue;
  541. break;
  542. case TF_TEAM_RED:
  543. pPlayerList = m_pPlayerListRed;
  544. break;
  545. }
  546. if ( null == pPlayerList )
  547. continue;
  548. KeyValues *pKeyValues = new KeyValues( "data" );
  549. pKeyValues->SetInt( "playerIndex", playerIndex );
  550. // this is just a placeholder in the sectioned list panel
  551. pKeyValues->SetInt( "medal", 0 );
  552. pKeyValues->SetString( "name", g_TF_PR->GetPlayerName( playerIndex ) );
  553. pKeyValues->SetInt( "score", g_TF_PR->GetTotalScore( playerIndex ) );
  554. int iClass = g_TF_PR->GetPlayerClass( playerIndex );
  555. if ( iClass >= TF_FIRST_NORMAL_CLASS && iClass <= TF_LAST_NORMAL_CLASS )
  556. {
  557. pKeyValues->SetInt( "class", tf_scoreboard_alt_class_icons.GetBool() ? m_iImageClassAlt[iClass] : m_iImageClass[iClass] );
  558. }
  559. else
  560. {
  561. pKeyValues->SetInt( "class", 0 );
  562. }
  563. pKeyValues->SetInt( "kills", g_TF_PR->GetPlayerScore( playerIndex ) );
  564. pKeyValues->SetInt( "damage", g_TF_PR->GetDamage( playerIndex ) );
  565. pKeyValues->SetInt( "healing", g_TF_PR->GetHealing( playerIndex ) );
  566. int nSupport = g_TF_PR->GetDamageAssist( playerIndex ) +
  567. g_TF_PR->GetHealingAssist( playerIndex ) +
  568. g_TF_PR->GetDamageBlocked( playerIndex ) +
  569. ( g_TF_PR->GetBonusPoints( playerIndex ) * 25 );
  570. pKeyValues->SetInt( "support", nSupport );
  571. matchsummary_columns_t eParticleColumn = MS_COLUMN_INVALID;
  572. StatMedal_t eParticleMedal = StatMedal_None;
  573. if ( m_iCurrentState == MS_STATE_GOLD_MEDALS )
  574. {
  575. // we can add the bronze and silver since we've already processed those
  576. InternalAddMedalKeyValues( playerIndex, StatMedal_Bronze, pKeyValues );
  577. InternalAddMedalKeyValues( playerIndex, StatMedal_Silver, pKeyValues );
  578. eParticleColumn = InternalAddMedalKeyValues( playerIndex, StatMedal_Gold, pKeyValues, m_nMedalsRevealed );
  579. eParticleMedal = StatMedal_Gold;
  580. }
  581. else if ( m_iCurrentState == MS_STATE_SILVER_MEDALS )
  582. {
  583. // we can add the bronze since we've already processed those
  584. InternalAddMedalKeyValues( playerIndex, StatMedal_Bronze, pKeyValues );
  585. eParticleColumn = InternalAddMedalKeyValues( playerIndex, StatMedal_Silver, pKeyValues, m_nMedalsRevealed );
  586. eParticleMedal = StatMedal_Silver;
  587. }
  588. else if ( m_iCurrentState == MS_STATE_BRONZE_MEDALS )
  589. {
  590. eParticleColumn = InternalAddMedalKeyValues( playerIndex, StatMedal_Bronze, pKeyValues, m_nMedalsRevealed );
  591. eParticleMedal = StatMedal_Bronze;
  592. }
  593. UpdatePlayerAvatar( playerIndex, pKeyValues );
  594. int itemID = pPlayerList->AddItem( 0, pKeyValues );
  595. pPlayerList->SetItemFgColor( itemID, g_PR->GetTeamColor( nTeam ) );
  596. // Green background for rematch folks
  597. pPlayerList->SetItemBgColor( itemID, Color( 80, 80, 80, 80 ) );
  598. pPlayerList->SetItemBgHorizFillInset( itemID, pPlayerList->m_iHorizFillInset );
  599. pPlayerList->SetItemFont( itemID, m_hFont );
  600. // This highlights the local player in grey
  601. if ( playerIndex == GetLocalPlayerIndex() )
  602. {
  603. pPlayerList->SetSelectedItem( itemID );
  604. }
  605. // loop through and setup our medal color overrides
  606. KeyValues *pKey = pKeyValues->FindKey( "score_medal" );
  607. if ( pKey && pKey->GetInt() )
  608. {
  609. int nMedal = pKey->GetInt();
  610. pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_SCORE, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal );
  611. }
  612. pKey = pKeyValues->FindKey( "kills_medal" );
  613. if ( pKey && pKey->GetInt() )
  614. {
  615. int nMedal = pKey->GetInt();
  616. pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_KILLS, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal );
  617. }
  618. pKey = pKeyValues->FindKey( "damage_medal" );
  619. if ( pKey && pKey->GetInt() )
  620. {
  621. int nMedal = pKey->GetInt();
  622. pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_DAMAGE, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal );
  623. }
  624. pKey = pKeyValues->FindKey( "healing_medal" );
  625. if ( pKey && pKey->GetInt() )
  626. {
  627. int nMedal = pKey->GetInt();
  628. pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_HEALING, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal );
  629. }
  630. pKey = pKeyValues->FindKey( "support_medal" );
  631. if ( pKey && pKey->GetInt() )
  632. {
  633. int nMedal = pKey->GetInt();
  634. pPlayerList->SetColorOverrideForCell( 0, itemID, MS_COLUMN_SUPPORT, ( nMedal == (int)StatMedal_Bronze ) ? m_clrBronzeMedal : ( nMedal == (int)StatMedal_Silver ) ? m_clrSilverMedal : m_clrGoldMedal );
  635. }
  636. pKeyValues->deleteThis();
  637. if ( ( eParticleColumn > MS_COLUMN_INVALID ) && ( eParticleMedal > StatMedal_None ) )
  638. {
  639. int nPanelXPos, nPanelYPos, nPanelWide, nPanelTall;
  640. pPlayerList->GetMaxCellBounds( itemID, eParticleColumn, nPanelXPos, nPanelYPos, nPanelWide, nPanelTall );
  641. FireMedalEffects( pPlayerList, nPanelXPos, nPanelYPos, nPanelWide, nPanelTall, eParticleMedal );
  642. }
  643. }
  644. }
  645. m_pPlayerListRed->SetSectionFgColor( 0, g_PR->GetTeamColor( TF_TEAM_RED ) );
  646. m_pPlayerListBlue->SetSectionFgColor( 0, g_PR->GetTeamColor( TF_TEAM_BLUE ) );
  647. // force the lists to PerformLayout() now so we can update our rank images after we return
  648. m_pPlayerListRed->InvalidateLayout( true );
  649. m_pPlayerListBlue->InvalidateLayout( true );
  650. }
  651. //-----------------------------------------------------------------------------
  652. // Purpose:
  653. //-----------------------------------------------------------------------------
  654. void CTFMatchSummary::FireMedalEffects( Panel *pPanel, int nPanelXPos, int nPanelYPos, int nPanelWide, int nPanelTall, StatMedal_t eParticleMedal )
  655. {
  656. if ( !pPanel )
  657. return;
  658. int nPanelCenterX = nPanelXPos + ( nPanelWide / 2 );
  659. int nPanelCenterY = nPanelYPos + ( nPanelTall / 2 );
  660. int iItemAbsX, iItemAbsY;
  661. vgui::ipanel()->GetAbsPos( pPanel->GetParent()->GetVPanel(), iItemAbsX, iItemAbsY );
  662. int x = iItemAbsX + nPanelCenterX;
  663. int y = iItemAbsY + nPanelCenterY;
  664. const char *pszSoundEffect = "MatchMaking.None";
  665. const char *pszParticleEffect = "mvm_loot_smoke";
  666. if ( eParticleMedal == StatMedal_Bronze )
  667. {
  668. pszSoundEffect = "MatchMaking.Bronze";
  669. pszParticleEffect = "mvm_loot_explosion";
  670. }
  671. else if ( eParticleMedal == StatMedal_Silver )
  672. {
  673. pszSoundEffect = "MatchMaking.Silver";
  674. pszParticleEffect = "mvm_loot_explosion";
  675. }
  676. else if ( eParticleMedal == StatMedal_Gold )
  677. {
  678. pszSoundEffect = "MatchMaking.Gold";
  679. pszParticleEffect = "mvm_pow_gold_seq_firework_mid";
  680. }
  681. m_pParticlePanel->FireParticleEffect( pszParticleEffect, x, y, 0.2f, false );
  682. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  683. if ( pLocalPlayer )
  684. {
  685. pLocalPlayer->EmitSound( pszSoundEffect );
  686. }
  687. }
  688. //-----------------------------------------------------------------------------
  689. // Purpose:
  690. //-----------------------------------------------------------------------------
  691. void CTFMatchSummary::UpdateBadgePanels( CUtlVector<CTFBadgePanel*> &pBadgePanels, TFSectionedListPanel *pPlayerList )
  692. {
  693. if ( !TFGameRules() )
  694. return;
  695. const IMatchGroupDescription *pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
  696. const IProgressionDesc *pProgressionDesc = pMatchDesc ? pMatchDesc->m_pProgressionDesc : NULL;
  697. if ( pProgressionDesc )
  698. {
  699. if ( pPlayerList )
  700. {
  701. int iNumPanels = 0;
  702. int parentTall = pPlayerList->GetTall();
  703. CTFBadgePanel *pPanel = NULL;
  704. for ( int i = 0; i < pPlayerList->GetItemCount(); i++ )
  705. {
  706. KeyValues *pKeyValues = pPlayerList->GetItemData( i );
  707. if ( !pKeyValues )
  708. continue;
  709. const CSteamID steamID = GetSteamIDForPlayerIndex( pKeyValues->GetInt( "playerIndex" ) );
  710. #ifdef STAGING_ONLY
  711. if ( steamID.IsValid() || tf_test_match_summary.GetBool() )
  712. #else
  713. if ( steamID.IsValid() )
  714. #endif // STAGING_ONLY
  715. {
  716. if ( iNumPanels >= pBadgePanels.Count() )
  717. {
  718. pPanel = new CTFBadgePanel( m_pMainStatsContainer, "BadgePanel" );
  719. pPanel->MakeReadyForUse();
  720. pPanel->SetVisible( true );
  721. pPanel->SetZPos( 9999 );
  722. pBadgePanels.AddToTail( pPanel );
  723. }
  724. else
  725. {
  726. pPanel = pBadgePanels[iNumPanels];
  727. }
  728. int x, y, wide, tall;
  729. pPlayerList->GetMaxCellBounds( i, 0, x, y, wide, tall );
  730. if ( y + tall > parentTall )
  731. continue;
  732. if ( !pPanel->IsVisible() )
  733. {
  734. pPanel->SetVisible( true );
  735. }
  736. int xParent = 0, yParent = 0;
  737. if ( pPlayerList->GetParent() )
  738. {
  739. pPlayerList->GetParent()->GetPos( xParent, yParent );
  740. }
  741. int xGrandParent = 0, yGrandParent = 0;
  742. if ( pPlayerList->GetParent()->GetParent() )
  743. {
  744. pPlayerList->GetParent()->GetParent()->GetPos( xGrandParent, yGrandParent );
  745. }
  746. int nPanelXPos, nPanelYPos, nPanelWide, nPanelTall;
  747. pPanel->GetBounds( nPanelXPos, nPanelYPos, nPanelWide, nPanelTall );
  748. if ( ( nPanelXPos != xGrandParent + xParent + x )
  749. || ( nPanelYPos != yGrandParent + yParent + y )
  750. || ( nPanelWide != wide )
  751. || ( nPanelTall != tall ) )
  752. {
  753. pPanel->SetBounds( xGrandParent + xParent + x, yGrandParent + yParent + y, wide, tall );
  754. pPanel->InvalidateLayout( true, true );
  755. }
  756. pPanel->SetupBadge( pProgressionDesc, steamID );
  757. iNumPanels++;
  758. }
  759. }
  760. // hide any unused images
  761. for ( int i = iNumPanels; i < pBadgePanels.Count(); i++ )
  762. {
  763. if ( pBadgePanels[i]->IsVisible() )
  764. {
  765. pBadgePanels[i]->SetVisible( false );
  766. }
  767. }
  768. }
  769. }
  770. }
  771. //-----------------------------------------------------------------------------
  772. // Purpose:
  773. //-----------------------------------------------------------------------------
  774. void CTFMatchSummary::UpdatePlayerAvatar( int playerIndex, KeyValues *kv )
  775. {
  776. if ( !g_PR )
  777. return;
  778. uint32 iAccountID = g_PR->GetAccountID( playerIndex );
  779. if ( iAccountID > 0 )
  780. {
  781. // Update their avatar
  782. if ( kv && steamapicontext->SteamFriends() && steamapicontext->SteamUtils() )
  783. {
  784. CSteamID steamIDForPlayer( iAccountID, 1, GetUniverse(), k_EAccountTypeIndividual );
  785. // See if we already have that avatar in our list
  786. int iMapIndex = m_mapAvatarsToImageList.Find( steamIDForPlayer );
  787. int iImageIndex;
  788. if ( iMapIndex == m_mapAvatarsToImageList.InvalidIndex() )
  789. {
  790. CAvatarImage *pImage = new CAvatarImage();
  791. pImage->SetAvatarSteamID( steamIDForPlayer );
  792. pImage->SetAvatarSize( 32, 32 ); // Deliberately non scaling
  793. iImageIndex = m_pImageList->AddImage( pImage );
  794. m_mapAvatarsToImageList.Insert( steamIDForPlayer, iImageIndex );
  795. }
  796. else
  797. {
  798. iImageIndex = m_mapAvatarsToImageList[iMapIndex];
  799. }
  800. kv->SetInt( "avatar", iImageIndex );
  801. CAvatarImage *pAvIm = (CAvatarImage *)m_pImageList->GetImage( iImageIndex );
  802. pAvIm->UpdateFriendStatus();
  803. }
  804. }
  805. }
  806. //-----------------------------------------------------------------------------
  807. // Purpose: Event handler
  808. //-----------------------------------------------------------------------------
  809. void CTFMatchSummary::FireGameEvent( IGameEvent *event )
  810. {
  811. const char *type = event->GetName();
  812. if ( FStrEq( type, "competitive_victory" ) )
  813. {
  814. Q_memset( m_SkillRatings, 0, sizeof( m_SkillRatings ) );
  815. Leaderboards_LadderRefresh();
  816. }
  817. else if ( FStrEq( type, "competitive_stats_update" ) )
  818. {
  819. int iIndex = event->GetInt( "index" );
  820. Assert( iIndex > 0 && iIndex <= MAX_PLAYERS );
  821. if ( iIndex > 0 && iIndex <= MAX_PLAYERS )
  822. {
  823. m_SkillRatings[iIndex].unRating = event->GetInt( "rating" ); // Rank
  824. m_SkillRatings[iIndex].nDelta = event->GetInt( "delta" );
  825. m_SkillRatings[iIndex].nScoreRank = event->GetInt( "score_rank" ); // Medal for Score (Gold, Silver, Bronze, or nothing)
  826. m_SkillRatings[iIndex].nKillsRank = event->GetInt( "kills_rank" ); // Medal for Kills
  827. m_SkillRatings[iIndex].nDamageRank = event->GetInt( "damage_rank" ); // Medal for Damage
  828. m_SkillRatings[iIndex].nHealingRank = event->GetInt( "healing_rank" ); // Medal for Healing
  829. m_SkillRatings[iIndex].nSupportRank = event->GetInt( "support_rank" ); // Medal for Rank
  830. RecalculateMedalCounts();
  831. }
  832. }
  833. else if ( FStrEq( type, "player_abandoned_match" ) )
  834. {
  835. m_bPlayerAbandoned = true;
  836. }
  837. else if ( FStrEq( type, "client_disconnect" ) )
  838. {
  839. m_bPlayerAbandoned = false;
  840. }
  841. else if ( FStrEq( type, "show_match_summary" ) )
  842. {
  843. SetVisible( true );
  844. if ( m_pPlayerListRedParent->GetParent() )
  845. {
  846. int nRedBadgeOffset = m_pPlayerListRedParent->GetParent()->GetXPos();
  847. FOR_EACH_VEC( m_pRedBadgePanels, i )
  848. {
  849. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedBadgePanels[i], "xpos", m_pRedBadgePanels[i]->GetXPos() - nRedBadgeOffset, 0.25, 0.25, vgui::AnimationController::INTERPOLATOR_ACCEL );
  850. }
  851. }
  852. if ( m_pPlayerListBlueParent->GetParent() )
  853. {
  854. int nBlueBadgeOffset = m_pPlayerListBlueParent->GetParent()->GetXPos();
  855. FOR_EACH_VEC( m_pBlueBadgePanels, i )
  856. {
  857. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueBadgePanels[i], "xpos", m_pBlueBadgePanels[i]->GetXPos() - nBlueBadgeOffset, 0.25, 0.25, vgui::AnimationController::INTERPOLATOR_ACCEL );
  858. }
  859. }
  860. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pTeamScoresPanel, "HudMatchSummary_SlideInPanels", false );
  861. }
  862. }
  863. //-----------------------------------------------------------------------------
  864. // Purpose:
  865. //-----------------------------------------------------------------------------
  866. void CTFMatchSummary::InternalUpdateMedalCountForType( int iTeam, StatMedal_t eMedal )
  867. {
  868. switch ( eMedal )
  869. {
  870. case StatMedal_Bronze:
  871. if ( iTeam == TF_TEAM_RED )
  872. {
  873. m_nMedalsToAward_Bronze_Red++;
  874. }
  875. else if ( iTeam == TF_TEAM_BLUE )
  876. {
  877. m_nMedalsToAward_Bronze_Blue++;
  878. }
  879. break;
  880. case StatMedal_Silver:
  881. if ( iTeam == TF_TEAM_RED )
  882. {
  883. m_nMedalsToAward_Silver_Red++;
  884. }
  885. else if ( iTeam == TF_TEAM_BLUE )
  886. {
  887. m_nMedalsToAward_Silver_Blue++;
  888. }
  889. break;
  890. case StatMedal_Gold:
  891. if ( iTeam == TF_TEAM_RED )
  892. {
  893. m_nMedalsToAward_Gold_Red++;
  894. }
  895. else if ( iTeam == TF_TEAM_BLUE )
  896. {
  897. m_nMedalsToAward_Gold_Blue++;
  898. }
  899. break;
  900. case StatMedal_None:
  901. default:
  902. break;
  903. }
  904. }
  905. //-----------------------------------------------------------------------------
  906. // Purpose:
  907. //-----------------------------------------------------------------------------
  908. void CTFMatchSummary::RecalculateMedalCounts()
  909. {
  910. m_nMedalsToAward_Bronze_Blue = 0;
  911. m_nMedalsToAward_Silver_Blue = 0;
  912. m_nMedalsToAward_Gold_Blue = 0;
  913. m_nMedalsToAward_Bronze_Red = 0;
  914. m_nMedalsToAward_Silver_Red = 0;
  915. m_nMedalsToAward_Gold_Red = 0;
  916. if ( !g_PR )
  917. return;
  918. for ( int playerIndex = 1; playerIndex <= MAX_PLAYERS; playerIndex++ )
  919. {
  920. if ( g_PR->IsConnected( playerIndex ) || g_PR->IsValid( playerIndex ) )
  921. {
  922. int nTeam = g_PR->GetTeam( playerIndex );
  923. if ( nTeam >= FIRST_GAME_TEAM )
  924. {
  925. InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nScoreRank ) );
  926. InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nKillsRank ) );
  927. InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nDamageRank ) );
  928. InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nHealingRank ) );
  929. InternalUpdateMedalCountForType( nTeam, (StatMedal_t)( m_SkillRatings[playerIndex].nSupportRank ) );
  930. }
  931. }
  932. }
  933. }
  934. //-----------------------------------------------------------------------------
  935. // Purpose:
  936. //-----------------------------------------------------------------------------
  937. void CTFMatchSummary::OnTick()
  938. {
  939. BaseClass::OnTick();
  940. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  941. if ( !IsVisible() || !pLocalPlayer )
  942. return;
  943. const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
  944. if ( !pMatchDesc )
  945. return;
  946. if ( pMatchDesc->m_params.m_bAllowDrawingAtMatchSummary
  947. && m_pDrawingPanel
  948. && ( m_flDrawingPanelTime > 0 )
  949. && ( m_flDrawingPanelTime < gpGlobals->curtime ) )
  950. {
  951. m_pDrawingPanel->SetVisible( true );
  952. m_pDrawingPanel->SetKeyBoardInputEnabled( false );
  953. m_flDrawingPanelTime = -1.f;
  954. if ( pLocalPlayer )
  955. {
  956. pLocalPlayer->EmitSound( "Announcer.SummaryScreenWinners" );
  957. }
  958. }
  959. int nMedalsToAward_Bronze_Total = m_nMedalsToAward_Bronze_Blue + m_nMedalsToAward_Bronze_Red;
  960. int nMedalsToAward_Silver_Total = m_nMedalsToAward_Silver_Blue + m_nMedalsToAward_Silver_Red;
  961. int nMedalsToAward_Gold_Total = m_nMedalsToAward_Gold_Blue + m_nMedalsToAward_Gold_Red;
  962. bool bShowPerformanceMedals = ShowPerformanceMedals();
  963. bool bMapHasMatchSummaryStage = ( TFGameRules() && TFGameRules()->MapHasMatchSummaryStage() );
  964. #ifdef STAGING_ONLY
  965. bool bUseMatchSummaryStage = tf_test_match_summary.GetBool() || ( pMatchDesc && pMatchDesc->m_params.m_bUseMatchSummaryStage );
  966. #else
  967. bool bUseMatchSummaryStage = ( pMatchDesc && pMatchDesc->m_params.m_bUseMatchSummaryStage );
  968. #endif
  969. switch ( m_iCurrentState )
  970. {
  971. case MS_STATE_INITIAL:
  972. {
  973. bool bUseStage = ( bMapHasMatchSummaryStage && bUseMatchSummaryStage );
  974. if ( GTFGCClientSystem()->GetSurveyRequest().has_match_id() )
  975. {
  976. Panel* pSurveyPanel = CreateSurveyQuestionPanel( this, GTFGCClientSystem()->GetSurveyRequest() );
  977. pSurveyPanel->MakePopup();
  978. }
  979. m_iCurrentState = MS_STATE_DRAWING;
  980. m_flNextActionTime = bUseStage ? gpGlobals->curtime + MS_STATE_TRANSITION_TO_STATS : gpGlobals->curtime + 2.f;
  981. m_bXPShown = false;
  982. if ( !bUseStage )
  983. {
  984. // if we're not using the stage we'll just show the doors and then skip to stats with no drawing
  985. if ( m_pDrawingPanel )
  986. {
  987. m_pDrawingPanel->SetVisible( false );
  988. }
  989. }
  990. break;
  991. }
  992. case MS_STATE_DRAWING:
  993. {
  994. if ( gpGlobals->curtime > m_flNextActionTime )
  995. {
  996. if ( m_pDrawingPanel )
  997. {
  998. m_pDrawingPanel->SetVisible( false );
  999. }
  1000. if ( m_pStatsBgPanel )
  1001. {
  1002. m_pStatsBgPanel->SetVisible( true );
  1003. }
  1004. if ( m_pStatsLabelPanel )
  1005. {
  1006. m_pStatsLabelPanel->SetVisible( true );
  1007. }
  1008. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pStatsLabelPanel, "ypos", m_bLargeMatchGroup ? m_iAnimStatsLabelPanel12v12YPos : m_iAnimStatsLabelPanel6v6YPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1009. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueMedalsPanel, "ypos", m_iAnimBlueMedalsYPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1010. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedMedalsPanel, "ypos", m_iAnimRedMedalsYPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1011. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamName, "ypos", m_bLargeMatchGroup ? m_iAnimBlueTeamLabel12v12YPos : m_iAnimBlueTeamLabel6v6YPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1012. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamName, "ypos", m_bLargeMatchGroup ? m_iAnimRedTeamLabel12v12YPos : m_iAnimRedTeamLabel6v6YPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1013. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pPlayerListBlueParent, "wide", m_iAnimBluePlayerListParent, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1014. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamScore, "wide", m_iAnimBlueTeamScore, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1015. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamScoreDropshadow, "wide", m_iAnimBlueTeamScoreDropshadow, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1016. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamScoreBG, "wide", m_iAnimBlueTeamScoreBG, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1017. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBluePlayerListBG, "wide", m_iAnimBluePlayerListBG, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1018. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScore, "wide", m_iAnimRedTeamScoreWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1019. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScore, "xpos", m_iAnimRedTeamScoreXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1020. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScoreDropshadow, "wide", m_iAnimRedTeamScoreDropshadowWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1021. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScoreDropshadow, "xpos", m_iAnimRedTeamScoreDropshadowXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1022. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScoreBG, "wide", m_iAnimRedTeamScoreBGWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1023. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamScoreBG, "xpos", m_iAnimRedTeamScoreBGXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1024. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pPlayerListRedParent, "wide", m_iAnimRedPlayerListParentWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1025. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pPlayerListRedParent, "xpos", m_iAnimRedPlayerListParentXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1026. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedPlayerListBG, "wide", m_iAnimRedPlayerListBGWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1027. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedPlayerListBG, "xpos", m_iAnimRedPlayerListBGXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1028. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamWinner, "wide", m_iAnimBlueTeamScore, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1029. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pBlueTeamWinnerDropshadow, "wide", m_iAnimBlueTeamScoreDropshadow, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1030. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamWinner, "wide", m_iAnimRedTeamScoreWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1031. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamWinner, "xpos", m_iAnimRedTeamScoreXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1032. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamWinnerDropshadow, "wide", m_iAnimRedTeamScoreDropshadowWide, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1033. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedTeamWinnerDropshadow, "xpos", m_iAnimRedTeamScoreDropshadowXPos, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1034. int nRedBadgeOffset = m_pPlayerListRedParent->GetXPos() - m_iAnimRedPlayerListParentXPos;
  1035. FOR_EACH_VEC( m_pRedBadgePanels, i )
  1036. {
  1037. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( m_pRedBadgePanels[i], "xpos", m_pRedBadgePanels[i]->GetXPos() - nRedBadgeOffset, 0.0, 0.1, vgui::AnimationController::INTERPOLATOR_ACCEL );
  1038. }
  1039. float flDelay = MS_STATE_TRANSITION_TO_MEDALS;
  1040. if ( pLocalPlayer )
  1041. {
  1042. if ( bShowPerformanceMedals )
  1043. {
  1044. const char *pszEntryName = UTIL_GetRandomSoundFromEntry( "Announcer.CompSummaryScreenOutlierQuestion" );
  1045. if ( pszEntryName && pszEntryName[0] )
  1046. {
  1047. flDelay = enginesound->GetSoundDuration( pszEntryName );
  1048. pLocalPlayer->EmitSound( pszEntryName );
  1049. }
  1050. }
  1051. pLocalPlayer->EmitSound( "MatchMaking.ScoreboardPanelSlide" );
  1052. }
  1053. m_iCurrentState = MS_STATE_STATS;
  1054. m_flNextActionTime = gpGlobals->curtime + flDelay;
  1055. m_pRedMedalsPanel->SetVisible( bShowPerformanceMedals );
  1056. m_pBlueMedalsPanel->SetVisible( bShowPerformanceMedals );
  1057. m_pStatsAndMedals->SetText( bShowPerformanceMedals ? g_pVGuiLocalize->Find( "#TF_CompSummary_StatsAndMedals" ) : L"" );
  1058. m_pStatsAndMedalsShadow->SetText( bShowPerformanceMedals ? g_pVGuiLocalize->Find( "#TF_CompSummary_StatsAndMedals" ) : L"" );
  1059. }
  1060. break;
  1061. }
  1062. case MS_STATE_STATS:
  1063. {
  1064. if ( gpGlobals->curtime > m_flNextActionTime )
  1065. {
  1066. m_iCurrentState = bShowPerformanceMedals ? MS_STATE_BRONZE_MEDALS : MS_STATE_FINAL;
  1067. m_nMedalsRevealed = 0;
  1068. m_flNextActionTime = -1;
  1069. }
  1070. break;
  1071. }
  1072. case MS_STATE_BRONZE_MEDALS:
  1073. {
  1074. if ( gpGlobals->curtime > m_flNextActionTime )
  1075. {
  1076. if ( !m_bBlueBronzeValueRevealed && !m_bRedBronzeValueRevealed )
  1077. {
  1078. m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_bronze", m_nMedalsToAward_Bronze_Blue );
  1079. m_bBlueBronzeValueRevealed = true;
  1080. Panel *pChild = m_pBlueMedalsPanel->FindChildByName( "BlueBronzeMedalValue" );
  1081. if ( pChild )
  1082. {
  1083. int nXPos, nYPos, nWide, nTall;
  1084. pChild->GetBounds( nXPos, nYPos, nWide, nTall );
  1085. FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Bronze_Blue > 0 ) ? StatMedal_Bronze : StatMedal_None );
  1086. }
  1087. m_pRedMedalsPanel->SetDialogVariable( "redteammedals_bronze", m_nMedalsToAward_Bronze_Red );
  1088. m_bRedBronzeValueRevealed = true;
  1089. pChild = m_pRedMedalsPanel->FindChildByName( "RedBronzeMedalValue" );
  1090. if ( pChild )
  1091. {
  1092. int nXPos, nYPos, nWide, nTall;
  1093. pChild->GetBounds( nXPos, nYPos, nWide, nTall );
  1094. FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Bronze_Red > 0 ) ? StatMedal_Bronze : StatMedal_None );
  1095. }
  1096. m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES;
  1097. }
  1098. else
  1099. {
  1100. if ( ( nMedalsToAward_Bronze_Total > 0 ) && ( m_nMedalsRevealed < nMedalsToAward_Bronze_Total ) )
  1101. {
  1102. Update();
  1103. m_nMedalsRevealed++;
  1104. m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS;
  1105. }
  1106. else
  1107. {
  1108. m_iCurrentState = MS_STATE_SILVER_MEDALS;
  1109. m_nMedalsRevealed = 0;
  1110. m_flNextActionTime = MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES;
  1111. }
  1112. }
  1113. }
  1114. break;
  1115. }
  1116. case MS_STATE_SILVER_MEDALS:
  1117. {
  1118. if ( gpGlobals->curtime > m_flNextActionTime )
  1119. {
  1120. if ( !m_bBlueSilverValueRevealed && !m_bRedSilverValueRevealed )
  1121. {
  1122. m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_silver", m_nMedalsToAward_Silver_Blue );
  1123. m_bBlueSilverValueRevealed = true;
  1124. Panel *pChild = m_pBlueMedalsPanel->FindChildByName( "BlueSilverMedalValue" );
  1125. if ( pChild )
  1126. {
  1127. int nXPos, nYPos, nWide, nTall;
  1128. pChild->GetBounds( nXPos, nYPos, nWide, nTall );
  1129. FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Silver_Blue > 0 ) ? StatMedal_Silver : StatMedal_None );
  1130. }
  1131. m_pRedMedalsPanel->SetDialogVariable( "redteammedals_silver", m_nMedalsToAward_Silver_Red );
  1132. m_bRedSilverValueRevealed = true;
  1133. pChild = m_pRedMedalsPanel->FindChildByName( "RedSilverMedalValue" );
  1134. if ( pChild )
  1135. {
  1136. int nXPos, nYPos, nWide, nTall;
  1137. pChild->GetBounds( nXPos, nYPos, nWide, nTall );
  1138. FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Silver_Red > 0 ) ? StatMedal_Silver : StatMedal_None );
  1139. }
  1140. m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES;
  1141. }
  1142. else
  1143. {
  1144. if ( ( nMedalsToAward_Silver_Total > 0 ) && ( m_nMedalsRevealed < nMedalsToAward_Silver_Total ) )
  1145. {
  1146. Update();
  1147. m_nMedalsRevealed++;
  1148. m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS;
  1149. }
  1150. else
  1151. {
  1152. m_iCurrentState = MS_STATE_GOLD_MEDALS;
  1153. m_nMedalsRevealed = 0;
  1154. m_flNextActionTime = MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES;
  1155. }
  1156. }
  1157. }
  1158. break;
  1159. }
  1160. case MS_STATE_GOLD_MEDALS:
  1161. {
  1162. if ( gpGlobals->curtime > m_flNextActionTime )
  1163. {
  1164. if ( !m_bBlueGoldValueRevealed && !m_bRedGoldValueRevealed )
  1165. {
  1166. m_pBlueMedalsPanel->SetDialogVariable( "blueteammedals_gold", m_nMedalsToAward_Gold_Blue );
  1167. m_bBlueGoldValueRevealed = true;
  1168. Panel *pChild = m_pBlueMedalsPanel->FindChildByName( "BlueGoldMedalValue" );
  1169. if ( pChild )
  1170. {
  1171. int nXPos, nYPos, nWide, nTall;
  1172. pChild->GetBounds( nXPos, nYPos, nWide, nTall );
  1173. FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Gold_Blue > 0 ) ? StatMedal_Gold : StatMedal_None );
  1174. }
  1175. m_pRedMedalsPanel->SetDialogVariable( "redteammedals_gold", m_nMedalsToAward_Gold_Red );
  1176. m_bRedGoldValueRevealed = true;
  1177. pChild = m_pRedMedalsPanel->FindChildByName( "RedGoldMedalValue" );
  1178. if ( pChild )
  1179. {
  1180. int nXPos, nYPos, nWide, nTall;
  1181. pChild->GetBounds( nXPos, nYPos, nWide, nTall );
  1182. FireMedalEffects( pChild, nXPos, nYPos, nWide, nTall, ( m_nMedalsToAward_Gold_Red > 0 ) ? StatMedal_Gold : StatMedal_None );
  1183. }
  1184. m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS_CATEGORIES;
  1185. }
  1186. else
  1187. {
  1188. if ( ( nMedalsToAward_Gold_Total > 0 ) && ( m_nMedalsRevealed < nMedalsToAward_Gold_Total ) )
  1189. {
  1190. Update();
  1191. m_nMedalsRevealed++;
  1192. m_flNextActionTime = gpGlobals->curtime + MS_STATE_TIME_BETWEEN_MEDALS;
  1193. }
  1194. else
  1195. {
  1196. m_iCurrentState = MS_STATE_FINAL;
  1197. m_nMedalsRevealed = 0;
  1198. m_flNextActionTime = -1;
  1199. if ( pLocalPlayer )
  1200. {
  1201. const char *pszSoundScriptEntry = "Announcer.CompSummaryScreenOutlierNo";
  1202. if ( nMedalsToAward_Bronze_Total || nMedalsToAward_Silver_Total || nMedalsToAward_Gold_Total )
  1203. {
  1204. pszSoundScriptEntry = "Announcer.CompSummaryScreenOutlierYes";
  1205. }
  1206. const char *pszSoundName = UTIL_GetRandomSoundFromEntry( pszSoundScriptEntry );
  1207. m_flMedalSoundTime = gpGlobals->curtime + enginesound->GetSoundDuration( pszSoundName ) + 0.5f;
  1208. pLocalPlayer->EmitSound( pszSoundName );
  1209. IGameEvent *event = gameeventmanager->CreateEvent( "ds_screenshot" );
  1210. if ( event )
  1211. {
  1212. event->SetFloat( "delay", 0.5f );
  1213. gameeventmanager->FireEventClientSide( event );
  1214. }
  1215. }
  1216. }
  1217. }
  1218. }
  1219. break;
  1220. }
  1221. default:
  1222. case MS_STATE_FINAL:
  1223. {
  1224. bool bMedalSoundTimeComplete = ( m_flMedalSoundTime > 0 ) && ( m_flMedalSoundTime < gpGlobals->curtime );
  1225. if ( !m_bXPShown /*&& ( !bShowMedals || bMedalSoundTimeComplete ) */)
  1226. {
  1227. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "CompetitiveGame_ShowPvPRankPanel", false );
  1228. m_bXPShown = true;
  1229. }
  1230. if ( bShowPerformanceMedals )
  1231. {
  1232. if ( bMedalSoundTimeComplete )
  1233. {
  1234. m_flMedalSoundTime = -1.f;
  1235. int iLocalPlayerIndex = GetLocalPlayerIndex();
  1236. if ( ( m_SkillRatings[iLocalPlayerIndex].nScoreRank != StatMedal_None ) ||
  1237. ( m_SkillRatings[iLocalPlayerIndex].nKillsRank != StatMedal_None ) ||
  1238. ( m_SkillRatings[iLocalPlayerIndex].nDamageRank != StatMedal_None ) ||
  1239. ( m_SkillRatings[iLocalPlayerIndex].nHealingRank != StatMedal_None ) ||
  1240. ( m_SkillRatings[iLocalPlayerIndex].nSupportRank != StatMedal_None ) )
  1241. {
  1242. if ( pLocalPlayer )
  1243. {
  1244. int iClass = RandomInt( TF_CLASS_SCOUT, TF_CLASS_ENGINEER );
  1245. if ( pLocalPlayer->GetPlayerClass() && ( pLocalPlayer->GetPlayerClass()->GetClassIndex() > TF_CLASS_UNDEFINED ) )
  1246. {
  1247. iClass = pLocalPlayer->GetPlayerClass()->GetClassIndex();
  1248. }
  1249. pLocalPlayer->EmitSound( VarArgs( "%s.CompSummaryScreenOutlier", g_aPlayerClassNames_NonLocalized[iClass] ) );
  1250. }
  1251. }
  1252. }
  1253. }
  1254. break;
  1255. }
  1256. }
  1257. }
  1258. //-----------------------------------------------------------------------------
  1259. // Purpose:
  1260. //-----------------------------------------------------------------------------
  1261. void CTFMatchSummary::LevelInit( void )
  1262. {
  1263. SetVisible( false );
  1264. }
  1265. void CTFMatchSummary::LevelShutdown( void )
  1266. {
  1267. SetVisible( false );
  1268. }
  1269. //-----------------------------------------------------------------------------
  1270. // Purpose:
  1271. //-----------------------------------------------------------------------------
  1272. bool CTFMatchSummary::ShowPerformanceMedals( void )
  1273. {
  1274. bool bDistributePerformanceMedals = false;
  1275. const IMatchGroupDescription* pMatchDesc = GetMatchGroupDescription( TFGameRules()->GetCurrentMatchGroup() );
  1276. if ( pMatchDesc )
  1277. {
  1278. bDistributePerformanceMedals = pMatchDesc->m_params.m_bDistributePerformanceMedals;
  1279. }
  1280. return ( bDistributePerformanceMedals && !m_bPlayerAbandoned );
  1281. }