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.

1436 lines
39 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "hudelement.h"
  8. #include "iclientmode.h"
  9. #include <KeyValues.h>
  10. #include <vgui/IScheme.h>
  11. #include <vgui/ISurface.h>
  12. #include <vgui/ISystem.h>
  13. #include <vgui_controls/AnimationController.h>
  14. #include <vgui_controls/EditablePanel.h>
  15. #include <vgui_controls/ImagePanel.h>
  16. #include <vgui/IVGui.h>
  17. #include <vgui/ISurface.h>
  18. #include <vgui/IImage.h>
  19. #include <vgui_controls/Label.h>
  20. #include "c_playerresource.h"
  21. #include "teamplay_round_timer.h"
  22. #include "utlvector.h"
  23. #include "entity_capture_flag.h"
  24. #include "c_tf_player.h"
  25. #include "c_team.h"
  26. #include "c_tf_team.h"
  27. #include "c_team_objectiveresource.h"
  28. #include "tf_hud_objectivestatus.h"
  29. #include "tf_spectatorgui.h"
  30. #include "teamplayroundbased_gamerules.h"
  31. #include "tf_gamerules.h"
  32. #include "tf_hud_freezepanel.h"
  33. #include "c_func_capture_zone.h"
  34. #include "clientmode_shared.h"
  35. #include "tf_hud_mediccallers.h"
  36. #include "view.h"
  37. #include "prediction.h"
  38. #include "tf_logic_robot_destruction.h"
  39. using namespace vgui;
  40. DECLARE_BUILD_FACTORY( CTFArrowPanel );
  41. DECLARE_BUILD_FACTORY( CTFFlagStatus );
  42. DECLARE_HUDELEMENT( CTFFlagCalloutPanel );
  43. ConVar tf_rd_flag_ui_mode( "tf_rd_flag_ui_mode", "3", FCVAR_DEVELOPMENTONLY, "When flags are stolen and not visible: 0 = Show outlines (glows), 1 = Show most valuable enemy flag (icons), 2 = Show all enemy flags (icons), 3 = Show all flags (icons)." );
  44. extern ConVar tf_flag_caps_per_round;
  45. void AddSubKeyNamed( KeyValues *pKeys, const char *pszName );
  46. //-----------------------------------------------------------------------------
  47. // Purpose:
  48. //-----------------------------------------------------------------------------
  49. CTFArrowPanel::CTFArrowPanel( Panel *parent, const char *name ) : vgui::Panel( parent, name )
  50. {
  51. m_RedMaterial.Init( "hud/objectives_flagpanel_compass_red", TEXTURE_GROUP_VGUI );
  52. m_BlueMaterial.Init( "hud/objectives_flagpanel_compass_blue", TEXTURE_GROUP_VGUI );
  53. m_NeutralMaterial.Init( "hud/objectives_flagpanel_compass_grey", TEXTURE_GROUP_VGUI );
  54. m_NeutralRedMaterial.Init( "hud/objectives_flagpanel_compass_grey_with_red", TEXTURE_GROUP_VGUI );
  55. m_RedMaterialNoArrow.Init( "hud/objectives_flagpanel_compass_red_noArrow", TEXTURE_GROUP_VGUI );
  56. m_BlueMaterialNoArrow.Init( "hud/objectives_flagpanel_compass_blue_noArrow", TEXTURE_GROUP_VGUI );
  57. m_pMaterial = m_NeutralMaterial;
  58. m_bUseRed = false;
  59. m_flNextColorSwitch = 0.0f;
  60. ivgui()->AddTickSignal( GetVPanel(), 100 );
  61. }
  62. //-----------------------------------------------------------------------------
  63. // Purpose:
  64. //-----------------------------------------------------------------------------
  65. void CTFArrowPanel::OnTick( void )
  66. {
  67. if ( !m_hEntity.Get() )
  68. return;
  69. C_BaseEntity *pEnt = m_hEntity.Get();
  70. m_pMaterial = m_NeutralMaterial;
  71. C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
  72. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
  73. {
  74. if ( m_bUseRed )
  75. {
  76. m_pMaterial = m_NeutralRedMaterial;
  77. }
  78. else
  79. {
  80. m_pMaterial = m_NeutralMaterial;
  81. }
  82. if ( pEnt && TFGameRules()->GetMannVsMachineAlarmStatus() == true )
  83. {
  84. CCaptureFlag *pFlag = dynamic_cast<CCaptureFlag *>( pEnt );
  85. if ( pFlag && pFlag->IsStolen() )
  86. {
  87. if ( m_flNextColorSwitch < gpGlobals->curtime )
  88. {
  89. m_flNextColorSwitch = gpGlobals->curtime + 0.2f;
  90. m_bUseRed = !m_bUseRed;
  91. }
  92. }
  93. else
  94. {
  95. m_bUseRed = false;
  96. }
  97. }
  98. else
  99. {
  100. m_bUseRed = false;
  101. }
  102. }
  103. else
  104. {
  105. // figure out what material we need to use
  106. if ( pEnt->GetTeamNumber() == TF_TEAM_RED )
  107. {
  108. m_pMaterial = m_RedMaterial;
  109. if ( pLocalPlayer && ( pLocalPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) )
  110. {
  111. // is our target a player?
  112. C_BaseEntity *pTargetEnt = pLocalPlayer->GetObserverTarget();
  113. if ( pTargetEnt && pTargetEnt->IsPlayer() )
  114. {
  115. // does our target have the flag and are they carrying the flag we're currently drawing?
  116. C_TFPlayer *pTarget = static_cast< C_TFPlayer* >( pTargetEnt );
  117. if ( pTarget->HasTheFlag() && ( pTarget->GetItem() == pEnt ) )
  118. {
  119. m_pMaterial = m_RedMaterialNoArrow;
  120. }
  121. }
  122. }
  123. }
  124. else if ( pEnt->GetTeamNumber() == TF_TEAM_BLUE )
  125. {
  126. m_pMaterial = m_BlueMaterial;
  127. if ( pLocalPlayer && ( pLocalPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) )
  128. {
  129. // is our target a player?
  130. C_BaseEntity *pTargetEnt = pLocalPlayer->GetObserverTarget();
  131. if ( pTargetEnt && pTargetEnt->IsPlayer() )
  132. {
  133. // does our target have the flag and are they carrying the flag we're currently drawing?
  134. C_TFPlayer *pTarget = static_cast< C_TFPlayer* >( pTargetEnt );
  135. if ( pTarget->HasTheFlag() && ( pTarget->GetItem() == pEnt ) )
  136. {
  137. m_pMaterial = m_BlueMaterialNoArrow;
  138. }
  139. }
  140. }
  141. }
  142. }
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Purpose:
  146. //-----------------------------------------------------------------------------
  147. float CTFArrowPanel::GetAngleRotation( void )
  148. {
  149. float flRetVal = 0.0f;
  150. C_TFPlayer *pPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() );
  151. C_BaseEntity *pEnt = m_hEntity.Get();
  152. if ( pPlayer && pEnt )
  153. {
  154. QAngle vangles;
  155. Vector eyeOrigin;
  156. float zNear, zFar, fov;
  157. pPlayer->CalcView( eyeOrigin, vangles, zNear, zFar, fov );
  158. Vector vecFlag = pEnt->WorldSpaceCenter() - eyeOrigin;
  159. vecFlag.z = 0;
  160. vecFlag.NormalizeInPlace();
  161. Vector forward, right, up;
  162. AngleVectors( vangles, &forward, &right, &up );
  163. forward.z = 0;
  164. right.z = 0;
  165. forward.NormalizeInPlace();
  166. right.NormalizeInPlace();
  167. float dot = DotProduct( vecFlag, forward );
  168. float angleBetween = acos( dot );
  169. dot = DotProduct( vecFlag, right );
  170. if ( dot < 0.0f )
  171. {
  172. angleBetween *= -1;
  173. }
  174. flRetVal = RAD2DEG( angleBetween );
  175. }
  176. return flRetVal;
  177. }
  178. //-----------------------------------------------------------------------------
  179. // Purpose:
  180. //-----------------------------------------------------------------------------
  181. void CTFArrowPanel::Paint()
  182. {
  183. int x = 0;
  184. int y = 0;
  185. ipanel()->GetAbsPos( GetVPanel(), x, y );
  186. int nWidth = GetWide();
  187. int nHeight = GetTall();
  188. CMatRenderContextPtr pRenderContext( materials );
  189. pRenderContext->MatrixMode( MATERIAL_MODEL );
  190. pRenderContext->PushMatrix();
  191. VMatrix panelRotation;
  192. panelRotation.Identity();
  193. MatrixBuildRotationAboutAxis( panelRotation, Vector( 0, 0, 1 ), GetAngleRotation() );
  194. // MatrixRotate( panelRotation, Vector( 1, 0, 0 ), 5 );
  195. panelRotation.SetTranslation( Vector( x + nWidth/2, y + nHeight/2, 0 ) );
  196. pRenderContext->LoadMatrix( panelRotation );
  197. IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_pMaterial );
  198. CMeshBuilder meshBuilder;
  199. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  200. meshBuilder.TexCoord2f( 0, 0, 0 );
  201. meshBuilder.Position3f( -nWidth/2, -nHeight/2, 0 );
  202. meshBuilder.Color4ub( 255, 255, 255, 255 );
  203. meshBuilder.AdvanceVertex();
  204. meshBuilder.TexCoord2f( 0, 1, 0 );
  205. meshBuilder.Position3f( nWidth/2, -nHeight/2, 0 );
  206. meshBuilder.Color4ub( 255, 255, 255, 255 );
  207. meshBuilder.AdvanceVertex();
  208. meshBuilder.TexCoord2f( 0, 1, 1 );
  209. meshBuilder.Position3f( nWidth/2, nHeight/2, 0 );
  210. meshBuilder.Color4ub( 255, 255, 255, 255 );
  211. meshBuilder.AdvanceVertex();
  212. meshBuilder.TexCoord2f( 0, 0, 1 );
  213. meshBuilder.Position3f( -nWidth/2, nHeight/2, 0 );
  214. meshBuilder.Color4ub( 255, 255, 255, 255 );
  215. meshBuilder.AdvanceVertex();
  216. meshBuilder.End();
  217. pMesh->Draw();
  218. pRenderContext->PopMatrix();
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose:
  222. //-----------------------------------------------------------------------------
  223. bool CTFArrowPanel::IsVisible( void )
  224. {
  225. if( IsTakingAFreezecamScreenshot() )
  226. return false;
  227. return BaseClass::IsVisible();
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Purpose:
  231. //-----------------------------------------------------------------------------
  232. CTFFlagStatus::CTFFlagStatus( Panel *parent, const char *name ) : EditablePanel( parent, name )
  233. {
  234. m_pArrow = new CTFArrowPanel( this, "Arrow" );
  235. m_pStatusIcon = new CTFImagePanel( this, "StatusIcon" );
  236. m_pBriefcase = new CTFImagePanel( this, "Briefcase" );
  237. m_hEntity = NULL;
  238. }
  239. //-----------------------------------------------------------------------------
  240. // Purpose:
  241. //-----------------------------------------------------------------------------
  242. void CTFFlagStatus::ApplySchemeSettings( IScheme *pScheme )
  243. {
  244. BaseClass::ApplySchemeSettings( pScheme );
  245. KeyValues *pConditions = NULL;
  246. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() )
  247. {
  248. pConditions = new KeyValues( "conditions" );
  249. if ( pConditions )
  250. {
  251. AddSubKeyNamed( pConditions, "if_mvm" );
  252. }
  253. }
  254. // load control settings...
  255. LoadControlSettings( "resource/UI/FlagStatus.res", NULL, NULL, pConditions );
  256. if ( pConditions )
  257. {
  258. pConditions->deleteThis();
  259. }
  260. }
  261. //-----------------------------------------------------------------------------
  262. // Purpose:
  263. //-----------------------------------------------------------------------------
  264. bool CTFFlagStatus::IsVisible( void )
  265. {
  266. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  267. if ( pPlayer && pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM )
  268. return false;
  269. return BaseClass::IsVisible();
  270. }
  271. //-----------------------------------------------------------------------------
  272. // Purpose:
  273. //-----------------------------------------------------------------------------
  274. void CTFFlagStatus::UpdateStatus( void )
  275. {
  276. if ( m_hEntity.Get() )
  277. {
  278. CCaptureFlag *pFlag = dynamic_cast<CCaptureFlag *>( m_hEntity.Get() );
  279. if ( pFlag )
  280. {
  281. const char *pszImage = "../hud/objectives_flagpanel_ico_flag_home";
  282. const char *pszBombImage = "../hud/bomb_dropped";
  283. if ( pFlag->IsDropped() )
  284. {
  285. pszImage = "../hud/objectives_flagpanel_ico_flag_dropped";
  286. }
  287. else if ( pFlag->IsStolen() )
  288. {
  289. pszImage = "../hud/objectives_flagpanel_ico_flag_moving";
  290. pszBombImage = "../hud/bomb_carried";
  291. }
  292. if ( m_pStatusIcon )
  293. {
  294. m_pStatusIcon->SetImage( pszImage );
  295. }
  296. if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && m_pBriefcase )
  297. {
  298. m_pBriefcase->SetImage( pszBombImage );
  299. }
  300. }
  301. }
  302. }
  303. //-----------------------------------------------------------------------------
  304. // Purpose:
  305. //-----------------------------------------------------------------------------
  306. CTFHudFlagObjectives::CTFHudFlagObjectives( Panel *parent, const char *name ) : EditablePanel( parent, name )
  307. {
  308. m_pCarriedImage = NULL;
  309. m_pPlayingTo = NULL;
  310. m_bFlagAnimationPlayed = false;
  311. m_bCarryingFlag = false;
  312. m_pSpecCarriedImage = NULL;
  313. m_pPoisonImage = NULL;
  314. m_pPoisonTimeLabel = NULL;
  315. m_pRedFlag = new CTFFlagStatus( this, "RedFlag" );
  316. m_pBlueFlag = new CTFFlagStatus( this, "BlueFlag" );
  317. m_bPlayingHybrid_CTF_CP = false;
  318. m_bPlayingSpecialDeliveryMode = false;
  319. vgui::ivgui()->AddTickSignal( GetVPanel(), 250 );
  320. ListenForGameEvent( "flagstatus_update" );
  321. m_nNumValidFlags = -1;
  322. }
  323. //-----------------------------------------------------------------------------
  324. // Purpose:
  325. //-----------------------------------------------------------------------------
  326. bool CTFHudFlagObjectives::IsVisible( void )
  327. {
  328. if( IsTakingAFreezecamScreenshot() )
  329. return false;
  330. return BaseClass::IsVisible();
  331. }
  332. //-----------------------------------------------------------------------------
  333. // Purpose:
  334. //-----------------------------------------------------------------------------
  335. void CTFHudFlagObjectives::ApplySchemeSettings( IScheme *pScheme )
  336. {
  337. BaseClass::ApplySchemeSettings( pScheme );
  338. KeyValues *pConditions = NULL;
  339. bool bHybrid = TFGameRules() && TFGameRules()->IsPlayingHybrid_CTF_CP();
  340. bool bMVM = TFGameRules() && TFGameRules()->IsMannVsMachineMode();
  341. bool bSpecialDeliveryMode = TFGameRules() && TFGameRules()->IsPlayingSpecialDeliveryMode();
  342. int nNumFlags = 0;
  343. if ( m_pRedFlag && m_pRedFlag->GetEntity() != NULL )
  344. {
  345. nNumFlags++;
  346. }
  347. if ( m_pBlueFlag && m_pBlueFlag->GetEntity() != NULL )
  348. {
  349. nNumFlags++;
  350. }
  351. if ( nNumFlags == 2 && m_pRedFlag->GetEntity() == m_pBlueFlag->GetEntity() )
  352. {
  353. // They're both pointing at the same flag! There's really only 1
  354. nNumFlags = 1;
  355. }
  356. if ( nNumFlags == 0 )
  357. {
  358. pConditions = new KeyValues( "conditions" );
  359. if ( pConditions )
  360. {
  361. AddSubKeyNamed( pConditions, "if_no_flags" );
  362. }
  363. if ( bSpecialDeliveryMode )
  364. {
  365. AddSubKeyNamed( pConditions, "if_specialdelivery" );
  366. }
  367. }
  368. else
  369. {
  370. if ( bHybrid || ( nNumFlags == 1 ) || bMVM || bSpecialDeliveryMode )
  371. {
  372. pConditions = new KeyValues( "conditions" );
  373. if ( pConditions )
  374. {
  375. if ( bHybrid )
  376. {
  377. AddSubKeyNamed( pConditions, "if_hybrid" );
  378. }
  379. if ( nNumFlags == 1 || bSpecialDeliveryMode )
  380. {
  381. AddSubKeyNamed( pConditions, "if_hybrid_single" );
  382. }
  383. else if ( nNumFlags == 2 )
  384. {
  385. AddSubKeyNamed( pConditions, "if_hybrid_double" );
  386. }
  387. if ( bMVM )
  388. {
  389. AddSubKeyNamed( pConditions, "if_mvm" );
  390. }
  391. if ( bSpecialDeliveryMode )
  392. {
  393. AddSubKeyNamed( pConditions, "if_specialdelivery" );
  394. }
  395. }
  396. }
  397. }
  398. // load control settings...
  399. LoadControlSettings( "resource/UI/HudObjectiveFlagPanel.res", NULL, NULL, pConditions );
  400. m_pCarriedImage = dynamic_cast<ImagePanel *>( FindChildByName( "CarriedImage" ) );
  401. m_pPlayingTo = dynamic_cast<CExLabel *>( FindChildByName( "PlayingTo" ) );
  402. m_pPlayingToBG = FindChildByName( "PlayingToBG" );
  403. m_pCapturePoint = dynamic_cast<CTFArrowPanel *>( FindChildByName( "CaptureFlag" ) );
  404. m_pSpecCarriedImage = dynamic_cast<ImagePanel *>( FindChildByName( "SpecCarriedImage" ) );
  405. m_pPoisonImage = dynamic_cast<ImagePanel *>( FindChildByName( "PoisonIcon" ) );
  406. m_pPoisonTimeLabel = dynamic_cast<CExLabel *>( FindChildByName( "PoisonTimeLabel" ) );
  407. // outline is always on, so we need to init the alpha to 0
  408. vgui::Panel *pOutline = FindChildByName( "OutlineImage" );
  409. if ( pOutline )
  410. {
  411. pOutline->SetAlpha( 0 );
  412. }
  413. if ( pConditions )
  414. {
  415. pConditions->deleteThis();
  416. }
  417. UpdateStatus();
  418. }
  419. //-----------------------------------------------------------------------------
  420. // Purpose:
  421. //-----------------------------------------------------------------------------
  422. void CTFHudFlagObjectives::Reset()
  423. {
  424. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "FlagOutlineHide" );
  425. UpdateStatus();
  426. }
  427. //-----------------------------------------------------------------------------
  428. // Purpose:
  429. //-----------------------------------------------------------------------------
  430. void CTFHudFlagObjectives::SetPlayingToLabelVisible( bool bVisible )
  431. {
  432. if ( m_pPlayingTo && m_pPlayingToBG )
  433. {
  434. if ( m_pPlayingTo->IsVisible() != bVisible )
  435. {
  436. m_pPlayingTo->SetVisible( bVisible );
  437. }
  438. if ( m_pPlayingToBG->IsVisible() != bVisible )
  439. {
  440. m_pPlayingToBG->SetVisible( bVisible );
  441. }
  442. }
  443. }
  444. //-----------------------------------------------------------------------------
  445. // Purpose:
  446. //-----------------------------------------------------------------------------
  447. void CTFHudFlagObjectives::OnTick()
  448. {
  449. int nNumValidFlags = 0;
  450. // check that our blue panel still points at a valid flag
  451. if ( m_pBlueFlag && m_pBlueFlag->GetEntity() )
  452. {
  453. CCaptureFlag *pFlag = dynamic_cast< CCaptureFlag* >( m_pBlueFlag->GetEntity() );
  454. if ( !pFlag || pFlag->IsDisabled() )
  455. {
  456. m_pBlueFlag->SetEntity( NULL );
  457. }
  458. }
  459. // check that our red panel still points at a valid flag
  460. if ( m_pRedFlag && m_pRedFlag->GetEntity() )
  461. {
  462. CCaptureFlag *pFlag = dynamic_cast< CCaptureFlag* >( m_pRedFlag->GetEntity() );
  463. if ( !pFlag || pFlag->IsDisabled() )
  464. {
  465. m_pRedFlag->SetEntity( NULL );
  466. }
  467. }
  468. // iterate through the flags to set their position in our HUD
  469. for ( int i = 0; i<ICaptureFlagAutoList::AutoList().Count(); i++ )
  470. {
  471. CCaptureFlag *pFlag = static_cast< CCaptureFlag* >( ICaptureFlagAutoList::AutoList()[i] );
  472. if ( !pFlag->IsDisabled() || pFlag->IsVisibleWhenDisabled() )
  473. {
  474. if ( pFlag->GetTeamNumber() == TF_TEAM_RED )
  475. {
  476. if ( m_pRedFlag )
  477. {
  478. bool bNeedsUpdate = m_pRedFlag->GetEntity() != pFlag;
  479. m_pRedFlag->SetEntity( pFlag );
  480. if ( bNeedsUpdate )
  481. {
  482. UpdateStatus();
  483. }
  484. }
  485. }
  486. else if ( pFlag->GetTeamNumber() == TF_TEAM_BLUE )
  487. {
  488. if ( m_pBlueFlag )
  489. {
  490. bool bNeedsUpdate = m_pBlueFlag->GetEntity() != pFlag;
  491. m_pBlueFlag->SetEntity( pFlag );
  492. if ( bNeedsUpdate )
  493. {
  494. UpdateStatus();
  495. }
  496. }
  497. }
  498. else if ( pFlag->GetTeamNumber() == TEAM_UNASSIGNED )
  499. {
  500. if ( m_pBlueFlag && !m_pBlueFlag->GetEntity() )
  501. {
  502. m_pBlueFlag->SetEntity( pFlag );
  503. if ( !m_pBlueFlag->IsVisible() )
  504. {
  505. m_pBlueFlag->SetVisible( true );
  506. }
  507. if ( m_pRedFlag && m_pRedFlag->IsVisible() )
  508. {
  509. m_pRedFlag->SetVisible( false );
  510. }
  511. }
  512. else if ( m_pRedFlag && !m_pRedFlag->GetEntity() )
  513. {
  514. // make sure both panels aren't pointing at the same entity
  515. if ( !m_pBlueFlag || ( pFlag != m_pBlueFlag->GetEntity() ) )
  516. {
  517. m_pRedFlag->SetEntity( pFlag );
  518. if ( !m_pRedFlag->IsVisible() )
  519. {
  520. m_pRedFlag->SetVisible( true );
  521. }
  522. }
  523. }
  524. }
  525. nNumValidFlags++;
  526. }
  527. // VGUI callout panels
  528. if ( CTFRobotDestructionLogic::GetRobotDestructionLogic() && CTFRobotDestructionLogic::GetRobotDestructionLogic()->GetType() == CTFRobotDestructionLogic::TYPE_ROBOT_DESTRUCTION )
  529. {
  530. if ( tf_rd_flag_ui_mode.GetInt() && !pFlag->IsDisabled() && !pFlag->IsHome() )
  531. {
  532. Vector vecLocation = pFlag->GetAbsOrigin() + Vector( 0.f, 0.f, 18.f );
  533. CTFFlagCalloutPanel::AddFlagCalloutIfNotFound( pFlag, FLT_MAX, vecLocation );
  534. }
  535. }
  536. }
  537. if ( m_nNumValidFlags != nNumValidFlags )
  538. {
  539. m_nNumValidFlags = nNumValidFlags;
  540. InvalidateLayout( false, true );
  541. }
  542. // are we playing captures for rounds?
  543. if ( !TFGameRules() || ( !TFGameRules()->IsPlayingHybrid_CTF_CP() && !TFGameRules()->IsPlayingSpecialDeliveryMode() && !TFGameRules()->IsMannVsMachineMode() ) )
  544. {
  545. if ( tf_flag_caps_per_round.GetInt() > 0 )
  546. {
  547. C_TFTeam *pTeam = GetGlobalTFTeam( TF_TEAM_BLUE );
  548. if ( pTeam )
  549. {
  550. SetDialogVariable( "bluescore", pTeam->GetFlagCaptures() );
  551. }
  552. pTeam = GetGlobalTFTeam( TF_TEAM_RED );
  553. if ( pTeam )
  554. {
  555. SetDialogVariable( "redscore", pTeam->GetFlagCaptures() );
  556. }
  557. SetPlayingToLabelVisible( true );
  558. SetDialogVariable( "rounds", tf_flag_caps_per_round.GetInt() );
  559. }
  560. else // we're just playing straight score
  561. {
  562. C_TFTeam *pTeam = GetGlobalTFTeam( TF_TEAM_BLUE );
  563. if ( pTeam )
  564. {
  565. SetDialogVariable( "bluescore", pTeam->Get_Score() );
  566. }
  567. pTeam = GetGlobalTFTeam( TF_TEAM_RED );
  568. if ( pTeam )
  569. {
  570. SetDialogVariable( "redscore", pTeam->Get_Score() );
  571. }
  572. SetPlayingToLabelVisible( false );
  573. }
  574. }
  575. // check the local player to see if they're spectating, OBS_MODE_IN_EYE, and the target entity is carrying the flag
  576. bool bSpecCarriedImage = false;
  577. CCaptureFlag *pPoisonFlag = NULL;
  578. C_TFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
  579. if ( pPlayer )
  580. {
  581. if ( pPlayer->GetObserverMode() == OBS_MODE_IN_EYE )
  582. {
  583. // does our target have the flag?
  584. C_BaseEntity *pEnt = pPlayer->GetObserverTarget();
  585. if ( pEnt && pEnt->IsPlayer() )
  586. {
  587. C_TFPlayer *pTarget = static_cast< C_TFPlayer* >( pEnt );
  588. if ( pTarget->HasTheFlag() )
  589. {
  590. bSpecCarriedImage = true;
  591. if ( pTarget->GetTeamNumber() == TF_TEAM_RED )
  592. {
  593. if ( m_pSpecCarriedImage )
  594. {
  595. m_pSpecCarriedImage->SetImage( "../hud/objectives_flagpanel_carried_blue" );
  596. }
  597. }
  598. else
  599. {
  600. if ( m_pSpecCarriedImage )
  601. {
  602. m_pSpecCarriedImage->SetImage( "../hud/objectives_flagpanel_carried_red" );
  603. }
  604. }
  605. }
  606. }
  607. }
  608. if ( pPlayer->HasTheFlag() && TFGameRules()->IsPowerupMode() )
  609. {
  610. CCaptureFlag *pFlag = dynamic_cast<CCaptureFlag *>( pPlayer->GetItem() );
  611. if ( pFlag )
  612. {
  613. pPoisonFlag = pFlag;
  614. }
  615. }
  616. }
  617. if ( m_pSpecCarriedImage )
  618. {
  619. m_pSpecCarriedImage->SetVisible( bSpecCarriedImage );
  620. }
  621. if ( m_pPoisonImage )
  622. {
  623. m_pPoisonImage->SetVisible( pPoisonFlag && pPoisonFlag->IsPoisonous() );
  624. }
  625. if ( m_pPoisonTimeLabel )
  626. {
  627. m_pPoisonTimeLabel->SetVisible( pPoisonFlag && pPoisonFlag->GetPoisonTime() > 0.f && !pPoisonFlag->IsPoisonous() );
  628. if ( m_pPoisonTimeLabel->IsVisible() )
  629. {
  630. int nNumSecondsToPoisonous = pPoisonFlag->GetPoisonTime() - gpGlobals->curtime;
  631. m_pPoisonTimeLabel->SetText( CFmtStr( "%d", nNumSecondsToPoisonous ) );
  632. }
  633. }
  634. if ( TFGameRules() )
  635. {
  636. if ( m_bPlayingHybrid_CTF_CP != TFGameRules()->IsPlayingHybrid_CTF_CP() )
  637. {
  638. m_bPlayingHybrid_CTF_CP = TFGameRules()->IsPlayingHybrid_CTF_CP();
  639. InvalidateLayout( false, true );
  640. }
  641. if ( m_bPlayingSpecialDeliveryMode != TFGameRules()->IsPlayingSpecialDeliveryMode() )
  642. {
  643. m_bPlayingSpecialDeliveryMode = TFGameRules()->IsPlayingSpecialDeliveryMode();
  644. InvalidateLayout( false, true );
  645. }
  646. }
  647. }
  648. //-----------------------------------------------------------------------------
  649. // Purpose:
  650. //-----------------------------------------------------------------------------
  651. void CTFHudFlagObjectives::SetCarriedImage( const char *pchIcon )
  652. {
  653. if ( m_pCarriedImage )
  654. {
  655. m_pCarriedImage->SetImage( pchIcon );
  656. }
  657. }
  658. //-----------------------------------------------------------------------------
  659. // Purpose:
  660. //-----------------------------------------------------------------------------
  661. void CTFHudFlagObjectives::UpdateStatus( C_BasePlayer *pNewOwner /*= NULL*/, C_BaseEntity *pFlagEntity /*= NULL*/ )
  662. {
  663. C_TFPlayer *pLocalPlayer = ToTFPlayer( C_BasePlayer::GetLocalPlayer() );
  664. // are we carrying a flag?
  665. CCaptureFlag *pPlayerFlag = NULL;
  666. if ( pLocalPlayer && pLocalPlayer->HasItem() && pLocalPlayer->GetItem()->GetItemID() == TF_ITEM_CAPTURE_FLAG )
  667. {
  668. if ( !pNewOwner || pNewOwner == pLocalPlayer )
  669. {
  670. pPlayerFlag = dynamic_cast< CCaptureFlag* >( pLocalPlayer->GetItem() );
  671. }
  672. }
  673. if ( !pPlayerFlag && pLocalPlayer && pLocalPlayer == pNewOwner )
  674. {
  675. pPlayerFlag = dynamic_cast< CCaptureFlag* >( pFlagEntity );
  676. }
  677. if ( pPlayerFlag )
  678. {
  679. m_bCarryingFlag = true;
  680. // make sure the panels are on, set the initial alpha values,
  681. // set the color of the flag we're carrying, and start the animations
  682. if ( m_pBlueFlag && m_pBlueFlag->IsVisible() )
  683. {
  684. m_pBlueFlag->SetVisible( false );
  685. }
  686. if ( m_pRedFlag && m_pRedFlag->IsVisible() )
  687. {
  688. m_pRedFlag->SetVisible( false );
  689. }
  690. if ( m_pCarriedImage && !m_pCarriedImage->IsVisible() )
  691. {
  692. int nTeam;
  693. if ( pPlayerFlag->GetType() == TF_FLAGTYPE_ATTACK_DEFEND ||
  694. pPlayerFlag->GetType() == TF_FLAGTYPE_TERRITORY_CONTROL ||
  695. pPlayerFlag->GetType() == TF_FLAGTYPE_INVADE ||
  696. pPlayerFlag->GetType() == TF_FLAGTYPE_RESOURCE_CONTROL )
  697. {
  698. nTeam = ( ( GetLocalPlayerTeam() == TF_TEAM_BLUE ) ? ( TF_TEAM_BLUE ) : ( TF_TEAM_RED ) );
  699. }
  700. else
  701. {
  702. // normal CTF behavior (carrying the enemy flag)
  703. nTeam = ( ( GetLocalPlayerTeam() == TF_TEAM_RED ) ? ( TF_TEAM_BLUE ) : ( TF_TEAM_RED ) );
  704. }
  705. char szImage[ MAX_PATH ];
  706. pPlayerFlag->GetHudIcon( nTeam, szImage, sizeof( szImage ) );
  707. SetCarriedImage( szImage );
  708. m_pCarriedImage->SetVisible( true );
  709. }
  710. if ( !m_bFlagAnimationPlayed )
  711. {
  712. m_bFlagAnimationPlayed = true;
  713. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "FlagOutline" );
  714. }
  715. if ( m_pCapturePoint && !m_pCapturePoint->IsVisible() )
  716. {
  717. m_pCapturePoint->SetVisible( true );
  718. }
  719. if ( pLocalPlayer && m_pCapturePoint )
  720. {
  721. // go through all the capture zones and find ours
  722. for ( int i = 0; i<ICaptureZoneAutoList::AutoList().Count(); i++ )
  723. {
  724. C_CaptureZone *pCaptureZone = static_cast< C_CaptureZone* >( ICaptureZoneAutoList::AutoList()[i] );
  725. if ( !pCaptureZone->IsDormant() )
  726. {
  727. if ( pCaptureZone->GetTeamNumber() == pLocalPlayer->GetTeamNumber() && !pCaptureZone->IsDisabled() )
  728. {
  729. m_pCapturePoint->SetEntity( pCaptureZone );
  730. }
  731. }
  732. }
  733. }
  734. }
  735. else
  736. {
  737. // were we carrying the flag?
  738. if ( m_bCarryingFlag )
  739. {
  740. m_bCarryingFlag = false;
  741. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "FlagOutline" );
  742. }
  743. m_bFlagAnimationPlayed = false;
  744. if ( m_pCarriedImage && m_pCarriedImage->IsVisible() )
  745. {
  746. m_pCarriedImage->SetVisible( false );
  747. }
  748. if ( m_pCapturePoint && m_pCapturePoint->IsVisible() )
  749. {
  750. m_pCapturePoint->SetVisible( false );
  751. }
  752. if ( m_pBlueFlag )
  753. {
  754. if ( m_pBlueFlag->GetEntity() != NULL )
  755. {
  756. if ( !m_pBlueFlag->IsVisible() )
  757. {
  758. m_pBlueFlag->SetVisible( true );
  759. }
  760. m_pBlueFlag->UpdateStatus();
  761. }
  762. else
  763. {
  764. if ( m_pBlueFlag->IsVisible() )
  765. {
  766. m_pBlueFlag->SetVisible( false );
  767. }
  768. }
  769. }
  770. if ( m_pRedFlag )
  771. {
  772. if ( m_pRedFlag->GetEntity() != NULL )
  773. {
  774. if ( !m_pRedFlag->IsVisible() )
  775. {
  776. m_pRedFlag->SetVisible( true );
  777. }
  778. m_pRedFlag->UpdateStatus();
  779. }
  780. else
  781. {
  782. if ( m_pRedFlag->IsVisible() )
  783. {
  784. m_pRedFlag->SetVisible( false );
  785. }
  786. }
  787. }
  788. }
  789. }
  790. //-----------------------------------------------------------------------------
  791. // Purpose:
  792. //-----------------------------------------------------------------------------
  793. void CTFHudFlagObjectives::FireGameEvent( IGameEvent *event )
  794. {
  795. const char *eventName = event->GetName();
  796. if ( FStrEq( eventName, "flagstatus_update" ) )
  797. {
  798. int nVictimID = event->GetInt( "userid" );
  799. C_BasePlayer *pNewOwner = USERID2PLAYER( nVictimID );
  800. int nFlagEntIndex = event->GetInt( "entindex" );
  801. C_BaseEntity *pFlagEntity = ClientEntityList().GetEnt( nFlagEntIndex );
  802. UpdateStatus( pNewOwner, pFlagEntity );
  803. }
  804. }
  805. //-----------------------------------------------------------------------------
  806. // Purpose:
  807. //-----------------------------------------------------------------------------
  808. #define FLAG_CALLER_WIDE ( XRES( 30 ) )
  809. #define FLAG_CALLER_TALL ( YRES( 30 ) )
  810. #define FLAG_CALLER_ARROW_WIDE ( XRES( 8 ) )
  811. #define FLAG_CALLER_ARROW_TALL ( YRES( 10 ) )
  812. #define FLAG_CALLER_DISPLAY_ENEMY_ONE 1
  813. #define FLAG_CALLER_DISPLAY_ENEMY_ALL 2
  814. #define FLAG_CALLER_DISPLAY_ALL 3
  815. CUtlVector< CTFFlagCalloutPanel* > CTFFlagCalloutPanel::m_FlagCalloutPanels;
  816. //-----------------------------------------------------------------------------
  817. // Purpose:
  818. //-----------------------------------------------------------------------------
  819. CTFFlagCalloutPanel::CTFFlagCalloutPanel( const char *pElementName ) : CHudElement( pElementName ), BaseClass( NULL, pElementName )
  820. {
  821. m_FlagCalloutPanels.AddToTail( this );
  822. SetParent( g_pClientMode->GetViewport() );
  823. RegisterForRenderGroup( "mid" );
  824. RegisterForRenderGroup( "commentary" );
  825. SetHiddenBits( HIDEHUD_MISCSTATUS );
  826. // SetBounds( 0, 0, FLAG_CALLER_WIDE, FLAG_CALLER_TALL );
  827. vgui::ivgui()->AddTickSignal( GetVPanel() );
  828. m_pFlagCalloutPanel = new CTFImagePanel( this, "FlagCalloutPanel" );
  829. m_pFlagValueLabel = new Label( this, "FlagValueLabel", "" );
  830. m_pFlagStatusIcon = new CTFImagePanel( this, "StatusIcon" );
  831. m_flRemoveTime = 1.f;
  832. m_flFirstDisplayTime = 1.f;
  833. m_pArrowMaterial = NULL;
  834. m_iDrawArrow = DRAW_ARROW_UP;
  835. m_bFlagVisible = false; // On screen, line-of-sight
  836. m_flPrevScale = 0.f;
  837. m_nPanelWideOrig = 0;
  838. m_nPanelTallOrig = 0;
  839. m_nLabelWideOrig = 0;
  840. m_nLabelTallOrig = 0;
  841. m_nIconWideOrig = 0;
  842. m_nIconTallOrig = 0;
  843. }
  844. //-----------------------------------------------------------------------------
  845. // Purpose:
  846. //-----------------------------------------------------------------------------
  847. CTFFlagCalloutPanel::~CTFFlagCalloutPanel( void )
  848. {
  849. bool bFound = false;
  850. FOR_EACH_VEC_BACK( m_FlagCalloutPanels, i )
  851. {
  852. if ( m_FlagCalloutPanels[i] == this )
  853. {
  854. m_FlagCalloutPanels.Remove( i );
  855. bFound = true;
  856. break;
  857. }
  858. }
  859. // We should have found the panel and returned earlier
  860. Assert( bFound );
  861. if ( m_pArrowMaterial )
  862. {
  863. m_pArrowMaterial->DecrementReferenceCount();
  864. }
  865. }
  866. //-----------------------------------------------------------------------------
  867. // Purpose:
  868. //-----------------------------------------------------------------------------
  869. void CTFFlagCalloutPanel::ApplySchemeSettings( vgui::IScheme *pScheme )
  870. {
  871. BaseClass::ApplySchemeSettings( pScheme );
  872. LoadControlSettings( "resource/UI/FlagCalloutPanel.res" );
  873. if ( m_pArrowMaterial )
  874. {
  875. m_pArrowMaterial->DecrementReferenceCount();
  876. }
  877. m_pArrowMaterial = materials->FindMaterial( "HUD/medic_arrow", TEXTURE_GROUP_VGUI );
  878. m_pArrowMaterial->IncrementReferenceCount();
  879. if ( !m_pFlagCalloutPanel )
  880. return;
  881. if ( !m_pFlagValueLabel )
  882. return;
  883. if ( !m_pFlagStatusIcon )
  884. return;
  885. m_pFlagCalloutPanel->GetSize( m_nPanelWideOrig, m_nPanelTallOrig );
  886. m_pFlagValueLabel->GetSize( m_nLabelWideOrig, m_nLabelTallOrig );
  887. m_pFlagStatusIcon->GetSize( m_nIconWideOrig, m_nIconTallOrig );
  888. }
  889. //-----------------------------------------------------------------------------
  890. // Purpose:
  891. //-----------------------------------------------------------------------------
  892. void CTFFlagCalloutPanel::PerformLayout( void )
  893. {
  894. BaseClass::PerformLayout();
  895. // SetSize( FLAG_CALLER_WIDE, FLAG_CALLER_TALL );
  896. }
  897. //-----------------------------------------------------------------------------
  898. // Purpose:
  899. //-----------------------------------------------------------------------------
  900. void CTFFlagCalloutPanel::GetCalloutPosition( const Vector &vecDelta, float flRadius, float *xpos, float *ypos, float *flRotation )
  901. {
  902. // Player Data
  903. QAngle playerAngles = MainViewAngles();
  904. Vector forward, right, up( 0.f, 0.f, 1.f );
  905. AngleVectors( playerAngles, &forward, NULL, NULL );
  906. forward.z = 0.f;
  907. VectorNormalize( forward );
  908. CrossProduct( up, forward, right );
  909. float front = DotProduct( vecDelta, forward );
  910. float side = DotProduct( vecDelta, right );
  911. *xpos = flRadius * -side;
  912. *ypos = flRadius * -front;
  913. // Get the rotation (yaw)
  914. *flRotation = atan2( *xpos, *ypos ) + M_PI;
  915. *flRotation *= 180.f / M_PI;
  916. float yawRadians = -( *flRotation ) * M_PI / 180.f;
  917. float ca = cos( yawRadians );
  918. float sa = sin( yawRadians );
  919. // Rotate it around the circle
  920. *xpos = (int)( ( ScreenWidth() / 2 ) + ( flRadius * sa ) );
  921. *ypos = (int)( ( ScreenHeight() / 2 ) - ( flRadius * ca ) );
  922. }
  923. //-----------------------------------------------------------------------------
  924. // Purpose:
  925. //-----------------------------------------------------------------------------
  926. void CTFFlagCalloutPanel::OnTick( void )
  927. {
  928. int nDisplayMode = tf_rd_flag_ui_mode.GetInt();
  929. // Panels self-manage their existence and visibility
  930. C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
  931. if ( !pLocalTFPlayer || !m_hFlag || m_hFlag->IsHome() || m_hFlag->IsDisabled() || !nDisplayMode )
  932. {
  933. MarkForDeletion();
  934. return;
  935. }
  936. bool bShouldDraw = ShouldShowFlagIconToLocalPlayer();
  937. // Only show the most valuable enemy flag in this mode
  938. if ( nDisplayMode == FLAG_CALLER_DISPLAY_ENEMY_ONE )
  939. {
  940. int nHighestValue = 0;
  941. CCaptureFlag *pMostValuableFlag = NULL;
  942. for ( int i = 0; i < ICaptureFlagAutoList::AutoList().Count(); ++i )
  943. {
  944. CCaptureFlag *pFlag = static_cast< CCaptureFlag* >( ICaptureFlagAutoList::AutoList()[i] );
  945. if ( pFlag && pFlag->GetPointValue() > nHighestValue )
  946. {
  947. if ( pFlag->IsDisabled() )
  948. continue;
  949. if ( pFlag->IsHome() )
  950. continue;
  951. if ( pFlag->InSameTeam( pLocalTFPlayer ) )
  952. continue;
  953. if ( pFlag->GetPointValue() > nHighestValue )
  954. {
  955. nHighestValue = pFlag->GetPointValue();
  956. pMostValuableFlag = pFlag;
  957. }
  958. }
  959. }
  960. // If we're not it
  961. if ( pMostValuableFlag != m_hFlag )
  962. bShouldDraw = false;
  963. }
  964. if ( IsVisible() != bShouldDraw )
  965. {
  966. if ( !IsVisible() )
  967. {
  968. m_flFirstDisplayTime = gpGlobals->curtime;
  969. m_flPrevScale = 0.f;
  970. }
  971. SetVisible( bShouldDraw );
  972. }
  973. if ( IsEnabled() != bShouldDraw )
  974. {
  975. SetEnabled( bShouldDraw );
  976. }
  977. if ( !bShouldDraw )
  978. return;
  979. bool bCarried = ( !m_hFlag->IsDropped() && m_hFlag->GetPrevOwner() );
  980. if ( bCarried && !prediction->IsFirstTimePredicted() )
  981. return;
  982. // Adjust scale based on distance
  983. Vector vecDistance = m_hFlag->GetAbsOrigin() - pLocalTFPlayer->GetAbsOrigin();
  984. ScaleAndPositionCallout( RemapValClamped( vecDistance.LengthSqr(), ( 1000.f * 1000.f ), ( 4000.f * 4000.f ), 1.f, 0.6f ) );
  985. // Reposition the callout based on our target's position
  986. int iX, iY;
  987. Vector vecTarget = ( bCarried ) ? m_hFlag->GetPrevOwner()->GetAbsOrigin() : m_hFlag->GetAbsOrigin();
  988. Vector vecDelta = vecTarget - MainViewOrigin();
  989. bool bOnScreen = GetVectorInHudSpace( vecTarget, iX, iY );
  990. int nHalfWidth = GetWide() / 2;
  991. if ( !bOnScreen || iX < nHalfWidth || iX > ScreenWidth() - nHalfWidth )
  992. {
  993. // Only show side panel for a short period of time in this mode
  994. if ( TFGameRules() && TFGameRules()->IsPlayingRobotDestructionMode() && gpGlobals->curtime > m_flFirstDisplayTime + 5.f )
  995. {
  996. m_iDrawArrow = DRAW_ARROW_UP;
  997. SetAlpha( 0 );
  998. }
  999. else
  1000. {
  1001. // It's off the screen. Position the callout.
  1002. VectorNormalize( vecDelta );
  1003. float xpos, ypos;
  1004. float flRotation;
  1005. float flRadius = YRES( 100 );
  1006. GetCalloutPosition( vecDelta, flRadius, &xpos, &ypos, &flRotation );
  1007. iX = xpos;
  1008. iY = ypos;
  1009. Vector vCenter = m_hFlag->WorldSpaceCenter( );
  1010. if ( MainViewRight().Dot( vCenter - MainViewOrigin() ) > 0 )
  1011. {
  1012. m_iDrawArrow = DRAW_ARROW_RIGHT;
  1013. }
  1014. else
  1015. {
  1016. m_iDrawArrow = DRAW_ARROW_LEFT;
  1017. }
  1018. // Move the icon there
  1019. SetPos( iX - nHalfWidth, iY - ( GetTall() / 2 ) );
  1020. SetAlpha( 128 );
  1021. }
  1022. }
  1023. else
  1024. {
  1025. // On screen
  1026. // If our target isn't visible, we draw transparently
  1027. trace_t tr;
  1028. UTIL_TraceLine( vecTarget, MainViewOrigin(), MASK_VISIBLE, NULL, COLLISION_GROUP_NONE, &tr );
  1029. if ( tr.fraction >= 1.f )
  1030. {
  1031. m_bFlagVisible = true;
  1032. SetAlpha( 0 );
  1033. return;
  1034. }
  1035. else
  1036. {
  1037. m_iDrawArrow = DRAW_ARROW_UP;
  1038. SetAlpha( 128 );
  1039. SetPos( iX - nHalfWidth, iY - ( GetTall() / 2 ) );
  1040. }
  1041. }
  1042. m_bFlagVisible = false;
  1043. if ( !m_pFlagCalloutPanel )
  1044. return;
  1045. if ( !m_pFlagValueLabel )
  1046. return;
  1047. if ( !m_pFlagStatusIcon )
  1048. return;
  1049. m_pFlagCalloutPanel->SetImage( m_hFlag->GetTeamNumber() == TF_TEAM_BLUE ? "../hud/obj_briefcase_blue" : "../hud/obj_briefcase_red" );
  1050. m_pFlagValueLabel->SetText( CFmtStr( "%i", m_hFlag->GetPointValue() ) );
  1051. const char *pszImage = "../hud/objectives_flagpanel_ico_flag_home";
  1052. if ( m_hFlag->IsDropped() )
  1053. {
  1054. pszImage = "../hud/objectives_flagpanel_ico_flag_dropped";
  1055. }
  1056. else if ( m_hFlag->IsStolen() )
  1057. {
  1058. pszImage = "../hud/objectives_flagpanel_ico_flag_moving";
  1059. }
  1060. m_pFlagStatusIcon->SetImage( pszImage );
  1061. }
  1062. //-----------------------------------------------------------------------------
  1063. // Purpose:
  1064. //-----------------------------------------------------------------------------
  1065. void CTFFlagCalloutPanel::PaintBackground( void )
  1066. {
  1067. C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
  1068. if ( !pLocalTFPlayer )
  1069. return;
  1070. if ( !m_hFlag )
  1071. {
  1072. SetAlpha( 0 );
  1073. return;
  1074. }
  1075. BaseClass::PaintBackground();
  1076. }
  1077. //-----------------------------------------------------------------------------
  1078. // Purpose:
  1079. //-----------------------------------------------------------------------------
  1080. void CTFFlagCalloutPanel::Paint( void )
  1081. {
  1082. // Don't draw side panels if our target is visible. The particle effect will be doing it for us.
  1083. if ( m_bFlagVisible )
  1084. return;
  1085. BaseClass::Paint();
  1086. if ( m_iDrawArrow == DRAW_ARROW_UP )
  1087. return;
  1088. float uA, uB, yA, yB;
  1089. int x, y;
  1090. GetPos( x, y );
  1091. if ( m_iDrawArrow == DRAW_ARROW_LEFT )
  1092. {
  1093. uA = 1.f;
  1094. uB = 0.f;
  1095. yA = 0.f;
  1096. yB = 1.f;
  1097. x -= FLAG_CALLER_ARROW_WIDE;
  1098. }
  1099. else
  1100. {
  1101. uA = 0.f;
  1102. uB = 1.f;
  1103. yA = 0.f;
  1104. yB = 1.f;
  1105. x += m_pFlagCalloutPanel->GetWide();
  1106. }
  1107. int iyindent = ( GetTall() - FLAG_CALLER_ARROW_TALL ) * 0.5f;
  1108. y += iyindent;
  1109. CMatRenderContextPtr pRenderContext( materials );
  1110. pRenderContext->Bind( m_pArrowMaterial );
  1111. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  1112. CMeshBuilder meshBuilder;
  1113. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  1114. meshBuilder.Position3f( x, y, 0.f );
  1115. meshBuilder.TexCoord2f( 0, uA, yA );
  1116. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1117. meshBuilder.AdvanceVertex();
  1118. meshBuilder.Position3f( x + FLAG_CALLER_ARROW_WIDE, y, 0.f );
  1119. meshBuilder.TexCoord2f( 0, uB, yA );
  1120. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1121. meshBuilder.AdvanceVertex();
  1122. meshBuilder.Position3f( x + FLAG_CALLER_ARROW_WIDE, y + FLAG_CALLER_ARROW_TALL, 0.f );
  1123. meshBuilder.TexCoord2f( 0, uB, yB );
  1124. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1125. meshBuilder.AdvanceVertex();
  1126. meshBuilder.Position3f( x, y + FLAG_CALLER_ARROW_TALL, 0.f );
  1127. meshBuilder.TexCoord2f( 0, uA, yB );
  1128. meshBuilder.Color4ub( 255, 255, 255, 255 );
  1129. meshBuilder.AdvanceVertex();
  1130. meshBuilder.End();
  1131. pMesh->Draw();
  1132. }
  1133. //-----------------------------------------------------------------------------
  1134. // Purpose:
  1135. //-----------------------------------------------------------------------------
  1136. void CTFFlagCalloutPanel::SetFlag( CCaptureFlag *pFlag, float flDuration, Vector &vecOffset )
  1137. {
  1138. m_hFlag = pFlag;
  1139. m_flRemoveTime = gpGlobals->curtime + flDuration;
  1140. m_vecOffset = vecOffset;
  1141. m_flFirstDisplayTime = gpGlobals->curtime;
  1142. }
  1143. //-----------------------------------------------------------------------------
  1144. // Purpose:
  1145. //-----------------------------------------------------------------------------
  1146. CTFFlagCalloutPanel *CTFFlagCalloutPanel::AddFlagCalloutIfNotFound( CCaptureFlag *pFlag, float flDuration, Vector &vecLocation )
  1147. {
  1148. // How this system works:
  1149. // CTFHudFlagObjectives::OnTick() will attempt to create one panel per-flag that is stolen.
  1150. // CTFFlagCalloutPanel::OnTick() tries to manage whether or not the panel is visible, based on the UI mode.
  1151. // See if we have a panel for this flag already
  1152. FOR_EACH_VEC_BACK( m_FlagCalloutPanels, i )
  1153. {
  1154. if ( m_FlagCalloutPanels[i]->m_hFlag == pFlag )
  1155. {
  1156. return NULL;
  1157. }
  1158. }
  1159. CTFFlagCalloutPanel *pCallout = new CTFFlagCalloutPanel( "FlagCalloutHUD" );
  1160. if ( pCallout )
  1161. {
  1162. pCallout->SetFlag( pFlag, flDuration, vecLocation );
  1163. }
  1164. return pCallout;
  1165. }
  1166. //-----------------------------------------------------------------------------
  1167. // Purpose:
  1168. //-----------------------------------------------------------------------------
  1169. bool CTFFlagCalloutPanel::ShouldShowFlagIconToLocalPlayer( void )
  1170. {
  1171. C_TFPlayer *pLocalTFPlayer = C_TFPlayer::GetLocalTFPlayer();
  1172. if ( !pLocalTFPlayer )
  1173. return false;
  1174. int nDisplayMode = tf_rd_flag_ui_mode.GetInt();
  1175. // In "show all" mode, don't show flags on the local player's team that are being carried
  1176. if ( m_hFlag->IsStolen() &&
  1177. m_hFlag->InSameTeam( pLocalTFPlayer ) &&
  1178. nDisplayMode == FLAG_CALLER_DISPLAY_ALL )
  1179. return false;
  1180. // In all other modes, don't show flags on the local player's team
  1181. if ( m_hFlag->InSameTeam( pLocalTFPlayer ) &&
  1182. nDisplayMode < FLAG_CALLER_DISPLAY_ALL )
  1183. return false;
  1184. // Don't show the player running this flag
  1185. if ( m_hFlag->IsStolen() && pLocalTFPlayer == m_hFlag->GetPrevOwner() )
  1186. return false;
  1187. return true;
  1188. }
  1189. //-----------------------------------------------------------------------------
  1190. // Purpose:
  1191. //-----------------------------------------------------------------------------
  1192. void CTFFlagCalloutPanel::ScaleAndPositionCallout( float flScale /*= 1.f*/ )
  1193. {
  1194. if ( flScale == m_flPrevScale )
  1195. return;
  1196. SetSize( ( FLAG_CALLER_WIDE * flScale ), ( FLAG_CALLER_TALL * flScale ) );
  1197. if ( !m_pFlagCalloutPanel )
  1198. return;
  1199. if ( !m_pFlagValueLabel )
  1200. return;
  1201. if ( !m_pFlagStatusIcon )
  1202. return;
  1203. // Briefcase - top-left
  1204. m_pFlagCalloutPanel->SetSize( ( m_nPanelWideOrig * flScale ), ( m_nPanelTallOrig * flScale ) );
  1205. m_pFlagCalloutPanel->SetPos( 0, 0 );
  1206. // Label - centered
  1207. m_pFlagValueLabel->SetSize( ( m_nLabelWideOrig * flScale ), ( m_nLabelTallOrig * flScale ) );
  1208. m_pFlagValueLabel->SetPos( ( m_pFlagCalloutPanel->GetWide() - m_pFlagValueLabel->GetWide() ) * 0.5f, ( m_pFlagCalloutPanel->GetWide() - m_pFlagValueLabel->GetTall() ) * 0.65f );
  1209. // Icon - lower-right
  1210. m_pFlagStatusIcon->SetSize( ( m_nIconWideOrig * flScale ), ( m_nIconTallOrig * flScale ) );
  1211. m_pFlagStatusIcon->SetPos( ( m_pFlagCalloutPanel->GetWide() - m_pFlagStatusIcon->GetWide() ) * 1.05f, ( m_pFlagCalloutPanel->GetWide() - m_pFlagStatusIcon->GetTall() ) * 0.85f );
  1212. m_flPrevScale = flScale;
  1213. }