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.

946 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_controls/EditablePanel.h>
  11. #include <vgui_controls/ImagePanel.h>
  12. #include <vgui/ISurface.h>
  13. #include "c_baseplayer.h"
  14. #include "iclientmode.h"
  15. #include "c_team_objectiveresource.h"
  16. #include "c_team.h"
  17. #include "view.h"
  18. #include "teamplay_gamerules.h"
  19. #define INTRO_NUM_FAKE_PLAYERS 3
  20. extern ConVar mp_capstyle;
  21. extern ConVar mp_blockstyle;
  22. //-----------------------------------------------------------------------------
  23. // Purpose: Draws the progress bar
  24. //-----------------------------------------------------------------------------
  25. class CHudCapturePanelProgressBar : public vgui::ImagePanel
  26. {
  27. public:
  28. DECLARE_CLASS_SIMPLE( CHudCapturePanelProgressBar, vgui::ImagePanel );
  29. CHudCapturePanelProgressBar( vgui::Panel *parent, const char *name );
  30. virtual void Paint();
  31. void SetPercentage( float flPercentage ){ m_flPercent = flPercentage; }
  32. private:
  33. float m_flPercent;
  34. int m_iTexture;
  35. CPanelAnimationVar( Color, m_clrActive, "color_active", "HudCaptureProgressBar.Active" );
  36. CPanelAnimationVar( Color, m_clrInActive, "color_inactive", "HudCaptureProgressBar.InActive" );
  37. };
  38. //-----------------------------------------------------------------------------
  39. // Purpose:
  40. //-----------------------------------------------------------------------------
  41. class CHudCapturePanelIcon : public vgui::ImagePanel
  42. {
  43. public:
  44. DECLARE_CLASS_SIMPLE( CHudCapturePanelIcon, vgui::ImagePanel );
  45. CHudCapturePanelIcon( vgui::Panel *parent, const char *name );
  46. virtual void Paint();
  47. void SetActive( bool state ){ m_bActive = state; }
  48. private:
  49. bool m_bActive;
  50. int m_iTexture;
  51. CPanelAnimationVar( Color, m_clrActive, "color_active", "HudCaptureIcon.Active" );
  52. CPanelAnimationVar( Color, m_clrInActive, "color_inactive", "HudCaptureIcon.InActive" );
  53. };
  54. //-----------------------------------------------------------------------------
  55. //
  56. //-----------------------------------------------------------------------------
  57. class CHudCapturePanel : public CHudElement, public vgui::EditablePanel
  58. {
  59. public:
  60. DECLARE_CLASS_SIMPLE( CHudCapturePanel, vgui::EditablePanel );
  61. CHudCapturePanel( const char *pElementName );
  62. virtual void Init( void );
  63. virtual void LevelInit( void );
  64. virtual void OnThink();
  65. virtual void ApplySchemeSettings( vgui::IScheme *pScheme );
  66. virtual void OnScreenSizeChanged( int iOldWide, int iOldTall );
  67. virtual void FireGameEvent( IGameEvent *event );
  68. private:
  69. int m_iCurrentCP; // the index of the control point the local is currently in
  70. int m_iOriginalYPos;
  71. CHudCapturePanelProgressBar *m_pProgressBar;
  72. CUtlVector<CHudCapturePanelIcon *> m_PlayerIcons;
  73. bool m_bInitializedFlags;
  74. vgui::ImagePanel *m_pTeamFlags[ MAX_TEAMS ];
  75. vgui::Label *m_pMessage;
  76. vgui::Panel *m_pBackground;
  77. CPanelAnimationVarAliasType( float, m_nSpaceBetweenIcons, "icon_space", "2", "proportional_float" );
  78. // For demonstrations of the element in the intro
  79. bool m_bFakingCapture;
  80. bool m_bFakingMultCapture;
  81. float m_flFakeCaptureTime;
  82. C_BaseAnimating *m_pFakePlayers[INTRO_NUM_FAKE_PLAYERS];
  83. };
  84. DECLARE_HUDELEMENT( CHudCapturePanel );
  85. ConVar hud_capturepanel( "hud_capturepanel", "1", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Set to 0 to not draw the HUD capture panel" );
  86. //-----------------------------------------------------------------------------
  87. // Purpose:
  88. //-----------------------------------------------------------------------------
  89. CHudCapturePanelProgressBar::CHudCapturePanelProgressBar( vgui::Panel *parent, const char *name ) : vgui::ImagePanel( parent, name )
  90. {
  91. m_flPercent = 0.0f;
  92. m_iTexture = vgui::surface()->DrawGetTextureId( "vgui/progress_bar" );
  93. if ( m_iTexture == -1 ) // we didn't find it, so create a new one
  94. {
  95. m_iTexture = vgui::surface()->CreateNewTextureID();
  96. vgui::surface()->DrawSetTextureFile( m_iTexture, "vgui/progress_bar", true, false );
  97. }
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Purpose:
  101. //-----------------------------------------------------------------------------
  102. void CHudCapturePanelProgressBar::Paint()
  103. {
  104. int wide, tall;
  105. GetSize( wide, tall );
  106. float uv1 = 0.0f, uv2 = 1.0f;
  107. Vector2D uv11( uv1, uv1 );
  108. Vector2D uv21( uv2, uv1 );
  109. Vector2D uv22( uv2, uv2 );
  110. Vector2D uv12( uv1, uv2 );
  111. vgui::Vertex_t verts[4];
  112. verts[0].Init( Vector2D( 0, 0 ), uv11 );
  113. verts[1].Init( Vector2D( wide, 0 ), uv21 );
  114. verts[2].Init( Vector2D( wide, tall ), uv22 );
  115. verts[3].Init( Vector2D( 0, tall ), uv12 );
  116. // first, just draw the whole thing inactive.
  117. vgui::surface()->DrawSetTexture( m_iTexture );
  118. vgui::surface()->DrawSetColor( m_clrInActive );
  119. vgui::surface()->DrawTexturedPolygon( 4, verts );
  120. // now, let's calculate the "active" part of the progress bar
  121. vgui::surface()->DrawSetColor( m_clrActive );
  122. // we're going to do this using quadrants
  123. // -------------------------
  124. // | | |
  125. // | | |
  126. // | 4 | 1 |
  127. // | | |
  128. // | | |
  129. // -------------------------
  130. // | | |
  131. // | | |
  132. // | 3 | 2 |
  133. // | | |
  134. // | | |
  135. // -------------------------
  136. float flCompleteCircle = ( 2.0f * M_PI );
  137. float fl90degrees = flCompleteCircle / 4.0f;
  138. float flEndAngle = flCompleteCircle * ( 1.0f - m_flPercent ); // count DOWN (counter-clockwise)
  139. // float flEndAngle = flCompleteCircle * m_flPercent; // count UP (clockwise)
  140. float flHalfWide = (float)wide / 2.0f;
  141. float flHalfTall = (float)tall / 2.0f;
  142. if ( flEndAngle >= fl90degrees * 3.0f ) // >= 270 degrees
  143. {
  144. // draw the first and second quadrants
  145. uv11.Init( 0.5f, 0.0f );
  146. uv21.Init( 1.0f, 0.0f );
  147. uv22.Init( 1.0f, 1.0f );
  148. uv12.Init( 0.5, 1.0f );
  149. verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 );
  150. verts[1].Init( Vector2D( wide, 0.0f ), uv21 );
  151. verts[2].Init( Vector2D( wide, tall ), uv22 );
  152. verts[3].Init( Vector2D( flHalfWide, tall ), uv12 );
  153. vgui::surface()->DrawTexturedPolygon( 4, verts );
  154. // draw the third quadrant
  155. uv11.Init( 0.0f, 0.5f );
  156. uv21.Init( 0.5f, 0.5f );
  157. uv22.Init( 0.5f, 1.0f );
  158. uv12.Init( 0.0f, 1.0f );
  159. verts[0].Init( Vector2D( 0.0f, flHalfTall ), uv11 );
  160. verts[1].Init( Vector2D( flHalfWide, flHalfTall ), uv21 );
  161. verts[2].Init( Vector2D( flHalfWide, tall ), uv22 );
  162. verts[3].Init( Vector2D( 0.0f, tall ), uv12 );
  163. vgui::surface()->DrawTexturedPolygon( 4, verts );
  164. // draw the partial fourth quadrant
  165. if ( flEndAngle > fl90degrees * 3.5f ) // > 315 degrees
  166. {
  167. uv11.Init( 0.0f, 0.0f );
  168. uv21.Init( 0.5f - ( tan(fl90degrees * 4.0f - flEndAngle) * 0.5 ), 0.0f );
  169. uv22.Init( 0.5f, 0.5f );
  170. uv12.Init( 0.0f, 0.5f );
  171. verts[0].Init( Vector2D( 0.0f, 0.0f ), uv11 );
  172. verts[1].Init( Vector2D( flHalfWide - ( tan(fl90degrees * 4.0f - flEndAngle) * flHalfTall ), 0.0f ), uv21 );
  173. verts[2].Init( Vector2D( flHalfWide, flHalfTall ), uv22 );
  174. verts[3].Init( Vector2D( 0.0f, flHalfTall ), uv12 );
  175. vgui::surface()->DrawTexturedPolygon( 4, verts );
  176. }
  177. else // <= 315 degrees
  178. {
  179. uv11.Init( 0.0f, 0.5f );
  180. uv21.Init( 0.0f, 0.5f - ( tan(flEndAngle - fl90degrees * 3.0f) * 0.5 ) );
  181. uv22.Init( 0.5f, 0.5f );
  182. uv12.Init( 0.0f, 0.5f );
  183. verts[0].Init( Vector2D( 0.0f, flHalfTall ), uv11 );
  184. verts[1].Init( Vector2D( 0.0f, flHalfTall - ( tan(flEndAngle - fl90degrees * 3.0f) * flHalfWide ) ), uv21 );
  185. verts[2].Init( Vector2D( flHalfWide, flHalfTall ), uv22 );
  186. verts[3].Init( Vector2D( 0.0f, flHalfTall ), uv12 );
  187. vgui::surface()->DrawTexturedPolygon( 4, verts );
  188. }
  189. }
  190. else if ( flEndAngle >= fl90degrees * 2.0f ) // >= 180 degrees
  191. {
  192. // draw the first and second quadrants
  193. uv11.Init( 0.5f, 0.0f );
  194. uv21.Init( 1.0f, 0.0f );
  195. uv22.Init( 1.0f, 1.0f );
  196. uv12.Init( 0.5, 1.0f );
  197. verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 );
  198. verts[1].Init( Vector2D( wide, 0.0f ), uv21 );
  199. verts[2].Init( Vector2D( wide, tall ), uv22 );
  200. verts[3].Init( Vector2D( flHalfWide, tall ), uv12 );
  201. vgui::surface()->DrawTexturedPolygon( 4, verts );
  202. // draw the partial third quadrant
  203. if ( flEndAngle > fl90degrees * 2.5f ) // > 225 degrees
  204. {
  205. uv11.Init( 0.5f, 0.5f );
  206. uv21.Init( 0.5f, 1.0f );
  207. uv22.Init( 0.0f, 1.0f );
  208. uv12.Init( 0.0f, 0.5f + ( tan(fl90degrees * 3.0f - flEndAngle) * 0.5 ) );
  209. verts[0].Init( Vector2D( flHalfWide, flHalfTall ), uv11 );
  210. verts[1].Init( Vector2D( flHalfWide, tall ), uv21 );
  211. verts[2].Init( Vector2D( 0.0f, tall ), uv22 );
  212. verts[3].Init( Vector2D( 0.0f, flHalfTall + ( tan(fl90degrees * 3.0f - flEndAngle) * flHalfWide ) ), uv12 );
  213. vgui::surface()->DrawTexturedPolygon( 4, verts );
  214. }
  215. else // <= 225 degrees
  216. {
  217. uv11.Init( 0.5f, 0.5f );
  218. uv21.Init( 0.5f, 1.0f );
  219. uv22.Init( 0.5f - ( tan( flEndAngle - fl90degrees * 2.0f) * 0.5 ), 1.0f );
  220. uv12.Init( 0.5f, 0.5f );
  221. verts[0].Init( Vector2D( flHalfWide, flHalfTall ), uv11 );
  222. verts[1].Init( Vector2D( flHalfWide, tall ), uv21 );
  223. verts[2].Init( Vector2D( flHalfWide - ( tan(flEndAngle - fl90degrees * 2.0f) * flHalfTall ), tall ), uv22 );
  224. verts[3].Init( Vector2D( flHalfWide, flHalfTall ), uv12 );
  225. vgui::surface()->DrawTexturedPolygon( 4, verts );
  226. }
  227. }
  228. else if ( flEndAngle >= fl90degrees ) // >= 90 degrees
  229. {
  230. // draw the first quadrant
  231. uv11.Init( 0.5f, 0.0f );
  232. uv21.Init( 1.0f, 0.0f );
  233. uv22.Init( 1.0f, 0.5f );
  234. uv12.Init( 0.5f, 0.5f );
  235. verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 );
  236. verts[1].Init( Vector2D( wide, 0.0f ), uv21 );
  237. verts[2].Init( Vector2D( wide, flHalfTall ), uv22 );
  238. verts[3].Init( Vector2D( flHalfWide, flHalfTall ), uv12 );
  239. vgui::surface()->DrawTexturedPolygon( 4, verts );
  240. // draw the partial second quadrant
  241. if ( flEndAngle > fl90degrees * 1.5f ) // > 135 degrees
  242. {
  243. uv11.Init( 0.5f, 0.5f );
  244. uv21.Init( 1.0f, 0.5f );
  245. uv22.Init( 1.0f, 1.0f );
  246. uv12.Init( 0.5f + ( tan(fl90degrees * 2.0f - flEndAngle) * 0.5f ), 1.0f );
  247. verts[0].Init( Vector2D( flHalfWide, flHalfTall ), uv11 );
  248. verts[1].Init( Vector2D( wide, flHalfTall ), uv21 );
  249. verts[2].Init( Vector2D( wide, tall ), uv22 );
  250. verts[3].Init( Vector2D( flHalfWide + ( tan(fl90degrees * 2.0f - flEndAngle) * flHalfTall ), tall ), uv12 );
  251. vgui::surface()->DrawTexturedPolygon( 4, verts );
  252. }
  253. else // <= 135 degrees
  254. {
  255. uv11.Init( 0.5f, 0.5f );
  256. uv21.Init( 1.0f, 0.5f );
  257. uv22.Init( 1.0f, 0.5f + ( tan(flEndAngle - fl90degrees) * 0.5f ) );
  258. uv12.Init( 0.5f, 0.5f );
  259. verts[0].Init( Vector2D( flHalfWide, flHalfTall ), uv11 );
  260. verts[1].Init( Vector2D( wide, flHalfTall ), uv21 );
  261. verts[2].Init( Vector2D( wide, flHalfTall + ( tan(flEndAngle - fl90degrees) * flHalfWide ) ), uv22 );
  262. verts[3].Init( Vector2D( flHalfWide, flHalfTall ), uv12 );
  263. vgui::surface()->DrawTexturedPolygon( 4, verts );
  264. }
  265. }
  266. else // > 0 degrees
  267. {
  268. if ( flEndAngle > fl90degrees / 2.0f ) // > 45 degrees
  269. {
  270. uv11.Init( 0.5f, 0.0f );
  271. uv21.Init( 1.0f, 0.0f );
  272. uv22.Init( 1.0f, 0.5f - ( tan(fl90degrees - flEndAngle) * 0.5 ) );
  273. uv12.Init( 0.5f, 0.5f );
  274. verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 );
  275. verts[1].Init( Vector2D( wide, 0.0f ), uv21 );
  276. verts[2].Init( Vector2D( wide, flHalfTall - ( tan(fl90degrees - flEndAngle) * flHalfWide ) ), uv22 );
  277. verts[3].Init( Vector2D( flHalfWide, flHalfTall ), uv12 );
  278. vgui::surface()->DrawTexturedPolygon( 4, verts );
  279. }
  280. else // <= 45 degrees
  281. {
  282. uv11.Init( 0.5f, 0.0f );
  283. uv21.Init( 0.5 + ( tan(flEndAngle) * 0.5 ), 0.0f );
  284. uv22.Init( 0.5f, 0.5f );
  285. uv12.Init( 0.5f, 0.0f );
  286. verts[0].Init( Vector2D( flHalfWide, 0.0f ), uv11 );
  287. verts[1].Init( Vector2D( flHalfWide + ( tan(flEndAngle) * flHalfTall ), 0.0f ), uv21 );
  288. verts[2].Init( Vector2D( flHalfWide, flHalfTall ), uv22 );
  289. verts[3].Init( Vector2D( flHalfWide, 0.0f ), uv12 );
  290. vgui::surface()->DrawTexturedPolygon( 4, verts );
  291. }
  292. }
  293. }
  294. //-----------------------------------------------------------------------------
  295. // Purpose:
  296. //-----------------------------------------------------------------------------
  297. CHudCapturePanelIcon::CHudCapturePanelIcon( vgui::Panel *parent, const char *name ) : vgui::ImagePanel( parent, name )
  298. {
  299. m_bActive = false;
  300. m_iTexture = vgui::surface()->DrawGetTextureId( "vgui/capture_icon" );
  301. if ( m_iTexture == -1 ) // we didn't find it, so create a new one
  302. {
  303. m_iTexture = vgui::surface()->CreateNewTextureID();
  304. vgui::surface()->DrawSetTextureFile( m_iTexture, "vgui/capture_icon", true, false );
  305. }
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose:
  309. //-----------------------------------------------------------------------------
  310. void CHudCapturePanelIcon::Paint()
  311. {
  312. int wide, tall;
  313. GetSize( wide, tall );
  314. float uv1 = 0.0f, uv2 = 1.0f;
  315. Vector2D uv11( uv1, uv1 );
  316. Vector2D uv12( uv1, uv2 );
  317. Vector2D uv21( uv2, uv1 );
  318. Vector2D uv22( uv2, uv2 );
  319. vgui::Vertex_t verts[4];
  320. verts[0].Init( Vector2D( 0, 0 ), uv11 );
  321. verts[1].Init( Vector2D( wide, 0 ), uv21 );
  322. verts[2].Init( Vector2D( wide, tall ), uv22 );
  323. verts[3].Init( Vector2D( 0, tall ), uv12 );
  324. // just draw the whole thing
  325. vgui::surface()->DrawSetTexture( m_iTexture );
  326. vgui::surface()->DrawSetColor( m_bActive ? m_clrActive : m_clrInActive );
  327. vgui::surface()->DrawTexturedPolygon( 4, verts );
  328. }
  329. //-----------------------------------------------------------------------------
  330. // Purpose: Constructor
  331. //-----------------------------------------------------------------------------
  332. CHudCapturePanel::CHudCapturePanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, "HudCapturePanel" )
  333. {
  334. SetParent( g_pClientMode->GetViewport() );
  335. m_iCurrentCP = -1;
  336. m_bFakingCapture = false;
  337. m_pBackground = new vgui::Panel( this, "CapturePanelBackground" );
  338. m_pProgressBar = new CHudCapturePanelProgressBar( this, "CapturePanelProgressBar" );
  339. for ( int i = 0 ; i < 5 ; i++ )
  340. {
  341. CHudCapturePanelIcon *pPanel;
  342. char szName[64];
  343. Q_snprintf( szName, sizeof( szName ), "CapturePanelPlayerIcon%d", i + 1 );
  344. pPanel = new CHudCapturePanelIcon( this, szName );
  345. m_PlayerIcons.AddToTail( pPanel );
  346. }
  347. m_bInitializedFlags = false;
  348. for ( int i = 0; i < MAX_TEAMS; i++ )
  349. {
  350. m_pTeamFlags[i] = NULL;
  351. }
  352. m_pMessage = new vgui::Label( this, "CapturePanelMessage", " " );
  353. // load control settings...
  354. LoadControlSettings( "resource/UI/HudCapturePanel.res" );
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose:
  358. //-----------------------------------------------------------------------------
  359. void CHudCapturePanel::Init( void )
  360. {
  361. ListenForGameEvent( "controlpoint_starttouch" );
  362. ListenForGameEvent( "controlpoint_endtouch" );
  363. ListenForGameEvent( "teamplay_round_start" );
  364. ListenForGameEvent( "controlpoint_fake_capture" );
  365. ListenForGameEvent( "controlpoint_fake_capture_mult" );
  366. ListenForGameEvent( "intro_finish" );
  367. }
  368. //-----------------------------------------------------------------------------
  369. // Purpose:
  370. //-----------------------------------------------------------------------------
  371. void CHudCapturePanel::LevelInit( void )
  372. {
  373. m_iCurrentCP = -1;
  374. m_bFakingCapture = false;
  375. }
  376. //-----------------------------------------------------------------------------
  377. // Purpose:
  378. //-----------------------------------------------------------------------------
  379. void CHudCapturePanel::OnScreenSizeChanged( int iOldWide, int iOldTall )
  380. {
  381. LoadControlSettings( "resource/UI/HudCapturePanel.res" );
  382. }
  383. //-----------------------------------------------------------------------------
  384. // Purpose:
  385. //-----------------------------------------------------------------------------
  386. void CHudCapturePanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  387. {
  388. BaseClass::ApplySchemeSettings( pScheme );
  389. if ( m_pBackground )
  390. {
  391. m_pBackground->SetBgColor( GetSchemeColor( "HintMessageBg", pScheme ) );
  392. m_pBackground->SetPaintBackgroundType( 2 );
  393. }
  394. SetFgColor( GetSchemeColor( "HudProgressBar.Active", pScheme ) );
  395. int iX;
  396. GetPos( iX, m_iOriginalYPos );
  397. }
  398. //-----------------------------------------------------------------------------
  399. // Purpose:
  400. //-----------------------------------------------------------------------------
  401. void CHudCapturePanel::OnThink()
  402. {
  403. BaseClass::OnThink();
  404. if ( !GetNumberOfTeams() )
  405. return;
  406. if ( !m_bInitializedFlags )
  407. {
  408. m_bInitializedFlags = true;
  409. for ( int i = 0; i < GetNumberOfTeams(); i++ )
  410. {
  411. if ( i == TEAM_SPECTATOR )
  412. continue;
  413. m_pTeamFlags[i] = dynamic_cast< vgui::ImagePanel * >(FindChildByName( VarArgs("CapturePanelTeamFlag_%d", i) ));
  414. }
  415. InvalidateLayout();
  416. }
  417. if ( m_bFakingCapture && gpGlobals->curtime > m_flFakeCaptureTime )
  418. {
  419. m_bFakingCapture = false;
  420. if ( m_bFakingMultCapture )
  421. {
  422. for ( int i = 0; i < INTRO_NUM_FAKE_PLAYERS; i++ )
  423. {
  424. m_pFakePlayers[i]->Release();
  425. m_pFakePlayers[i] = NULL;
  426. }
  427. }
  428. }
  429. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  430. if ( pPlayer )
  431. {
  432. bool bInCapZone = ( m_iCurrentCP >= 0 );
  433. // Turn off the panel and children if the player is dead or not in a cap zone
  434. if ( !m_bFakingCapture && (!bInCapZone || !hud_capturepanel.GetBool() || !pPlayer->IsAlive()) )
  435. {
  436. if ( IsVisible() )
  437. {
  438. SetVisible( false );
  439. }
  440. return;
  441. }
  442. int nOwningTeam = ObjectiveResource()->GetOwningTeam( m_iCurrentCP );
  443. int nPlayerTeam = pPlayer->GetTeamNumber();
  444. int nNumTeammates = ObjectiveResource()->GetNumPlayersInArea( m_iCurrentCP, nPlayerTeam );
  445. int nRequiredTeammates = ObjectiveResource()->GetRequiredCappers( m_iCurrentCP, nPlayerTeam );
  446. int nNumEnemies = 0;
  447. bool bEnemyTeamReadyToCap = false;
  448. for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ )
  449. {
  450. if ( i == nPlayerTeam )
  451. continue;
  452. int iTeamInArea = ObjectiveResource()->GetNumPlayersInArea( m_iCurrentCP, i );
  453. nNumEnemies += iTeamInArea;
  454. if ( iTeamInArea >= ObjectiveResource()->GetRequiredCappers( m_iCurrentCP, i ) )
  455. {
  456. // There's an enemy team here that has enough players to cap
  457. bEnemyTeamReadyToCap = true;
  458. }
  459. }
  460. int iCappingTeam = ObjectiveResource()->GetCappingTeam( m_iCurrentCP );
  461. // If we're faking it, stomp all the data
  462. if ( m_bFakingCapture )
  463. {
  464. nOwningTeam = TEAM_UNASSIGNED;
  465. iCappingTeam = nPlayerTeam;
  466. if ( m_bFakingMultCapture )
  467. {
  468. nNumTeammates = nRequiredTeammates = 3;
  469. }
  470. else
  471. {
  472. nNumTeammates = nRequiredTeammates = 1;
  473. }
  474. nNumEnemies = 0;
  475. bEnemyTeamReadyToCap = false;
  476. }
  477. // If we're in more-players-cap-faster mode, we have no required amount.
  478. // Just show the number of players in the zone.
  479. if ( mp_capstyle.GetInt() == 1 )
  480. {
  481. // Clip to max number of players we can show
  482. if ( nNumTeammates > 5 )
  483. {
  484. nNumTeammates = 5;
  485. }
  486. nRequiredTeammates = nNumTeammates;
  487. }
  488. // if we already own this capture point and there are no enemies in the area
  489. // or we're playing minirounds and the current cap zone is not in the current round
  490. if ( ( nOwningTeam == nPlayerTeam && !bEnemyTeamReadyToCap ) ||
  491. ( ObjectiveResource()->PlayingMiniRounds() && !ObjectiveResource()->IsInMiniRound( m_iCurrentCP ) ) )
  492. {
  493. // don't need to do anything
  494. if ( IsVisible() )
  495. {
  496. SetVisible( false );
  497. }
  498. return;
  499. }
  500. // okay, turn on the capture point panel
  501. if ( !IsVisible() )
  502. {
  503. SetVisible( true );
  504. }
  505. // If there's a hint onscreen, move ourselves off it
  506. int iX,iY;
  507. GetPos( iX, iY );
  508. if ( pPlayer->Hints() && pPlayer->Hints()->HintIsCurrentlyVisible() )
  509. {
  510. int iMovedY = (m_iOriginalYPos - YRES(50));
  511. if ( iY != iMovedY )
  512. {
  513. SetPos( iX, iMovedY );
  514. }
  515. }
  516. else if ( iY != m_iOriginalYPos )
  517. {
  518. SetPos( iX, m_iOriginalYPos );
  519. }
  520. // set the correct flag image
  521. for ( int i = 0; i < GetNumberOfTeams(); i++ )
  522. {
  523. if ( !m_pTeamFlags[i] )
  524. continue;
  525. m_pTeamFlags[i]->SetVisible( nOwningTeam == i );
  526. }
  527. // arrange the player icons
  528. for ( int i = 0 ; i < m_PlayerIcons.Count() ; i++ )
  529. {
  530. CHudCapturePanelIcon *pPanel = m_PlayerIcons[i];
  531. if ( !pPanel )
  532. {
  533. continue;
  534. }
  535. if ( i < nRequiredTeammates )
  536. {
  537. if ( i < nNumTeammates )
  538. {
  539. pPanel->SetActive( true );
  540. if ( !pPanel->IsVisible() )
  541. pPanel->SetVisible( true );
  542. }
  543. else
  544. {
  545. pPanel->SetActive( false );
  546. if ( !pPanel->IsVisible() )
  547. pPanel->SetVisible( true );
  548. }
  549. }
  550. else
  551. {
  552. if ( pPanel->IsVisible() )
  553. pPanel->SetVisible( false );
  554. }
  555. }
  556. int wide = 0, tall = 0, iconWide = 0, iconTall = 0;
  557. GetSize( wide, tall );
  558. vgui::ImagePanel *pPanel = m_PlayerIcons[0];
  559. if ( pPanel )
  560. pPanel->GetSize( iconWide, iconTall );
  561. int width = ( nRequiredTeammates * iconWide ) + ( ( nRequiredTeammates - 1 ) * m_nSpaceBetweenIcons );
  562. int xpos = wide / 2.0 - width / 2.0;
  563. // rearrange the player icon panels
  564. for ( int i = 0 ; i < nRequiredTeammates ; i++ )
  565. {
  566. CHudCapturePanelIcon *pPanel = m_PlayerIcons[i];
  567. if ( pPanel )
  568. {
  569. int x, y, w, t;
  570. pPanel->GetBounds( x, y, w, t );
  571. pPanel->SetBounds( xpos, y, w, t );
  572. }
  573. xpos += iconWide + m_nSpaceBetweenIcons;
  574. }
  575. // are we capping an area?
  576. if ( iCappingTeam == TEAM_UNASSIGNED || iCappingTeam != nPlayerTeam )
  577. {
  578. // turn off the progress bar, we're not capping
  579. if ( m_pProgressBar && m_pProgressBar->IsVisible() )
  580. {
  581. m_pProgressBar->SetVisible( false );
  582. }
  583. // turn on the message
  584. if ( m_pMessage )
  585. {
  586. m_pMessage->SetFgColor( GetFgColor() );
  587. if ( !m_pMessage->IsVisible() )
  588. {
  589. m_pMessage->SetVisible( true );
  590. }
  591. char szReason[256];
  592. // If a team's not allowed to cap a point, don't count players in it at all
  593. if ( !TeamplayGameRules()->TeamMayCapturePoint( nPlayerTeam, m_iCurrentCP ) )
  594. {
  595. m_pMessage->SetText( "#Team_Capture_Linear" );
  596. if ( m_pTeamFlags[ nOwningTeam ] )
  597. {
  598. m_pTeamFlags[ nOwningTeam ]->SetVisible( false );
  599. }
  600. }
  601. else if ( !TeamplayGameRules()->PlayerMayCapturePoint( pPlayer, m_iCurrentCP, szReason, sizeof(szReason) ) )
  602. {
  603. m_pMessage->SetText( szReason );
  604. if ( m_pTeamFlags[ nOwningTeam ] )
  605. {
  606. m_pTeamFlags[ nOwningTeam ]->SetVisible( false );
  607. }
  608. }
  609. else if ( nNumTeammates >= nRequiredTeammates && nNumEnemies > 0 )
  610. {
  611. m_pMessage->SetText( "#Team_Capture_Blocked" );
  612. }
  613. else if ( bEnemyTeamReadyToCap )
  614. {
  615. m_pMessage->SetText( "#Team_Blocking_Capture" );
  616. }
  617. else if ( mp_blockstyle.GetInt() == 1 && iCappingTeam != TEAM_UNASSIGNED )
  618. {
  619. m_pMessage->SetText( "#Team_Blocking_Capture" );
  620. for ( int i = 0; i < GetNumberOfTeams(); i++ )
  621. {
  622. if ( m_pTeamFlags[i] )
  623. {
  624. m_pTeamFlags[i]->SetVisible( false );
  625. }
  626. }
  627. }
  628. else if ( !ObjectiveResource()->TeamCanCapPoint( m_iCurrentCP, nPlayerTeam ) )
  629. {
  630. m_pMessage->SetText( "#Team_Cannot_Capture" );
  631. if ( m_pTeamFlags[ nOwningTeam ] )
  632. {
  633. m_pTeamFlags[ nOwningTeam ]->SetVisible( false );
  634. }
  635. }
  636. else
  637. {
  638. m_pMessage->SetText( "#Team_Waiting_for_teammate" );
  639. }
  640. if ( m_pBackground )
  641. {
  642. // do we need to resize our background?
  643. int textW, textH, bgX, bgY, bgW, bgH;
  644. m_pMessage->GetContentSize( textW, textH );
  645. m_pBackground->GetBounds( bgX, bgY, bgW, bgH );
  646. if ( bgW < textW )
  647. {
  648. m_pBackground->SetBounds( bgX + ( bgW / 2.0 ) - ( ( textW + XRES(3) ) / 2.0 ), bgY, textW + XRES(3), bgH );
  649. }
  650. }
  651. }
  652. }
  653. else
  654. {
  655. // turn on the progress bar, we're capping
  656. if ( m_pProgressBar )
  657. {
  658. if ( !m_pProgressBar->IsVisible() )
  659. {
  660. m_pProgressBar->SetVisible( true );
  661. }
  662. if ( m_bFakingCapture )
  663. {
  664. float flProgress = RemapVal( m_flFakeCaptureTime - gpGlobals->curtime, 0, 5.0, 0, 1 );
  665. m_pProgressBar->SetPercentage( flProgress );
  666. }
  667. else
  668. {
  669. m_pProgressBar->SetPercentage( ObjectiveResource()->GetCPCapPercentage( m_iCurrentCP ) );
  670. }
  671. }
  672. // If our cap is being paused by blocking enemies, show that
  673. if ( mp_blockstyle.GetInt() == 1 && nNumTeammates == 0 )
  674. {
  675. m_pMessage->SetText( "#Team_Capture_Blocked" );
  676. if ( !m_pMessage->IsVisible() )
  677. {
  678. m_pMessage->SetVisible( true );
  679. }
  680. for ( int i = 0; i < GetNumberOfTeams(); i++ )
  681. {
  682. if ( m_pTeamFlags[i] )
  683. {
  684. m_pTeamFlags[i]->SetVisible( false );
  685. }
  686. }
  687. }
  688. else if ( m_pMessage && m_pMessage->IsVisible() )
  689. {
  690. // turn off the message
  691. m_pMessage->SetVisible( false );
  692. }
  693. }
  694. }
  695. }
  696. //-----------------------------------------------------------------------------
  697. // Purpose:
  698. //-----------------------------------------------------------------------------
  699. void CHudCapturePanel::FireGameEvent( IGameEvent *event )
  700. {
  701. m_iCurrentCP = -1;
  702. return;
  703. const char *eventname = event->GetName();
  704. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  705. if ( FStrEq( "controlpoint_starttouch", eventname ) )
  706. {
  707. int iPlayer = event->GetInt( "player" );
  708. if ( pPlayer && iPlayer == pPlayer->entindex() )
  709. {
  710. m_iCurrentCP = event->GetInt( "area" );
  711. }
  712. }
  713. else if ( FStrEq( "controlpoint_endtouch", eventname ) )
  714. {
  715. int iPlayer = event->GetInt( "player" );
  716. if ( pPlayer && iPlayer == pPlayer->entindex() )
  717. {
  718. Assert( m_iCurrentCP == event->GetInt( "area" ) );
  719. m_iCurrentCP = -1;
  720. }
  721. }
  722. else if ( FStrEq( "teamplay_round_start", eventname ) )
  723. {
  724. m_iCurrentCP = -1;
  725. }
  726. else if ( FStrEq( "controlpoint_fake_capture", eventname ) )
  727. {
  728. int iPlayer = event->GetInt( "player" );
  729. if ( pPlayer && iPlayer == pPlayer->entindex() )
  730. {
  731. m_iCurrentCP = event->GetInt( "int_data" );
  732. m_bFakingCapture = true;
  733. m_bFakingMultCapture = false;
  734. m_flFakeCaptureTime = gpGlobals->curtime + 5.0;
  735. }
  736. }
  737. else if ( FStrEq( "controlpoint_fake_capture_mult", eventname ) )
  738. {
  739. int iPlayer = event->GetInt( "player" );
  740. if ( pPlayer && iPlayer == pPlayer->entindex() )
  741. {
  742. m_iCurrentCP = event->GetInt( "int_data" );
  743. m_bFakingCapture = true;
  744. m_bFakingMultCapture = true;
  745. m_flFakeCaptureTime = gpGlobals->curtime + 5.0;
  746. // Trace forward & find the world
  747. trace_t tr;
  748. Vector vecEnd;
  749. VectorMA( MainViewOrigin(), MAX_TRACE_LENGTH, MainViewForward(), vecEnd );
  750. UTIL_TraceLine( MainViewOrigin(), vecEnd, MASK_SOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr );
  751. if ( !tr.startsolid && tr.fraction < 1.0 )
  752. {
  753. Vector vecPositions[INTRO_NUM_FAKE_PLAYERS] =
  754. {
  755. Vector( 100, 100, 0 ),
  756. Vector( 0, -100, 0 ),
  757. Vector( -100, 0, 0 ),
  758. };
  759. const char *pszModels[INTRO_NUM_FAKE_PLAYERS] =
  760. {
  761. "models/player/engineer.mdl",
  762. "models/player/medic.mdl",
  763. "models/player/soldier.mdl",
  764. };
  765. for ( int i = 0; i < INTRO_NUM_FAKE_PLAYERS; i++ )
  766. {
  767. m_pFakePlayers[i] = new C_BaseAnimating;
  768. if ( m_pFakePlayers[i]->InitializeAsClientEntity( pszModels[i], RENDER_GROUP_OPAQUE_ENTITY ) )
  769. {
  770. Vector vecOrigin = tr.endpos + vecPositions[i];
  771. m_pFakePlayers[i]->SetAbsOrigin( vecOrigin );
  772. m_pFakePlayers[i]->SetAbsAngles( QAngle(0,RandomInt(0,360),0) );
  773. }
  774. }
  775. }
  776. }
  777. }
  778. else if ( FStrEq( "intro_finish", eventname ) )
  779. {
  780. int iPlayer = event->GetInt( "player" );
  781. if ( pPlayer && iPlayer == pPlayer->entindex() )
  782. {
  783. m_iCurrentCP = -1;
  784. m_bFakingCapture = false;
  785. m_bFakingMultCapture = false;
  786. m_flFakeCaptureTime = 0;
  787. for ( int i = 0; i < INTRO_NUM_FAKE_PLAYERS; i++ )
  788. {
  789. if ( m_pFakePlayers[i] )
  790. {
  791. m_pFakePlayers[i]->Release();
  792. m_pFakePlayers[i] = NULL;
  793. }
  794. }
  795. }
  796. }
  797. }