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.

334 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //
  4. //=============================================================================//
  5. #include "cbase.h"
  6. #include "match_stats_page.h"
  7. #include <vgui_controls/SectionedListPanel.h>
  8. #include "c_team.h"
  9. #include "cs_client_gamestats.h"
  10. using namespace vgui;
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. //-----------------------------------------------------------------------------
  14. // Purpose: creates child panels, passes down name to pick up any settings from res files.
  15. //-----------------------------------------------------------------------------
  16. CMatchStatsPage::CMatchStatsPage(vgui::Panel *parent, const char *name) : BaseClass(parent, "CSMatchStatsDialog")
  17. {
  18. m_allStatsGroupPanel = AddGroup( L"all", "Stats_Button_All", L"All" );
  19. m_detailedWeaponStatsGroupPanel = AddGroup( L"weapon", "Stats_Button_Weapon", L"Weapon Stats" );
  20. m_specialSkillsStatsGroupPanel = AddGroup( L"skills", "Stats_Button_Skills", L"Special Skills" );
  21. m_mapAndMiscellanyStatsGroupPanel = AddGroup( L"map", "Stats_Button_Misc", L"Miscellaneous" );
  22. m_missionAndObjectiveStatsGroupPanel = AddGroup( L"mission", "Stats_Button_Mission", L"Mission && Objectives" );
  23. m_allStatsGroupPanel->SetGroupActive(true);
  24. m_ResetNotice = new Label( this, "ResetNotice", "");
  25. }
  26. //-----------------------------------------------------------------------------
  27. // Purpose: Loads settings from statsdialog.res in hl2/resource/ui/
  28. //-----------------------------------------------------------------------------
  29. void CMatchStatsPage::ApplySchemeSettings( vgui::IScheme *pScheme )
  30. {
  31. BaseClass::ApplySchemeSettings( pScheme );
  32. LoadControlSettings("resource/ui/CSMatchStatsDialog.res");
  33. m_statsList->AddColumnToSection( 0, "name", "", SectionedListPanel::COLUMN_CENTER, 180);
  34. m_statsList->AddColumnToSection( 0, "playerValue", "", SectionedListPanel::COLUMN_CENTER, 100);
  35. m_statsList->AddColumnToSection( 0, "ctValue", "", SectionedListPanel::COLUMN_CENTER, 100);
  36. m_statsList->AddColumnToSection( 0, "tValue", " ", SectionedListPanel::COLUMN_CENTER, 100);
  37. m_statsList->AddColumnToSection( 0, "serverValue", "", SectionedListPanel::COLUMN_CENTER, 100);
  38. }
  39. void CMatchStatsPage::RepopulateStats()
  40. {
  41. m_statsList->RemoveAll();
  42. RoundStatsDirectAverage_t* tStats = g_CSClientGameStats.GetDirectTStatsAverages();
  43. RoundStatsDirectAverage_t* ctStats = g_CSClientGameStats.GetDirectCTStatsAverages();
  44. RoundStatsDirectAverage_t* serverStats = g_CSClientGameStats.GetDirectPlayerStatsAverages();
  45. const StatsCollection_t& personalMatchStats = g_CSClientGameStats.GetMatchStats();
  46. if (m_missionAndObjectiveStatsGroupPanel->IsGroupActive() || m_allStatsGroupPanel->IsGroupActive())
  47. {
  48. AddSimpleStat(CSSTAT_ROUNDS_WON, personalMatchStats, tStats, ctStats, serverStats);
  49. AddSimpleStat(CSSTAT_KILLS, personalMatchStats, tStats, ctStats, serverStats);
  50. AddSimpleStat(CSSTAT_DEATHS, personalMatchStats, tStats, ctStats, serverStats);
  51. AddKillToDeathStat(personalMatchStats, tStats, ctStats, serverStats);
  52. AddSimpleStat(CSSTAT_DAMAGE, personalMatchStats, tStats, ctStats, serverStats);
  53. AddSimpleStat(CSSTAT_NUM_BOMBS_PLANTED, personalMatchStats, tStats, ctStats, serverStats);
  54. AddSimpleStat(CSSTAT_NUM_BOMBS_DEFUSED, personalMatchStats, tStats, ctStats, serverStats);
  55. AddSimpleStat(CSSTAT_NUM_HOSTAGES_RESCUED, personalMatchStats, tStats, ctStats, serverStats);
  56. AddSimpleStat(CSSTAT_PISTOLROUNDS_WON, personalMatchStats, tStats, ctStats, serverStats);
  57. }
  58. if (m_specialSkillsStatsGroupPanel->IsGroupActive() || m_allStatsGroupPanel->IsGroupActive())
  59. {
  60. AddSimpleStat(CSSTAT_MVPS, personalMatchStats, tStats, ctStats, serverStats);
  61. AddSimpleStat(CSSTAT_SHOTS_FIRED, personalMatchStats, tStats, ctStats, serverStats);
  62. AddSimpleStat(CSSTAT_SHOTS_HIT, personalMatchStats, tStats, ctStats, serverStats);
  63. AddAccuracyStat(personalMatchStats, tStats, ctStats, serverStats);
  64. AddSimpleStat(CSSTAT_DOMINATIONS, personalMatchStats, tStats, ctStats, serverStats);
  65. AddSimpleStat(CSSTAT_DOMINATION_OVERKILLS, personalMatchStats, tStats, ctStats, serverStats);
  66. AddSimpleStat(CSSTAT_REVENGES, personalMatchStats, tStats, ctStats, serverStats);
  67. AddSimpleStat(CSSTAT_KILLS_HEADSHOT, personalMatchStats, tStats, ctStats, serverStats);
  68. AddSimpleStat(CSSTAT_KILLS_AGAINST_ZOOMED_SNIPER, personalMatchStats, tStats, ctStats, serverStats);
  69. AddSimpleStat(CSSTAT_KILLS_ENEMY_BLINDED, personalMatchStats, tStats, ctStats, serverStats);
  70. AddSimpleStat(CSSTAT_KILLS_ENEMY_WEAPON, personalMatchStats, tStats, ctStats, serverStats);
  71. AddSimpleStat(CSSTAT_KILLS_KNIFE_FIGHT, personalMatchStats, tStats, ctStats, serverStats);
  72. }
  73. if (m_mapAndMiscellanyStatsGroupPanel->IsGroupActive() || m_allStatsGroupPanel->IsGroupActive())
  74. {
  75. AddSimpleStat(CSSTAT_MONEY_EARNED, personalMatchStats, tStats, ctStats, serverStats);
  76. AddSimpleStat(CSSTAT_DECAL_SPRAYS, personalMatchStats, tStats, ctStats, serverStats);
  77. AddSimpleStat(CSSTAT_NIGHTVISION_DAMAGE, personalMatchStats, tStats, ctStats, serverStats);
  78. AddSimpleStat(CSSTAT_NUM_BROKEN_WINDOWS, personalMatchStats, tStats, ctStats, serverStats);
  79. AddSimpleStat(CSSTAT_WEAPONS_DONATED, personalMatchStats, tStats, ctStats, serverStats);
  80. }
  81. if (m_detailedWeaponStatsGroupPanel->IsGroupActive() || m_allStatsGroupPanel->IsGroupActive())
  82. {
  83. CSStatType_t hitsStat = CSSTAT_HITS_DEAGLE;
  84. CSStatType_t shotsStat = CSSTAT_SHOTS_DEAGLE;
  85. for (CSStatType_t killStat = CSSTAT_KILLS_DEAGLE ; killStat <= CSSTAT_KILLS_HEGRENADE ; killStat = (CSStatType_t)(killStat + 1))
  86. {
  87. if (shotsStat <= CSSTAT_SHOTS_M249)
  88. {
  89. AddSimpleStat(shotsStat, personalMatchStats, tStats, ctStats, serverStats);
  90. }
  91. if (hitsStat <= CSSTAT_HITS_M249)
  92. {
  93. AddSimpleStat(hitsStat, personalMatchStats, tStats, ctStats, serverStats);
  94. }
  95. AddSimpleStat(killStat, personalMatchStats, tStats, ctStats, serverStats);
  96. hitsStat = (CSStatType_t)(hitsStat + 1);
  97. shotsStat = (CSStatType_t)(shotsStat + 1);
  98. }
  99. }
  100. int itemCount = m_statsList->GetItemCount();
  101. for (int i = 0; i < itemCount ; ++i)
  102. {
  103. m_statsList->SetItemBgColor(i, Color(0,0,0,0));
  104. }
  105. }
  106. int CMatchStatsPage::AddSimpleStat( int desiredStat, const StatsCollection_t& personalMatchStats, RoundStatsDirectAverage_t* tStats, RoundStatsDirectAverage_t* ctStats, RoundStatsDirectAverage_t* serverStats )
  107. {
  108. PlayerStatData_t stat = g_CSClientGameStats.GetStatById(desiredStat);
  109. KeyValues *pKeyValues = new KeyValues( "data" );
  110. pKeyValues->SetWString( "name", stat.pStatDisplayName );
  111. pKeyValues->SetFloat( "playerValue", 0 );
  112. char buf[64];
  113. Q_snprintf( buf, sizeof( buf ), "%d", personalMatchStats[stat.iStatId] );
  114. pKeyValues->SetString( "playerValue", (personalMatchStats[stat.iStatId])?buf:"" );
  115. if (desiredStat == CSSTAT_ROUNDS_WON)
  116. {
  117. C_Team *ts = GetGlobalTeam(TEAM_TERRORIST);
  118. if (ts)
  119. {
  120. Q_snprintf( buf, sizeof( buf ), "%d", ts->Get_Score() );
  121. pKeyValues->SetString( "tValue", buf );
  122. }
  123. C_Team *cts = GetGlobalTeam(TEAM_CT);
  124. if (cts){
  125. Q_snprintf( buf, sizeof( buf ), "%d", cts->Get_Score());
  126. pKeyValues->SetString( "ctValue", buf );
  127. }
  128. }
  129. else
  130. {
  131. Q_snprintf( buf, sizeof( buf ), "%.1f", tStats->m_fStat[stat.iStatId] );
  132. pKeyValues->SetString( "tValue", (tStats->m_fStat[stat.iStatId]||personalMatchStats[stat.iStatId])?buf:"" );
  133. Q_snprintf( buf, sizeof( buf ), "%.1f", ctStats->m_fStat[stat.iStatId] );
  134. pKeyValues->SetString( "ctValue", (ctStats->m_fStat[stat.iStatId]||personalMatchStats[stat.iStatId])?buf:"" );
  135. }
  136. Q_snprintf( buf, sizeof( buf ), "%.1f", serverStats->m_fStat[stat.iStatId] );
  137. pKeyValues->SetString( "serverValue", (serverStats->m_fStat[stat.iStatId]||personalMatchStats[stat.iStatId])?buf:"" );
  138. int newItem = m_statsList->AddItem(0, pKeyValues);
  139. pKeyValues->deleteThis();
  140. m_statsList->SetItemFont(newItem , m_listItemFont);
  141. m_statsList->SetItemFgColor(newItem, Color(197,197,197,255));
  142. return newItem;
  143. }
  144. int CMatchStatsPage::AddKillToDeathStat(const StatsCollection_t& personalMatchStats, RoundStatsDirectAverage_t* tStats, RoundStatsDirectAverage_t* ctStats, RoundStatsDirectAverage_t* serverStats )
  145. {
  146. PlayerStatData_t statKills = g_CSClientGameStats.GetStatById(CSSTAT_KILLS);
  147. PlayerStatData_t statDeaths = g_CSClientGameStats.GetStatById(CSSTAT_DEATHS);
  148. KeyValues *pKeyValues = new KeyValues( "data" );
  149. pKeyValues->SetWString( "name", LocalizeTagOrUseDefault( "Stats_KillToDeathRatio", L"Kill to Death Ratio" ) );
  150. pKeyValues->SetFloat( "playerValue", 0 );
  151. float playerKills = personalMatchStats[statKills.iStatId];
  152. float tKills = tStats->m_fStat[statKills.iStatId];
  153. float ctKills = ctStats->m_fStat[statKills.iStatId];
  154. float serverKills = serverStats->m_fStat[statKills.iStatId];
  155. float playerDeaths = personalMatchStats[statDeaths.iStatId];
  156. float tDeaths = tStats->m_fStat[statDeaths.iStatId];
  157. float ctDeaths = ctStats->m_fStat[statDeaths.iStatId];
  158. float serverDeaths = serverStats->m_fStat[statDeaths.iStatId];
  159. char buf[64];
  160. if (playerDeaths > 0)
  161. {
  162. float playerKillToDeathRatio = playerKills / playerDeaths;
  163. Q_snprintf( buf, sizeof( buf ), "%.2f", playerKillToDeathRatio );
  164. pKeyValues->SetString( "playerValue", (playerKillToDeathRatio)?buf:"" );
  165. }
  166. else
  167. {
  168. pKeyValues->SetString( "playerValue", "" );
  169. }
  170. if (tDeaths > 0)
  171. {
  172. float tKillToDeathRatio = tKills / tDeaths;
  173. Q_snprintf( buf, sizeof( buf ), "%.2f", tKillToDeathRatio );
  174. pKeyValues->SetString( "tValue", ((playerKills&&playerDeaths)||tKillToDeathRatio)?buf:"" );
  175. }
  176. else
  177. {
  178. pKeyValues->SetString( "tValue", "" );
  179. }
  180. if (ctDeaths > 0)
  181. {
  182. float ctKillToDeathRatio = ctKills / ctDeaths;
  183. Q_snprintf( buf, sizeof( buf ), "%.2f", ctKillToDeathRatio);
  184. pKeyValues->SetString( "ctValue", ((playerKills&&playerDeaths)||ctKillToDeathRatio)?buf:"" );
  185. }
  186. else
  187. {
  188. pKeyValues->SetString( "ctValue", "" );
  189. }
  190. if (serverDeaths > 0)
  191. {
  192. float serverKillToDeathRatio = serverKills / serverDeaths;
  193. Q_snprintf( buf, sizeof( buf ), "%.2f", serverKillToDeathRatio );
  194. pKeyValues->SetString( "serverValue", ((playerKills&&playerDeaths)||serverKillToDeathRatio)?buf:"" );
  195. }
  196. else
  197. {
  198. pKeyValues->SetString( "serverValue", "" );
  199. }
  200. int newItem = m_statsList->AddItem(0, pKeyValues);
  201. pKeyValues->deleteThis();
  202. m_statsList->SetItemFont(newItem , m_listItemFont);
  203. m_statsList->SetItemFgColor(newItem, Color(197,197,197,255));
  204. return newItem;
  205. }
  206. int CMatchStatsPage::AddAccuracyStat(const StatsCollection_t& personalMatchStats, RoundStatsDirectAverage_t* tStats, RoundStatsDirectAverage_t* ctStats, RoundStatsDirectAverage_t* serverStats )
  207. {
  208. PlayerStatData_t statHits = g_CSClientGameStats.GetStatById(CSSTAT_SHOTS_HIT);
  209. PlayerStatData_t statShots = g_CSClientGameStats.GetStatById(CSSTAT_SHOTS_FIRED);
  210. KeyValues *pKeyValues = new KeyValues( "data" );
  211. pKeyValues->SetWString( "name", LocalizeTagOrUseDefault( "Stats_Accuracy", L"Accuracy" ) );
  212. pKeyValues->SetFloat( "playerValue", 0 );
  213. float playerHits = personalMatchStats[statHits.iStatId];
  214. float tHits = tStats->m_fStat[statHits.iStatId];
  215. float ctHits = ctStats->m_fStat[statHits.iStatId];
  216. float serverHits = serverStats->m_fStat[statHits.iStatId];
  217. float playerShots = personalMatchStats[statShots.iStatId];
  218. float tShots = tStats->m_fStat[statShots.iStatId];
  219. float ctShots = ctStats->m_fStat[statShots.iStatId];
  220. float serverShots = serverStats->m_fStat[statShots.iStatId];
  221. float playerAccuracy = 0.0;
  222. float tAccuracy = 0.0;
  223. float ctAccuracy = 0.0;
  224. float serverAccuracy = 0.0;
  225. if (playerShots > 0)
  226. {
  227. playerAccuracy = 100.0f * playerHits / playerShots;
  228. }
  229. if (tShots > 0)
  230. {
  231. tAccuracy = 100.0f * tHits / tShots;
  232. }
  233. if (ctShots > 0)
  234. {
  235. ctAccuracy = 100.0f * ctHits / ctShots;
  236. }
  237. if (serverShots > 0)
  238. {
  239. serverAccuracy = 100.0f * serverHits / serverShots;
  240. }
  241. char buf[64];
  242. Q_snprintf( buf, sizeof( buf ), "%.1f%%", playerAccuracy );
  243. pKeyValues->SetString( "playerValue", (playerAccuracy)?buf:"" );
  244. Q_snprintf( buf, sizeof( buf ), "%.1f%%", tAccuracy);
  245. pKeyValues->SetString( "tValue", (playerAccuracy||tAccuracy)?buf:"" );
  246. Q_snprintf( buf, sizeof( buf ), "%.1f%%", ctAccuracy );
  247. pKeyValues->SetString( "ctValue", (playerAccuracy||ctAccuracy)?buf:"" );
  248. Q_snprintf( buf, sizeof( buf ), "%.1f%%", serverAccuracy );
  249. pKeyValues->SetString( "serverValue", (playerAccuracy||serverAccuracy)?buf:"" );
  250. int newItem = m_statsList->AddItem(0, pKeyValues);
  251. pKeyValues->deleteThis();
  252. m_statsList->SetItemFont(newItem , m_listItemFont);
  253. m_statsList->SetItemFgColor(newItem, Color(197,197,197,255));
  254. return newItem;
  255. }
  256. void CMatchStatsPage::OnSizeChanged(int newWide, int newTall)
  257. {
  258. BaseClass::OnSizeChanged(newWide, newTall);
  259. if (m_statsList)
  260. {
  261. if (m_ResetNotice)
  262. {
  263. int labelX, labelY, listX, listY, listWide, listTall;
  264. m_statsList->GetBounds(listX, listY, listWide, listTall);
  265. m_ResetNotice->GetPos(labelX, labelY);
  266. m_ResetNotice->SetPos(labelX, listY + listTall + 4);
  267. }
  268. }
  269. }