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.

343 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "cbase.h"
  8. #include "tf_duckleaderboard.h"
  9. #ifdef CLIENT_DLL
  10. #include "vgui_avatarimage.h"
  11. #include "tf_item_inventory.h"
  12. #endif
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include <tier0/memdbgon.h>
  15. //-------------------------------
  16. const char *g_szDuckLeaderboardNames[] =
  17. {
  18. "TF_DUCK_SCORING_OVERALL_RATING", // TF_DUCK_SCORING_OVERALL_RATING
  19. "TF_DUCK_SCORING_PERSONAL_GENERATION", // TF_DUCK_SCORING_PERSONAL_GENERATION
  20. "TF_DUCK_SCORING_PERSONAL_PICKUP_OFFENSE", // TF_DUCK_SCORING_PERSONAL_PICKUP_OFFENSE
  21. "TF_DUCK_SCORING_PERSONAL_PICKUP_DEFENDED", // TF_DUCK_SCORING_PERSONAL_PICKUP_DEFENDED
  22. "TF_DUCK_SCORING_PERSONAL_PICKUP_OBJECTIVE", // TF_DUCK_SCORING_PERSONAL_PICKUP_OBJECTIVE
  23. "TF_DUCK_SCORING_TEAM_PICKUP_MY_DUCKS", // TF_DUCK_SCORING_TEAM_PICKUP_MY_DUCKS
  24. "TF_DUCK_SCORING_PERSONAL_BONUS_PICKUP", // TF_DUCK_SCORING_PERSONAL_BONUS_PICKUP
  25. };
  26. COMPILE_TIME_ASSERT( ARRAYSIZE( g_szDuckLeaderboardNames ) == DUCK_NUM_LEADERBOARDS );
  27. #ifdef CLIENT_DLL
  28. //-----------------------------------------------------------------------------
  29. CDucksLeaderboard::CDucksLeaderboard( Panel *parent, const char *panelName, const char *pszDuckLeaderboardname )
  30. : CTFLeaderboardPanel( parent, panelName )
  31. , m_pszDuckLeaderboardName( pszDuckLeaderboardname )
  32. , m_pToolTip( NULL )
  33. {
  34. m_pToolTip = new CTFTextToolTip( this );
  35. m_pToolTipEmbeddedPanel = new vgui::EditablePanel( this, "TooltipPanel" );
  36. m_pToolTipEmbeddedPanel->SetKeyBoardInputEnabled( false );
  37. m_pToolTipEmbeddedPanel->SetMouseInputEnabled( false );
  38. m_pToolTip->SetEmbeddedPanel( m_pToolTipEmbeddedPanel );
  39. m_pToolTip->SetTooltipDelay( 0 );
  40. }
  41. //-----------------------------------------------------------------------------
  42. CDucksLeaderboard::~CDucksLeaderboard()
  43. {}
  44. //-----------------------------------------------------------------------------
  45. void CDucksLeaderboard::ApplySchemeSettings( IScheme *pScheme )
  46. {
  47. BaseClass::ApplySchemeSettings( pScheme );
  48. LoadControlSettings( "Resource/UI/econ/DucksLeaderboardPanel.res" );
  49. }
  50. //-----------------------------------------------------------------------------
  51. bool CDucksLeaderboard::GetLeaderboardData( CUtlVector< LeaderboardEntry_t* > &scores )
  52. {
  53. return Leaderboards_GetDuckLeaderboard( scores, m_pszDuckLeaderboardName );
  54. }
  55. //-----------------------------------------------------------------------------
  56. bool CDucksLeaderboard::UpdateLeaderboards()
  57. {
  58. CUtlVector< LeaderboardEntry_t* > scores;
  59. if ( !GetLeaderboardData( scores ) )
  60. return false;
  61. CSteamID localSteamID;
  62. if ( steamapicontext && steamapicontext->SteamUser() )
  63. {
  64. localSteamID = steamapicontext->SteamUser()->GetSteamID();
  65. }
  66. // Scores were empty but the leaderboard query was OK? This will happen while the user
  67. // and their friends has no scores. For now, insert a dummy value for the local player.
  68. LeaderboardEntry_t dummyentry;
  69. if ( scores.IsEmpty() )
  70. {
  71. dummyentry.m_nScore = 0;
  72. dummyentry.m_steamIDUser = localSteamID;
  73. scores.AddToTail( &dummyentry );
  74. }
  75. int nStartingIndex = 0;
  76. FOR_EACH_VEC( scores, i )
  77. {
  78. if ( scores[ i ]->m_steamIDUser == localSteamID )
  79. {
  80. // Try to go 3 past where the player is if we can, then go back 6
  81. nStartingIndex = Max( Min( i + 3, scores.Count() ) - 6, 0 );
  82. break;
  83. }
  84. }
  85. int x=0,y=0;
  86. FOR_EACH_VEC( m_vecLeaderboardEntries, i )
  87. {
  88. Color colorToUse = i % 2 == 1 ? m_OddTextColor : m_EvenTextColor;
  89. EditablePanel *pContainer = dynamic_cast< EditablePanel* >( m_vecLeaderboardEntries[i] );
  90. int nScoreIndex = nStartingIndex + i;
  91. if ( pContainer )
  92. {
  93. bool bIsEntryVisible = nScoreIndex < scores.Count();
  94. pContainer->SetVisible( bIsEntryVisible );
  95. pContainer->SetPos( x, y );
  96. y += m_yEntryStep;
  97. if ( bIsEntryVisible )
  98. {
  99. const LeaderboardEntry_t *leaderboardEntry = scores[nScoreIndex];
  100. const CSteamID &steamID = leaderboardEntry->m_steamIDUser;
  101. bool bIsLocalPlayer = steamapicontext && steamapicontext->SteamUser() && steamapicontext->SteamUser()->GetSteamID() == steamID;
  102. pContainer->SetDialogVariable( "username", InventoryManager()->PersonaName_Get( steamID.GetAccountID() ) );
  103. float flXPToLevel = DUCK_XP_SCALE;
  104. const float flPreciseLevel = leaderboardEntry->m_nScore / flXPToLevel;
  105. const int nCurrentLevel = floor( flPreciseLevel );
  106. const float flPercentToNextLevel = flPreciseLevel - nCurrentLevel;
  107. pContainer->SetDialogVariable( "score", nCurrentLevel );
  108. ProgressBar* pProgressBar = pContainer->FindControl<ProgressBar>( "ProgressToNextLevel", true );
  109. if ( pProgressBar )
  110. {
  111. pProgressBar->SetProgress( 1.f - flPercentToNextLevel );
  112. pProgressBar->SetProgressDirection( ProgressBar::PROGRESS_WEST );
  113. //const int nNextLevelXP = ( nCurrentLevel + 1 ) * DUCK_XP_SCALE;
  114. pProgressBar->SetTooltip( m_pToolTip, CFmtStr( "%d / %d", leaderboardEntry->m_nScore % DUCK_XP_SCALE, DUCK_XP_SCALE ) );
  115. }
  116. CExLabel *pText = pContainer->FindControl< CExLabel >( "UserName" );
  117. if ( pText )
  118. {
  119. pText->SetColorStr( bIsLocalPlayer ? m_LocalPlayerTextColor : colorToUse );
  120. }
  121. pText = pContainer->FindControl< CExLabel >( "Score" );
  122. if ( pText )
  123. {
  124. pText->SetColorStr( bIsLocalPlayer ? m_LocalPlayerTextColor : colorToUse );
  125. }
  126. CAvatarImagePanel *pAvatar = dynamic_cast< CAvatarImagePanel* >( pContainer->FindChildByName( "AvatarImage" ) );
  127. if ( pAvatar )
  128. {
  129. pAvatar->SetShouldDrawFriendIcon( false );
  130. pAvatar->SetPlayer( steamID, k_EAvatarSize32x32 );
  131. }
  132. }
  133. }
  134. }
  135. return true;
  136. }
  137. //-----------------------------------------------------------------------------
  138. CDucksLeaderboardManager::CDucksLeaderboardManager( Panel *parent, const char *panelName )
  139. : EditablePanel( parent, panelName )
  140. , m_nCurrentPage( 0 )
  141. , m_flFadeStartTime( Plat_FloatTime() )
  142. , m_pDimmer( NULL )
  143. {
  144. ListenForGameEvent( "gameui_hidden" );
  145. m_pToolTip = new CTFTextToolTip( this );
  146. m_pToolTipEmbeddedPanel = new vgui::EditablePanel( this, "TooltipPanel" );
  147. m_pToolTipEmbeddedPanel->SetKeyBoardInputEnabled( false );
  148. m_pToolTipEmbeddedPanel->SetMouseInputEnabled( false );
  149. m_pToolTip->SetEmbeddedPanel( m_pToolTipEmbeddedPanel );
  150. m_pToolTip->SetTooltipDelay( 0 );
  151. static CSchemaItemDefHandle pDuckBadgeDef( "Duck Badge" );
  152. // Prevent users who don't own the badge from opening the duck leaderboards
  153. if( CTFPlayerInventory::GetFirstItemOfItemDef( pDuckBadgeDef->GetDefinitionIndex() ) == NULL )
  154. {
  155. SetVisible( false );
  156. MarkForDeletion();
  157. return;
  158. }
  159. }
  160. //-----------------------------------------------------------------------------
  161. void CDucksLeaderboardManager::ApplySchemeSettings( IScheme *pScheme )
  162. {
  163. BaseClass::ApplySchemeSettings( pScheme );
  164. LoadControlSettings( "Resource/UI/econ/DucksLeaderboards.res" );
  165. m_pDimmer = FindControl<EditablePanel>( "Dimmer" );
  166. ShowPage( 0 );
  167. }
  168. //-----------------------------------------------------------------------------
  169. void CDucksLeaderboardManager::ApplySettings( KeyValues *inResourceData )
  170. {
  171. BaseClass::ApplySettings( inResourceData );
  172. m_vecLeaderboards.PurgeAndDeleteElements();
  173. EditablePanel* pBackgroundPanel = FindControl< EditablePanel >( "Background", true );
  174. if ( pBackgroundPanel )
  175. {
  176. EDuckLeaderboardTypes eShowLeaderboard = TF_DUCK_SCORING_OVERALL_RATING;
  177. CDucksLeaderboard *pLeaderboard = new CDucksLeaderboard( pBackgroundPanel, "DuckLeaderboard", g_szDuckLeaderboardNames[eShowLeaderboard] );
  178. pLeaderboard->SetDialogVariable( "title", g_pVGuiLocalize->Find( CFmtStr( "#%s", g_szDuckLeaderboardNames[eShowLeaderboard] ) ) );
  179. pLeaderboard->SetDialogVariable( "description", g_pVGuiLocalize->Find( CFmtStr( "#%s_Desc", g_szDuckLeaderboardNames[eShowLeaderboard] ) ) );
  180. pLeaderboard->InvalidateLayout( true, true );
  181. m_vecLeaderboards.AddToTail( pLeaderboard );
  182. EditablePanel *pStatsPanel = pBackgroundPanel->FindControl<EditablePanel>( "SecondaryStatsContainer", true );
  183. if ( pStatsPanel )
  184. {
  185. m_vecLeaderboards.AddToTail( pStatsPanel );
  186. Panel* pScoresContainer = pStatsPanel->FindChildByName( "ScoresContainer", true );
  187. if ( pScoresContainer )
  188. {
  189. CSteamID localSteamID;
  190. if ( steamapicontext && steamapicontext->SteamUser() )
  191. {
  192. localSteamID= steamapicontext->SteamUser()->GetSteamID();
  193. }
  194. KeyValues* pScoreEntryKVs = inResourceData->FindKey( "ScoreEntryKVs" );
  195. if ( pScoreEntryKVs )
  196. {
  197. for( int i = 1; i < DUCK_NUM_LEADERBOARDS; ++i )
  198. {
  199. EditablePanel *pNewEntry = new EditablePanel( pScoresContainer , "Score%d" );
  200. pNewEntry->ApplySettings( pScoreEntryKVs );
  201. pNewEntry->SetDialogVariable( "name", g_pVGuiLocalize->Find( CFmtStr( "#%s", g_szDuckLeaderboardNames[i] ) ) );
  202. pNewEntry->SetTooltip( m_pToolTip, CFmtStr( "#%s_Desc", g_szDuckLeaderboardNames[i] ) );
  203. pNewEntry->SetVisible( true );
  204. pNewEntry->SetPos( 0, m_iScoreStep * i ); // This is off by 1, but that's what we want. It starts at 1, but we want it to start lower
  205. // so it matches the leaderboard entries
  206. CUtlVector< LeaderboardEntry_t* > scores;
  207. Leaderboards_GetDuckLeaderboard( scores, g_szDuckLeaderboardNames[i] );
  208. int nScore = 0;
  209. FOR_EACH_VEC( scores, j )
  210. {
  211. if ( scores[j]->m_steamIDUser == localSteamID )
  212. {
  213. nScore = scores[j]->m_nScore;
  214. break;
  215. }
  216. }
  217. pNewEntry->SetDialogVariable( "score", nScore );
  218. }
  219. }
  220. }
  221. }
  222. }
  223. }
  224. //-----------------------------------------------------------------------------
  225. void CDucksLeaderboardManager::OnCommand( const char *command )
  226. {
  227. if ( FStrEq( command, "close" ) )
  228. {
  229. SetVisible( false );
  230. MarkForDeletion();
  231. return;
  232. }
  233. else if ( FStrEq( command, "nextpage" ) )
  234. {
  235. NextPage();
  236. }
  237. else if ( FStrEq( command, "prevpage" ) )
  238. {
  239. PrevPage();
  240. }
  241. }
  242. //-----------------------------------------------------------------------------
  243. void CDucksLeaderboardManager::FireGameEvent( IGameEvent *event )
  244. {
  245. if ( FStrEq( event->GetName(), "gameui_hidden" ) )
  246. {
  247. SetVisible( false );
  248. MarkForDeletion();
  249. return;
  250. }
  251. }
  252. void CDucksLeaderboardManager::OnThink()
  253. {
  254. if ( m_pDimmer )
  255. {
  256. float flDelta = Plat_FloatTime() - m_flFadeStartTime;
  257. float flAlpha = RemapValClamped( flDelta, 0.f, 0.2f, 0.f, 253.f );
  258. m_pDimmer->SetAlpha( flAlpha );
  259. }
  260. }
  261. //-----------------------------------------------------------------------------
  262. void CDucksLeaderboardManager::NextPage()
  263. {
  264. ++m_nCurrentPage;
  265. if ( m_nCurrentPage == m_vecLeaderboards.Count() )
  266. {
  267. m_nCurrentPage = 0;
  268. }
  269. ShowPage( m_nCurrentPage );
  270. }
  271. //-----------------------------------------------------------------------------
  272. void CDucksLeaderboardManager::PrevPage()
  273. {
  274. --m_nCurrentPage;
  275. if ( m_nCurrentPage < 0 )
  276. {
  277. m_nCurrentPage = m_vecLeaderboards.Count() - 1;
  278. }
  279. ShowPage( m_nCurrentPage );
  280. }
  281. //-----------------------------------------------------------------------------
  282. void CDucksLeaderboardManager::ShowPage( int nPage )
  283. {
  284. for( int i=0; i < m_vecLeaderboards.Count(); ++i )
  285. {
  286. m_vecLeaderboards[i]->SetVisible( i == nPage );
  287. }
  288. EditablePanel* pBackgroundPanel = dynamic_cast< EditablePanel* >( FindChildByName( "Background", true ) );
  289. if ( pBackgroundPanel )
  290. {
  291. pBackgroundPanel->SetDialogVariable( "pagenumber", CFmtStr( "%d/%d", nPage + 1, m_vecLeaderboards.Count() ) );
  292. }
  293. }
  294. #endif