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.

353 lines
9.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "dodclassmenu.h"
  9. #include <KeyValues.h>
  10. #include <filesystem.h>
  11. #include <vgui_controls/Button.h>
  12. #include <vgui_controls/RichText.h>
  13. #include <vgui/IVGui.h>
  14. #include "hud.h" // for gEngfuncs
  15. #include "c_dod_player.h"
  16. #include "c_dod_team.h"
  17. #include "imagemouseoverbutton.h"
  18. #include "dodmouseoverpanelbutton.h"
  19. #include "dodrandombutton.h"
  20. #include "IconPanel.h"
  21. #include "IGameUIFuncs.h" // for key bindings
  22. extern IGameUIFuncs *gameuifuncs; // for key binding details
  23. using namespace vgui;
  24. extern ConVar hud_classautokill;
  25. //-----------------------------------------------------------------------------
  26. // Purpose:
  27. //-----------------------------------------------------------------------------
  28. Panel *CDODClassInfoPanel::CreateControlByName( const char *controlName )
  29. {
  30. if( !Q_stricmp( "ProgressBar", controlName ) )
  31. {
  32. return new CDODProgressBar(this);
  33. }
  34. else if ( !Q_stricmp( "CIconPanel", controlName ) )
  35. {
  36. return new CIconPanel(this, "icon_panel");
  37. }
  38. else
  39. {
  40. return BaseClass::CreateControlByName( controlName );
  41. }
  42. }
  43. void CDODClassInfoPanel::ApplySchemeSettings( IScheme *pScheme )
  44. {
  45. RichText *pClassInfo = dynamic_cast<RichText*>(FindChildByName("classInfo"));
  46. if ( pClassInfo )
  47. {
  48. pClassInfo->SetBorder(pScheme->GetBorder("NoBorder"));
  49. pClassInfo->SetBgColor(pScheme->GetColor("Blank", Color(0,0,0,0)));
  50. }
  51. BaseClass::ApplySchemeSettings( pScheme );
  52. }
  53. CDODClassMenu::CDODClassMenu(IViewPort *pViewPort) : CClassMenu(pViewPort)
  54. {
  55. m_mouseoverButtons.RemoveAll();
  56. m_iClassMenuKey = BUTTON_CODE_INVALID;
  57. m_pInitialButton = NULL;
  58. m_pBackground = SETUP_PANEL( new CDODMenuBackground( this ) );
  59. m_pClassInfoPanel = new CDODClassInfoPanel( this, "ClassInfoPanel" );
  60. vgui::ivgui()->AddTickSignal( GetVPanel() );
  61. m_iActivePlayerClass = -1;
  62. m_iLastPlayerClassCount = -1;
  63. m_pClassNumLabel[0] = new Label( this, "class_1_num", "" );
  64. m_pClassNumLabel[1] = new Label( this, "class_2_num", "" );
  65. m_pClassNumLabel[2] = new Label( this, "class_3_num", "" );
  66. m_pClassNumLabel[3] = new Label( this, "class_4_num", "" );
  67. m_pClassNumLabel[4] = new Label( this, "class_5_num", "" );
  68. m_pClassNumLabel[5] = new Label( this, "class_6_num", "" );
  69. m_pClassFullLabel[0] = new Label( this, "class_1_full", "" );
  70. m_pClassFullLabel[1] = new Label( this, "class_2_full", "" );
  71. m_pClassFullLabel[2] = new Label( this, "class_3_full", "" );
  72. m_pClassFullLabel[3] = new Label( this, "class_4_full", "" );
  73. m_pClassFullLabel[4] = new Label( this, "class_5_full", "" );
  74. m_pClassFullLabel[5] = new Label( this, "class_6_full", "" );
  75. m_pSuicideOption = new CheckButton( this, "suicide_option", "Sky is blue?" );
  76. }
  77. void CDODClassMenu::ShowPanel( bool bShow )
  78. {
  79. if ( bShow )
  80. {
  81. engine->CheckPoint( "ClassMenu" );
  82. m_iClassMenuKey = gameuifuncs->GetButtonCodeForBind( "changeclass" );
  83. m_pSuicideOption->SetSelected( hud_classautokill.GetBool() );
  84. }
  85. for( int i = 0; i< GetChildCount(); i++ )
  86. {
  87. CImageMouseOverButton<CDODClassInfoPanel> *button =
  88. dynamic_cast<CImageMouseOverButton<CDODClassInfoPanel> *>(GetChild(i));
  89. if ( button )
  90. {
  91. if( button == m_pInitialButton && bShow == true )
  92. button->ShowPage();
  93. else
  94. button->HidePage();
  95. }
  96. }
  97. CDODRandomButton<CDODClassInfoPanel> *pRandom =
  98. dynamic_cast<CDODRandomButton<CDODClassInfoPanel> *>( FindChildByName("random") );
  99. if ( pRandom )
  100. pRandom->HidePage();
  101. // recalc position of checkbox, since it doesn't do right alignment
  102. m_pSuicideOption->SizeToContents();
  103. int x, y, wide, tall;
  104. m_pSuicideOption->GetBounds( x, y, wide, tall );
  105. int parentW, parentH;
  106. GetSize( parentW, parentH );
  107. x = parentW / 2; // - wide;
  108. m_pSuicideOption->SetPos( x, y );
  109. BaseClass::ShowPanel( bShow );
  110. }
  111. void CDODClassMenu::OnKeyCodePressed( KeyCode code )
  112. {
  113. #ifdef REFRESH_CLASSMENU_TOOL
  114. if ( code == KEY_PAD_MULTIPLY )
  115. {
  116. OnRefreshClassMenu();
  117. }
  118. #endif
  119. if ( m_iClassMenuKey != BUTTON_CODE_INVALID && m_iClassMenuKey == code )
  120. {
  121. ShowPanel( false );
  122. }
  123. else
  124. {
  125. BaseClass::OnKeyCodePressed( code );
  126. }
  127. }
  128. void CDODClassMenu::Update()
  129. {
  130. C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer();
  131. if ( pPlayer && pPlayer->m_Shared.DesiredPlayerClass() == PLAYERCLASS_UNDEFINED )
  132. {
  133. SetVisibleButton( "CancelButton", false );
  134. }
  135. else
  136. {
  137. SetVisibleButton( "CancelButton", true );
  138. }
  139. }
  140. //-----------------------------------------------------------------------------
  141. // Purpose:
  142. //-----------------------------------------------------------------------------
  143. Panel *CDODClassMenu::CreateControlByName( const char *controlName )
  144. {
  145. if ( !Q_stricmp( "DODMouseOverPanelButton", controlName ) )
  146. {
  147. return new CDODMouseOverButton<CDODClassInfoPanel>( this, NULL, m_pClassInfoPanel );
  148. }
  149. else if( !Q_stricmp( "DODButton", controlName ) )
  150. {
  151. return new CDODButton(this);
  152. }
  153. else if( !Q_stricmp( "DODRandomButton", controlName ) )
  154. {
  155. return new CDODRandomButton<CDODClassInfoPanel>(this, NULL, m_pClassInfoPanel );
  156. }
  157. else if ( !Q_stricmp( "ImageButton", controlName ) )
  158. {
  159. CImageMouseOverButton<CDODClassInfoPanel> *newButton = new CImageMouseOverButton<CDODClassInfoPanel>( this, NULL, m_pClassInfoPanel );
  160. if( !m_pInitialButton )
  161. {
  162. m_pInitialButton = newButton;
  163. }
  164. return newButton;
  165. }
  166. else if ( !Q_stricmp( "CIconPanel", controlName ) )
  167. {
  168. return new CIconPanel(this, "icon_panel");
  169. }
  170. else
  171. {
  172. return BaseClass::CreateControlByName( controlName );
  173. }
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Catch the mouseover event and set the active class
  177. //-----------------------------------------------------------------------------
  178. void CDODClassMenu::OnShowPage( const char *pagename )
  179. {
  180. // change which class we are counting based on class name
  181. // turn the button name into a classname
  182. char buf[64];
  183. Q_snprintf( buf, sizeof(buf), "cls_%s", pagename );
  184. C_DODTeam *pTeam = dynamic_cast<C_DODTeam *>( GetGlobalTeam(GetTeamNumber()) );
  185. if( !pTeam )
  186. return;
  187. // Pull the index of this class via IsClassOnTeam
  188. if ( !pTeam->IsClassOnTeam( buf, m_iActivePlayerClass ) )
  189. {
  190. Assert( !"bad class name on class button" );
  191. }
  192. UpdateNumClassLabel();
  193. }
  194. //-----------------------------------------------------------------------------
  195. // Draw nothing
  196. //-----------------------------------------------------------------------------
  197. void CDODClassMenu::PaintBackground( void )
  198. {
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Do things that should be done often, eg number of players in the
  202. // selected class
  203. //-----------------------------------------------------------------------------
  204. void CDODClassMenu::OnTick( void )
  205. {
  206. //When a player changes teams, their class and team values don't get here
  207. //necessarily before the command to update the class menu. This leads to the cancel button
  208. //being visible and people cancelling before they have a class. check for class == DOD_CLASS_NONE and if so
  209. //hide the cancel button
  210. if ( !IsVisible() )
  211. return;
  212. C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer();
  213. if( pPlayer && pPlayer->m_Shared.PlayerClass() == PLAYERCLASS_UNDEFINED )
  214. {
  215. SetVisibleButton("CancelButton", false);
  216. }
  217. UpdateNumClassLabel();
  218. BaseClass::OnTick();
  219. }
  220. void CDODClassMenu::UpdateNumClassLabel( void )
  221. {
  222. int iClassCount[NUM_CLASSES];
  223. // Initialize to zero. Was previously used uninitialized.
  224. int iClassLimit[NUM_CLASSES] = {};
  225. // count how many of this class there are
  226. C_DODTeam *pTeam = dynamic_cast<C_DODTeam *>( GetGlobalTeam(GetTeamNumber()) );
  227. if ( !pTeam )
  228. return;
  229. char buf[16];
  230. for( int i=0;i<NUM_CLASSES;i++ )
  231. {
  232. iClassCount[i] = pTeam->CountPlayersOfThisClass( i );
  233. if ( !m_pClassNumLabel[i] || !m_pClassFullLabel[i] )
  234. continue;
  235. if ( pTeam->IsClassOnTeam( i ) )
  236. {
  237. // FIXME - store pointers to these cvars
  238. const CDODPlayerClassInfo &pClassInfo = pTeam->GetPlayerClassInfo( i );
  239. ConVar *pLimitCvar = ( ConVar * )cvar->FindVar( pClassInfo.m_szLimitCvar );
  240. if ( pLimitCvar )
  241. iClassLimit[i] = MIN( 32, pLimitCvar->GetInt() );
  242. }
  243. if ( iClassLimit[i] < 0 || iClassCount[i] < iClassLimit[i] )
  244. m_pClassFullLabel[i]->SetVisible( false );
  245. else
  246. m_pClassFullLabel[i]->SetVisible( true );
  247. if ( iClassLimit[i] > -1 )
  248. {
  249. // draw "3 / 4"
  250. Q_snprintf( buf, sizeof(buf), "%d / %d", iClassCount[i], iClassLimit[i] );
  251. }
  252. else
  253. {
  254. // just "3"
  255. Q_snprintf( buf, sizeof(buf), "x %d", iClassCount[i] );
  256. }
  257. m_pClassNumLabel[i]->SetText( buf );
  258. }
  259. }
  260. void CDODClassMenu::SetVisible( bool state )
  261. {
  262. BaseClass::SetVisible( state );
  263. }
  264. void CDODClassMenu::OnSuicideOptionChanged( vgui::Panel *Panel )
  265. {
  266. hud_classautokill.SetValue( m_pSuicideOption->IsSelected() );
  267. }
  268. #ifdef REFRESH_CLASSMENU_TOOL
  269. void CDODClassMenu::OnRefreshClassMenu( void )
  270. {
  271. for( int i = 0; i< GetChildCount(); i++ )
  272. {
  273. CImageMouseOverButton<CDODClassInfoPanel> *button =
  274. dynamic_cast<CImageMouseOverButton<CDODClassInfoPanel> *>(GetChild(i));
  275. if ( button )
  276. {
  277. button->RefreshClassPage();
  278. }
  279. }
  280. }
  281. #endif