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.

345 lines
9.2 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "cbase.h"
  8. #include "hud.h"
  9. #include "hudelement.h"
  10. #include "c_tf_player.h"
  11. #include "iclientmode.h"
  12. #include "ienginevgui.h"
  13. #include <vgui/ILocalize.h>
  14. #include <vgui/ISurface.h>
  15. #include <vgui/IVGui.h>
  16. #include <vgui_controls/EditablePanel.h>
  17. #include <vgui_controls/ProgressBar.h>
  18. #include "tf_weapon_medigun.h"
  19. #include <vgui_controls/AnimationController.h>
  20. #include "tf_imagepanel.h"
  21. #include "vgui_controls/Label.h"
  22. // memdbgon must be the last include file in a .cpp file!!!
  23. #include "tier0/memdbgon.h"
  24. using namespace vgui;
  25. extern ConVar weapon_medigun_resist_num_chunks;
  26. //-----------------------------------------------------------------------------
  27. // Purpose:
  28. //-----------------------------------------------------------------------------
  29. class CHudMedicChargeMeter : public CHudElement, public EditablePanel
  30. {
  31. DECLARE_CLASS_SIMPLE( CHudMedicChargeMeter, EditablePanel );
  32. public:
  33. CHudMedicChargeMeter( const char *pElementName );
  34. virtual void ApplySchemeSettings( IScheme *scheme );
  35. virtual bool ShouldDraw( void );
  36. virtual void OnTick( void );
  37. private:
  38. void UpdateKnownChargeType( bool bForce );
  39. void UpdateControlVisibility();
  40. vgui::ContinuousProgressBar* m_pChargeMeter;
  41. CTFImagePanel* m_pResistPanel;
  42. CUtlVector<vgui::ContinuousProgressBar*> m_vecpChargeMeters;
  43. Label* m_pUberchargeLabel;
  44. Label* m_pUberchargeCountLabel;
  45. bool m_bCharged;
  46. float m_flLastChargeValue;
  47. int m_nLastActiveResist;
  48. medigun_weapontypes_t m_eLastKnownMedigunType;
  49. };
  50. DECLARE_HUDELEMENT( CHudMedicChargeMeter );
  51. struct ResistIcons_t
  52. {
  53. const char* m_pzsRed;
  54. const char* m_pzsBlue;
  55. };
  56. static ResistIcons_t g_ResistIcons[MEDIGUN_NUM_RESISTS] =
  57. {
  58. { "../HUD/defense_buff_bullet_blue", "../HUD/defense_buff_bullet_red" },
  59. { "../HUD/defense_buff_explosion_blue", "../HUD/defense_buff_explosion_red" },
  60. { "../HUD/defense_buff_fire_blue", "../HUD/defense_buff_fire_red" },
  61. };
  62. //-----------------------------------------------------------------------------
  63. // Purpose:
  64. //-----------------------------------------------------------------------------
  65. CHudMedicChargeMeter::CHudMedicChargeMeter( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudMedicCharge" )
  66. {
  67. Panel *pParent = g_pClientMode->GetViewport();
  68. SetParent( pParent );
  69. m_pChargeMeter = new ContinuousProgressBar( this, "ChargeMeter" );
  70. for( int i=0; i<weapon_medigun_resist_num_chunks.GetInt(); ++i )
  71. {
  72. m_vecpChargeMeters.AddToTail( new ContinuousProgressBar( this, CFmtStr( "ChargeMeter%d", i+1 ) ) );
  73. }
  74. m_pResistPanel = new CTFImagePanel( this, "ResistIcon" );
  75. m_pResistPanel->SetVisible( false );
  76. SetHiddenBits( HIDEHUD_MISCSTATUS );
  77. vgui::ivgui()->AddTickSignal( GetVPanel() );
  78. m_bCharged = false;
  79. m_flLastChargeValue = -1;
  80. m_eLastKnownMedigunType = MEDIGUN_STANDARD;
  81. m_nLastActiveResist = MEDIGUN_BULLET_RESIST;
  82. SetDialogVariable( "charge", 0 );
  83. SetDialogVariable( "charge_count", 0 );
  84. RegisterForRenderGroup( "inspect_panel" );
  85. }
  86. //-----------------------------------------------------------------------------
  87. // Purpose:
  88. //-----------------------------------------------------------------------------
  89. void CHudMedicChargeMeter::ApplySchemeSettings( IScheme *pScheme )
  90. {
  91. // load control settings...
  92. LoadControlSettings( "resource/UI/HudMedicCharge.res" );
  93. m_pUberchargeLabel = dynamic_cast<Label*>( FindChildByName("ChargeLabel") );
  94. Assert( m_pUberchargeLabel );
  95. m_pUberchargeCountLabel = dynamic_cast<Label*>( FindChildByName("IndividualChargesLabel") );
  96. Assert( m_pUberchargeCountLabel );
  97. if( m_pUberchargeCountLabel )
  98. {
  99. m_pUberchargeCountLabel->SetVisible( false );
  100. }
  101. for( int i=0; i<weapon_medigun_resist_num_chunks.GetInt(); ++i )
  102. {
  103. m_vecpChargeMeters[i]->SetVisible( false );
  104. }
  105. m_pResistPanel->SetVisible( false );
  106. // Figure out which controls to show
  107. UpdateKnownChargeType( true );
  108. BaseClass::ApplySchemeSettings( pScheme );
  109. }
  110. //-----------------------------------------------------------------------------
  111. // Purpose:
  112. //-----------------------------------------------------------------------------
  113. bool CHudMedicChargeMeter::ShouldDraw( void )
  114. {
  115. C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
  116. if ( !pPlayer || !pPlayer->IsPlayerClass( TF_CLASS_MEDIC ) || !pPlayer->IsAlive() )
  117. {
  118. return false;
  119. }
  120. CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
  121. if ( !pWpn )
  122. {
  123. return false;
  124. }
  125. if ( pWpn->GetWeaponID() != TF_WEAPON_MEDIGUN && pWpn->GetWeaponID() != TF_WEAPON_BONESAW &&
  126. !( pWpn->GetWeaponID() == TF_WEAPON_SYRINGEGUN_MEDIC && pWpn->UberChargeAmmoPerShot() > 0.0f ) )
  127. {
  128. return false;
  129. }
  130. return CHudElement::ShouldDraw();
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Purpose:
  134. //-----------------------------------------------------------------------------
  135. void CHudMedicChargeMeter::OnTick( void )
  136. {
  137. C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
  138. if ( !pPlayer )
  139. return;
  140. CTFWeaponBase *pWpn = pPlayer->GetActiveTFWeapon();
  141. // Might have switched medigun types
  142. UpdateKnownChargeType( false);
  143. if ( !pWpn )
  144. return;
  145. if ( pWpn->GetWeaponID() == TF_WEAPON_BONESAW ||
  146. ( pWpn->GetWeaponID() == TF_WEAPON_SYRINGEGUN_MEDIC && pWpn->UberChargeAmmoPerShot() > 0.0f ) )
  147. {
  148. pWpn = pPlayer->Weapon_OwnsThisID( TF_WEAPON_MEDIGUN );
  149. }
  150. if ( !pWpn || ( pWpn->GetWeaponID() != TF_WEAPON_MEDIGUN ) )
  151. return;
  152. CWeaponMedigun *pMedigun = assert_cast< CWeaponMedigun *>( pWpn );
  153. // We need to update the resist that we show here. Only do so if the medigun is actually
  154. // the gun that's eruipped
  155. if( pMedigun->GetMedigunType() == MEDIGUN_RESIST && pPlayer->GetActiveTFWeapon() == pMedigun )
  156. {
  157. int nCurrentActiveResist = pMedigun->GetResistType();
  158. CBaseEntity* pOwner = pMedigun->GetOwner();
  159. // Figure out which image to show based on team
  160. const char* pzsImage = g_ResistIcons[nCurrentActiveResist].m_pzsBlue;
  161. if( pOwner && pOwner->GetTeamNumber() == TF_TEAM_BLUE )
  162. {
  163. pzsImage = g_ResistIcons[nCurrentActiveResist].m_pzsRed;
  164. }
  165. // Resist Medigun is equipped. Update visibulity
  166. m_pResistPanel->SetVisible( true );
  167. m_pResistPanel->MoveToFront();
  168. m_pResistPanel->SetPos( 0, 0 );
  169. m_pResistPanel->SetImage( pzsImage );
  170. }
  171. else
  172. {
  173. m_pResistPanel->SetVisible( false );
  174. }
  175. float flCharge = pMedigun->GetChargeLevel();
  176. if ( flCharge != m_flLastChargeValue )
  177. {
  178. if( pMedigun->GetMedigunType() == MEDIGUN_RESIST )
  179. {
  180. float flChunkSize = 1.f / weapon_medigun_resist_num_chunks.GetFloat();
  181. for( int i=0; i<weapon_medigun_resist_num_chunks.GetInt(); ++i )
  182. {
  183. float flChunkCharge = flCharge - (flChunkSize * i);
  184. float flProgress = MIN(flChunkCharge, flChunkSize) / flChunkSize;
  185. // Not-full bars are dimmed a bit
  186. if( flProgress < 1.f && !pMedigun->IsReleasingCharge() )
  187. {
  188. m_vecpChargeMeters[i]->SetFgColor( Color( 190, 190, 190, 255 ) );
  189. }
  190. else // Full bars are white
  191. {
  192. m_vecpChargeMeters[i]->SetFgColor( Color( 255, 255, 255, 255 ) );
  193. }
  194. m_vecpChargeMeters[i]->SetProgress( flProgress );
  195. }
  196. // We want to count full bars
  197. SetDialogVariable( "charge_count", int(floor(flCharge / flChunkSize)) );
  198. }
  199. else if ( m_pChargeMeter ) // Regular uber
  200. {
  201. m_pChargeMeter->SetProgress( flCharge );
  202. SetDialogVariable( "charge", (int)( flCharge * 100 ) );
  203. }
  204. if ( !m_bCharged )
  205. {
  206. if ( flCharge >= 1.0 )
  207. {
  208. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudMedicCharged" );
  209. m_bCharged = true;
  210. }
  211. }
  212. else
  213. {
  214. // we've got invuln charge or we're using our invuln
  215. if ( !pMedigun->IsReleasingCharge() )
  216. {
  217. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( this, "HudMedicChargedStop" );
  218. m_bCharged = false;
  219. }
  220. }
  221. }
  222. m_flLastChargeValue = flCharge;
  223. }
  224. void CHudMedicChargeMeter::UpdateKnownChargeType( bool bForce )
  225. {
  226. C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
  227. if ( !pPlayer )
  228. return;
  229. CTFWeaponBase *pWpn = pPlayer->Weapon_OwnsThisID( TF_WEAPON_MEDIGUN );
  230. if( !pWpn )
  231. return;
  232. CWeaponMedigun *pMedigun = static_cast< CWeaponMedigun *>( pWpn );
  233. if( pMedigun->GetMedigunType() != m_eLastKnownMedigunType || bForce )
  234. {
  235. m_eLastKnownMedigunType = (medigun_weapontypes_t)pMedigun->GetMedigunType();
  236. UpdateControlVisibility();
  237. }
  238. }
  239. void CHudMedicChargeMeter::UpdateControlVisibility()
  240. {
  241. C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
  242. if ( !pPlayer )
  243. return;
  244. CTFWeaponBase *pWpn = pPlayer->Weapon_OwnsThisID( TF_WEAPON_MEDIGUN );
  245. if ( !pWpn || ( pWpn->GetWeaponID() != TF_WEAPON_MEDIGUN ) )
  246. return;
  247. CWeaponMedigun *pMedigun = static_cast< CWeaponMedigun *>( pWpn );
  248. if ( !pMedigun )
  249. return;
  250. bool bResistMedigun = m_eLastKnownMedigunType == MEDIGUN_RESIST;
  251. // Using the resist medigun
  252. if( !bResistMedigun )
  253. {
  254. m_pResistPanel->SetVisible( false );
  255. }
  256. // Conditionally show the medigun chunks
  257. for( int i=0; i<m_vecpChargeMeters.Count(); ++i )
  258. {
  259. m_vecpChargeMeters[i]->SetVisible( bResistMedigun );
  260. }
  261. m_pChargeMeter->SetVisible( !bResistMedigun );
  262. if( m_pUberchargeLabel )
  263. {
  264. m_pUberchargeLabel->SetVisible( !bResistMedigun );
  265. }
  266. if( m_pUberchargeCountLabel )
  267. {
  268. m_pUberchargeCountLabel->SetVisible( bResistMedigun );
  269. }
  270. }