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.

903 lines
27 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "hudelement.h"
  8. #include <vgui_controls/Panel.h>
  9. #include <vgui_controls/Label.h>
  10. #include <vgui/ISurface.h>
  11. #include "c_baseplayer.h"
  12. #include <vgui_controls/Panel.h>
  13. #include "dod_gamerules.h"
  14. #include "iclientmode.h"
  15. #include "c_dod_objective_resource.h"
  16. #include "c_dod_playerresource.h"
  17. #include "c_dod_player.h"
  18. #include "VGuiMatSurface/IMatSystemSurface.h"
  19. #include "hud_macros.h"
  20. #include <baseviewport.h> //for IViewPortPanel
  21. #include "spectatorgui.h"
  22. #include "dod_round_timer.h"
  23. #include "vgui_controls/AnimationController.h"
  24. #include "dod_hud_freezepanel.h"
  25. class CHudObjectiveIcons : public CHudElement, public vgui::Panel
  26. {
  27. public:
  28. DECLARE_CLASS_SIMPLE( CHudObjectiveIcons, vgui::Panel );
  29. CHudObjectiveIcons( const char *pName );
  30. virtual void ApplySchemeSettings( IScheme *scheme );
  31. virtual void Paint();
  32. virtual void Init();
  33. virtual void VidInit();
  34. virtual void Reset();
  35. virtual void FireGameEvent( IGameEvent *event );
  36. void DrawBackgroundBox( int xpos, int ypos, int nBoxWidth, int nBoxHeight, bool bCutCorner );
  37. virtual bool IsVisible( void );
  38. private:
  39. vgui::Label *m_pTimer;
  40. vgui::Label *m_pTimeAdded;
  41. CHudTexture *m_pIconDefended;
  42. int m_iCPTextures[8];
  43. int m_iCPCappingTextures[8];
  44. int m_iBackgroundTexture;
  45. Color m_clrBackground;
  46. Color m_clrBorder;
  47. int m_iLastCP; // the index of the area we were last in
  48. CHudTexture *m_pC4Icon;
  49. CHudTexture *m_pExplodedIcon;
  50. CHudTexture *m_pC4PlantedBG;
  51. int m_iSecondsAdded; // how many seconds were added in the last time_added event
  52. bool bInTimerWarningAnim;
  53. float m_flDrawTimeAddedUntil;
  54. CPanelAnimationVar( vgui::HFont, m_hTimerFont, "TimerFont", "Default" );
  55. CPanelAnimationVar( vgui::HFont, m_hTimerFontSmall, "TimerFontSmall", "DefaultSmall" );
  56. CPanelAnimationVar( vgui::HFont, m_hTextFont, "ChatFont", "Default" );
  57. CPanelAnimationVarAliasType( int, m_nIconSize, "iconsize", "24", "proportional_int" );
  58. CPanelAnimationVarAliasType( int, m_nSeparatorWidth, "separator_width", "7", "proportional_int" );
  59. CPanelAnimationVarAliasType( int, m_nCornerCutSize, "CornerCutSize", "5", "proportional_int" );
  60. CPanelAnimationVarAliasType( int, m_nBackgroundOverlap, "BackgroundOverlap", "5", "proportional_int" );
  61. CPanelAnimationVarAliasType( int, m_iIconStartX, "icon_start_x", "10", "proportional_int" );
  62. CPanelAnimationVarAliasType( int, m_iIconStartY, "icon_start_y", "10", "proportional_int" );
  63. CPanelAnimationVarAliasType( float, m_flIconExpand, "icon_expand", "0", "proportional_float" );
  64. CPanelAnimationVar( Color, m_clrTimer, "TimerBG", "255 0 0 128" );
  65. CPanelAnimationVarAliasType( int, m_nTimeAddedHeight, "time_added_height", "12", "proportional_int" );
  66. CPanelAnimationVar( float, m_flTimeAddedExpandPercent, "time_added_height_anim", "0.0" );
  67. CPanelAnimationVar( float, m_flTimeAddedAlpha, "time_added_alpha", "0" );
  68. CPanelAnimationVar( float, m_flTimeAddedDuration, "time_added_duration", "3.5" );
  69. };
  70. DECLARE_HUDELEMENT( CHudObjectiveIcons );
  71. //-----------------------------------------------------------------------------
  72. // Purpose:
  73. //-----------------------------------------------------------------------------
  74. CHudObjectiveIcons::CHudObjectiveIcons( const char *pName ) : vgui::Panel( NULL, "HudObjectiveIcons" ), CHudElement( pName )
  75. {
  76. SetParent( g_pClientMode->GetViewport() );
  77. SetHiddenBits( 0 );
  78. m_pTimer = new vgui::Label( this, "HudObjectivesRoundTimer", " " );
  79. if ( m_pTimer )
  80. {
  81. m_pTimer->SetContentAlignment( Label::a_center );
  82. }
  83. m_pTimeAdded = new vgui::Label( this, "HudObjectivesTimeAdded", " " );
  84. if ( m_pTimeAdded )
  85. {
  86. m_pTimeAdded->SetContentAlignment( Label::a_center );
  87. }
  88. m_iBackgroundTexture = vgui::surface()->DrawGetTextureId( "vgui/white" );
  89. if ( m_iBackgroundTexture == -1 )
  90. {
  91. m_iBackgroundTexture = vgui::surface()->CreateNewTextureID();
  92. }
  93. vgui::surface()->DrawSetTextureFile( m_iBackgroundTexture, "vgui/white", true, true );
  94. m_iLastCP = -1;
  95. m_iSecondsAdded = 0;
  96. bInTimerWarningAnim = false;
  97. m_flDrawTimeAddedUntil = -1;
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Purpose:
  101. //-----------------------------------------------------------------------------
  102. void CHudObjectiveIcons::Init( void )
  103. {
  104. for( int i = 0 ; i < 8 ; i++ )
  105. {
  106. m_iCPTextures[i] = vgui::surface()->CreateNewTextureID();
  107. m_iCPCappingTextures[i] = vgui::surface()->CreateNewTextureID();
  108. }
  109. ListenForGameEvent( "dod_timer_time_added" );
  110. ListenForGameEvent( "dod_timer_flash" );
  111. }
  112. void CHudObjectiveIcons::VidInit( void )
  113. {
  114. m_flTimeAddedExpandPercent = 0.0;
  115. m_flTimeAddedAlpha = 0.0;
  116. m_flDrawTimeAddedUntil = -1;
  117. CHudElement::VidInit();
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Purpose:
  121. //-----------------------------------------------------------------------------
  122. void CHudObjectiveIcons::Reset( void )
  123. {
  124. m_iLastCP = -1;
  125. m_flIconExpand = 0;
  126. }
  127. //-----------------------------------------------------------------------------
  128. // Purpose:
  129. //-----------------------------------------------------------------------------
  130. bool CHudObjectiveIcons::IsVisible( void )
  131. {
  132. if ( IsTakingAFreezecamScreenshot() )
  133. return false;
  134. return BaseClass::IsVisible();
  135. }
  136. //-----------------------------------------------------------------------------
  137. // Purpose:
  138. //-----------------------------------------------------------------------------
  139. void CHudObjectiveIcons::FireGameEvent( IGameEvent *event )
  140. {
  141. const char *eventname = event->GetName();
  142. if ( FStrEq( "dod_timer_time_added", eventname ) )
  143. {
  144. // show time added under the timer, flash
  145. m_iSecondsAdded = event->GetInt( "seconds_added" );
  146. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "TimerFlash" );
  147. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "ShowTimeAdded" );
  148. if ( !m_pTimeAdded->IsVisible() )
  149. {
  150. m_pTimeAdded->SetVisible( true );
  151. }
  152. wchar_t wText[12];
  153. int iSecondsToDraw = abs(m_iSecondsAdded);
  154. bool bNegative = ( m_iSecondsAdded < 0 );
  155. #ifdef WIN32
  156. _snwprintf( wText, sizeof(wText)/sizeof(wchar_t), L"%s %d:%02d", bNegative ? L"-" : L"+", iSecondsToDraw / 60, iSecondsToDraw % 60 );
  157. #else
  158. _snwprintf( wText, sizeof(wText)/sizeof(wchar_t), L"%S %d:%02d", bNegative ? L"-" : L"+", iSecondsToDraw / 60, iSecondsToDraw % 60 );
  159. #endif
  160. m_pTimeAdded->SetText( wText );
  161. m_flDrawTimeAddedUntil = gpGlobals->curtime + m_flTimeAddedDuration;
  162. }
  163. else if ( FStrEq( "dod_timer_flash", eventname ) )
  164. {
  165. // generic flash, used for 5, 2, 1 minute warnings
  166. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "TimerFlash" );
  167. }
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Purpose:
  171. //-----------------------------------------------------------------------------
  172. void CHudObjectiveIcons::ApplySchemeSettings( IScheme *pScheme )
  173. {
  174. BaseClass::ApplySchemeSettings( pScheme );
  175. m_hTextFont = pScheme->GetFont( "ChatFont" );
  176. m_hTimerFontSmall = pScheme->GetFont( "TimerFontSmall" );
  177. m_clrBackground = pScheme->GetColor( "HudPanelBackground", GetFgColor() );
  178. m_clrBorder = pScheme->GetColor( "HudPanelBorder", GetBgColor() );
  179. m_pC4Icon = gHUD.GetIcon( "icon_c4" );
  180. m_pExplodedIcon = gHUD.GetIcon( "icon_c4_exploded" );
  181. m_pC4PlantedBG = gHUD.GetIcon( "icon_c4_planted_bg" );
  182. m_pIconDefended = gHUD.GetIcon( "icon_defended" );
  183. m_pTimer->SetFont( m_hTimerFont );
  184. m_pTimeAdded->SetFont( m_hTimerFontSmall );
  185. }
  186. //-----------------------------------------------------------------------------
  187. // Purpose:
  188. //-----------------------------------------------------------------------------
  189. void CHudObjectiveIcons::DrawBackgroundBox( int xpos, int ypos, int nBoxWidth, int nBoxHeight, bool bCutCorner )
  190. {
  191. int nCornerCutSize = bCutCorner ? m_nCornerCutSize : 0;
  192. vgui::Vertex_t verts[5];
  193. verts[0].Init( Vector2D( xpos, ypos ) );
  194. verts[1].Init( Vector2D( xpos + nBoxWidth, ypos ) );
  195. verts[2].Init( Vector2D( xpos + nBoxWidth + 1, ypos + nBoxHeight - nCornerCutSize + 1 ) );
  196. verts[3].Init( Vector2D( xpos + nBoxWidth - nCornerCutSize + 1, ypos + nBoxHeight + 1 ) );
  197. verts[4].Init( Vector2D( xpos, ypos + nBoxHeight ) );
  198. vgui::surface()->DrawSetTexture( m_iBackgroundTexture );
  199. vgui::surface()->DrawSetColor( Color( m_clrBackground ) );
  200. vgui::surface()->DrawTexturedPolygon( 5, verts );
  201. vgui::Vertex_t borderverts[5];
  202. borderverts[0].Init( Vector2D( xpos, ypos ) );
  203. borderverts[1].Init( Vector2D( xpos + nBoxWidth, ypos ) );
  204. borderverts[2].Init( Vector2D( xpos + nBoxWidth, ypos + nBoxHeight - nCornerCutSize ) );
  205. borderverts[3].Init( Vector2D( xpos + nBoxWidth - nCornerCutSize, ypos + nBoxHeight ) );
  206. borderverts[4].Init( Vector2D( xpos, ypos + nBoxHeight ) );
  207. vgui::surface()->DrawSetColor( Color( m_clrBorder ) );
  208. vgui::surface()->DrawTexturedPolyLine( borderverts, 5 );
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Purpose:
  212. //-----------------------------------------------------------------------------
  213. void CHudObjectiveIcons::Paint()
  214. {
  215. int ypos = m_iIconStartY;
  216. int xpos = m_iIconStartX;
  217. static Color clrIcon( 255, 255, 255, 255 );
  218. if( !g_pObjectiveResource ) // MATTTODO: hasn't been transmited yet .. fix ?
  219. {
  220. return;
  221. }
  222. // Hide the time added if it is time to do so
  223. if ( m_flDrawTimeAddedUntil > 0 && m_flDrawTimeAddedUntil < gpGlobals->curtime )
  224. {
  225. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HideTimeAdded" );
  226. m_flDrawTimeAddedUntil = -1;
  227. }
  228. vgui::surface()->DrawSetTextFont( m_hTextFont );
  229. vgui::surface()->DrawSetColor( clrIcon );
  230. if ( g_pSpectatorGUI && g_pSpectatorGUI->IsVisible() )
  231. {
  232. ypos += g_pSpectatorGUI->GetTopBarHeight();
  233. }
  234. int num = g_pObjectiveResource->GetNumControlPoints();
  235. bool bShowTimer = ( g_DODRoundTimer != NULL );
  236. if ( num <= 0 && !bShowTimer )
  237. {
  238. if ( m_pTimer && m_pTimer->IsVisible() )
  239. {
  240. m_pTimer->SetVisible( false );
  241. }
  242. if ( m_pTimeAdded && m_pTimeAdded->IsVisible() )
  243. {
  244. m_pTimeAdded->SetVisible( false );
  245. }
  246. return; // nothing to draw yet
  247. }
  248. int iLastVisible = 0;
  249. int k;
  250. // let's count how many visible capture points we have (for cutting the corner of the last visible one)
  251. for( k = 0 ; k < num ; k++ )
  252. {
  253. if( g_pObjectiveResource->IsCPVisible( k ) )
  254. {
  255. iLastVisible = k;
  256. }
  257. }
  258. // do we have a round timer?
  259. if( bShowTimer )
  260. {
  261. if ( m_pTimer )
  262. {
  263. if ( !m_pTimer->IsVisible() )
  264. {
  265. m_pTimer->SetVisible( true );
  266. }
  267. m_pTimer->SetBounds( xpos, ypos, 2 * m_nIconSize, m_nIconSize );
  268. m_pTimer->SetBgColor( m_clrTimer );
  269. m_pTimeAdded->SetBounds( xpos, ypos + m_nIconSize, 2 * m_nIconSize, m_nTimeAddedHeight + m_nBackgroundOverlap );
  270. m_pTimeAdded->SetBgColor( Color(0,0,0,0) );
  271. int iRoundTime = (int)g_DODRoundTimer->GetTimeRemaining();
  272. int minutes = iRoundTime / 60;
  273. int seconds = iRoundTime % 60;
  274. if( minutes < 0 ) minutes = 0;
  275. if( minutes > 99 ) minutes = 99;
  276. if( seconds < 0 ) seconds = 0;
  277. // cut the corner if this is all we're drawing
  278. // figure out the height. will change if we're drawing the +1:00 below it
  279. int boxHeight = 2*m_nBackgroundOverlap + m_nIconSize + (int)( (float)m_nTimeAddedHeight * m_flTimeAddedExpandPercent );
  280. DrawBackgroundBox( xpos - m_nBackgroundOverlap, ypos - m_nBackgroundOverlap, m_pTimer->GetWide() + 2 * m_nBackgroundOverlap, boxHeight, ( num <= 0 ) ? true : false );
  281. // set the time
  282. char szTime[16];
  283. Q_snprintf( szTime, sizeof( szTime ), "%02d:%02d", minutes, seconds );
  284. m_pTimer->SetText( szTime );
  285. m_pTimeAdded->SetAlpha( (int)m_flTimeAddedAlpha );
  286. xpos += ( m_pTimer->GetWide() + m_nSeparatorWidth + m_nBackgroundOverlap * 2 );
  287. }
  288. }
  289. else
  290. {
  291. if ( m_pTimer && m_pTimer->IsVisible() )
  292. {
  293. m_pTimer->SetVisible( false );
  294. }
  295. }
  296. C_DODPlayer *pPlayer = C_DODPlayer::GetLocalDODPlayer();
  297. int iCurrentCapAreaIndex = pPlayer->GetCPIndex();
  298. if ( pPlayer->IsAlive() == false )
  299. {
  300. m_iLastCP = -1;
  301. }
  302. int index;
  303. for( index = 0 ; index < num ; index++ )
  304. {
  305. if( g_pObjectiveResource->IsCPVisible( index ) )
  306. {
  307. int iOwnerIcon = g_pObjectiveResource->GetCPCurrentOwnerIcon( index );
  308. float uv1 = 0.0f;
  309. float uv2 = 1.0f;
  310. float flXPos = (float)xpos;
  311. float flYPos = (float)ypos;
  312. float flIconSize = (float)m_nIconSize;
  313. if ( index == iCurrentCapAreaIndex )
  314. {
  315. // animate the current cp
  316. flXPos -= m_flIconExpand;
  317. flYPos -= m_flIconExpand;
  318. flIconSize += m_flIconExpand*2;
  319. m_iLastCP = iCurrentCapAreaIndex;
  320. }
  321. else if ( m_iLastCP == index )
  322. {
  323. // as a backup, animate out of the one we just left
  324. flXPos -= m_flIconExpand;
  325. flYPos -= m_flIconExpand;
  326. flIconSize += m_flIconExpand*2;
  327. }
  328. int iBombsRequired = g_pObjectiveResource->GetBombsRequired( index );
  329. if ( iBombsRequired > 0 )
  330. {
  331. DrawBackgroundBox( flXPos - m_nBackgroundOverlap, flYPos - m_nBackgroundOverlap, flIconSize + 2 * m_nBackgroundOverlap, flIconSize + 2 * m_nBackgroundOverlap + m_nTimeAddedHeight, ( index != iLastVisible ) ? false : true );
  332. }
  333. else
  334. {
  335. DrawBackgroundBox( flXPos - m_nBackgroundOverlap, flYPos - m_nBackgroundOverlap, flIconSize + 2 * m_nBackgroundOverlap, flIconSize + 2 * m_nBackgroundOverlap, ( index != iLastVisible ) ? false : true );
  336. }
  337. // Draw the background for the icon
  338. // allow for error
  339. if ( g_pObjectiveResource->IsBombSetAtPoint( index ) )
  340. {
  341. // if bomb timer is > 0, draw swipe
  342. float flBombTime = g_pObjectiveResource->GetBombTimeForPoint( index ); // round up
  343. // draw the 'white' version underneath
  344. int iBlankIcon = g_pObjectiveResource->GetCPTimerCapIcon( index );
  345. if ( iBlankIcon == 0 )
  346. {
  347. iBlankIcon = g_pObjectiveResource->GetIconForTeam( index, TEAM_UNASSIGNED );
  348. }
  349. const char *szMatName = GetMaterialNameFromIndex( iBlankIcon );
  350. vgui::surface()->DrawSetTextureFile( m_iCPTextures[index], szMatName, true, false );
  351. Vector2D uv11( uv1, uv1 );
  352. Vector2D uv21( uv2, uv1 );
  353. Vector2D uv22( uv2, uv2 );
  354. Vector2D uv12( uv1, uv2 );
  355. vgui::Vertex_t vert[4];
  356. vert[0].Init( Vector2D( flXPos, flYPos ), uv11 );
  357. vert[1].Init( Vector2D( flXPos + flIconSize, flYPos ), uv21 );
  358. vert[2].Init( Vector2D( flXPos + flIconSize, flYPos + flIconSize ), uv22 );
  359. vert[3].Init( Vector2D( flXPos, flYPos + flIconSize ), uv12 );
  360. vgui::surface()->DrawSetColor( Color(255,255,255,255) );
  361. vgui::surface()->DrawTexturedPolygon( 4, vert );
  362. // draw the real version in a circular swipe
  363. float flPercentRemaining = ( flBombTime / DOD_BOMB_TIMER_LENGTH );
  364. float flHalfWide = (float)flIconSize / 2.0f;
  365. float flHalfTall = (float)flIconSize / 2.0f;
  366. const float flCompleteCircle = ( 2.0f * M_PI );
  367. const float fl90degrees = flCompleteCircle * 0.25f;
  368. const float fl45degrees = fl90degrees * 0.5f;
  369. float flEndAngle = flCompleteCircle * flPercentRemaining; // clockwise
  370. typedef struct
  371. {
  372. Vector2D vecTrailing;
  373. Vector2D vecLeading;
  374. } icon_quadrant_t;
  375. /*
  376. Quadrants are numbered 0 - 7 counter-clockwise
  377. _________________
  378. | 0 | 7 |
  379. | | |
  380. | 1 | 6 |
  381. -----------------
  382. | 2 | 5 |
  383. | | |
  384. | 3 | 4 |
  385. -----------------
  386. */
  387. // Encode the leading and trailing edge of each quadrant
  388. // in the range 0.0 -> 1.0
  389. icon_quadrant_t quadrants[8];
  390. quadrants[0].vecTrailing.Init( 0.5, 0.0 );
  391. quadrants[0].vecLeading.Init( 0.0, 0.0 );
  392. quadrants[1].vecTrailing.Init( 0.0, 0.0 );
  393. quadrants[1].vecLeading.Init( 0.0, 0.5 );
  394. quadrants[2].vecTrailing.Init( 0.0, 0.5 );
  395. quadrants[2].vecLeading.Init( 0.0, 1.0 );
  396. quadrants[3].vecTrailing.Init( 0.0, 1.0 );
  397. quadrants[3].vecLeading.Init( 0.5, 1.0 );
  398. quadrants[4].vecTrailing.Init( 0.5, 1.0 );
  399. quadrants[4].vecLeading.Init( 1.0, 1.0 );
  400. quadrants[5].vecTrailing.Init( 1.0, 1.0 );
  401. quadrants[5].vecLeading.Init( 1.0, 0.5 );
  402. quadrants[6].vecTrailing.Init( 1.0, 0.5 );
  403. quadrants[6].vecLeading.Init( 1.0, 0.0 );
  404. quadrants[7].vecTrailing.Init( 1.0, 0.0 );
  405. quadrants[7].vecLeading.Init( 0.5, 0.0 );
  406. szMatName = GetMaterialNameFromIndex( iOwnerIcon );
  407. vgui::surface()->DrawSetTextureFile( m_iCPTextures[index], szMatName, true, false );
  408. vgui::surface()->DrawSetColor( Color(255,255,255,255) );
  409. Vector2D uvMid( 0.5, 0.5 );
  410. Vector2D vecMid( flXPos + flHalfWide, flYPos + flHalfTall );
  411. int j;
  412. for ( j=0;j<=7;j++ )
  413. {
  414. float flMinAngle = j * fl45degrees;
  415. float flAngle = clamp( flEndAngle - flMinAngle, 0, fl45degrees );
  416. if ( flAngle <= 0 )
  417. {
  418. // past our quadrant, draw nothing
  419. continue;
  420. }
  421. else
  422. {
  423. // draw our segment
  424. vgui::Vertex_t vert[3];
  425. // vert 0 is mid ( 0.5, 0.5 )
  426. vert[0].Init( vecMid, uvMid );
  427. int xdir = 0, ydir = 0;
  428. switch( j )
  429. {
  430. case 0:
  431. case 7:
  432. //right
  433. xdir = 1;
  434. ydir = 0;
  435. break;
  436. case 1:
  437. case 2:
  438. //up
  439. xdir = 0;
  440. ydir = -1;
  441. break;
  442. case 3:
  443. case 4:
  444. //left
  445. xdir = -1;
  446. ydir = 0;
  447. break;
  448. case 5:
  449. case 6:
  450. //down
  451. xdir = 0;
  452. ydir = 1;
  453. break;
  454. }
  455. Vector2D vec1;
  456. Vector2D uv1;
  457. // vert 1 is the variable vert based on leading edge
  458. vec1.x = flXPos + quadrants[j].vecTrailing.x * flIconSize - xdir * tan(flAngle) * flHalfWide;
  459. vec1.y = flYPos + quadrants[j].vecTrailing.y * flIconSize - ydir * tan(flAngle) * flHalfTall;
  460. uv1.x = quadrants[j].vecTrailing.x - xdir * abs( quadrants[j].vecLeading.x - quadrants[j].vecTrailing.x ) * tan(flAngle);
  461. uv1.y = quadrants[j].vecTrailing.y - ydir * abs( quadrants[j].vecLeading.y - quadrants[j].vecTrailing.y ) * tan(flAngle);
  462. vert[1].Init( vec1, uv1 );
  463. // vert 2 is our trailing edge
  464. vert[2].Init( Vector2D( flXPos + quadrants[j].vecTrailing.x * flIconSize,
  465. flYPos + quadrants[j].vecTrailing.y * flIconSize ),
  466. quadrants[j].vecTrailing );
  467. vgui::surface()->DrawTexturedPolygon( 3, vert );
  468. }
  469. }
  470. if ( g_pObjectiveResource->IsBombBeingDefused( index ) )
  471. {
  472. float flSize = 0.75;
  473. int iconX = (int)( flXPos + flIconSize * ( ( 1.0 - flSize ) / 2 ) );
  474. int iconY = (int)( flYPos + flIconSize * ( ( 1.0 - flSize ) / 2 ) );
  475. int iconW = (int)( flIconSize * flSize );
  476. Color c(255,255,255,255);
  477. m_pIconDefended->DrawSelf( iconX, iconY, iconW, iconW, c );
  478. }
  479. }
  480. else
  481. {
  482. // Draw the owner's icon
  483. if( iOwnerIcon != 0 )
  484. {
  485. const char *szMatName = GetMaterialNameFromIndex( iOwnerIcon );
  486. vgui::surface()->DrawSetTextureFile( m_iCPTextures[index], szMatName, true, false );
  487. /*
  488. // re-enable if we want to have animating cp icons
  489. // todo: framerate
  490. IVguiMatInfo *pMat = vgui::surface()->DrawGetTextureMatInfoFactory( m_iCPTextures[index] );
  491. if ( !pMat )
  492. return;
  493. int iNumFrames = pMat->GetNumAnimationFrames();
  494. IVguiMatInfoVar *m_pFrameVar;
  495. bool bFound = false;
  496. m_pFrameVar = pMat->FindVarFactory( "$frame", &bFound );
  497. static int frame = 0;
  498. if ( bFound )
  499. {
  500. frame++;
  501. m_pFrameVar->SetIntValue( frame % iNumFrames );
  502. }
  503. */
  504. Vector2D uv11( uv1, uv1 );
  505. Vector2D uv21( uv2, uv1 );
  506. Vector2D uv22( uv2, uv2 );
  507. Vector2D uv12( uv1, uv2 );
  508. vgui::Vertex_t vert[4];
  509. vert[0].Init( Vector2D( flXPos, flYPos ), uv11 );
  510. vert[1].Init( Vector2D( flXPos + flIconSize, flYPos ), uv21 );
  511. vert[2].Init( Vector2D( flXPos + flIconSize, flYPos + flIconSize ), uv22 );
  512. vert[3].Init( Vector2D( flXPos, flYPos + flIconSize ), uv12 );
  513. vgui::surface()->DrawSetColor( Color(255,255,255,255) );
  514. vgui::surface()->DrawTexturedPolygon( 4, vert );
  515. }
  516. }
  517. // see if there are players in the area
  518. int iNumAllies = g_pObjectiveResource->GetNumPlayersInArea( index, TEAM_ALLIES );
  519. int iNumAxis = g_pObjectiveResource->GetNumPlayersInArea( index, TEAM_AXIS );
  520. int iCappingTeam = g_pObjectiveResource->GetCappingTeam( index );
  521. // Draw bomb icons under cap points
  522. if ( iBombsRequired > 0 )
  523. {
  524. int iBombsRemaining = g_pObjectiveResource->GetBombsRemaining( index );
  525. bool bBombPlanted = g_pObjectiveResource->IsBombSetAtPoint( index );
  526. int yIcon = ypos + flIconSize + YRES(2);
  527. int iIconHalfWidth = XRES(5);
  528. int iIconWidth = iIconHalfWidth * 2;
  529. Color c(255,255,255,255);
  530. switch( iBombsRequired )
  531. {
  532. case 1:
  533. {
  534. int xMid = xpos + ( flIconSize * 0.50f );
  535. switch( iBombsRemaining )
  536. {
  537. case 0:
  538. m_pExplodedIcon->DrawSelf( xMid - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  539. break;
  540. case 1:
  541. if ( bBombPlanted )
  542. {
  543. // draw the background behind 1
  544. int alpha = (float)( abs( sin(2*gpGlobals->curtime) ) * 205.0 + 50.0 );
  545. m_pC4PlantedBG->DrawSelf( xMid - iIconWidth, yIcon - iIconHalfWidth, iIconWidth*2, iIconWidth*2, Color( 255,255,255,alpha) );
  546. }
  547. m_pC4Icon->DrawSelf( xMid - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  548. break;
  549. }
  550. }
  551. break;
  552. case 2:
  553. {
  554. int xMid1 = xpos + ( flIconSize * 0.25f );
  555. int xMid2 = xpos + ( flIconSize * 0.75f );
  556. switch( iBombsRemaining )
  557. {
  558. case 0:
  559. m_pExplodedIcon->DrawSelf( xMid1 - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  560. m_pExplodedIcon->DrawSelf( xMid2 - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  561. break;
  562. case 1:
  563. if ( bBombPlanted )
  564. {
  565. // draw the background behind 1
  566. int alpha = (float)( abs( sin(2*gpGlobals->curtime) ) * 205.0 + 50.0 );
  567. m_pC4PlantedBG->DrawSelf( xMid1 - iIconWidth, yIcon - iIconHalfWidth, iIconWidth*2, iIconWidth*2, Color( 255,255,255,alpha) );
  568. }
  569. m_pC4Icon->DrawSelf( xMid1 - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  570. m_pExplodedIcon->DrawSelf( xMid2 - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  571. break;
  572. case 2:
  573. if ( bBombPlanted )
  574. {
  575. // draw the background behind 2
  576. int alpha = (float)( abs( sin(2*gpGlobals->curtime) ) * 205.0 + 50.0 );
  577. m_pC4PlantedBG->DrawSelf( xMid2 - iIconWidth, yIcon - iIconHalfWidth, iIconWidth*2, iIconWidth*2, Color( 255,255,255,alpha) );
  578. }
  579. m_pC4Icon->DrawSelf( xMid1 - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  580. m_pC4Icon->DrawSelf( xMid2 - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  581. break;
  582. }
  583. }
  584. break;
  585. default:
  586. {
  587. // general solution for > 2 bombs
  588. if ( iBombsRemaining > 0 )
  589. {
  590. // draw a bomb icon, then a 'x 3' for how many there are remaining
  591. if ( bBombPlanted )
  592. {
  593. // draw the background behind 2
  594. int alpha = (float)( abs( sin( 2*gpGlobals->curtime) ) * 205.0 + 50.0 );
  595. m_pC4PlantedBG->DrawSelf( xpos - iIconHalfWidth, yIcon - iIconHalfWidth, iIconWidth*2, iIconWidth*2, Color( 255,255,255,alpha) );
  596. }
  597. m_pC4Icon->DrawSelf( xpos, yIcon, iIconWidth, iIconWidth, c );
  598. // draw text saying how many bombs there are
  599. {
  600. wchar_t wText[6];
  601. _snwprintf( wText, sizeof(wText)/sizeof(wchar_t), L"x %d", iBombsRemaining );
  602. vgui::surface()->DrawSetTextColor( g_PR->GetTeamColor( TEAM_SPECTATOR ) );
  603. // set pos centered under icon
  604. vgui::surface()->DrawSetTextPos( xpos + ( flIconSize * 0.50f ), yIcon + YRES(2) );
  605. for ( wchar_t *wch = wText ; *wch != 0 ; wch++ )
  606. {
  607. vgui::surface()->DrawUnicodeChar( *wch );
  608. }
  609. }
  610. }
  611. else
  612. {
  613. int xMid = xpos + ( flIconSize * 0.50f );
  614. m_pExplodedIcon->DrawSelf( xMid - iIconHalfWidth, yIcon, iIconWidth, iIconWidth, c );
  615. }
  616. }
  617. break;
  618. }
  619. }
  620. // see if one team is partially capping,
  621. // should show a 1/2 under the cap icon
  622. if ( iCappingTeam == TEAM_UNASSIGNED )
  623. {
  624. if ( iNumAllies > 0 && iNumAxis == 0 )
  625. {
  626. iCappingTeam = TEAM_ALLIES;
  627. }
  628. else if ( iNumAxis > 0 && iNumAllies == 0 )
  629. {
  630. iCappingTeam = TEAM_AXIS;
  631. }
  632. if ( iCappingTeam == TEAM_UNASSIGNED || iCappingTeam == g_pObjectiveResource->GetOwningTeam( index ) )
  633. {
  634. // no team is capping, even partially
  635. // or the person in the area already owns it
  636. xpos += ( m_nIconSize + m_nSeparatorWidth + m_nBackgroundOverlap * 2 );
  637. continue;
  638. }
  639. }
  640. // Draw the number of cappers below the icon
  641. int numPlayers = g_pObjectiveResource->GetNumPlayersInArea( index, iCappingTeam );
  642. int requiredPlayers = g_pObjectiveResource->GetRequiredCappers( index, iCappingTeam );
  643. if ( requiredPlayers > 1 )
  644. {
  645. numPlayers = MIN( numPlayers, requiredPlayers );
  646. wchar_t wText[6];
  647. _snwprintf( wText, sizeof(wText)/sizeof(wchar_t), L"%d/%d", numPlayers, requiredPlayers );
  648. vgui::surface()->DrawSetTextColor( g_PR->GetTeamColor( iCappingTeam ) );
  649. // get string length
  650. int len = g_pMatSystemSurface->DrawTextLen( m_hTextFont, "2/2" );
  651. // set pos centered under icon
  652. vgui::surface()->DrawSetTextPos( xpos + ( m_nIconSize / 2.0f ) - ( len / 2 ), ypos + flIconSize + m_nBackgroundOverlap + YRES( 2 ) ); // + 2 to account for the outlined box
  653. for ( wchar_t *wch = wText ; *wch != 0 ; wch++ )
  654. {
  655. vgui::surface()->DrawUnicodeChar( *wch );
  656. }
  657. }
  658. if ( g_pObjectiveResource->GetCappingTeam( index ) != TEAM_UNASSIGNED )
  659. {
  660. int iCapperIcon = g_pObjectiveResource->GetCPCappingIcon( index );
  661. // Draw the capper's icon
  662. if( iOwnerIcon != iCapperIcon && iCapperIcon != 0 )
  663. {
  664. // axis caps swipe from right to left...allied from left to right
  665. bool bAxis = ( g_pObjectiveResource->GetCappingTeam(index) == TEAM_AXIS ) ? true : false;
  666. //swipe!
  667. float flCapPercentage = g_pObjectiveResource->GetCPCapPercentage(index);
  668. // reversing the direction of the swipe effect
  669. if ( bAxis )
  670. {
  671. flCapPercentage = 1.0f - g_pObjectiveResource->GetCPCapPercentage(index);
  672. }
  673. float width = ( flIconSize * flCapPercentage );
  674. const char *szCappingMatName = GetMaterialNameFromIndex( iCapperIcon );
  675. vgui::surface()->DrawSetTextureFile( m_iCPCappingTextures[index], szCappingMatName, true, false );
  676. vgui::Vertex_t vert[4];
  677. Vector2D uv11( uv1, uv1 );
  678. Vector2D uv21( flCapPercentage, uv1 );
  679. Vector2D uv22( flCapPercentage, uv2 );
  680. Vector2D uv12( uv1, uv2 );
  681. // reversing the direction of the swipe effect
  682. if ( bAxis )
  683. {
  684. uv11.x = flCapPercentage;
  685. uv21.x = uv2;
  686. uv22.x = uv2;
  687. uv12.x = flCapPercentage;
  688. }
  689. Vector2D upperLeft ( flXPos, flYPos );
  690. Vector2D upperRight( flXPos + width, flYPos );
  691. Vector2D lowerRight( flXPos + width, flYPos + flIconSize );
  692. Vector2D lowerLeft ( flXPos, flYPos + flIconSize );
  693. /// reversing the direction of the swipe effect
  694. if ( bAxis )
  695. {
  696. upperLeft.x = flXPos + width;
  697. upperRight.x = flXPos + flIconSize;
  698. lowerRight.x = flXPos + flIconSize;
  699. lowerLeft.x = flXPos + width;
  700. }
  701. vert[0].Init( upperLeft, uv11 );
  702. vert[1].Init( upperRight, uv21 );
  703. vert[2].Init( lowerRight, uv22 );
  704. vert[3].Init( lowerLeft, uv12 );
  705. vgui::surface()->DrawSetColor( Color(255,255,255,255) );
  706. vgui::surface()->DrawTexturedPolygon( 4, vert );
  707. }
  708. }
  709. xpos += ( m_nIconSize + m_nSeparatorWidth + m_nBackgroundOverlap * 2 );
  710. }
  711. }
  712. }