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.

1719 lines
51 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: HUD Target ID element
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "cbase.h"
  8. #include "hud.h"
  9. #include "iclientmode.h"
  10. #include "c_baseobject.h"
  11. #include "c_tf_player.h"
  12. #include "ienginevgui.h"
  13. #include "vgui/ILocalize.h"
  14. #include "vgui/ISurface.h"
  15. #include <vgui/IVGui.h>
  16. #include <vgui_controls/ProgressBar.h>
  17. #include <vgui_controls/AnimationController.h>
  18. #include "game_controls/IconPanel.h"
  19. #include "teamplay_round_timer.h"
  20. #include "tf_hud_building_status.h"
  21. #include "c_obj_sentrygun.h"
  22. #include "c_obj_dispenser.h"
  23. #include "c_obj_teleporter.h"
  24. #include "c_obj_sapper.h"
  25. #include "tf_gamerules.h"
  26. #include "tf_logic_halloween_2014.h"
  27. // memdbgon must be the last include file in a .cpp file!!!
  28. #include "tier0/memdbgon.h"
  29. class C_ObjectSentrygun;
  30. extern CUtlVector<int> g_TeamRoundTimers;
  31. using namespace vgui;
  32. ConVar tf_hud_num_building_alert_beeps( "tf_hud_num_building_alert_beeps", "2", FCVAR_ARCHIVE, "Number of times to play warning sound when a new alert displays on building hud objects", true, 0, false, 0 );
  33. //============================================================================
  34. DECLARE_BUILD_FACTORY( CBuildingHealthBar );
  35. //-----------------------------------------------------------------------------
  36. // Purpose:
  37. //-----------------------------------------------------------------------------
  38. CBuildingHealthBar::CBuildingHealthBar(Panel *parent, const char *panelName) : vgui::ProgressBar( parent, panelName )
  39. {
  40. }
  41. //-----------------------------------------------------------------------------
  42. // Purpose:
  43. //-----------------------------------------------------------------------------
  44. void CBuildingHealthBar::Paint()
  45. {
  46. if ( _progress < 0.5 )
  47. {
  48. SetFgColor( m_cLowHealthColor );
  49. }
  50. else
  51. {
  52. SetFgColor( m_cHealthColor );
  53. }
  54. BaseClass::Paint();
  55. }
  56. //-----------------------------------------------------------------------------
  57. // Purpose:
  58. //-----------------------------------------------------------------------------
  59. void CBuildingHealthBar::PaintBackground()
  60. {
  61. // save progress and real fg color
  62. float flProgress = _progress;
  63. Color fgColor = GetFgColor();
  64. // stuff our fake info
  65. _progress = 1.0;
  66. SetFgColor( GetBgColor() );
  67. BaseClass::Paint();
  68. // restore actual progress / color
  69. _progress = flProgress;
  70. SetFgColor( fgColor );
  71. }
  72. //-----------------------------------------------------------------------------
  73. // Purpose:
  74. //-----------------------------------------------------------------------------
  75. void CBuildingHealthBar::ApplySchemeSettings(vgui::IScheme *pScheme)
  76. {
  77. BaseClass::ApplySchemeSettings(pScheme);
  78. SetBgColor(GetSchemeColor("BuildingHealthBar.BgColor", pScheme));
  79. m_cHealthColor = GetSchemeColor("BuildingHealthBar.Health", pScheme);
  80. m_cLowHealthColor = GetSchemeColor("BuildingHealthBar.LowHealth", pScheme);
  81. SetBorder(NULL);
  82. }
  83. //============================================================================
  84. //-----------------------------------------------------------------------------
  85. // Purpose:
  86. //-----------------------------------------------------------------------------
  87. CBuildingStatusItem::CBuildingStatusItem( Panel *parent, const char *szLayout, int iObjectType, int iObjectMode=0 ) :
  88. BaseClass( parent, "BuildingStatusItem" )
  89. {
  90. SetProportional( true );
  91. // Save our layout file for re-loading
  92. Q_strncpy( m_szLayout, szLayout, sizeof(m_szLayout) );
  93. // load control settings...
  94. LoadControlSettings( szLayout );
  95. SetPositioned( false );
  96. m_pObject = NULL;
  97. m_iObjectType = iObjectType;
  98. m_iObjectMode = iObjectMode;
  99. m_pBuiltPanel = new vgui::EditablePanel( this, "BuiltPanel" );
  100. m_pNotBuiltPanel = new vgui::EditablePanel( this, "NotBuiltPanel" );
  101. // sub panels
  102. m_pBuildingPanel = new vgui::EditablePanel( m_pBuiltPanel, "BuildingPanel" );
  103. m_pRunningPanel = new vgui::EditablePanel( m_pBuiltPanel, "RunningPanel" );
  104. // Shared between All sub panels
  105. m_pBackground = new CIconPanel( this, "Background" );
  106. // Running and Building sub panels only
  107. m_pHealthBar = new CBuildingHealthBar( m_pBuiltPanel, "Health" );
  108. m_pHealthBar->SetSegmentInfo( YRES(1), YRES(3) );
  109. m_pHealthBar->SetProgressDirection( ProgressBar::PROGRESS_NORTH );
  110. m_pHealthBar->SetBarInset( 0 );
  111. m_pBuildingProgress = new vgui::ContinuousProgressBar( m_pBuildingPanel, "BuildingProgress" );
  112. m_pAlertTray = new CBuildingStatusAlertTray( m_pBuiltPanel, "AlertTray" );
  113. m_pWrenchIcon = new CIconPanel( m_pBuiltPanel, "WrenchIcon" );
  114. m_pSapperIcon = new CIconPanel( m_pBuiltPanel, "SapperIcon" );
  115. m_pUpgradeIcons[0] = new CIconPanel( m_pBuiltPanel, "Icon_Upgrade_1" );
  116. m_pUpgradeIcons[1] = new CIconPanel( m_pBuiltPanel, "Icon_Upgrade_2" );
  117. m_pUpgradeIcons[2] = new CIconPanel( m_pBuiltPanel, "Icon_Upgrade_3" );
  118. m_iUpgradeLevel = 1;
  119. vgui::ivgui()->AddTickSignal( GetVPanel() );
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Purpose:
  123. //-----------------------------------------------------------------------------
  124. void CBuildingStatusItem::ApplySchemeSettings( IScheme *pScheme )
  125. {
  126. // This lets us use hud_reloadscheme to reload the status items
  127. int x, y;
  128. GetPos( x, y );
  129. LoadControlSettings( m_szLayout );
  130. SetPos( x, y );
  131. BaseClass::ApplySchemeSettings( pScheme );
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Purpose: Calc visibility of subpanels
  135. //-----------------------------------------------------------------------------
  136. void CBuildingStatusItem::PerformLayout( void )
  137. {
  138. BaseClass::PerformLayout();
  139. C_BaseObject *pObj = m_pObject.Get();
  140. m_bActive = ( pObj != NULL );
  141. m_pHealthBar->SetVisible( m_bActive );
  142. m_pNotBuiltPanel->SetVisible( !m_bActive );
  143. m_pBuiltPanel->SetVisible( m_bActive );
  144. if ( pObj )
  145. {
  146. // redo the background
  147. m_pBackground->SetIcon( GetBackgroundImage() );
  148. if ( pObj->IsBuilding() )
  149. {
  150. m_pBuildingPanel->SetVisible( true );
  151. m_pRunningPanel->SetVisible( false );
  152. m_pUpgradeIcons[0]->SetVisible( false );
  153. m_pUpgradeIcons[1]->SetVisible( false );
  154. m_pUpgradeIcons[2]->SetVisible( false );
  155. }
  156. else
  157. {
  158. m_pBuildingPanel->SetVisible( false );
  159. m_pRunningPanel->SetVisible( true );
  160. int iUpgradeLevel = pObj->GetUpgradeLevel();
  161. Assert( iUpgradeLevel >= 1 && iUpgradeLevel <= 3 );
  162. m_pUpgradeIcons[0]->SetVisible( false );
  163. m_pUpgradeIcons[1]->SetVisible( false );
  164. m_pUpgradeIcons[2]->SetVisible( false );
  165. // show the correct upgrade level icon
  166. if ( !pObj->IsMiniBuilding() )
  167. {
  168. m_pUpgradeIcons[iUpgradeLevel-1]->SetVisible( true );
  169. }
  170. }
  171. }
  172. else
  173. {
  174. // redo the background
  175. m_pBackground->SetIcon( GetInactiveBackgroundImage() );
  176. if ( m_pAlertTray->IsTrayOut() )
  177. {
  178. m_pAlertTray->HideTray();
  179. m_pWrenchIcon->SetVisible( false );
  180. m_pSapperIcon->SetVisible( false );
  181. }
  182. }
  183. }
  184. //-----------------------------------------------------------------------------
  185. // Purpose: Setup
  186. //-----------------------------------------------------------------------------
  187. void CBuildingStatusItem::LevelInit( void )
  188. {
  189. if ( m_pAlertTray )
  190. m_pAlertTray->LevelInit();
  191. }
  192. //-----------------------------------------------------------------------------
  193. // Purpose: Setup
  194. //-----------------------------------------------------------------------------
  195. void CBuildingStatusItem::SetObject( C_BaseObject *pObj )
  196. {
  197. m_pObject = pObj;
  198. Assert( !pObj || ( pObj && !pObj->IsMarkedForDeletion() ) );
  199. if ( !pObj )
  200. {
  201. m_pAlertTray->HideTray();
  202. m_pWrenchIcon->SetVisible( false );
  203. m_pSapperIcon->SetVisible( false );
  204. m_pAlertTray->SetAlertType( BUILDING_HUD_ALERT_NONE );
  205. }
  206. }
  207. //-----------------------------------------------------------------------------
  208. // Purpose:
  209. //-----------------------------------------------------------------------------
  210. void CBuildingStatusItem::Paint( void )
  211. {
  212. }
  213. //-----------------------------------------------------------------------------
  214. // Purpose:
  215. //-----------------------------------------------------------------------------
  216. void CBuildingStatusItem::PaintBackground( void )
  217. {
  218. }
  219. //-----------------------------------------------------------------------------
  220. // Purpose:
  221. //-----------------------------------------------------------------------------
  222. const char *CBuildingStatusItem::GetBackgroundImage( void )
  223. {
  224. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  225. const char *pResult = "obj_status_background_blue";
  226. if ( !pLocalPlayer )
  227. {
  228. Assert( 0 );
  229. return pResult;
  230. }
  231. switch( pLocalPlayer->GetTeamNumber() )
  232. {
  233. case TF_TEAM_BLUE:
  234. pResult = "obj_status_background_blue";
  235. break;
  236. case TF_TEAM_RED:
  237. pResult = "obj_status_background_red";
  238. break;
  239. default:
  240. break;
  241. }
  242. return pResult;
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Purpose:
  246. //-----------------------------------------------------------------------------
  247. const char *CBuildingStatusItem::GetInactiveBackgroundImage( void )
  248. {
  249. return "obj_status_background_disabled";
  250. }
  251. //-----------------------------------------------------------------------------
  252. // Purpose:
  253. //-----------------------------------------------------------------------------
  254. void CBuildingStatusItem::OnTick()
  255. {
  256. // We only tick while active and with a valid built object
  257. C_BaseObject *pObj = GetRepresentativeObject();
  258. if ( !pObj ) // implies not active
  259. {
  260. if ( m_bActive )
  261. {
  262. // we lost our object. force relayout to inactive mode
  263. InvalidateLayout();
  264. // tell our parent that we're gone
  265. IGameEvent *event = gameeventmanager->CreateEvent( "building_info_changed" );
  266. if ( event )
  267. {
  268. event->SetInt( "building_type", GetRepresentativeObjectType() );
  269. event->SetInt( "object_mode", GetRepresentativeObjectMode() );
  270. gameeventmanager->FireEventClientSide( event );
  271. }
  272. }
  273. // We don't want to tick while inactive regardless
  274. return;
  275. }
  276. float flHealth = (float)pObj->GetHealth() / (float)pObj->GetMaxHealth();
  277. m_pHealthBar->SetProgress( flHealth );
  278. if ( pObj->IsBuilding() )
  279. {
  280. m_pBuildingPanel->SetVisible( true );
  281. m_pRunningPanel->SetVisible( false );
  282. m_pBuildingProgress->SetProgress( pObj->GetPercentageConstructed() );
  283. }
  284. else
  285. {
  286. m_pBuildingPanel->SetVisible( false );
  287. m_pRunningPanel->SetVisible( true );
  288. }
  289. // what is our current alert state?
  290. BuildingHudAlert_t alertLevel = pObj->GetBuildingAlertLevel();
  291. if ( alertLevel <= BUILDING_HUD_ALERT_NONE )
  292. {
  293. // if the tray is out, hide it
  294. if ( m_pAlertTray->IsTrayOut() )
  295. {
  296. m_pAlertTray->HideTray();
  297. m_pWrenchIcon->SetVisible( false );
  298. m_pSapperIcon->SetVisible( false );
  299. }
  300. }
  301. else
  302. {
  303. m_pWrenchIcon->SetVisible( false );
  304. m_pSapperIcon->SetVisible( false );
  305. bool bShowAlertTray = false;
  306. bool bAlertTrayFullyDeployed = m_pAlertTray->GetPercentDeployed() >= 1.0f;
  307. switch( alertLevel )
  308. {
  309. // show low ammo for normal sentry and mini-sentry
  310. case BUILDING_HUD_ALERT_LOW_AMMO:
  311. case BUILDING_HUD_ALERT_VERY_LOW_AMMO:
  312. bShowAlertTray = true;
  313. m_pWrenchIcon->SetVisible( bAlertTrayFullyDeployed );
  314. break;
  315. // do not show low health for mini-sentry
  316. case BUILDING_HUD_ALERT_LOW_HEALTH:
  317. case BUILDING_HUD_ALERT_VERY_LOW_HEALTH:
  318. bShowAlertTray = pObj->IsMiniBuilding() == false;
  319. m_pWrenchIcon->SetVisible( bAlertTrayFullyDeployed && bShowAlertTray );
  320. break;
  321. // always show when being sapped
  322. case BUILDING_HUD_ALERT_SAPPER:
  323. bShowAlertTray = true;
  324. m_pSapperIcon->SetVisible( bAlertTrayFullyDeployed );
  325. break;
  326. default:
  327. bShowAlertTray = false;
  328. break;
  329. }
  330. if ( bShowAlertTray && !pObj->IsDisposableBuilding() )
  331. {
  332. if ( !m_pAlertTray->IsTrayOut() )
  333. {
  334. m_pAlertTray->ShowTray();
  335. }
  336. m_pAlertTray->SetAlertType( alertLevel );
  337. }
  338. else
  339. {
  340. if ( m_pAlertTray->IsTrayOut() )
  341. {
  342. m_pAlertTray->HideTray();
  343. }
  344. m_pAlertTray->SetAlertType( BUILDING_HUD_ALERT_NONE );
  345. }
  346. }
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Purpose:
  350. //-----------------------------------------------------------------------------
  351. C_BaseObject *CBuildingStatusItem::GetRepresentativeObject( void )
  352. {
  353. if ( !m_bActive )
  354. {
  355. return NULL;
  356. }
  357. else
  358. {
  359. return m_pObject.Get();
  360. }
  361. }
  362. //-----------------------------------------------------------------------------
  363. // Purpose:
  364. //-----------------------------------------------------------------------------
  365. int CBuildingStatusItem::GetRepresentativeObjectType( void )
  366. {
  367. return m_iObjectType;
  368. }
  369. //-----------------------------------------------------------------------------
  370. // Purpose:
  371. //-----------------------------------------------------------------------------
  372. int CBuildingStatusItem::GetRepresentativeObjectMode( void )
  373. {
  374. return m_iObjectMode;
  375. }
  376. //-----------------------------------------------------------------------------
  377. // Purpose:
  378. //-----------------------------------------------------------------------------
  379. int CBuildingStatusItem::GetObjectPriority( void )
  380. {
  381. int nPriority = GetObjectInfo( GetRepresentativeObjectType() )->m_iDisplayPriority;
  382. // MvM hack to sort buildings properly since we can have more than one sentry via upgrades
  383. if ( GetRepresentativeObjectType() == OBJ_SENTRYGUN && GetRepresentativeObjectMode() == MODE_SENTRYGUN_DISPOSABLE )
  384. {
  385. nPriority = 0;
  386. }
  387. return nPriority;
  388. }
  389. //============================================================================
  390. DECLARE_BUILD_FACTORY( CBuildingStatusAlertTray );
  391. //-----------------------------------------------------------------------------
  392. // Purpose:
  393. //-----------------------------------------------------------------------------
  394. CBuildingStatusAlertTray::CBuildingStatusAlertTray(Panel *parent, const char *panelName) : BaseClass( parent, panelName )
  395. {
  396. m_pAlertPanelMaterial = NULL;
  397. m_flAlertDeployedPercent = 0.0f;
  398. m_bIsTrayOut = false;
  399. m_pAlertPanelHudTexture = NULL;
  400. m_pAlertPanelMaterial = NULL;
  401. }
  402. //-----------------------------------------------------------------------------
  403. // Purpose:
  404. //-----------------------------------------------------------------------------
  405. void CBuildingStatusAlertTray::ApplySettings( KeyValues *inResourceData )
  406. {
  407. m_pAlertPanelHudTexture = gHUD.GetIcon( inResourceData->GetString( "icon", "" ) );
  408. if ( m_pAlertPanelHudTexture )
  409. {
  410. m_pAlertPanelMaterial = materials->FindMaterial( m_pAlertPanelHudTexture->szTextureFile, TEXTURE_GROUP_VGUI );
  411. }
  412. BaseClass::ApplySettings( inResourceData );
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Purpose:
  416. //-----------------------------------------------------------------------------
  417. void CBuildingStatusAlertTray::Paint( void )
  418. {
  419. // Paint the alert tray
  420. if ( !m_pAlertPanelMaterial || !m_pAlertPanelHudTexture )
  421. {
  422. return;
  423. }
  424. int x = 0;
  425. int y = 0;
  426. ipanel()->GetAbsPos(GetVPanel(), x,y );
  427. int iWidth = GetWide();
  428. int iHeight = GetTall();
  429. // Position the alert panel image based on the deployed percent
  430. float flXa = m_pAlertPanelHudTexture->texCoords[0];
  431. float flXb = m_pAlertPanelHudTexture->texCoords[2];
  432. float flYa = m_pAlertPanelHudTexture->texCoords[1];
  433. float flYb = m_pAlertPanelHudTexture->texCoords[3];
  434. float flMaskXa = flXa;
  435. float flMaskXb = flXb;
  436. float flMaskYa = flYa;
  437. float flMaskYb = flYb;
  438. float flFrameDelta = ( flXb - flXa ) * ( 1.0 - m_flAlertDeployedPercent );
  439. flXa += flFrameDelta;
  440. flXb += flFrameDelta;
  441. CMatRenderContextPtr pRenderContext( materials );
  442. pRenderContext->Bind( m_pAlertPanelMaterial );
  443. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  444. int r, g, b, a;
  445. r = a = 255;
  446. switch( m_lastAlertType )
  447. {
  448. case BUILDING_HUD_ALERT_VERY_LOW_AMMO:
  449. case BUILDING_HUD_ALERT_VERY_LOW_HEALTH:
  450. g = b = (int)( 127.0f + 127.0f * cos( gpGlobals->curtime * 2.0f * M_PI * 0.5 ) );
  451. break;
  452. case BUILDING_HUD_ALERT_SAPPER:
  453. g = b = (int)( 127.0f + 127.0f * cos( gpGlobals->curtime * 2.0f * M_PI * 1.5 ) );
  454. break;
  455. case BUILDING_HUD_ALERT_LOW_AMMO:
  456. case BUILDING_HUD_ALERT_LOW_HEALTH:
  457. case BUILDING_HUD_ALERT_NONE:
  458. default:
  459. g = b = 255;
  460. break;
  461. }
  462. CMeshBuilder meshBuilder;
  463. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  464. meshBuilder.Position3f( x, y, 0.0f );
  465. meshBuilder.TexCoord2f( 0, flXa, flYa );
  466. meshBuilder.TexCoord2f( 1, flMaskXa, flMaskYa );
  467. meshBuilder.Color4ub( r, g, b, a );
  468. meshBuilder.AdvanceVertex();
  469. meshBuilder.Position3f( x + iWidth, y, 0.0f );
  470. meshBuilder.TexCoord2f( 0, flXb, flYa );
  471. meshBuilder.TexCoord2f( 1, flMaskXb, flMaskYa );
  472. meshBuilder.Color4ub( r, g, b, a );
  473. meshBuilder.AdvanceVertex();
  474. meshBuilder.Position3f( x + iWidth, y + iHeight, 0.0f );
  475. meshBuilder.TexCoord2f( 0, flXb, flYb );
  476. meshBuilder.TexCoord2f( 1, flMaskXb, flMaskYb );
  477. meshBuilder.Color4ub( r, g, b, a );
  478. meshBuilder.AdvanceVertex();
  479. meshBuilder.Position3f( x, y + iHeight, 0.0f );
  480. meshBuilder.TexCoord2f( 0, flXa, flYb );
  481. meshBuilder.TexCoord2f( 1, flMaskXa, flMaskYb );
  482. meshBuilder.Color4ub( r, g, b, a );
  483. meshBuilder.AdvanceVertex();
  484. meshBuilder.End();
  485. pMesh->Draw();
  486. }
  487. void CBuildingStatusAlertTray::PaintBackground( void )
  488. {
  489. }
  490. void CBuildingStatusAlertTray::ShowTray( void )
  491. {
  492. if ( m_bIsTrayOut == false )
  493. {
  494. m_flAlertDeployedPercent = 0.0;
  495. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( this, "deployed", 1.0, 0.0, 0.3, AnimationController::INTERPOLATOR_LINEAR );
  496. m_bIsTrayOut = true;
  497. }
  498. }
  499. void CBuildingStatusAlertTray::HideTray( void )
  500. {
  501. if ( m_bIsTrayOut == true )
  502. {
  503. m_flAlertDeployedPercent = 1.0;
  504. g_pClientMode->GetViewportAnimationController()->RunAnimationCommand( this, "deployed", 0.0, 0.0, 0.3, AnimationController::INTERPOLATOR_LINEAR );
  505. m_bIsTrayOut = false;
  506. }
  507. }
  508. //-----------------------------------------------------------------------------
  509. // Purpose: Setup
  510. //-----------------------------------------------------------------------------
  511. void CBuildingStatusAlertTray::LevelInit( void )
  512. {
  513. m_bIsTrayOut = false;
  514. m_flAlertDeployedPercent = 0.0f;
  515. }
  516. void CBuildingStatusAlertTray::SetAlertType( BuildingHudAlert_t alertLevel )
  517. {
  518. m_lastAlertType = alertLevel;
  519. }
  520. //============================================================================
  521. //-----------------------------------------------------------------------------
  522. // Purpose:
  523. //-----------------------------------------------------------------------------
  524. CBuildingStatusItem_SentryGun::CBuildingStatusItem_SentryGun( Panel *parent ) :
  525. CBuildingStatusItem( parent, "resource/UI/hud_obj_sentrygun.res", OBJ_SENTRYGUN, MODE_SENTRYGUN_NORMAL )
  526. {
  527. m_pShellsProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Shells" );
  528. m_pRocketsProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Rockets" );
  529. m_pUpgradeProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Upgrade" );
  530. m_pRocketIcon = new vgui::ImagePanel( GetRunningPanel(), "RocketIcon" );
  531. m_pUpgradeIcon = new CIconPanel( GetRunningPanel(), "UpgradeIcon" );
  532. m_pSentryIcons[0] = new CIconPanel( this, "Icon_Sentry_1" );
  533. m_pSentryIcons[1] = new CIconPanel( this, "Icon_Sentry_2" );
  534. m_pSentryIcons[2] = new CIconPanel( this, "Icon_Sentry_3" );
  535. m_iUpgradeLevel = 1;
  536. }
  537. //-----------------------------------------------------------------------------
  538. // Purpose:
  539. //-----------------------------------------------------------------------------
  540. void CBuildingStatusItem_SentryGun::ApplySchemeSettings( vgui::IScheme *scheme )
  541. {
  542. BaseClass::ApplySchemeSettings( scheme );
  543. m_cLowAmmoColor = scheme->GetColor( "LowHealthRed", Color(255,0,0,255) );
  544. m_cNormalAmmoColor = scheme->GetColor( "ProgressOffWhite", Color(255,255,255,255) );
  545. }
  546. //-----------------------------------------------------------------------------
  547. // Purpose: Calc visibility of subpanels
  548. //-----------------------------------------------------------------------------
  549. void CBuildingStatusItem_SentryGun::PerformLayout( void )
  550. {
  551. BaseClass::PerformLayout();
  552. C_ObjectSentrygun *pSentrygun = dynamic_cast<C_ObjectSentrygun *>( GetRepresentativeObject() );
  553. if ( !pSentrygun || ( pSentrygun && pSentrygun->IsDisposableBuilding() ) )
  554. {
  555. return;
  556. }
  557. GetRunningPanel()->SetDialogVariable( "numkills", pSentrygun->GetKills() );
  558. GetRunningPanel()->SetDialogVariable( "numassists", pSentrygun->GetAssists() );
  559. int iShells, iMaxShells;
  560. int iRockets, iMaxRockets;
  561. pSentrygun->GetAmmoCount( iShells, iMaxShells, iRockets, iMaxRockets );
  562. // Shells label
  563. float flShells = (float)iShells / (float)iMaxShells;
  564. m_pShellsProgress->SetProgress( flShells );
  565. if ( flShells < 0.25f )
  566. {
  567. m_pShellsProgress->SetFgColor( m_cLowAmmoColor );
  568. }
  569. else
  570. {
  571. m_pShellsProgress->SetFgColor( m_cNormalAmmoColor );
  572. }
  573. // Rockets label
  574. float flRockets = (float)iRockets / (float)SENTRYGUN_MAX_ROCKETS;
  575. m_pRocketsProgress->SetProgress( flRockets );
  576. if ( flRockets < 0.25f )
  577. {
  578. m_pRocketsProgress->SetFgColor( m_cLowAmmoColor );
  579. }
  580. else
  581. {
  582. m_pRocketsProgress->SetFgColor( m_cNormalAmmoColor );
  583. }
  584. int iUpgradeLevel = pSentrygun->GetUpgradeLevel();
  585. Assert( iUpgradeLevel >= 1 && iUpgradeLevel <= 3 );
  586. // show the correct icon
  587. m_pSentryIcons[0]->SetVisible( false );
  588. m_pSentryIcons[1]->SetVisible( false );
  589. m_pSentryIcons[2]->SetVisible( false );
  590. m_pSentryIcons[iUpgradeLevel-1]->SetVisible( true );
  591. // upgrade progress
  592. int iMetal = pSentrygun->GetUpgradeMetal();
  593. int iMetalRequired = pSentrygun->GetUpgradeMetalRequired();
  594. float flUpgrade = (float)iMetal / (float)iMetalRequired;
  595. m_pUpgradeProgress->SetProgress( flUpgrade );
  596. // upgrade label only in 1 or 2
  597. m_pUpgradeIcon->SetVisible( iUpgradeLevel < 3 );
  598. m_pUpgradeProgress->SetVisible( iUpgradeLevel < 3 );
  599. // rockets label only in 3
  600. m_pRocketIcon->SetVisible( iUpgradeLevel == 3 );
  601. m_pRocketsProgress->SetVisible( iUpgradeLevel == 3 );
  602. }
  603. //-----------------------------------------------------------------------------
  604. // Purpose:
  605. //-----------------------------------------------------------------------------
  606. void CBuildingStatusItem_SentryGun::OnTick()
  607. {
  608. BaseClass::OnTick();
  609. }
  610. //-----------------------------------------------------------------------------
  611. // Purpose:
  612. //-----------------------------------------------------------------------------
  613. const char *CBuildingStatusItem_SentryGun::GetBackgroundImage( void )
  614. {
  615. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  616. const char *pResult = "obj_status_background_tall_blue";
  617. if ( !pLocalPlayer )
  618. {
  619. return pResult;
  620. }
  621. switch( pLocalPlayer->GetTeamNumber() )
  622. {
  623. case TF_TEAM_BLUE:
  624. pResult = "obj_status_background_tall_blue";
  625. break;
  626. case TF_TEAM_RED:
  627. pResult = "obj_status_background_tall_red";
  628. break;
  629. default:
  630. break;
  631. }
  632. return pResult;
  633. }
  634. //-----------------------------------------------------------------------------
  635. // Purpose:
  636. //-----------------------------------------------------------------------------
  637. const char *CBuildingStatusItem_SentryGun::GetInactiveBackgroundImage( void )
  638. {
  639. return "obj_status_background_tall_disabled";
  640. }
  641. //============================================================================
  642. //-----------------------------------------------------------------------------
  643. // Purpose:
  644. //-----------------------------------------------------------------------------
  645. CBuildingStatusItem_SentryGun_Disposable::CBuildingStatusItem_SentryGun_Disposable( Panel *parent ) :
  646. CBuildingStatusItem( parent, "resource/UI/hud_obj_sentrygun_disp.res", OBJ_SENTRYGUN, MODE_SENTRYGUN_DISPOSABLE )
  647. {
  648. m_pShellsProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Shells" );
  649. m_pUpgradeIcon = new CIconPanel( GetRunningPanel(), "UpgradeIcon" );
  650. m_pSentryIcons[0] = new CIconPanel( this, "Icon_Sentry_1" );
  651. m_pSentryIcons[1] = new CIconPanel( this, "Icon_Sentry_2" );
  652. m_pSentryIcons[2] = new CIconPanel( this, "Icon_Sentry_3" );
  653. m_iUpgradeLevel = 1;
  654. }
  655. //-----------------------------------------------------------------------------
  656. // Purpose:
  657. //-----------------------------------------------------------------------------
  658. void CBuildingStatusItem_SentryGun_Disposable::ApplySchemeSettings( vgui::IScheme *scheme )
  659. {
  660. BaseClass::ApplySchemeSettings( scheme );
  661. m_cLowAmmoColor = scheme->GetColor( "LowHealthRed", Color(255,0,0,255) );
  662. m_cNormalAmmoColor = scheme->GetColor( "ProgressOffWhite", Color(255,255,255,255) );
  663. }
  664. //-----------------------------------------------------------------------------
  665. // Purpose: Calc visibility of subpanels
  666. //-----------------------------------------------------------------------------
  667. void CBuildingStatusItem_SentryGun_Disposable::PerformLayout( void )
  668. {
  669. BaseClass::PerformLayout();
  670. C_ObjectSentrygun *pSentrygun = dynamic_cast<C_ObjectSentrygun *>( GetRepresentativeObject() );
  671. if ( !pSentrygun || ( pSentrygun && !pSentrygun->IsDisposableBuilding() ) )
  672. {
  673. return;
  674. }
  675. GetRunningPanel()->SetDialogVariable( "numkills", pSentrygun->GetKills() );
  676. GetRunningPanel()->SetDialogVariable( "numassists", pSentrygun->GetAssists() );
  677. int iShells, iMaxShells;
  678. int iRockets, iMaxRockets;
  679. pSentrygun->GetAmmoCount( iShells, iMaxShells, iRockets, iMaxRockets );
  680. // Shells label
  681. float flShells = (float)iShells / (float)iMaxShells;
  682. m_pShellsProgress->SetProgress( flShells );
  683. if ( flShells < 0.25f )
  684. {
  685. m_pShellsProgress->SetFgColor( m_cLowAmmoColor );
  686. }
  687. else
  688. {
  689. m_pShellsProgress->SetFgColor( m_cNormalAmmoColor );
  690. }
  691. int iUpgradeLevel = pSentrygun->GetUpgradeLevel();
  692. Assert( iUpgradeLevel >= 1 && iUpgradeLevel <= 3 );
  693. // show the correct icon
  694. m_pSentryIcons[0]->SetVisible( false );
  695. m_pSentryIcons[1]->SetVisible( false );
  696. m_pSentryIcons[2]->SetVisible( false );
  697. m_pSentryIcons[iUpgradeLevel-1]->SetVisible( true );
  698. m_pUpgradeIcon->SetEnabled( false );
  699. }
  700. //-----------------------------------------------------------------------------
  701. // Purpose:
  702. //-----------------------------------------------------------------------------
  703. void CBuildingStatusItem_SentryGun_Disposable::OnTick()
  704. {
  705. BaseClass::OnTick();
  706. }
  707. //-----------------------------------------------------------------------------
  708. // Purpose:
  709. //-----------------------------------------------------------------------------
  710. const char *CBuildingStatusItem_SentryGun_Disposable::GetBackgroundImage( void )
  711. {
  712. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  713. const char *pResult = "obj_status_background_tall_blue";
  714. if ( !pLocalPlayer )
  715. {
  716. return pResult;
  717. }
  718. switch( pLocalPlayer->GetTeamNumber() )
  719. {
  720. case TF_TEAM_BLUE:
  721. pResult = "obj_status_background_blue";
  722. break;
  723. case TF_TEAM_RED:
  724. pResult = "obj_status_background_red";
  725. break;
  726. default:
  727. break;
  728. }
  729. return pResult;
  730. }
  731. //-----------------------------------------------------------------------------
  732. // Purpose:
  733. //-----------------------------------------------------------------------------
  734. const char *CBuildingStatusItem_SentryGun_Disposable::GetInactiveBackgroundImage( void )
  735. {
  736. return "obj_status_background_disabled";
  737. }
  738. //============================================================================
  739. //-----------------------------------------------------------------------------
  740. // Purpose:
  741. //-----------------------------------------------------------------------------
  742. CBuildingStatusItem_Dispenser::CBuildingStatusItem_Dispenser( Panel *parent ) :
  743. CBuildingStatusItem( parent, "resource/UI/hud_obj_dispenser.res", OBJ_DISPENSER )
  744. {
  745. m_pAmmoProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Ammo" );
  746. m_pUpgradeProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Upgrade" );
  747. m_pUpgradeIcon = new CIconPanel( GetRunningPanel(), "UpgradeIcon" );
  748. }
  749. //-----------------------------------------------------------------------------
  750. // Purpose: Calc visibility of subpanels
  751. //-----------------------------------------------------------------------------
  752. void CBuildingStatusItem_Dispenser::PerformLayout( void )
  753. {
  754. BaseClass::PerformLayout();
  755. C_ObjectDispenser *pDispenser = static_cast<C_ObjectDispenser*>(GetRepresentativeObject());
  756. if ( !pDispenser )
  757. {
  758. return;
  759. }
  760. int iAmmo = pDispenser->GetMetalAmmoCount();
  761. float flMaxMetal = pDispenser->IsMiniBuilding() ? MINI_DISPENSER_MAX_METAL : DISPENSER_MAX_METAL_AMMO;
  762. float flProgress = (float)iAmmo / flMaxMetal;
  763. m_pAmmoProgress->SetProgress( flProgress );
  764. int iUpgradeLevel = pDispenser->GetUpgradeLevel();
  765. Assert( iUpgradeLevel >= 1 && iUpgradeLevel <= 3 );
  766. // upgrade progress
  767. int iMetal = pDispenser->GetUpgradeMetal();
  768. int iMetalRequired = pDispenser->GetUpgradeMetalRequired();
  769. flProgress = (float)iMetal / (float)iMetalRequired;
  770. m_pUpgradeProgress->SetProgress( flProgress );
  771. // upgrade label only in 1 or 2
  772. bool bShowUpgradeInfo = iUpgradeLevel < 3;
  773. m_pUpgradeIcon->SetVisible( bShowUpgradeInfo );
  774. m_pUpgradeProgress->SetVisible( bShowUpgradeInfo );
  775. }
  776. //============================================================================
  777. //-----------------------------------------------------------------------------
  778. // Purpose:
  779. //-----------------------------------------------------------------------------
  780. CBuildingStatusItem_TeleporterEntrance::CBuildingStatusItem_TeleporterEntrance( Panel *parent ) :
  781. CBuildingStatusItem( parent, "resource/UI/hud_obj_tele_entrance.res", OBJ_TELEPORTER, MODE_TELEPORTER_ENTRANCE )
  782. {
  783. // Panel and children when we are charging
  784. m_pChargingPanel = new vgui::EditablePanel( GetRunningPanel(), "ChargingPanel" );
  785. m_pRechargeTimer = new vgui::ContinuousProgressBar( m_pChargingPanel, "Recharge" );
  786. // Panel and children when we are fully charged
  787. m_pFullyChargedPanel = new vgui::EditablePanel( GetRunningPanel(), "FullyChargedPanel" );
  788. m_iTimesUsed = -1; // force first update of 0
  789. m_iTeleporterState = -1;
  790. m_pUpgradeProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Upgrade" );
  791. m_pUpgradeIcon = new CIconPanel( GetRunningPanel(), "UpgradeIcon" );
  792. vgui::ivgui()->AddTickSignal( GetVPanel() );
  793. }
  794. //-----------------------------------------------------------------------------
  795. // Purpose:
  796. //-----------------------------------------------------------------------------
  797. void CBuildingStatusItem_TeleporterEntrance::OnTick( void )
  798. {
  799. // We only tick while active and with a valid built object
  800. C_ObjectTeleporter *pTeleporter = static_cast<C_ObjectTeleporter*>(GetRepresentativeObject());
  801. if ( pTeleporter && IsActive() )
  802. {
  803. if ( pTeleporter->GetState() == TELEPORTER_STATE_RECHARGING )
  804. {
  805. // Update the recharge
  806. float flMaxRecharge = pTeleporter->GetCurrentRechargeDuration();
  807. float flChargeTime = pTeleporter->GetChargeTime();
  808. m_pRechargeTimer->SetProgress( 1.0 - ( flChargeTime / flMaxRecharge ) );
  809. }
  810. }
  811. BaseClass::OnTick();
  812. }
  813. //-----------------------------------------------------------------------------
  814. // Purpose:
  815. //-----------------------------------------------------------------------------
  816. void CBuildingStatusItem_TeleporterEntrance::PerformLayout( void )
  817. {
  818. BaseClass::PerformLayout();
  819. // We only tick while active and with a valid built object
  820. C_ObjectTeleporter *pTeleporter = static_cast<C_ObjectTeleporter*>(GetRepresentativeObject());
  821. if ( !IsActive() || !pTeleporter )
  822. {
  823. return;
  824. }
  825. bool bRecharging = ( pTeleporter->GetState() == TELEPORTER_STATE_RECHARGING );
  826. m_pChargingPanel->SetVisible( bRecharging );
  827. m_pFullyChargedPanel->SetVisible( !bRecharging );
  828. // How many times has this teleporter been used?
  829. m_pFullyChargedPanel->SetDialogVariable( "timesused", pTeleporter->GetTimesUsed() );
  830. int iUpgradeLevel = pTeleporter->GetUpgradeLevel();
  831. Assert( iUpgradeLevel >= 1 && iUpgradeLevel <= 3 );
  832. // upgrade progress
  833. int iMetal = pTeleporter->GetUpgradeMetal();
  834. int iMetalRequired = pTeleporter->GetUpgradeMetalRequired();
  835. float flUpgrade = (float)iMetal / (float)iMetalRequired;
  836. m_pUpgradeProgress->SetProgress( flUpgrade );
  837. // upgrade label only in 1 or 2
  838. m_pUpgradeIcon->SetVisible( iUpgradeLevel < 3 );
  839. m_pUpgradeProgress->SetVisible( iUpgradeLevel < 3 );
  840. }
  841. //============================================================================
  842. CBuildingStatusItem_TeleporterExit::CBuildingStatusItem_TeleporterExit( Panel *parent ) :
  843. CBuildingStatusItem( parent, "resource/UI/hud_obj_tele_exit.res", OBJ_TELEPORTER, MODE_TELEPORTER_EXIT )
  844. {
  845. m_pUpgradeProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Upgrade" );
  846. m_pUpgradeIcon = new CIconPanel( GetRunningPanel(), "UpgradeIcon" );
  847. }
  848. //-----------------------------------------------------------------------------
  849. // Purpose:
  850. //-----------------------------------------------------------------------------
  851. void CBuildingStatusItem_TeleporterExit::PerformLayout( void )
  852. {
  853. BaseClass::PerformLayout();
  854. // We only tick while active and with a valid built object
  855. C_ObjectTeleporter *pTeleporter = static_cast<C_ObjectTeleporter*>(GetRepresentativeObject());
  856. if ( !IsActive() || !pTeleporter )
  857. {
  858. return;
  859. }
  860. int iUpgradeLevel = pTeleporter->GetUpgradeLevel();
  861. Assert( iUpgradeLevel >= 1 && iUpgradeLevel <= 3 );
  862. // upgrade progress
  863. int iMetal = pTeleporter->GetUpgradeMetal();
  864. int iMetalRequired = pTeleporter->GetUpgradeMetalRequired();
  865. float flUpgrade = (float)iMetal / (float)iMetalRequired;
  866. m_pUpgradeProgress->SetProgress( flUpgrade );
  867. // upgrade label only in 1 or 2
  868. m_pUpgradeIcon->SetVisible( iUpgradeLevel < 3 );
  869. m_pUpgradeProgress->SetVisible( iUpgradeLevel < 3 );
  870. }
  871. #ifdef STAGING_ONLY
  872. //============================================================================
  873. CBuildingStatusItem_TeleporterSpeed::CBuildingStatusItem_TeleporterSpeed( Panel *parent, int ETeleporterMode ) :
  874. CBuildingStatusItem( parent, "resource/UI/hud_obj_tele_speedpad.res", OBJ_TELEPORTER, ETeleporterMode )
  875. {
  876. // Panel and children when we are charging
  877. m_pChargingPanel = new vgui::EditablePanel( GetRunningPanel(), "ChargingPanel" );
  878. m_pRechargeTimer = new vgui::ContinuousProgressBar( m_pChargingPanel, "Recharge" );
  879. // Panel and children when we are fully charged
  880. m_pFullyChargedPanel = new vgui::EditablePanel( GetRunningPanel(), "FullyChargedPanel" );
  881. m_iTimesUsed = -1; // force first update of 0
  882. m_iTeleporterState = -1;
  883. m_pUpgradeProgress = new vgui::ContinuousProgressBar( GetRunningPanel(), "Upgrade" );
  884. m_pUpgradeIcon = new CIconPanel( GetRunningPanel(), "UpgradeIcon" );
  885. vgui::ivgui()->AddTickSignal( GetVPanel() );
  886. }
  887. //-----------------------------------------------------------------------------
  888. // Purpose:
  889. //-----------------------------------------------------------------------------
  890. void CBuildingStatusItem_TeleporterSpeed::OnTick( void )
  891. {
  892. // We only tick while active and with a valid built object
  893. C_ObjectTeleporter *pTeleporter = static_cast<C_ObjectTeleporter*>( GetRepresentativeObject() );
  894. if ( pTeleporter && IsActive() )
  895. {
  896. if ( pTeleporter->GetState() == TELEPORTER_STATE_RECHARGING )
  897. {
  898. // Update the recharge
  899. float flMaxRecharge = pTeleporter->GetCurrentRechargeDuration();
  900. float flChargeTime = pTeleporter->GetChargeTime();
  901. m_pRechargeTimer->SetProgress( 1.0 - ( flChargeTime / flMaxRecharge ) );
  902. }
  903. }
  904. BaseClass::OnTick();
  905. }
  906. //-----------------------------------------------------------------------------
  907. // Purpose:
  908. //-----------------------------------------------------------------------------
  909. void CBuildingStatusItem_TeleporterSpeed::PerformLayout( void )
  910. {
  911. BaseClass::PerformLayout();
  912. // We only tick while active and with a valid built object
  913. C_ObjectTeleporter *pTeleporter = static_cast<C_ObjectTeleporter*>( GetRepresentativeObject() );
  914. if ( !IsActive() || !pTeleporter )
  915. {
  916. return;
  917. }
  918. bool bRecharging = ( pTeleporter->GetState() == TELEPORTER_STATE_RECHARGING );
  919. m_pChargingPanel->SetVisible( bRecharging );
  920. m_pFullyChargedPanel->SetVisible( !bRecharging );
  921. // How many times has this teleporter been used?
  922. m_pFullyChargedPanel->SetDialogVariable( "timesused", pTeleporter->GetTimesUsed() );
  923. int iUpgradeLevel = pTeleporter->GetUpgradeLevel();
  924. Assert( iUpgradeLevel >= 1 && iUpgradeLevel <= 3 );
  925. // upgrade progress
  926. int iMetal = pTeleporter->GetUpgradeMetal();
  927. int iMetalRequired = pTeleporter->GetUpgradeMetalRequired();
  928. float flUpgrade = (float)iMetal / (float)iMetalRequired;
  929. m_pUpgradeProgress->SetProgress( flUpgrade );
  930. // upgrade label only in 1 or 2
  931. m_pUpgradeIcon->SetVisible( iUpgradeLevel < 3 );
  932. m_pUpgradeProgress->SetVisible( iUpgradeLevel < 3 );
  933. }
  934. #endif
  935. //-----------------------------------------------------------------------------
  936. // Purpose:
  937. //-----------------------------------------------------------------------------
  938. CBuildingStatusItem_Sapper::CBuildingStatusItem_Sapper( Panel *parent ) :
  939. CBuildingStatusItem( parent, "resource/UI/hud_obj_sapper.res", OBJ_ATTACHMENT_SAPPER )
  940. {
  941. // health of target building
  942. m_pTargetHealthBar = new ContinuousProgressBar( GetRunningPanel(), "TargetHealth" );
  943. // image of target building
  944. m_pTargetIcon = new CIconPanel( GetRunningPanel(), "TargetIcon" );
  945. // force first think to set the icon
  946. m_iTargetType = -1;
  947. }
  948. void CBuildingStatusItem_Sapper::PerformLayout( void )
  949. {
  950. BaseClass::PerformLayout();
  951. // We only tick while active and with a valid built object
  952. C_ObjectSapper *pSapper = static_cast<C_ObjectSapper*>(GetRepresentativeObject());
  953. // only visible
  954. SetVisible( pSapper != NULL );
  955. if ( !IsActive() || !pSapper )
  956. {
  957. return;
  958. }
  959. C_BaseObject *pTarget = pSapper->GetParentObject();
  960. if ( pTarget )
  961. {
  962. float flHealth = (float)pTarget->GetHealth() / (float)pTarget->GetMaxHealth();
  963. m_pTargetHealthBar->SetProgress( flHealth );
  964. int iTargetType = pTarget->GetType();
  965. if ( m_iTargetType != iTargetType )
  966. {
  967. m_pTargetIcon->SetIcon( pTarget->GetHudStatusIcon() );
  968. m_iTargetType = iTargetType;
  969. }
  970. }
  971. else
  972. {
  973. m_pTargetHealthBar->SetProgress( 0.0f );
  974. }
  975. }
  976. //============================================================================
  977. DECLARE_HUDELEMENT( CHudBuildingStatusContainer_Spy );
  978. //-----------------------------------------------------------------------------
  979. // Purpose:
  980. //-----------------------------------------------------------------------------
  981. CHudBuildingStatusContainer_Spy::CHudBuildingStatusContainer_Spy( const char *pElementName ) :
  982. BaseClass( "BuildingStatus_Spy" )
  983. {
  984. AddBuildingPanel( OBJ_ATTACHMENT_SAPPER );
  985. }
  986. //-----------------------------------------------------------------------------
  987. // Purpose:
  988. //-----------------------------------------------------------------------------
  989. bool CHudBuildingStatusContainer_Spy::ShouldDraw( void )
  990. {
  991. // Don't draw in freezecam
  992. C_TFPlayer *pPlayer = CTFPlayer::GetLocalTFPlayer();
  993. if ( !pPlayer || !pPlayer->IsPlayerClass( TF_CLASS_SPY ) || pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM )
  994. {
  995. return false;
  996. }
  997. if ( pPlayer->GetTeamNumber() <= TEAM_SPECTATOR )
  998. {
  999. return false;
  1000. }
  1001. return CHudElement::ShouldDraw();
  1002. }
  1003. //============================================================================
  1004. DECLARE_HUDELEMENT( CHudBuildingStatusContainer_Engineer );
  1005. //-----------------------------------------------------------------------------
  1006. // Purpose:
  1007. //-----------------------------------------------------------------------------
  1008. CHudBuildingStatusContainer_Engineer::CHudBuildingStatusContainer_Engineer( const char *pElementName ) :
  1009. BaseClass( "BuildingStatus_Engineer" )
  1010. {
  1011. AddBuildingPanel( OBJ_SENTRYGUN, MODE_SENTRYGUN_NORMAL );
  1012. AddBuildingPanel( OBJ_DISPENSER );
  1013. AddBuildingPanel( OBJ_TELEPORTER, MODE_TELEPORTER_ENTRANCE );
  1014. AddBuildingPanel( OBJ_TELEPORTER, MODE_TELEPORTER_EXIT );
  1015. AddBuildingPanel( OBJ_SENTRYGUN, MODE_SENTRYGUN_DISPOSABLE );
  1016. #ifdef STAGING_ONLY
  1017. AddBuildingPanel( OBJ_TELEPORTER, MODE_TELEPORTER_SPEED );
  1018. AddBuildingPanel( OBJ_TELEPORTER, MODE_TELEPORTER_SPEED2 );
  1019. #endif
  1020. vgui::ivgui()->AddTickSignal( GetVPanel(), 500 );
  1021. }
  1022. //-----------------------------------------------------------------------------
  1023. // Purpose:
  1024. //-----------------------------------------------------------------------------
  1025. bool CHudBuildingStatusContainer_Engineer::ShouldDraw( void )
  1026. {
  1027. // Don't draw in freezecam
  1028. C_TFPlayer *pPlayer = CTFPlayer::GetLocalTFPlayer();
  1029. if ( !pPlayer || !pPlayer->IsPlayerClass( TF_CLASS_ENGINEER ) || pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM )
  1030. return false;
  1031. if ( pPlayer->GetTeamNumber() <= TEAM_SPECTATOR )
  1032. return false;
  1033. if ( CTFMinigameLogic::GetMinigameLogic() && CTFMinigameLogic::GetMinigameLogic()->GetActiveMinigame() )
  1034. return false;
  1035. if ( TFGameRules() && TFGameRules()->ShowMatchSummary() )
  1036. return false;
  1037. return CHudElement::ShouldDraw();
  1038. }
  1039. //-----------------------------------------------------------------------------
  1040. // Purpose:
  1041. //-----------------------------------------------------------------------------
  1042. void CHudBuildingStatusContainer_Engineer::OnTick()
  1043. {
  1044. BaseClass::OnTick();
  1045. if ( !ShouldDraw() )
  1046. return;
  1047. C_TFPlayer *pLocalPlayer = CTFPlayer::GetLocalTFPlayer();
  1048. if ( pLocalPlayer )
  1049. {
  1050. bool bDisposableSentriesVisible = false;
  1051. if ( TFGameRules() && TFGameRules()->GameModeUsesUpgrades() )
  1052. {
  1053. int nDisposableSentries = 0;
  1054. CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, nDisposableSentries, engy_disposable_sentries );
  1055. if ( nDisposableSentries )
  1056. {
  1057. bDisposableSentriesVisible = true;
  1058. }
  1059. }
  1060. #ifdef STAGING_ONLY
  1061. int iSpeedPad = 0;
  1062. CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, iSpeedPad, teleporter_is_speedpad );
  1063. #endif // STAGING_ONLY
  1064. for ( int i = 0 ; i < m_BuildingPanels.Count() ; i++ )
  1065. {
  1066. CBuildingStatusItem *pItem = m_BuildingPanels.Element( i );
  1067. if ( pItem && ( pItem->GetRepresentativeObjectType() == OBJ_SENTRYGUN ) && ( pItem->GetRepresentativeObjectMode() == MODE_SENTRYGUN_DISPOSABLE ) )
  1068. {
  1069. if ( pItem->IsVisible() != bDisposableSentriesVisible )
  1070. {
  1071. pItem->SetVisible( bDisposableSentriesVisible );
  1072. }
  1073. #ifndef STAGING_ONLY
  1074. break;
  1075. #endif // !STAGING_ONLY
  1076. }
  1077. #ifdef STAGING_ONLY
  1078. // Disable entrance and exit
  1079. if ( pItem && ( pItem->GetRepresentativeObjectType() == OBJ_TELEPORTER ) )
  1080. {
  1081. if ( pItem->GetRepresentativeObjectMode() == MODE_TELEPORTER_SPEED || pItem->GetRepresentativeObjectMode() == MODE_TELEPORTER_SPEED2 )
  1082. {
  1083. pItem->SetVisible( iSpeedPad );
  1084. }
  1085. else
  1086. {
  1087. pItem->SetVisible( !(bool)(iSpeedPad) );
  1088. }
  1089. }
  1090. #endif // STAGING_ONLY
  1091. }
  1092. }
  1093. }
  1094. //============================================================================
  1095. // order the buildings in our m_BuildingsList by their object priority
  1096. typedef CBuildingStatusItem *BUILDINGSTATUSITEM_PTR;
  1097. static bool BuildingOrderLessFunc( const BUILDINGSTATUSITEM_PTR &left, const BUILDINGSTATUSITEM_PTR &right )
  1098. {
  1099. return ( left->GetObjectPriority() <= right->GetObjectPriority() );
  1100. }
  1101. //-----------------------------------------------------------------------------
  1102. // Purpose:
  1103. //-----------------------------------------------------------------------------
  1104. CHudBuildingStatusContainer::CHudBuildingStatusContainer( const char *pElementName ) :
  1105. CHudElement( pElementName ), BaseClass( NULL, pElementName )
  1106. {
  1107. vgui::Panel *pParent = g_pClientMode->GetViewport();
  1108. SetParent( pParent );
  1109. SetHiddenBits( HIDEHUD_MISCSTATUS );
  1110. SetProportional(true);
  1111. ListenForGameEvent( "building_info_changed" );
  1112. m_BuildingPanels.SetLessFunc( BuildingOrderLessFunc );
  1113. m_AlertLevel = BUILDING_HUD_ALERT_NONE;
  1114. m_flNextBeep = 0;
  1115. m_iNumBeepsToBeep = 0;
  1116. // for beeping
  1117. vgui::ivgui()->AddTickSignal( GetVPanel() );
  1118. }
  1119. //-----------------------------------------------------------------------------
  1120. // Purpose:
  1121. //-----------------------------------------------------------------------------
  1122. bool CHudBuildingStatusContainer::ShouldDraw( void )
  1123. {
  1124. // Don't draw in freezecam
  1125. C_TFPlayer *pPlayer = CTFPlayer::GetLocalTFPlayer();
  1126. if ( pPlayer && pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM )
  1127. return false;
  1128. return CHudElement::ShouldDraw();
  1129. }
  1130. //-----------------------------------------------------------------------------
  1131. // Purpose:
  1132. //-----------------------------------------------------------------------------
  1133. void CHudBuildingStatusContainer::LevelInit( void )
  1134. {
  1135. CHudElement::LevelInit();
  1136. for ( int i = 0; i < m_BuildingPanels.Count(); i++ )
  1137. {
  1138. CBuildingStatusItem *pItem = m_BuildingPanels.Element(i);
  1139. if ( pItem )
  1140. {
  1141. pItem->LevelInit();
  1142. }
  1143. }
  1144. }
  1145. //-----------------------------------------------------------------------------
  1146. // Purpose: Create the appropriate info panel for the object
  1147. //-----------------------------------------------------------------------------
  1148. CBuildingStatusItem *CHudBuildingStatusContainer::CreateItemPanel( int iObjectType, int iObjectMode )
  1149. {
  1150. CBuildingStatusItem *pBuildingItem = NULL;
  1151. switch( iObjectType )
  1152. {
  1153. case OBJ_SENTRYGUN:
  1154. if ( iObjectMode == 0 )
  1155. {
  1156. pBuildingItem = new CBuildingStatusItem_SentryGun( this );
  1157. }
  1158. else
  1159. {
  1160. pBuildingItem = new CBuildingStatusItem_SentryGun_Disposable( this );
  1161. }
  1162. break;
  1163. case OBJ_DISPENSER:
  1164. pBuildingItem = new CBuildingStatusItem_Dispenser( this );
  1165. break;
  1166. case OBJ_TELEPORTER:
  1167. if ( iObjectMode == 0 )
  1168. {
  1169. pBuildingItem = new CBuildingStatusItem_TeleporterEntrance( this );
  1170. }
  1171. else if ( iObjectMode == 1 )
  1172. {
  1173. pBuildingItem = new CBuildingStatusItem_TeleporterExit( this );
  1174. }
  1175. #ifdef STAGING_ONLY
  1176. else if ( iObjectMode == 2 )
  1177. {
  1178. pBuildingItem = new CBuildingStatusItem_TeleporterSpeed( this, MODE_TELEPORTER_SPEED );
  1179. }
  1180. else
  1181. {
  1182. pBuildingItem = new CBuildingStatusItem_TeleporterSpeed( this, MODE_TELEPORTER_SPEED2 );
  1183. }
  1184. #endif
  1185. break;
  1186. case OBJ_ATTACHMENT_SAPPER:
  1187. pBuildingItem = new CBuildingStatusItem_Sapper( this );
  1188. break;
  1189. default:
  1190. pBuildingItem = NULL;
  1191. break;
  1192. }
  1193. Assert( pBuildingItem );
  1194. return pBuildingItem;
  1195. }
  1196. //-----------------------------------------------------------------------------
  1197. // Purpose:
  1198. //-----------------------------------------------------------------------------
  1199. void CHudBuildingStatusContainer::AddBuildingPanel( int iObjectType, int iObjectMode )
  1200. {
  1201. CBuildingStatusItem *pBuildingItem = CreateItemPanel( iObjectType, iObjectMode );
  1202. Assert( pBuildingItem );
  1203. pBuildingItem->SetPos( 0, 0 );
  1204. pBuildingItem->InvalidateLayout();
  1205. m_BuildingPanels.Insert( pBuildingItem );
  1206. RepositionObjectPanels();
  1207. }
  1208. //-----------------------------------------------------------------------------
  1209. // Purpose:
  1210. //-----------------------------------------------------------------------------
  1211. void CHudBuildingStatusContainer::UpdateAllBuildings( void )
  1212. {
  1213. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1214. if ( !pLocalPlayer )
  1215. return;
  1216. for ( int i = 0; i < m_BuildingPanels.Count(); i++ )
  1217. {
  1218. CBuildingStatusItem *pItem = m_BuildingPanels.Element(i);
  1219. if ( pItem )
  1220. {
  1221. // find the item that represents this building type
  1222. C_BaseObject *pObj = NULL;
  1223. if ( pObj )
  1224. {
  1225. // find the object
  1226. pObj = pLocalPlayer->GetObjectOfType( pItem->GetRepresentativeObjectType(), pItem->GetRepresentativeObjectMode() );
  1227. pItem->SetObject( pObj );
  1228. pItem->InvalidateLayout( true );
  1229. RecalculateAlertState();
  1230. }
  1231. }
  1232. }
  1233. }
  1234. void CHudBuildingStatusContainer::OnBuildingChanged( int iBuildingType, int iBuildingMode, bool bBuildingIsDead )
  1235. {
  1236. bool bFound = false;
  1237. for ( int i = 0; i < m_BuildingPanels.Count() && !bFound; i++ )
  1238. {
  1239. CBuildingStatusItem *pItem = m_BuildingPanels.Element(i);
  1240. if ( pItem && pItem->GetRepresentativeObjectType() == iBuildingType && pItem->GetRepresentativeObjectMode() == iBuildingMode )
  1241. {
  1242. // find the item that represents this building type
  1243. C_BaseObject *pObj = NULL;
  1244. // find the object
  1245. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1246. if ( pLocalPlayer )
  1247. {
  1248. pObj = pLocalPlayer->GetObjectOfType( iBuildingType, iBuildingMode );
  1249. pItem->SetObject( pObj );
  1250. pItem->InvalidateLayout( true );
  1251. bFound = true;
  1252. RecalculateAlertState();
  1253. }
  1254. }
  1255. }
  1256. }
  1257. //-----------------------------------------------------------------------------
  1258. // Purpose:
  1259. //-----------------------------------------------------------------------------
  1260. void CHudBuildingStatusContainer::ApplySchemeSettings( vgui::IScheme *scheme )
  1261. {
  1262. BaseClass::ApplySchemeSettings( scheme );
  1263. SetPaintBackgroundEnabled( false );
  1264. RepositionObjectPanels();
  1265. }
  1266. //-----------------------------------------------------------------------------
  1267. // Purpose: Contents of object list has changed, reposition the panels
  1268. //-----------------------------------------------------------------------------
  1269. void CHudBuildingStatusContainer::RepositionObjectPanels( void )
  1270. {
  1271. float flXPos = XRES(9);
  1272. float flYPos = YRES(9);
  1273. float flTeleEntranceY = YRES(9);
  1274. float flTeleExitY = YRES(9);
  1275. // Regular Panels
  1276. for ( int i = 0; i < m_BuildingPanels.Count(); i++ )
  1277. {
  1278. CBuildingStatusItem *pItem = m_BuildingPanels.Element(i);
  1279. if ( pItem )
  1280. {
  1281. // set position directly
  1282. pItem->SetPos( flXPos, flYPos );
  1283. // do not increment for speed pad (this is a minor hack)
  1284. // OBJ_TELEPORTER, MODE_TELEPORTER_SPEED
  1285. if ( pItem->GetRepresentativeObjectType() == OBJ_TELEPORTER )
  1286. {
  1287. switch ( pItem->GetRepresentativeObjectMode() )
  1288. {
  1289. case MODE_TELEPORTER_ENTRANCE:
  1290. flTeleEntranceY = flYPos;
  1291. flYPos += pItem->GetTall();
  1292. break;
  1293. case MODE_TELEPORTER_EXIT:
  1294. flTeleExitY = flYPos;
  1295. flYPos += pItem->GetTall();
  1296. break;
  1297. #ifdef STAGING_ONLY
  1298. case MODE_TELEPORTER_SPEED:
  1299. pItem->SetPos( flXPos, flTeleEntranceY );
  1300. break;
  1301. case MODE_TELEPORTER_SPEED2:
  1302. pItem->SetPos( flXPos, flTeleExitY );
  1303. break;
  1304. #endif
  1305. }
  1306. }
  1307. else
  1308. {
  1309. flYPos += pItem->GetTall(); // the fade around the panels gives a gap
  1310. }
  1311. }
  1312. }
  1313. }
  1314. //-----------------------------------------------------------------------------
  1315. // Purpose:
  1316. //-----------------------------------------------------------------------------
  1317. void CHudBuildingStatusContainer::FireGameEvent( IGameEvent *event )
  1318. {
  1319. const char * type = event->GetName();
  1320. if ( Q_strcmp(type, "building_info_changed" ) == 0 )
  1321. {
  1322. int iBuildingType = event->GetInt( "building_type" );
  1323. int iBuildingMode = event->GetInt( "object_mode" );
  1324. if ( iBuildingType >= 0 )
  1325. {
  1326. bool bRemove = ( event->GetInt( "remove" ) > 0 );
  1327. OnBuildingChanged( iBuildingType, iBuildingMode, bRemove );
  1328. }
  1329. else
  1330. {
  1331. UpdateAllBuildings();
  1332. }
  1333. }
  1334. else
  1335. {
  1336. CHudElement::FireGameEvent( event );
  1337. }
  1338. }
  1339. void CHudBuildingStatusContainer::RecalculateAlertState( void )
  1340. {
  1341. BuildingHudAlert_t maxAlertLevel = BUILDING_HUD_ALERT_NONE;
  1342. // find our highest warning level
  1343. for ( int i = 0; i < m_BuildingPanels.Count(); i++ )
  1344. {
  1345. CBuildingStatusItem *pItem = m_BuildingPanels.Element(i);
  1346. C_BaseObject * pObj = pItem->GetRepresentativeObject();
  1347. if ( pObj )
  1348. {
  1349. BuildingHudAlert_t alertLevel = pObj->GetBuildingAlertLevel();
  1350. if ( alertLevel > maxAlertLevel )
  1351. {
  1352. if ( pObj->IsMiniBuilding() && alertLevel != BUILDING_HUD_ALERT_LOW_HEALTH && alertLevel != BUILDING_HUD_ALERT_VERY_LOW_HEALTH && alertLevel != BUILDING_HUD_ALERT_SAPPER )
  1353. continue;
  1354. maxAlertLevel = alertLevel;
  1355. }
  1356. }
  1357. }
  1358. if ( maxAlertLevel != m_AlertLevel )
  1359. {
  1360. if ( maxAlertLevel >= BUILDING_HUD_ALERT_VERY_LOW_AMMO )
  1361. {
  1362. m_flNextBeep = gpGlobals->curtime; // beep asap
  1363. m_iNumBeepsToBeep = tf_hud_num_building_alert_beeps.GetInt();
  1364. }
  1365. m_AlertLevel = maxAlertLevel;
  1366. }
  1367. }
  1368. void CHudBuildingStatusContainer::OnTick( void )
  1369. {
  1370. if ( m_AlertLevel >= BUILDING_HUD_ALERT_VERY_LOW_AMMO &&
  1371. gpGlobals->curtime >= m_flNextBeep &&
  1372. m_iNumBeepsToBeep > 0 )
  1373. {
  1374. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  1375. if ( !pLocalPlayer )
  1376. return;
  1377. pLocalPlayer->EmitSound( "Hud.Warning" );
  1378. switch( m_AlertLevel )
  1379. {
  1380. case BUILDING_HUD_ALERT_VERY_LOW_AMMO:
  1381. case BUILDING_HUD_ALERT_VERY_LOW_HEALTH:
  1382. m_flNextBeep = gpGlobals->curtime + 2.0f;
  1383. m_iNumBeepsToBeep--;
  1384. break;
  1385. case BUILDING_HUD_ALERT_SAPPER:
  1386. m_flNextBeep = gpGlobals->curtime + 1.0f;
  1387. // don't decrement beeps, we want them to go on forever
  1388. break;
  1389. }
  1390. }
  1391. }