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.

1532 lines
44 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "hud_controlpointicons.h"
  8. #include "teamplayroundbased_gamerules.h"
  9. #include "IClientMode.h"
  10. #include "c_team_objectiveresource.h"
  11. #include "c_playerresource.h"
  12. #include "c_baseplayer.h"
  13. #include "vguimatsurface/IMatSystemSurface.h"
  14. #include "hud_macros.h"
  15. #include "spectatorgui.h"
  16. #include "c_team.h"
  17. #include "tf_hud_freezepanel.h"
  18. #include "tf_hud_objectivestatus.h"
  19. // NOTE: This has to be the last file included!
  20. #include "tier0/memdbgon.h"
  21. using namespace vgui;
  22. //-----------------------------------------------------------------------------
  23. // Purpose:
  24. //-----------------------------------------------------------------------------
  25. void CControlPointIconPulseable::ApplySchemeSettings( IScheme *pScheme )
  26. {
  27. BaseClass::ApplySchemeSettings( pScheme );
  28. if ( !m_pPulseImage )
  29. {
  30. m_pPulseImage = scheme()->GetImage( "../sprites/obj_icons/icon_obj_white", true );
  31. }
  32. }
  33. //-----------------------------------------------------------------------------
  34. // Purpose:
  35. //-----------------------------------------------------------------------------
  36. void CControlPointIconPulseable::OnSizeChanged(int newWide, int newTall)
  37. {
  38. if ( m_pPulseImage )
  39. {
  40. // scaling, force the image size to be our size
  41. m_pPulseImage->SetSize(newWide, newTall);
  42. }
  43. BaseClass::OnSizeChanged(newWide, newTall);
  44. }
  45. //-----------------------------------------------------------------------------
  46. // Purpose:
  47. //-----------------------------------------------------------------------------
  48. void CControlPointIconPulseable::PaintBackground( void )
  49. {
  50. if ( IsInFreezeCam() == true )
  51. return;
  52. if ( GetImage() )
  53. {
  54. SetAlpha(255);
  55. BaseClass::PaintBackground();
  56. }
  57. if ( m_flStartCapAnimStart && gpGlobals->curtime > m_flStartCapAnimStart )
  58. {
  59. float flElapsedTime = (gpGlobals->curtime - m_flStartCapAnimStart);
  60. // Pulse the white over the underlying color
  61. float flPulseSpeed = 20;
  62. if ( m_bAccelerateOverCapture )
  63. {
  64. float flCapPercentage = ObjectiveResource()->GetCPCapPercentage( m_iCPIndex );
  65. flPulseSpeed = RemapValClamped( flCapPercentage, 0, 1, 2, 5 );
  66. }
  67. float flPulseMod = fabs(sin( flElapsedTime * flPulseSpeed ));
  68. SetAlpha( 255 * flPulseMod );
  69. int wide, tall;
  70. GetSize( wide, tall );
  71. // Have to reset these - we're only referencing a material so the
  72. // size can be changed by CControlPointIconCapturePulse on a successful cap
  73. m_pPulseImage->SetPos( 0, 0 );
  74. m_pPulseImage->SetSize( wide, tall );
  75. m_pPulseImage->Paint();
  76. // Stop if we're only supposed to do this for a short time
  77. if ( m_flPulseTime && flElapsedTime >= m_flPulseTime )
  78. {
  79. StopPulsing();
  80. }
  81. }
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose:
  85. //-----------------------------------------------------------------------------
  86. void CControlPointIconPulseable::StartPulsing( float flDelay, float flPulseTime, bool bAccelerate )
  87. {
  88. m_flStartCapAnimStart = gpGlobals->curtime + flDelay;
  89. m_bAccelerateOverCapture = bAccelerate;
  90. m_flPulseTime = flPulseTime;
  91. }
  92. //-----------------------------------------------------------------------------
  93. // Purpose:
  94. //-----------------------------------------------------------------------------
  95. void CControlPointIconPulseable::StopPulsing( void )
  96. {
  97. m_flStartCapAnimStart = 0;
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Purpose:
  101. //-----------------------------------------------------------------------------
  102. CControlPointIcon::CControlPointIcon( Panel *parent, const char *pName, int iIndex ) : EditablePanel( parent, "ControlPointIcon" ), CHudElement( pName )
  103. {
  104. SetHiddenBits( HIDEHUD_MISCSTATUS );
  105. m_iCPIndex = iIndex;
  106. m_pBaseImage = NULL;
  107. m_pOverlayImage = NULL;
  108. m_pCapImage = NULL;
  109. m_pCapHighlightImage = NULL;
  110. m_pCapPulseImage = NULL;
  111. m_pCapPlayerImage = NULL;
  112. m_pCapNumPlayers = NULL;
  113. m_bSwipeUp = false;
  114. m_flStartCapAnimStart = 0;
  115. m_iCapProgressDir = CP_DIR_N;
  116. m_iPrevCappers = 0;
  117. }
  118. //-----------------------------------------------------------------------------
  119. // Purpose:
  120. //-----------------------------------------------------------------------------
  121. void CControlPointIcon::ApplySchemeSettings( IScheme *pScheme )
  122. {
  123. BaseClass::ApplySchemeSettings( pScheme );
  124. if ( !m_pCapHighlightImage )
  125. {
  126. m_pCapHighlightImage = new CControlPointIconSwoop( this, "CapHighlightImage" );
  127. m_pCapHighlightImage->SetParent( GetClientMode()->GetViewport() );
  128. m_pCapHighlightImage->SetZPos( 10 );
  129. m_pCapHighlightImage->SetShouldScaleImage( true );
  130. }
  131. if ( !m_pCapPulseImage )
  132. {
  133. m_pCapPulseImage = new CControlPointIconCapturePulse( this, "CapPulse" );
  134. m_pCapPulseImage->SetParent( GetClientMode()->GetViewport() );
  135. m_pCapPulseImage->SetZPos( -1 );
  136. m_pCapPulseImage->SetVisible( false );
  137. m_pCapPulseImage->SetShouldScaleImage( true );
  138. }
  139. if ( !m_pBaseImage )
  140. {
  141. m_pBaseImage = new CControlPointIconPulseable( this, "BaseImage", m_iCPIndex );
  142. m_pBaseImage->SetShouldScaleImage( true );
  143. }
  144. if ( !m_pCapImage )
  145. {
  146. m_pCapImage = new CControlPointIconCapArrow( this, this, "CapImage" );
  147. m_pCapImage->SetZPos( 2 );
  148. m_pCapImage->SetVisible( false );
  149. }
  150. LoadControlSettings( "resource/UI/ControlPointIcon.res" );
  151. m_pCapPlayerImage = dynamic_cast<ImagePanel *>( FindChildByName("CapPlayerImage") );
  152. m_pCapNumPlayers = dynamic_cast<Label *>( FindChildByName("CapNumPlayers") );
  153. m_pOverlayImage = dynamic_cast<ImagePanel *>( FindChildByName("OverlayImage") );
  154. UpdateImage();
  155. UpdateCapImage();
  156. }
  157. //-----------------------------------------------------------------------------
  158. // Purpose:
  159. //-----------------------------------------------------------------------------
  160. CControlPointIcon::~CControlPointIcon( void )
  161. {
  162. if ( m_pCapHighlightImage )
  163. {
  164. m_pCapHighlightImage->MarkForDeletion();
  165. m_pCapHighlightImage = NULL;
  166. }
  167. if ( m_pCapPulseImage )
  168. {
  169. m_pCapPulseImage->MarkForDeletion();
  170. m_pCapPulseImage = NULL;
  171. }
  172. }
  173. //-----------------------------------------------------------------------------
  174. // Purpose:
  175. //-----------------------------------------------------------------------------
  176. void CControlPointIcon::UpdateImage( void )
  177. {
  178. if ( !ObjectiveResource() )
  179. return;
  180. int iOwner = ObjectiveResource()->GetOwningTeam( m_iCPIndex );
  181. if ( m_pBaseImage )
  182. {
  183. int iOwnerIcon = ObjectiveResource()->GetCPCurrentOwnerIcon( m_iCPIndex, iOwner );
  184. const char *szMatName = GetMaterialNameFromIndex( iOwnerIcon );
  185. if ( IsPointLocked() )
  186. {
  187. m_pBaseImage->SetImage( VarArgs("..\\%s_locked", szMatName ) );
  188. }
  189. else
  190. {
  191. m_pBaseImage->SetImage( VarArgs("..\\%s", szMatName ) );
  192. }
  193. }
  194. if ( m_pOverlayImage )
  195. {
  196. int iOverlayIcon = ObjectiveResource()->GetOverlayForTeam( m_iCPIndex, iOwner );
  197. if ( iOverlayIcon )
  198. {
  199. const char *szMatName = GetMaterialNameFromIndex( iOverlayIcon );
  200. m_pOverlayImage->SetImage( VarArgs("..\\%s", szMatName ) );
  201. m_pOverlayImage->SetVisible( true );
  202. }
  203. else
  204. {
  205. m_pOverlayImage->SetVisible( false );
  206. }
  207. }
  208. // Whenever a successful cap occurs, flash the cap point
  209. if ( m_pCapPulseImage )
  210. {
  211. if ( m_iPrevCappers != 0 && iOwner == m_iPrevCappers )
  212. {
  213. m_iPrevCappers = 0;
  214. if ( ShouldDraw() )
  215. {
  216. m_pCapPulseImage->SetVisible( true );
  217. m_pCapPulseImage->StartPulse( gpGlobals->curtime, GetWide() );
  218. }
  219. m_pBaseImage->StartPulsing( FINISHCAPANIM_SWOOP_LENGTH, 0.5, false );
  220. }
  221. }
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Purpose:
  225. //-----------------------------------------------------------------------------
  226. void CControlPointIcon::UpdateCapImage( void )
  227. {
  228. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  229. if ( !pPlayer )
  230. return;
  231. if ( m_pCapImage )
  232. {
  233. int iCappingTeam = ObjectiveResource()->GetCappingTeam( m_iCPIndex );
  234. int iOwningTeam = ObjectiveResource()->GetOwningTeam( m_iCPIndex );
  235. if ( iCappingTeam != TEAM_UNASSIGNED && iCappingTeam != iOwningTeam )
  236. {
  237. const char *pszCapSwipe = ObjectiveResource()->GetGameSpecificCPCappingSwipe( m_iCPIndex, iCappingTeam );
  238. if ( m_bSwipeUp )
  239. {
  240. m_pCapImage->SetImage( VarArgs("%s_up",pszCapSwipe) );
  241. }
  242. else
  243. {
  244. m_pCapImage->SetImage( pszCapSwipe );
  245. }
  246. m_pCapImage->SetVisible( true );
  247. // Tell the cap highlight image to fire up if it's our point being capped
  248. if ( m_pCapHighlightImage && pPlayer->GetTeamNumber() != iCappingTeam && pPlayer->GetTeamNumber() > LAST_SHARED_TEAM )
  249. {
  250. if ( ShouldDraw() && GetParent() && GetParent()->IsVisible() )
  251. {
  252. m_pCapHighlightImage->SetVisible( true );
  253. m_pCapHighlightImage->StartSwoop();
  254. }
  255. m_pBaseImage->StartPulsing( STARTCAPANIM_ICON_SWITCH, 0, true );
  256. }
  257. else
  258. {
  259. m_pBaseImage->StartPulsing( 0, 0, true );
  260. }
  261. if ( m_pCapPlayerImage )
  262. {
  263. m_pCapPlayerImage->SetVisible( true );
  264. }
  265. m_iPrevCappers = iCappingTeam;
  266. InvalidateLayout( true );
  267. }
  268. else
  269. {
  270. m_pBaseImage->StopPulsing();
  271. m_pCapImage->SetVisible( false );
  272. if ( m_pCapHighlightImage )
  273. {
  274. m_pCapHighlightImage->SetVisible( false );
  275. }
  276. if ( m_pCapPlayerImage )
  277. {
  278. m_pCapPlayerImage->SetVisible( false );
  279. }
  280. if ( m_pCapNumPlayers )
  281. {
  282. m_pCapNumPlayers->SetVisible( false );
  283. }
  284. }
  285. }
  286. }
  287. //-----------------------------------------------------------------------------
  288. // Purpose: Lock cap points when neither team can cap them for map-specific reasons
  289. //-----------------------------------------------------------------------------
  290. bool CControlPointIcon::IsPointLocked( void )
  291. {
  292. bool bAnyTeamCanCap = false;
  293. for ( int gameteam = FIRST_GAME_TEAM; gameteam < GetNumberOfTeams(); gameteam++ )
  294. {
  295. // Ignore teams that already own the point
  296. if ( ObjectiveResource()->GetOwningTeam(m_iCPIndex) != gameteam )
  297. {
  298. if ( (ObjectiveResource()->TeamCanCapPoint( m_iCPIndex, gameteam)) )
  299. {
  300. if ( TeamplayGameRules()->TeamMayCapturePoint( gameteam, m_iCPIndex ) )
  301. {
  302. bAnyTeamCanCap = true;
  303. }
  304. }
  305. }
  306. }
  307. return ( !bAnyTeamCanCap );
  308. }
  309. //-----------------------------------------------------------------------------
  310. // Purpose: Used by the intro to fake the pulsing of this icon
  311. //-----------------------------------------------------------------------------
  312. void CControlPointIcon::FakePulse( float flTime )
  313. {
  314. if ( m_pCapPulseImage )
  315. {
  316. m_pCapPulseImage->SetVisible( true );
  317. m_pCapPulseImage->StartPulse( flTime, GetWide() );
  318. m_pBaseImage->StartPulsing( flTime + FINISHCAPANIM_SWOOP_LENGTH - gpGlobals->curtime, 0.8, false );
  319. InvalidateLayout();
  320. }
  321. }
  322. //-----------------------------------------------------------------------------
  323. // Purpose:
  324. //-----------------------------------------------------------------------------
  325. bool CControlPointIcon::IsVisible( void )
  326. {
  327. if ( IsInFreezeCam() == true )
  328. return false;
  329. return BaseClass::IsVisible();
  330. }
  331. //-----------------------------------------------------------------------------
  332. // Purpose:
  333. //-----------------------------------------------------------------------------
  334. void CControlPointIcon::Paint( void )
  335. {
  336. if ( m_bCachedLockedState != IsPointLocked() )
  337. {
  338. UpdateImage();
  339. }
  340. m_bCachedLockedState = IsPointLocked();
  341. BaseClass::Paint();
  342. }
  343. //-----------------------------------------------------------------------------
  344. // Purpose:
  345. //-----------------------------------------------------------------------------
  346. void CControlPointIcon::PerformLayout( void )
  347. {
  348. BaseClass::PerformLayout();
  349. if ( !ObjectiveResource() )
  350. return;
  351. int iBaseXPos = 0, iBaseYPos = 0;
  352. LocalToScreen( iBaseXPos, iBaseYPos );
  353. m_pBaseImage->SetBounds( 0, 0, GetWide(), GetTall() );
  354. if ( m_pCapImage->IsVisible() )
  355. {
  356. m_pCapImage->SetBounds( 0, 0, GetWide(), GetTall() );
  357. }
  358. if ( m_pCapHighlightImage->IsVisible() )
  359. {
  360. int iHeight = ScreenHeight() * 0.75;
  361. m_pCapHighlightImage->SetBounds( iBaseXPos + CAP_BOX_INDENT_X, iBaseYPos - iHeight, GetWide() - (CAP_BOX_INDENT_X*2), iHeight + GetTall() -CAP_BOX_INDENT_Y );
  362. }
  363. int iCappingTeam = ObjectiveResource()->GetCappingTeam( m_iCPIndex );
  364. int iPlayers = ObjectiveResource()->GetNumPlayersInArea( m_iCPIndex, iCappingTeam );
  365. if ( !m_pCapPlayerImage->IsVisible() && iPlayers )
  366. {
  367. m_pCapPlayerImage->SetVisible(true);
  368. }
  369. if ( m_pCapPlayerImage->IsVisible() )
  370. {
  371. if ( !iPlayers )
  372. {
  373. // We're a deteriorating point
  374. m_pCapPlayerImage->SetVisible( false );
  375. m_pCapNumPlayers->SetVisible( false );
  376. }
  377. else
  378. {
  379. int iXPos, iYPos;
  380. if ( iPlayers < 2 || !m_pCapNumPlayers )
  381. {
  382. iXPos = (GetWide() - m_pCapPlayerImage->GetWide()) * 0.5;
  383. }
  384. else
  385. {
  386. iXPos = (GetWide() - m_pCapPlayerImage->GetWide()) * 0.5 - XRES(4);
  387. }
  388. iYPos = (GetTall() - m_pCapPlayerImage->GetTall()) * 0.5;
  389. m_pCapPlayerImage->SetPos( iXPos, iYPos );
  390. if ( m_pCapNumPlayers )
  391. {
  392. m_pCapNumPlayers->SetVisible( (iPlayers>1) );
  393. SetDialogVariable( "numcappers", iPlayers );
  394. m_pCapNumPlayers->SetFgColor( Color(0,0,0,255) );
  395. }
  396. }
  397. }
  398. if ( m_pCapPulseImage )
  399. {
  400. int iSize = GetWide() * 3;
  401. int iXpos = iBaseXPos - ((iSize-GetWide()) * 0.5);
  402. int iYpos = iBaseYPos - ((iSize-GetTall()) * 0.5);
  403. m_pCapPulseImage->SetBounds( iXpos, iYpos, iSize, iSize );
  404. }
  405. }
  406. //-----------------------------------------------------------------------------
  407. // Purpose:
  408. //-----------------------------------------------------------------------------
  409. CHudControlPointIcons::CHudControlPointIcons( const char *pName ) : Panel( NULL, "HudControlPointIcons" ), CHudElement( pName )
  410. {
  411. SetParent( GetClientMode()->GetViewport() );
  412. SetHiddenBits( HIDEHUD_MISCSTATUS );
  413. m_iBackgroundTexture = surface()->DrawGetTextureId( "vgui/white" );
  414. if ( m_iBackgroundTexture == -1 )
  415. {
  416. m_iBackgroundTexture = surface()->CreateNewTextureID();
  417. }
  418. surface()->DrawSetTextureFile( m_iBackgroundTexture, "vgui/white", true, true );
  419. Reset();
  420. }
  421. DECLARE_HUDELEMENT( CHudControlPointIcons );
  422. //-----------------------------------------------------------------------------
  423. // Purpose:
  424. //-----------------------------------------------------------------------------
  425. CHudControlPointIcons::~CHudControlPointIcons( void )
  426. {
  427. ShutdownIcons();
  428. }
  429. //-----------------------------------------------------------------------------
  430. // Purpose:
  431. //-----------------------------------------------------------------------------
  432. void CHudControlPointIcons::Init( void )
  433. {
  434. for( int i = 0 ; i < 8 ; i++ )
  435. {
  436. m_iCPTextures[i] = surface()->CreateNewTextureID();
  437. m_iCPCappingTextures[i] = surface()->CreateNewTextureID();
  438. }
  439. for( int i = FIRST_GAME_TEAM; i < MAX_TEAMS; i++ )
  440. {
  441. m_iTeamBaseTextures[i].m_nMaterialIndex = INT_MAX;
  442. m_iTeamBaseTextures[i].m_nTextureId = surface()->CreateNewTextureID();
  443. }
  444. ListenForGameEvent( "controlpoint_initialized" );
  445. ListenForGameEvent( "controlpoint_updateimages" );
  446. ListenForGameEvent( "controlpoint_updatelayout" );
  447. ListenForGameEvent( "controlpoint_updatecapping" );
  448. ListenForGameEvent( "controlpoint_starttouch" );
  449. ListenForGameEvent( "controlpoint_endtouch" );
  450. ListenForGameEvent( "controlpoint_pulse_element" );
  451. ListenForGameEvent( "controlpoint_fake_capture" );
  452. ListenForGameEvent( "controlpoint_fake_capture_mult" );
  453. ListenForGameEvent( "intro_nextcamera" );
  454. ListenForGameEvent( "intro_finish" );
  455. }
  456. //-----------------------------------------------------------------------------
  457. // Purpose:
  458. //-----------------------------------------------------------------------------
  459. void CHudControlPointIcons::Reset( void )
  460. {
  461. m_iCurrentCP = -1;
  462. m_iLastCP = -1;
  463. m_flIconExpand = 0;
  464. m_flPulseTime = 0;
  465. }
  466. //-----------------------------------------------------------------------------
  467. // Purpose:
  468. //-----------------------------------------------------------------------------
  469. bool CHudControlPointIcons::IsVisible( void )
  470. {
  471. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( GetSplitScreenPlayerSlot() );
  472. if ( IsInFreezeCam() == true )
  473. return false;
  474. if ( CHudElement::ShouldDraw() == false )
  475. return false;
  476. return BaseClass::IsVisible();
  477. }
  478. //-----------------------------------------------------------------------------
  479. // Purpose:
  480. //-----------------------------------------------------------------------------
  481. void CHudControlPointIcons::LevelShutdown( void )
  482. {
  483. ShutdownIcons();
  484. }
  485. //-----------------------------------------------------------------------------
  486. // Purpose:
  487. //-----------------------------------------------------------------------------
  488. void CHudControlPointIcons::FireGameEvent( IGameEvent *event )
  489. {
  490. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( GetSplitScreenPlayerSlot() );
  491. const char *eventname = event->GetName();
  492. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  493. if ( FStrEq( "controlpoint_initialized", eventname ) )
  494. {
  495. // Create our control points
  496. InitIcons();
  497. return;
  498. }
  499. if ( FStrEq( "controlpoint_updateimages", eventname ) )
  500. {
  501. // Update the images of our control point icons
  502. int iIndex = event->GetInt( "index" );
  503. if ( iIndex == -1 )
  504. {
  505. for (int i = 0; i < m_Icons.Count(); i++)
  506. {
  507. m_Icons[i]->UpdateImage();
  508. }
  509. }
  510. else
  511. {
  512. // Only invalidate the specified cap point
  513. for (int i = 0; i < m_Icons.Count(); i++)
  514. {
  515. if ( m_Icons[i]->GetCapIndex() == iIndex )
  516. {
  517. m_Icons[i]->UpdateImage();
  518. }
  519. }
  520. }
  521. UpdateProgressBarFor( iIndex );
  522. return;
  523. }
  524. if ( FStrEq( "controlpoint_updatelayout", eventname ) )
  525. {
  526. // Update the layout of our control point icons
  527. int iIndex = event->GetInt( "index" );
  528. if ( iIndex == -1 )
  529. {
  530. InvalidateLayout();
  531. }
  532. else
  533. {
  534. // Only invalidate the specified cap point
  535. for (int i = 0; i < m_Icons.Count(); i++)
  536. {
  537. if ( m_Icons[i]->GetCapIndex() == iIndex )
  538. {
  539. m_Icons[i]->InvalidateLayout();
  540. }
  541. }
  542. }
  543. UpdateProgressBarFor( iIndex );
  544. return;
  545. }
  546. if ( FStrEq( "controlpoint_updatecapping", eventname ) )
  547. {
  548. // Update the capping status of our control point icons
  549. int iIndex = event->GetInt( "index" );
  550. if ( iIndex == -1 )
  551. {
  552. for (int i = 0; i < m_Icons.Count(); i++)
  553. {
  554. m_Icons[i]->UpdateCapImage();
  555. }
  556. }
  557. else
  558. {
  559. // Only invalidate the specified cap point
  560. for (int i = 0; i < m_Icons.Count(); i++)
  561. {
  562. if ( m_Icons[i]->GetCapIndex() == iIndex )
  563. {
  564. m_Icons[i]->UpdateCapImage();
  565. }
  566. }
  567. }
  568. UpdateProgressBarFor( iIndex );
  569. return;
  570. }
  571. if ( FStrEq( "controlpoint_starttouch", eventname ) )
  572. {
  573. int iPlayer = event->GetInt( "player" );
  574. if ( pPlayer && iPlayer == pPlayer->entindex() )
  575. {
  576. m_iCurrentCP = event->GetInt( "area" );
  577. UpdateProgressBarFor( m_iCurrentCP );
  578. }
  579. }
  580. else if ( FStrEq( "controlpoint_endtouch", eventname ) )
  581. {
  582. int iPlayer = event->GetInt( "player" );
  583. if ( pPlayer && iPlayer == pPlayer->entindex() )
  584. {
  585. m_iCurrentCP = -1;
  586. UpdateProgressBarFor( m_iCurrentCP );
  587. }
  588. }
  589. else if ( FStrEq( "controlpoint_pulse_element", eventname ) )
  590. {
  591. int iPlayer = event->GetInt( "player" );
  592. if ( pPlayer && iPlayer == pPlayer->entindex() )
  593. {
  594. for (int i = 0; i < m_Icons.Count(); i++)
  595. {
  596. m_Icons[i]->FakePulse( gpGlobals->curtime + (i * PULSE_TIME_PER_ICON) );
  597. }
  598. }
  599. }
  600. else if ( FStrEq( "controlpoint_fake_capture", eventname ) )
  601. {
  602. int iPlayer = event->GetInt( "player" );
  603. if ( pPlayer && iPlayer == pPlayer->entindex() )
  604. {
  605. m_iCurrentCP = event->GetInt( "int_data" );
  606. m_bFakingCapture = true;
  607. m_bFakingCaptureMult = false;
  608. m_flFakeCaptureTime = gpGlobals->curtime + FAKE_CAPTURE_TIME + FAKE_CAPTURE_POST_PAUSE;
  609. UpdateProgressBarFor( -1 );
  610. }
  611. }
  612. else if ( FStrEq( "controlpoint_fake_capture_mult", eventname ) )
  613. {
  614. int iPlayer = event->GetInt( "player" );
  615. if ( pPlayer && iPlayer == pPlayer->entindex() )
  616. {
  617. m_iCurrentCP = event->GetInt( "int_data" );
  618. m_bFakingCapture = true;
  619. m_bFakingCaptureMult = true;
  620. m_flFakeCaptureTime = gpGlobals->curtime + FAKE_CAPTURE_TIME + FAKE_CAPTURE_POST_PAUSE;
  621. UpdateProgressBarFor( -1 );
  622. }
  623. }
  624. else if ( FStrEq( "intro_nextcamera", eventname ) )
  625. {
  626. int iPlayer = event->GetInt( "player" );
  627. if ( pPlayer && iPlayer == pPlayer->entindex() )
  628. {
  629. m_iCurrentCP = -1;
  630. m_bFakingCapture = false;
  631. m_bFakingCaptureMult = false;
  632. UpdateProgressBarFor( -1 );
  633. }
  634. }
  635. else if ( FStrEq( "intro_finish", eventname ) )
  636. {
  637. int iPlayer = event->GetInt( "player" );
  638. if ( pPlayer && iPlayer == pPlayer->entindex() )
  639. {
  640. m_iCurrentCP = -1;
  641. m_flPulseTime = 0;
  642. m_bFakingCapture = false;
  643. m_bFakingCaptureMult = false;
  644. InitIcons();
  645. }
  646. }
  647. }
  648. //-----------------------------------------------------------------------------
  649. // Purpose:
  650. //-----------------------------------------------------------------------------
  651. void CHudControlPointIcons::ApplySchemeSettings( IScheme *pScheme )
  652. {
  653. BaseClass::ApplySchemeSettings( pScheme );
  654. m_hTextFont = pScheme->GetFont( "ChatFont" );
  655. m_clrBackground = pScheme->GetColor( "HudPanelBackground", GetFgColor() );
  656. m_clrBorder = pScheme->GetColor( "HudPanelBorder", GetBgColor() );
  657. }
  658. //-----------------------------------------------------------------------------
  659. // Purpose:
  660. //-----------------------------------------------------------------------------
  661. void CHudControlPointIcons::PerformLayout( void )
  662. {
  663. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( GetSplitScreenPlayerSlot() );
  664. BaseClass::PerformLayout();
  665. int iCapPointLines[MAX_CONTROL_POINTS][MAX_CONTROL_POINTS];
  666. memset( iCapPointLines, 0, sizeof(int) * MAX_CONTROL_POINTS * MAX_CONTROL_POINTS );
  667. bool bUseDefaultLines = true;
  668. if ( ObjectiveResource() )
  669. {
  670. // Allow the objective resource to override it
  671. const char *pszLayout = ObjectiveResource()->GetCapLayoutInHUD();
  672. if ( pszLayout && pszLayout[0] )
  673. {
  674. bUseDefaultLines = false;
  675. // Cap layout is a string with indexes of cap points seperated by ',' to denote
  676. // a new line. So "3,1 2" would create a pyramid, with cap point 3 on the
  677. // first line, and caps 1 & 2 on the second line.
  678. int iLine = 0;
  679. int iCapIndex = 0;
  680. char szBuffer[MAX_CAPLAYOUT_LENGTH];
  681. Q_strncpy( szBuffer, pszLayout, MAX_CAPLAYOUT_LENGTH );
  682. char *pszChar = szBuffer;
  683. char *pszLastNumber = pszChar;
  684. while ( *pszChar )
  685. {
  686. pszChar++;
  687. if ( *pszChar == ' ' || *pszChar == ',' )
  688. {
  689. // Get the number
  690. char cOrg = *pszChar;
  691. *pszChar = '\0';
  692. int iCPIndex = atoi( pszLastNumber );
  693. int iIconIndex = -1;
  694. for (int i = 0; i < m_Icons.Count(); i++)
  695. {
  696. if ( m_Icons[i]->GetCapIndex() == iCPIndex )
  697. {
  698. iIconIndex = i;
  699. break;
  700. }
  701. }
  702. if ( iIconIndex != -1 )
  703. {
  704. iCapPointLines[iLine][iCapIndex] = iIconIndex+1;
  705. *pszChar = cOrg;
  706. if ( *pszChar == ',' )
  707. {
  708. iLine++;
  709. iCapIndex = 0;
  710. }
  711. else
  712. {
  713. iCapIndex++;
  714. }
  715. }
  716. // Walk past the ,/space
  717. pszChar++;
  718. pszLastNumber = pszChar;
  719. }
  720. }
  721. // Now get the trailing number
  722. int iCPIndex = atoi( pszLastNumber );
  723. for (int i = 0; i < m_Icons.Count(); i++)
  724. {
  725. if ( m_Icons[i]->GetCapIndex() == iCPIndex )
  726. {
  727. iCapPointLines[iLine][iCapIndex] = i+1;
  728. break;
  729. }
  730. }
  731. }
  732. }
  733. if ( bUseDefaultLines )
  734. {
  735. // By default, put all the caps on a single line
  736. int iCPIndex = 0;
  737. for (int iIcon = 0; iIcon < m_Icons.Count(); iIcon++)
  738. {
  739. iCapPointLines[0][iCPIndex] = iIcon+1;
  740. iCPIndex++;
  741. }
  742. }
  743. int iTall = m_iIconGapHeight;
  744. int iTallest = m_iIconGapHeight;
  745. int iWidest = m_iIconGapWidth;
  746. int iTotalIconsPerLine[MAX_CONTROL_POINTS];
  747. int iLineWidth[MAX_CONTROL_POINTS];
  748. memset( iTotalIconsPerLine, 0, sizeof(int) * MAX_CONTROL_POINTS );
  749. memset( iLineWidth, 0, sizeof(int) * MAX_CONTROL_POINTS );
  750. int iTotalLines = 0;
  751. // Search through the lines and figure out our overall width & height
  752. for ( int iLine = 0; iLine < MAX_CONTROL_POINTS; iLine++ )
  753. {
  754. // If we've hit a line with nothing in it, we're done
  755. if ( !iCapPointLines[iLine][0] )
  756. break;
  757. iTotalLines++;
  758. iLineWidth[iLine] = m_iIconGapWidth;
  759. int iLineTall = 0;
  760. for ( int iPosition = 0; iPosition < MAX_CONTROL_POINTS; iPosition++ )
  761. {
  762. int iIconIndex = iCapPointLines[iLine][iPosition];
  763. if ( !iIconIndex )
  764. break;
  765. iIconIndex--;
  766. // Add the icon dimensions to our counts.
  767. if ( iIconIndex >= 0 && iIconIndex < m_Icons.Count() )
  768. {
  769. m_Icons[iIconIndex]->PerformLayout();
  770. iTotalIconsPerLine[iLine]++;
  771. iLineWidth[iLine] += m_Icons[iIconIndex]->GetWide() + m_iIconGapWidth;
  772. int iHeight = m_Icons[iIconIndex]->GetTall();
  773. if ( iHeight > iLineTall )
  774. {
  775. iLineTall = iHeight;
  776. }
  777. }
  778. }
  779. if ( iLineWidth[iLine] > iWidest )
  780. {
  781. iWidest = iLineWidth[iLine];
  782. }
  783. if ( iLineTall > iTallest )
  784. {
  785. iTallest = iLineTall;
  786. }
  787. iTall += iLineTall + m_iIconGapHeight;
  788. }
  789. // Setup the main panel
  790. SetBounds( (ScreenWidth() - iWidest) * 0.5, ScreenHeight() - iTall - m_nHeightOffset, iWidest, iTall );
  791. // Now that we know how wide we are, and how many icons are in each line,
  792. // we can lay the icons out, centered in the lines.
  793. for ( int iLine = 0; iLine < MAX_CONTROL_POINTS; iLine++ )
  794. {
  795. if ( !iTotalIconsPerLine[iLine] )
  796. break;
  797. int iLineXPos = ((iWidest - iLineWidth[iLine]) * 0.5) + m_iIconGapWidth;
  798. int iLineYPos = (iLine * m_iIconGapHeight) + ( iLine * iTallest ) + m_iIconGapHeight;
  799. for ( int iPosition = 0; iPosition < MAX_CONTROL_POINTS; iPosition++ )
  800. {
  801. int iIconIndex = iCapPointLines[iLine][iPosition];
  802. if ( !iIconIndex )
  803. break;
  804. iIconIndex--;
  805. if ( iIconIndex >= 0 && iIconIndex < m_Icons.Count() )
  806. {
  807. m_Icons[iIconIndex]->SetPos( iLineXPos, iLineYPos );
  808. iLineXPos += m_Icons[iIconIndex]->GetWide() + m_iIconGapWidth;
  809. // If we have multiple lines, swipe up when capping
  810. m_Icons[iIconIndex]->SetSwipeUp( iTotalLines > 1 );
  811. // Set the progress extrusion dir:
  812. // N if we're on the top line. Otherwise:
  813. // NW if we're left of the center.
  814. // NE if we're at or right of the center.
  815. int iDir = CP_DIR_N;
  816. if ( iLine > 0 )
  817. {
  818. if ( ((float)(iPosition+1) / (float)iTotalIconsPerLine[iLine]) > 0.5 )
  819. {
  820. iDir = CP_DIR_NE;
  821. }
  822. else
  823. {
  824. iDir = CP_DIR_NW;
  825. }
  826. }
  827. m_Icons[iIconIndex]->SetCapProgressDir( iDir );
  828. }
  829. }
  830. }
  831. }
  832. //-----------------------------------------------------------------------------
  833. // Purpose:
  834. //-----------------------------------------------------------------------------
  835. void CHudControlPointIcons::UpdateProgressBarFor( int iIndex )
  836. {
  837. // If they tell us to update all progress bars, update only the one we're standing on
  838. if ( iIndex == -1 )
  839. {
  840. iIndex = m_iCurrentCP;
  841. }
  842. // Ignore requests to display progress bars for points we're not standing on
  843. if ( ( m_iCurrentCP != iIndex ) )
  844. return;
  845. // This can happen at level load
  846. CTFHudObjectiveStatus *pStatus = GET_HUDELEMENT( CTFHudObjectiveStatus );
  847. if ( pStatus && pStatus->GetControlPointProgressBar() )
  848. {
  849. CControlPointProgressBar *pProgressBar = pStatus->GetControlPointProgressBar();
  850. if ( !IsVisible() || iIndex < 0 || iIndex >= ObjectiveResource()->GetNumControlPoints() )
  851. {
  852. pProgressBar->SetupForPoint( NULL );
  853. }
  854. else
  855. {
  856. for (int i = 0; i < m_Icons.Count(); i++)
  857. {
  858. if ( m_Icons[i]->GetCapIndex() == iIndex )
  859. {
  860. pProgressBar->SetupForPoint( m_Icons[i] );
  861. break;
  862. }
  863. }
  864. }
  865. }
  866. }
  867. //-----------------------------------------------------------------------------
  868. // Purpose: Create the icons we need to display the state of this map's control points
  869. //-----------------------------------------------------------------------------
  870. void CHudControlPointIcons::InitIcons( void )
  871. {
  872. ShutdownIcons();
  873. CTFHudObjectiveStatus *pStatus = GET_HUDELEMENT( CTFHudObjectiveStatus );
  874. if ( pStatus )
  875. {
  876. CControlPointProgressBar *pProgressBar = pStatus->GetControlPointProgressBar();
  877. if ( pProgressBar )
  878. {
  879. m_iCurrentCP = -1;
  880. pProgressBar->SetupForPoint( NULL );
  881. }
  882. }
  883. // Create an icon for each visible control point in this miniround
  884. int iPoints = ObjectiveResource()->GetNumControlPoints();
  885. for ( int i = 0; i < iPoints; i++ )
  886. {
  887. if ( ObjectiveResource()->IsInMiniRound(i) && ObjectiveResource()->IsCPVisible(i) )
  888. {
  889. CControlPointIcon *pIcon = new CControlPointIcon( this, VarArgs( "ControlPointIcon%d", i ), i );
  890. m_Icons.AddToTail( SETUP_PANEL(pIcon) );
  891. }
  892. }
  893. InvalidateLayout();
  894. }
  895. //-----------------------------------------------------------------------------
  896. // Purpose:
  897. //-----------------------------------------------------------------------------
  898. void CHudControlPointIcons::ShutdownIcons( void )
  899. {
  900. for (int i = 0; i < m_Icons.Count(); i++)
  901. {
  902. m_Icons[i]->MarkForDeletion();
  903. }
  904. m_Icons.RemoveAll();
  905. }
  906. //-----------------------------------------------------------------------------
  907. // Purpose:
  908. //-----------------------------------------------------------------------------
  909. void CHudControlPointIcons::DrawBackgroundBox( int xpos, int ypos, int nBoxWidth, int nBoxHeight, bool bCutCorner )
  910. {
  911. int nCornerCutSize = bCutCorner ? m_nCornerCutSize : 0;
  912. Vertex_t verts[5];
  913. verts[0].Init( Vector2D( xpos, ypos ) );
  914. verts[1].Init( Vector2D( xpos + nBoxWidth, ypos ) );
  915. verts[2].Init( Vector2D( xpos + nBoxWidth + 1, ypos + nBoxHeight - nCornerCutSize + 1 ) );
  916. verts[3].Init( Vector2D( xpos + nBoxWidth - nCornerCutSize + 1, ypos + nBoxHeight + 1 ) );
  917. verts[4].Init( Vector2D( xpos, ypos + nBoxHeight ) );
  918. surface()->DrawSetTexture( m_iBackgroundTexture );
  919. surface()->DrawSetColor( Color( m_clrBackground ) );
  920. surface()->DrawTexturedPolygon( 5, verts );
  921. Vertex_t borderverts[5];
  922. borderverts[0].Init( Vector2D( xpos, ypos ) );
  923. borderverts[1].Init( Vector2D( xpos + nBoxWidth, ypos ) );
  924. borderverts[2].Init( Vector2D( xpos + nBoxWidth, ypos + nBoxHeight - nCornerCutSize ) );
  925. borderverts[3].Init( Vector2D( xpos + nBoxWidth - nCornerCutSize, ypos + nBoxHeight ) );
  926. borderverts[4].Init( Vector2D( xpos, ypos + nBoxHeight ) );
  927. surface()->DrawSetColor( Color( m_clrBorder ) );
  928. surface()->DrawTexturedPolyLine( borderverts, 5 );
  929. }
  930. //-----------------------------------------------------------------------------
  931. // Purpose: Draw the team's base icon at either end of the icon panel
  932. //-----------------------------------------------------------------------------
  933. bool CHudControlPointIcons::PaintTeamBaseIcon( int index, float flXPos, float flYPos, float flIconSize )
  934. {
  935. float uv1 = 0.0f;
  936. float uv2 = 1.0f;
  937. // Find out which team owns the far left
  938. for ( int i = 0; i < MAX_TEAMS; i++ )
  939. {
  940. if ( ObjectiveResource()->GetBaseControlPointForTeam(i) == index )
  941. {
  942. int iTeamBaseIcon = ObjectiveResource()->GetBaseIconForTeam(i);
  943. if ( iTeamBaseIcon )
  944. {
  945. TeamBaseTexture_t &tbt = m_iTeamBaseTextures[ i ];
  946. if ( tbt.m_nMaterialIndex != iTeamBaseIcon )
  947. {
  948. tbt.m_nMaterialIndex = iTeamBaseIcon;
  949. // Draw the Team's Base texture
  950. const char *szMatName = GetMaterialNameFromIndex( iTeamBaseIcon );
  951. surface()->DrawSetTextureFile( tbt.m_nTextureId, szMatName, true, false );
  952. }
  953. surface()->DrawSetTexture( tbt.m_nTextureId );
  954. Vector2D uv11( uv1, uv1 );
  955. Vector2D uv21( uv2, uv1 );
  956. Vector2D uv22( uv2, uv2 );
  957. Vector2D uv12( uv1, uv2 );
  958. Vertex_t vert[4];
  959. vert[0].Init( Vector2D( flXPos, flYPos ), uv11 );
  960. vert[1].Init( Vector2D( flXPos + flIconSize, flYPos ), uv21 );
  961. vert[2].Init( Vector2D( flXPos + flIconSize, flYPos + flIconSize ), uv22 );
  962. vert[3].Init( Vector2D( flXPos, flYPos + flIconSize ), uv12 );
  963. surface()->DrawSetColor( Color(255,255,255,255) );
  964. surface()->DrawTexturedPolygon( 4, vert );
  965. return true;
  966. }
  967. }
  968. }
  969. return false;
  970. }
  971. //-----------------------------------------------------------------------------
  972. // Purpose:
  973. //-----------------------------------------------------------------------------
  974. void CHudControlPointIcons::Paint()
  975. {
  976. if ( IsInFreezeCam() == true )
  977. return;
  978. if( !ObjectiveResource() )
  979. return;
  980. int num = ObjectiveResource()->GetNumControlPoints();
  981. if ( num <= 0 )
  982. return; // nothing to draw yet
  983. //DrawBackgroundBox( 0, 0, GetWide(), GetTall(), false );
  984. BaseClass::Paint();
  985. }
  986. //========================================================================================================================
  987. // CONTROL POINT PROGRESS BAR
  988. //========================================================================================================================
  989. CControlPointProgressBar::CControlPointProgressBar(Panel *parent) : EditablePanel( parent, "ControlPointProgressBar" )
  990. {
  991. m_pAttachedToIcon = NULL;
  992. m_pBar = NULL;
  993. m_pBarText = NULL;
  994. m_pTeardrop = NULL;
  995. m_pTeardropSide = NULL;
  996. m_pBlocked = NULL;
  997. m_iOrgHeight = 0;
  998. m_iMidGroupIndex = -1;
  999. }
  1000. //-----------------------------------------------------------------------------
  1001. // Purpose:
  1002. //-----------------------------------------------------------------------------
  1003. void CControlPointProgressBar::ApplySchemeSettings( IScheme *pScheme )
  1004. {
  1005. BaseClass::ApplySchemeSettings( pScheme );
  1006. LoadControlSettings( "resource/UI/ControlPointProgressBar.res" );
  1007. m_pBar = dynamic_cast<CircularProgressBar *>( FindChildByName("ProgressBar") );
  1008. m_pBarText = dynamic_cast<Label *>( FindChildByName("ProgressText") );
  1009. m_pTeardrop = dynamic_cast<CIconPanel *>( FindChildByName("Teardrop") );
  1010. m_pTeardropSide = dynamic_cast<CIconPanel *>( FindChildByName("TeardropSide") );
  1011. m_pBlocked = dynamic_cast<CIconPanel *>( FindChildByName("Blocked") );
  1012. m_iOrgHeight = GetTall();
  1013. m_iMidGroupIndex = GetHud().LookupRenderGroupIndexByName( "mid" );
  1014. }
  1015. //-----------------------------------------------------------------------------
  1016. // Purpose:
  1017. //-----------------------------------------------------------------------------
  1018. void CControlPointProgressBar::PerformLayout( void )
  1019. {
  1020. BaseClass::PerformLayout();
  1021. if ( m_pAttachedToIcon && m_pTeardrop && m_pTeardropSide )
  1022. {
  1023. int iIconX = 0, iIconY = 0;
  1024. m_pAttachedToIcon->LocalToScreen( iIconX, iIconY );
  1025. int iDir = m_pAttachedToIcon->GetCapProgressDir();
  1026. int iXPos = 0;
  1027. int iYPos = 0;
  1028. int iEdgeSpace = (GetWide() - m_pTeardrop->GetWide()) * 0.5;
  1029. // Line up our middle with the middle of the icon
  1030. switch ( iDir )
  1031. {
  1032. default:
  1033. case CP_DIR_N:
  1034. SetSize( GetWide(), m_iOrgHeight );
  1035. m_pTeardrop->SetVisible( true );
  1036. m_pTeardropSide->SetVisible( false );
  1037. iXPos = iIconX - ((GetWide() - m_pAttachedToIcon->GetWide()) * 0.5);
  1038. iYPos = iIconY - GetTall();
  1039. break;
  1040. case CP_DIR_NE:
  1041. SetSize( GetWide(), YRES(53) );
  1042. m_pTeardropSide->SetIcon( "cappoint_progressbar_teardrop_right" );
  1043. m_pTeardrop->SetVisible( false );
  1044. m_pTeardropSide->SetVisible( true );
  1045. iXPos = iIconX + m_pAttachedToIcon->GetWide() - iEdgeSpace;
  1046. iYPos = iIconY - GetTall();
  1047. break;
  1048. case CP_DIR_NW:
  1049. SetSize( GetWide(), YRES(53) );
  1050. m_pTeardropSide->SetIcon( "cappoint_progressbar_teardrop_left" );
  1051. m_pTeardrop->SetVisible( false );
  1052. m_pTeardropSide->SetVisible( true );
  1053. iXPos = iIconX - GetWide() + iEdgeSpace;
  1054. iYPos = iIconY - GetTall();
  1055. break;
  1056. }
  1057. SetPos( iXPos, iYPos );
  1058. }
  1059. }
  1060. //-----------------------------------------------------------------------------
  1061. // Purpose:
  1062. //-----------------------------------------------------------------------------
  1063. void CControlPointProgressBar::Reset( void )
  1064. {
  1065. m_pAttachedToIcon = NULL;
  1066. }
  1067. //-----------------------------------------------------------------------------
  1068. // Purpose:
  1069. //-----------------------------------------------------------------------------
  1070. bool CControlPointProgressBar::IsVisible( void )
  1071. {
  1072. if ( IsInFreezeCam() == true )
  1073. return false;
  1074. if ( m_iMidGroupIndex != -1 && GetHud().IsRenderGroupLockedFor( NULL, m_iMidGroupIndex ) )
  1075. return false;
  1076. return BaseClass::IsVisible();
  1077. }
  1078. //-----------------------------------------------------------------------------
  1079. // Purpose:
  1080. //-----------------------------------------------------------------------------
  1081. void CControlPointProgressBar::Paint( void )
  1082. {
  1083. if ( m_pAttachedToIcon )
  1084. {
  1085. int iCP = m_pAttachedToIcon->GetCapIndex();
  1086. if ( m_pBar && m_pBar->IsVisible() )
  1087. {
  1088. m_pBar->SetProgress( ObjectiveResource()->GetCPCapPercentage( iCP ) );
  1089. }
  1090. }
  1091. BaseClass::Paint();
  1092. }
  1093. //-----------------------------------------------------------------------------
  1094. // Purpose:
  1095. //-----------------------------------------------------------------------------
  1096. void CControlPointProgressBar::SetupForPoint( CControlPointIcon *pIcon )
  1097. {
  1098. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  1099. if ( !pPlayer )
  1100. return;
  1101. m_pAttachedToIcon = pIcon;
  1102. bool bInWinState = TeamplayRoundBasedRules() ? TeamplayRoundBasedRules()->RoundHasBeenWon() : false;
  1103. if ( m_pAttachedToIcon && !bInWinState )
  1104. {
  1105. SetVisible( true );
  1106. int iCP = m_pAttachedToIcon->GetCapIndex();
  1107. int iCappingTeam = ObjectiveResource()->GetCappingTeam( iCP );
  1108. int iOwnerTeam = ObjectiveResource()->GetOwningTeam( iCP );
  1109. int iPlayerTeam = pPlayer->GetTeamNumber();
  1110. bool bCapBlocked = ObjectiveResource()->CapIsBlocked( iCP );
  1111. if ( !bCapBlocked && iCappingTeam != TEAM_UNASSIGNED && iCappingTeam != iOwnerTeam && iCappingTeam == iPlayerTeam )
  1112. {
  1113. m_pBar->SetBgImage( ObjectiveResource()->GetGameSpecificCPBarBG( iCP, iCappingTeam ) );
  1114. m_pBar->SetFgImage( ObjectiveResource()->GetGameSpecificCPBarFG( iCP, iOwnerTeam ) );
  1115. m_pBar->SetVisible( true );
  1116. m_pBlocked->SetVisible( false );
  1117. m_pBarText->SetVisible( false );
  1118. }
  1119. else
  1120. {
  1121. m_pBar->SetVisible( false );
  1122. m_pBlocked->SetVisible( true );
  1123. UpdateBarText();
  1124. }
  1125. InvalidateLayout();
  1126. }
  1127. else
  1128. {
  1129. SetVisible( false );
  1130. }
  1131. }
  1132. //-----------------------------------------------------------------------------
  1133. // Purpose:
  1134. //-----------------------------------------------------------------------------
  1135. void CControlPointProgressBar::UpdateBarText( void )
  1136. {
  1137. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  1138. if ( !pPlayer || !m_pBarText || !m_pAttachedToIcon )
  1139. return;
  1140. m_pBarText->SetVisible( true );
  1141. int iCP = m_pAttachedToIcon->GetCapIndex();
  1142. int iCappingTeam = ObjectiveResource()->GetCappingTeam( iCP );
  1143. int iPlayerTeam = pPlayer->GetTeamNumber();
  1144. int iOwnerTeam = ObjectiveResource()->GetOwningTeam( iCP );
  1145. m_pBarText->SetPos( XRES(25), YRES(20) );
  1146. if ( !TeamplayGameRules()->PointsMayBeCaptured() )
  1147. {
  1148. m_pBarText->SetText( "#Team_Capture_NotNow" );
  1149. return;
  1150. }
  1151. if ( mp_blockstyle.GetInt() == 1 && iCappingTeam != TEAM_UNASSIGNED && iCappingTeam != iPlayerTeam )
  1152. {
  1153. if ( ObjectiveResource()->IsCPBlocked(iCP) )
  1154. {
  1155. m_pBarText->SetText( "#Team_Blocking_Capture" );
  1156. return;
  1157. }
  1158. else if ( iOwnerTeam == TEAM_UNASSIGNED )
  1159. {
  1160. m_pBarText->SetText( "#Team_Reverting_Capture" );
  1161. return;
  1162. }
  1163. }
  1164. if ( ObjectiveResource()->GetOwningTeam(iCP) == iPlayerTeam )
  1165. {
  1166. // If the opponents can never recapture this point back, we use a different string
  1167. if ( iPlayerTeam != TEAM_UNASSIGNED )
  1168. {
  1169. int iEnemyTeam = ( iPlayerTeam == TF_TEAM_RED ) ? TF_TEAM_BLUE : TF_TEAM_RED;
  1170. if ( !ObjectiveResource()->TeamCanCapPoint( iCP, iEnemyTeam ) )
  1171. {
  1172. m_pBarText->SetText( "#Team_Capture_Owned" );
  1173. return;
  1174. }
  1175. }
  1176. m_pBarText->SetText( "#Team_Capture_OwnPoint" );
  1177. m_pBarText->SetPos( XRES(30), YRES(20) );
  1178. return;
  1179. }
  1180. if ( !TeamplayGameRules()->TeamMayCapturePoint( iPlayerTeam, iCP ) )
  1181. {
  1182. if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->IsInArenaMode() == true )
  1183. {
  1184. m_pBarText->SetText( "#Team_Capture_NotNow" );
  1185. }
  1186. else
  1187. {
  1188. m_pBarText->SetText( "#Team_Capture_Linear" );
  1189. }
  1190. return;
  1191. }
  1192. char szReason[256];
  1193. if ( !TeamplayGameRules()->PlayerMayCapturePoint( pPlayer, iCP, szReason, sizeof(szReason) ) )
  1194. {
  1195. m_pBarText->SetText( szReason );
  1196. return;
  1197. }
  1198. bool bHaveRequiredPlayers = true;
  1199. // In Capstyle 1, more players simply cap faster, no required amounts.
  1200. if ( mp_capstyle.GetInt() != 1 )
  1201. {
  1202. int nNumTeammates = ObjectiveResource()->GetNumPlayersInArea( iCP, iPlayerTeam );
  1203. int nRequiredTeammates = ObjectiveResource()->GetRequiredCappers( iCP, iPlayerTeam );
  1204. bHaveRequiredPlayers = (nNumTeammates >= nRequiredTeammates);
  1205. }
  1206. if ( iCappingTeam == iPlayerTeam && bHaveRequiredPlayers )
  1207. {
  1208. m_pBarText->SetText( "#Team_Capture_Blocked" );
  1209. return;
  1210. }
  1211. if ( !ObjectiveResource()->TeamCanCapPoint( iCP, iPlayerTeam ) )
  1212. {
  1213. m_pBarText->SetText( "#Team_Cannot_Capture" );
  1214. return;
  1215. }
  1216. m_pBarText->SetText( "#Team_Waiting_for_teammate" );
  1217. }
  1218. //========================================================================================================================
  1219. // CONTROL POINT CAPTURE ARROW SWIPE
  1220. //========================================================================================================================
  1221. //-----------------------------------------------------------------------------
  1222. // Purpose:
  1223. //-----------------------------------------------------------------------------
  1224. CControlPointIconCapArrow::CControlPointIconCapArrow( CControlPointIcon *pIcon, Panel *parent, const char *name)
  1225. : Panel( parent, name )
  1226. {
  1227. m_pArrowMaterial = NULL;
  1228. m_pAttachedToIcon = pIcon;
  1229. Assert( m_pAttachedToIcon );
  1230. }
  1231. bool CControlPointIconCapArrow::IsVisible( void )
  1232. {
  1233. if ( IsInFreezeCam() == true )
  1234. return false;
  1235. return BaseClass::IsVisible();
  1236. }
  1237. //-----------------------------------------------------------------------------
  1238. // Purpose:
  1239. //-----------------------------------------------------------------------------
  1240. void CControlPointIconCapArrow::Paint( void )
  1241. {
  1242. int nSlot = ipanel()->GetMessageContextId( GetVPanel() );
  1243. if ( !m_pArrowMaterial || !m_pAttachedToIcon )
  1244. return;
  1245. int x = 0;
  1246. int y = 0;
  1247. {
  1248. // We have to do this if we ever render using a meshbuilder, since we're rendering this view into a viewport which is
  1249. // not full screen in height for splitscreen players
  1250. VGUI_ABSPOS_SPLITSCREEN_GUARD_INVERT( nSlot );
  1251. LocalToScreen( x, y );
  1252. }
  1253. int iWidth = GetWide();
  1254. int iHeight = GetTall();
  1255. // Position the arrow based on the cap percentage
  1256. float flXa = 0;
  1257. float flXb = 1.0;
  1258. float flYa = 0;
  1259. float flYb = 1.0;
  1260. int iCappingTeam = ObjectiveResource()->GetCappingTeam( m_pAttachedToIcon->GetCapIndex() );
  1261. float flCapPercentage = ObjectiveResource()->GetCPCapPercentage( m_pAttachedToIcon->GetCapIndex() );
  1262. // The image needs to be remapped to the width of the underlying box,
  1263. // because we want the arrow head to move off the box at the exact time the cap ends.
  1264. float flArrowHeadPixelWidth = 15.0;
  1265. float flArrowBodyPixelWidth = 54.0;
  1266. float flBoxSize = 33.0;
  1267. // HACK: The arrow has an arrowhead portion that looks like this: >
  1268. // We want to start with the arrow entering the image, but we want to keep
  1269. // going until the arrow is fully off the edge. So we include extra width for it.
  1270. float flImageSize = (flArrowHeadPixelWidth+flArrowBodyPixelWidth);
  1271. float flMovementInTextureSpace = ( (flBoxSize+flArrowHeadPixelWidth) / flImageSize );
  1272. float flArrowSizeInTextureSpace = ( flArrowHeadPixelWidth / flImageSize );
  1273. // To help players spot the start & end of a cap, we indent a little on either side.
  1274. float flIndent = 0.07;
  1275. if ( m_pAttachedToIcon->ShouldSwipeUp() )
  1276. {
  1277. flYa = RemapVal( flCapPercentage, 0.0, 1.0, -flMovementInTextureSpace - flIndent, flArrowSizeInTextureSpace - flIndent );
  1278. flYb = RemapVal( flCapPercentage, 0.0, 1.0, flIndent, flMovementInTextureSpace - flIndent );
  1279. }
  1280. else
  1281. {
  1282. flIndent = 0.1;
  1283. float flStart = 1.0 - flIndent;
  1284. float flEnd = 1.0 + flIndent;
  1285. bool bSwipeLeftToRight = ( iCappingTeam % 2 ) ? false : true;
  1286. if ( bSwipeLeftToRight )
  1287. {
  1288. flXa = RemapVal( flCapPercentage, 0.0, 1.0, flStart + flMovementInTextureSpace, flEnd - flArrowSizeInTextureSpace );
  1289. flXb = RemapVal( flCapPercentage, 0.0, 1.0, flStart, 0.0 );
  1290. }
  1291. else
  1292. {
  1293. flXa = RemapVal( flCapPercentage, 0.0, 1.0, flStart, 0.0 );
  1294. flXb = RemapVal( flCapPercentage, 0.0, 1.0, flStart + flMovementInTextureSpace, flEnd - flArrowSizeInTextureSpace );
  1295. }
  1296. }
  1297. CMatRenderContextPtr pRenderContext( materials );
  1298. pRenderContext->Bind( m_pArrowMaterial );
  1299. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  1300. float zpos = surface()->GetZPos();
  1301. CMeshBuilder meshBuilder;
  1302. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  1303. meshBuilder.Position3f( x, y, zpos );
  1304. meshBuilder.TexCoord2f( 0, flXa, flYa );
  1305. meshBuilder.TexCoord2f( 1, 0.0f, 0.0f );
  1306. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1307. meshBuilder.AdvanceVertex();
  1308. meshBuilder.Position3f( x + iWidth, y, zpos );
  1309. meshBuilder.TexCoord2f( 0, flXb, flYa );
  1310. meshBuilder.TexCoord2f( 1, 1.0f, 0.0f );
  1311. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1312. meshBuilder.AdvanceVertex();
  1313. meshBuilder.Position3f( x + iWidth, y + iHeight, zpos );
  1314. meshBuilder.TexCoord2f( 0, flXb, flYb );
  1315. meshBuilder.TexCoord2f( 1, 1.0f, 1.0f );
  1316. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1317. meshBuilder.AdvanceVertex();
  1318. meshBuilder.Position3f( x, y + iHeight, zpos );
  1319. meshBuilder.TexCoord2f( 0, flXa, flYb );
  1320. meshBuilder.TexCoord2f( 1, 0.0f, 1.0f );
  1321. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1322. meshBuilder.AdvanceVertex();
  1323. meshBuilder.End();
  1324. pMesh->Draw();
  1325. }