Counter Strike : Global Offensive Source Code
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.

952 lines
27 KiB

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