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.

383 lines
11 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "hud.h"
  10. #include "hudelement.h"
  11. #include "iclientmode.h"
  12. #include "engine/IEngineSound.h"
  13. #include "vgui_controls/AnimationController.h"
  14. #include "vgui_controls/Controls.h"
  15. #include "vgui_controls/Panel.h"
  16. #include "vgui/ISurface.h"
  17. #include "c_portal_player.h"
  18. #include "c_weapon_portalgun.h"
  19. #include "IGameUIFuncs.h"
  20. // memdbgon must be the last include file in a .cpp file!!!
  21. #include "tier0/memdbgon.h"
  22. #define HEALTH_WARNING_THRESHOLD 25
  23. static ConVar hud_quickinfo( "hud_quickinfo", "1", FCVAR_ARCHIVE );
  24. static ConVar hud_quickinfo_swap( "hud_quickinfo_swap", "0", FCVAR_ARCHIVE );
  25. extern ConVar crosshair;
  26. #define QUICKINFO_EVENT_DURATION 1.0f
  27. #define QUICKINFO_BRIGHTNESS_FULL 255
  28. #define QUICKINFO_BRIGHTNESS_DIM 64
  29. #define QUICKINFO_FADE_IN_TIME 0.5f
  30. #define QUICKINFO_FADE_OUT_TIME 2.0f
  31. /*
  32. ==================================================
  33. CHUDQuickInfo
  34. ==================================================
  35. */
  36. using namespace vgui;
  37. class CHUDQuickInfo : public CHudElement, public vgui::Panel
  38. {
  39. DECLARE_CLASS_SIMPLE( CHUDQuickInfo, vgui::Panel );
  40. public:
  41. CHUDQuickInfo( const char *pElementName );
  42. void Init( void );
  43. void VidInit( void );
  44. bool ShouldDraw( void );
  45. //virtual void OnThink();
  46. virtual void Paint();
  47. virtual void ApplySchemeSettings( IScheme *scheme );
  48. private:
  49. void DrawWarning( int x, int y, CHudTexture *icon, float &time );
  50. void UpdateEventTime( void );
  51. bool EventTimeElapsed( void );
  52. float m_flLastEventTime;
  53. float m_fLastPlacedAlpha[2];
  54. bool m_bLastPlacedAlphaCountingUp[2];
  55. CHudTexture *m_icon_c;
  56. CHudTexture *m_icon_rbn; // right bracket
  57. CHudTexture *m_icon_lbn; // left bracket
  58. CHudTexture *m_icon_rb; // right bracket, full
  59. CHudTexture *m_icon_lb; // left bracket, full
  60. CHudTexture *m_icon_rbe; // right bracket, empty
  61. CHudTexture *m_icon_lbe; // left bracket, empty
  62. CHudTexture *m_icon_rbnone; // right bracket
  63. CHudTexture *m_icon_lbnone; // left bracket
  64. };
  65. DECLARE_HUDELEMENT( CHUDQuickInfo );
  66. CHUDQuickInfo::CHUDQuickInfo( const char *pElementName ) :
  67. CHudElement( pElementName ), BaseClass( NULL, "HUDQuickInfo" )
  68. {
  69. vgui::Panel *pParent = g_pClientMode->GetViewport();
  70. SetParent( pParent );
  71. SetHiddenBits( HIDEHUD_CROSSHAIR );
  72. m_fLastPlacedAlpha[0] = m_fLastPlacedAlpha[1] = 80;
  73. m_bLastPlacedAlphaCountingUp[0] = m_bLastPlacedAlphaCountingUp[1] = true;
  74. }
  75. void CHUDQuickInfo::ApplySchemeSettings( IScheme *scheme )
  76. {
  77. BaseClass::ApplySchemeSettings( scheme );
  78. SetPaintBackgroundEnabled( false );
  79. }
  80. void CHUDQuickInfo::Init( void )
  81. {
  82. m_flLastEventTime = 0.0f;
  83. }
  84. void CHUDQuickInfo::VidInit( void )
  85. {
  86. Init();
  87. m_icon_c = gHUD.GetIcon( "crosshair" );
  88. if ( IsX360() )
  89. {
  90. m_icon_rb = gHUD.GetIcon( "portal_crosshair_right_valid_x360" );
  91. m_icon_lb = gHUD.GetIcon( "portal_crosshair_left_valid_x360" );
  92. m_icon_rbe = gHUD.GetIcon( "portal_crosshair_last_placed_x360" );
  93. m_icon_lbe = gHUD.GetIcon( "portal_crosshair_last_placed_x360" );
  94. m_icon_rbn = gHUD.GetIcon( "portal_crosshair_right_invalid_x360" );
  95. m_icon_lbn = gHUD.GetIcon( "portal_crosshair_left_invalid_x360" );
  96. }
  97. else
  98. {
  99. m_icon_rb = gHUD.GetIcon( "portal_crosshair_right_valid" );
  100. m_icon_lb = gHUD.GetIcon( "portal_crosshair_left_valid" );
  101. m_icon_rbe = gHUD.GetIcon( "portal_crosshair_last_placed" );
  102. m_icon_lbe = gHUD.GetIcon( "portal_crosshair_last_placed" );
  103. m_icon_rbn = gHUD.GetIcon( "portal_crosshair_right_invalid" );
  104. m_icon_lbn = gHUD.GetIcon( "portal_crosshair_left_invalid" );
  105. m_icon_rbnone = gHUD.GetIcon( "crosshair_right" );
  106. m_icon_lbnone = gHUD.GetIcon( "crosshair_left" );
  107. }
  108. }
  109. void CHUDQuickInfo::DrawWarning( int x, int y, CHudTexture *icon, float &time )
  110. {
  111. float scale = (int)( fabs(sin(gpGlobals->curtime*8.0f)) * 128.0);
  112. // Only fade out at the low point of our blink
  113. if ( time <= (gpGlobals->frametime * 200.0f) )
  114. {
  115. if ( scale < 40 )
  116. {
  117. time = 0.0f;
  118. return;
  119. }
  120. else
  121. {
  122. // Counteract the offset below to survive another frame
  123. time += (gpGlobals->frametime * 200.0f);
  124. }
  125. }
  126. // Update our time
  127. time -= (gpGlobals->frametime * 200.0f);
  128. Color caution = gHUD.m_clrCaution;
  129. caution[3] = scale * 255;
  130. icon->DrawSelf( x, y, caution );
  131. }
  132. //-----------------------------------------------------------------------------
  133. // Purpose: Save CPU cycles by letting the HUD system early cull
  134. // costly traversal. Called per frame, return true if thinking and
  135. // painting need to occur.
  136. //-----------------------------------------------------------------------------
  137. bool CHUDQuickInfo::ShouldDraw( void )
  138. {
  139. if ( !m_icon_c || !m_icon_rb || !m_icon_rbe || !m_icon_lb || !m_icon_lbe )
  140. return false;
  141. C_Portal_Player *player = ToPortalPlayer(C_BasePlayer::GetLocalPlayer());
  142. if ( player == NULL )
  143. return false;
  144. if ( !crosshair.GetBool() )
  145. return false;
  146. if ( player->IsSuppressingCrosshair() )
  147. return false;
  148. return ( CHudElement::ShouldDraw() && !engine->IsDrawingLoadingImage() );
  149. }
  150. void CHUDQuickInfo::Paint()
  151. {
  152. C_Portal_Player *pPortalPlayer = (C_Portal_Player*)( C_BasePlayer::GetLocalPlayer() );
  153. if ( pPortalPlayer == NULL )
  154. return;
  155. C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
  156. if ( pWeapon == NULL )
  157. return;
  158. int xCenter = ( ScreenWidth() - m_icon_c->Width() ) / 2;
  159. int yCenter = ( ScreenHeight() - m_icon_c->Height() ) / 2;
  160. Color clrNormal = gHUD.m_clrNormal;
  161. clrNormal[3] = 255;
  162. SetActive( true );
  163. m_icon_c->DrawSelf( xCenter, yCenter, clrNormal );
  164. // adjust center for the bigger crosshairs
  165. xCenter = ScreenWidth() / 2;
  166. yCenter = ( ScreenHeight() - m_icon_lb->Height() ) / 2;
  167. C_WeaponPortalgun *pPortalgun = dynamic_cast<C_WeaponPortalgun*>( pWeapon );
  168. bool bPortalPlacability[2];
  169. if ( pPortalgun )
  170. {
  171. bPortalPlacability[0] = pPortalgun->GetPortal1Placablity() > 0.5f;
  172. bPortalPlacability[1] = pPortalgun->GetPortal2Placablity() > 0.5f;
  173. }
  174. if ( !hud_quickinfo.GetInt() || !pPortalgun || ( !pPortalgun->CanFirePortal1() && !pPortalgun->CanFirePortal2() ) )
  175. {
  176. // no quickinfo or we can't fire either portal, just draw the small versions of the crosshairs
  177. clrNormal[3] = 196;
  178. m_icon_lbnone->DrawSelf(xCenter - (m_icon_lbnone->Width() * 2), yCenter, clrNormal);
  179. m_icon_rbnone->DrawSelf(xCenter + m_icon_rbnone->Width(), yCenter, clrNormal);
  180. return;
  181. }
  182. const unsigned char iAlphaStart = 150;
  183. Color portal1Color = UTIL_Portal_Color( 1 );
  184. Color portal2Color = UTIL_Portal_Color( 2 );
  185. portal1Color[ 3 ] = iAlphaStart;
  186. portal2Color[ 3 ] = iAlphaStart;
  187. const int iBaseLastPlacedAlpha = 128;
  188. Color lastPlaced1Color = Color( portal1Color[0], portal1Color[1], portal1Color[2], iBaseLastPlacedAlpha );
  189. Color lastPlaced2Color = Color( portal2Color[0], portal2Color[1], portal2Color[2], iBaseLastPlacedAlpha );
  190. const float fLastPlacedAlphaLerpSpeed = 300.0f;
  191. float fLeftPlaceBarFill = 0.0f;
  192. float fRightPlaceBarFill = 0.0f;
  193. if ( pPortalgun->CanFirePortal1() && pPortalgun->CanFirePortal2() )
  194. {
  195. int iDrawLastPlaced = 0;
  196. //do last placed indicator effects
  197. if ( pPortalgun->GetLastFiredPortal() == 1 )
  198. {
  199. iDrawLastPlaced = 0;
  200. fLeftPlaceBarFill = 1.0f;
  201. }
  202. else if ( pPortalgun->GetLastFiredPortal() == 2 )
  203. {
  204. iDrawLastPlaced = 1;
  205. fRightPlaceBarFill = 1.0f;
  206. }
  207. if( m_bLastPlacedAlphaCountingUp[iDrawLastPlaced] )
  208. {
  209. m_fLastPlacedAlpha[iDrawLastPlaced] += gpGlobals->absoluteframetime * fLastPlacedAlphaLerpSpeed * 2.0f;
  210. if( m_fLastPlacedAlpha[iDrawLastPlaced] > 255.0f )
  211. {
  212. m_bLastPlacedAlphaCountingUp[iDrawLastPlaced] = false;
  213. m_fLastPlacedAlpha[iDrawLastPlaced] = 255.0f - (m_fLastPlacedAlpha[iDrawLastPlaced] - 255.0f);
  214. }
  215. }
  216. else
  217. {
  218. m_fLastPlacedAlpha[iDrawLastPlaced] -= gpGlobals->absoluteframetime * fLastPlacedAlphaLerpSpeed;
  219. if( m_fLastPlacedAlpha[iDrawLastPlaced] < (float)iBaseLastPlacedAlpha )
  220. {
  221. m_fLastPlacedAlpha[iDrawLastPlaced] = (float)iBaseLastPlacedAlpha;
  222. }
  223. }
  224. //reset the last placed indicator on the other side
  225. m_fLastPlacedAlpha[1 - iDrawLastPlaced] -= gpGlobals->absoluteframetime * fLastPlacedAlphaLerpSpeed;
  226. if( m_fLastPlacedAlpha[1 - iDrawLastPlaced] < 0.0f )
  227. {
  228. m_fLastPlacedAlpha[1 - iDrawLastPlaced] = 0.0f;
  229. }
  230. m_bLastPlacedAlphaCountingUp[1 - iDrawLastPlaced] = true;
  231. if ( pPortalgun->GetLastFiredPortal() != 0 )
  232. {
  233. lastPlaced1Color[3] = m_fLastPlacedAlpha[0];
  234. lastPlaced2Color[3] = m_fLastPlacedAlpha[1];
  235. }
  236. else
  237. {
  238. lastPlaced1Color[3] = 0.0f;
  239. lastPlaced2Color[3] = 0.0f;
  240. }
  241. }
  242. //can't fire both portals, and we want the crosshair to remain somewhat symmetrical without being confusing
  243. else if ( !pPortalgun->CanFirePortal1() )
  244. {
  245. // clone portal2 info to portal 1
  246. portal1Color = portal2Color;
  247. lastPlaced1Color[3] = 0.0f;
  248. lastPlaced2Color[3] = 0.0f;
  249. bPortalPlacability[0] = bPortalPlacability[1];
  250. }
  251. else if ( !pPortalgun->CanFirePortal2() )
  252. {
  253. // clone portal1 info to portal 2
  254. portal2Color = portal1Color;
  255. lastPlaced1Color[3] = 0.0f;
  256. lastPlaced2Color[3] = 0.0f;
  257. bPortalPlacability[1] = bPortalPlacability[0];
  258. }
  259. if ( pPortalgun->IsHoldingObject() )
  260. {
  261. // Change the middle to orange
  262. portal1Color = portal2Color = UTIL_Portal_Color( 0 );
  263. bPortalPlacability[0] = bPortalPlacability[1] = false;
  264. }
  265. if ( !hud_quickinfo_swap.GetBool() )
  266. {
  267. if ( bPortalPlacability[0] )
  268. m_icon_lb->DrawSelf(xCenter - (m_icon_lb->Width() * 0.64f ), yCenter - ( m_icon_rb->Height() * 0.17f ), portal1Color);
  269. else
  270. m_icon_lbn->DrawSelf(xCenter - (m_icon_lbn->Width() * 0.64f ), yCenter - ( m_icon_rb->Height() * 0.17f ), portal1Color);
  271. if ( bPortalPlacability[1] )
  272. m_icon_rb->DrawSelf(xCenter + ( m_icon_rb->Width() * -0.35f ), yCenter + ( m_icon_rb->Height() * 0.17f ), portal2Color);
  273. else
  274. m_icon_rbn->DrawSelf(xCenter + ( m_icon_rbn->Width() * -0.35f ), yCenter + ( m_icon_rb->Height() * 0.17f ), portal2Color);
  275. //last placed portal indicator
  276. m_icon_lbe->DrawSelf( xCenter - (m_icon_lbe->Width() * 1.85f), yCenter, lastPlaced1Color );
  277. m_icon_rbe->DrawSelf( xCenter + (m_icon_rbe->Width() * 0.75f), yCenter, lastPlaced2Color );
  278. }
  279. else
  280. {
  281. if ( bPortalPlacability[1] )
  282. m_icon_lb->DrawSelf(xCenter - (m_icon_lb->Width() * 0.64f ), yCenter - ( m_icon_rb->Height() * 0.17f ), portal2Color);
  283. else
  284. m_icon_lbn->DrawSelf(xCenter - (m_icon_lbn->Width() * 0.64f ), yCenter - ( m_icon_rb->Height() * 0.17f ), portal2Color);
  285. if ( bPortalPlacability[0] )
  286. m_icon_rb->DrawSelf(xCenter + ( m_icon_rb->Width() * -0.35f ), yCenter + ( m_icon_rb->Height() * 0.17f ), portal1Color);
  287. else
  288. m_icon_rbn->DrawSelf(xCenter + ( m_icon_rbn->Width() * -0.35f ), yCenter + ( m_icon_rb->Height() * 0.17f ), portal1Color);
  289. //last placed portal indicator
  290. m_icon_lbe->DrawSelf( xCenter - (m_icon_lbe->Width() * 1.85f), yCenter, lastPlaced2Color );
  291. m_icon_rbe->DrawSelf( xCenter + (m_icon_rbe->Width() * 0.75f), yCenter, lastPlaced1Color );
  292. }
  293. }
  294. //-----------------------------------------------------------------------------
  295. // Purpose:
  296. //-----------------------------------------------------------------------------
  297. void CHUDQuickInfo::UpdateEventTime( void )
  298. {
  299. m_flLastEventTime = gpGlobals->curtime;
  300. }
  301. //-----------------------------------------------------------------------------
  302. // Purpose:
  303. // Output : Returns true on success, false on failure.
  304. //-----------------------------------------------------------------------------
  305. bool CHUDQuickInfo::EventTimeElapsed( void )
  306. {
  307. if (( gpGlobals->curtime - m_flLastEventTime ) > QUICKINFO_EVENT_DURATION )
  308. return true;
  309. return false;
  310. }