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.

3994 lines
94 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "hudelement.h"
  8. #include "sfhudradar.h"
  9. #include "hudelement.h"
  10. #include "hud_macros.h"
  11. #include <filesystem.h>
  12. #include "cs_gamerules.h"
  13. #include "c_team.h"
  14. #include "c_cs_playerresource.h"
  15. #include "c_plantedc4.h"
  16. #include "c_cs_hostage.h"
  17. #include "vtf/vtf.h"
  18. #include "clientmode.h"
  19. #include "voice_status.h"
  20. #include "vgui/ILocalize.h"
  21. #include <vstdlib/vstrtools.h>
  22. #include "view.h"
  23. #include "gameui_util.h"
  24. #include "sfhudfreezepanel.h"
  25. #include "sfhudwinpanel.h"
  26. #include "c_plantedc4.h"
  27. #include "HUD/sfhud_teamcounter.h"
  28. #include "gametypes.h"
  29. #include "eventlist.h"
  30. #include <game/client/iviewport.h>
  31. // memdbgon must be the last include file in a .cpp file!!!
  32. #include "tier0/memdbgon.h"
  33. static const float RADARRADIUS = 58.0f;
  34. static const float DEAD_FADE_TIME = 4.0f;
  35. static const float GHOST_FADE_TIME = 6.0f;
  36. static const float BOMB_FADE_TIME = 8.0f;
  37. static const float DEFUSER_FADE_TIME = 8.0f;
  38. static const float TIMER_INIT = -1000.0f;
  39. static const int ABOVE_BELOW_HEIGHT = 94;
  40. static const int INVALID_INDEX = -1;
  41. extern ConVar cl_draw_only_deathnotices;
  42. extern ConVar cl_radar_square_with_scoreboard;
  43. /*******************************************************************************
  44. * data definitions
  45. */
  46. static const char* playerIconNames[] = {
  47. "PlayerNumber",
  48. "PlayerLetter",
  49. "PlayerIndicator",
  50. "SpeakingOnMap",
  51. "SpeakingOffMap",
  52. "AbovePlayer",
  53. "BelowPlayer",
  54. "HostageTransitOnMap",
  55. "HostageTransitOffMap",
  56. "CTOnMap",
  57. "CTOffMap",
  58. "CTDeath",
  59. "CTGhost",
  60. "TOnMap",
  61. "TOffMap",
  62. "TDeath",
  63. "TGhost",
  64. "EnemyOnMap",
  65. "EnemyOffMap",
  66. "EnemyDeath",
  67. "EnemyGhost",
  68. "HostageOnMap",
  69. "HostageOffMap",
  70. "HostageDeath",
  71. "HostageGhost",
  72. "DirectionalIndicator",
  73. "Defuser",
  74. "Selected",
  75. "ViewFrustrum",
  76. "EnemyOnMapSeeOther",
  77. NULL
  78. };
  79. static const char* hostageIconNames[] = {
  80. "HostageDead",
  81. "HostageRescued",
  82. "HostageAlive",
  83. "HostageTransit",
  84. NULL
  85. };
  86. static const char* radarIconNames[] = {
  87. "BombPlantedIcon",
  88. "BombPlantedIconMedium",
  89. "BombPlantedIconFast",
  90. "HostageZoneIcon",
  91. NULL
  92. };
  93. static const char *desiredMessageNames[] = {
  94. "game_newmap",
  95. "round_start",
  96. "player_connect",
  97. "player_info",
  98. "player_team",
  99. "player_spawn",
  100. "player_death",
  101. "player_disconnect",
  102. "hostage_killed",
  103. "hostage_rescued",
  104. "bomb_defused",
  105. "bomb_exploded",
  106. "bomb_planted",
  107. "bomb_pickup",
  108. "bomb_dropped",
  109. "defuser_pickup",
  110. "defuser_dropped",
  111. "decoy_started",
  112. "decoy_detonate",
  113. "bot_takeover",
  114. NULL
  115. };
  116. enum DESIRED_MESSAGE_INDICES
  117. {
  118. GAME_NEWMAP,
  119. ROUND_POST_START,
  120. PLAYER_CONNECT,
  121. PLAYER_INFO,
  122. PLAYER_TEAM,
  123. PLAYER_SPAWN,
  124. PLAYER_DEATH,
  125. PLAYER_DISCONNECT,
  126. HOSTAGE_KILLED,
  127. HOSTAGE_RESCUED,
  128. BOMB_DEFUSED,
  129. BOMB_EXPLODED,
  130. BOMB_PLANTED,
  131. BOMB_PICKUP,
  132. BOMB_DROPPED,
  133. DEFUSER_PICKUP,
  134. DEFUSER_DROPPED,
  135. DECOY_STARTED,
  136. DECOY_DETONATE,
  137. BOT_TAKEOVER,
  138. };
  139. /***************************************************
  140. * callback and function declarations
  141. */
  142. static bool maplessfunc( const char* const & s1, const char* const & s2 )
  143. {
  144. return V_strcmp( s1, s2 ) < 0;
  145. }
  146. CUtlMap<const char*, int> SFHudRadar::m_messageMap( maplessfunc );
  147. DECLARE_HUDELEMENT( SFHudRadar );
  148. DECLARE_HUD_MESSAGE( SFHudRadar, ProcessSpottedEntityUpdate );
  149. SFUI_BEGIN_GAME_API_DEF
  150. SFUI_DECL_METHOD( MapLoaded ),
  151. SFUI_END_GAME_API_DEF( SFHudRadar, Radar );
  152. CON_COMMAND( drawradar, "Draws HUD radar" )
  153. {
  154. ( GET_HUDELEMENT( SFHudRadar ) )->ShowRadar( true );
  155. }
  156. CON_COMMAND( hideradar, "Hides HUD radar" )
  157. {
  158. ( GET_HUDELEMENT( SFHudRadar ) )->ShowRadar( false );
  159. }
  160. CON_COMMAND( cl_reload_hud, "Reloads the hud scale and resets scale and borders" )
  161. {
  162. ( GET_HUDELEMENT( SFHudRadar ) )->ResizeHud();
  163. }
  164. ConVar cl_radar_rotate( "cl_radar_rotate", "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "1" );
  165. ConVar cl_radar_scale( "cl_radar_scale", "0.7", FCVAR_RELEASE | FCVAR_ARCHIVE, "Sets the radar scale. Valid values are 0.25 to 1.0.", true, 0.25f, true, 1.0f );
  166. ConVar cl_radar_always_centered( "cl_radar_always_centered", "1", FCVAR_RELEASE | FCVAR_ARCHIVE, "If set to 0, the radar is maximally used. Otherwise the player is always centered, even at map extents." );
  167. ConVar cl_radar_icon_scale_min( "cl_radar_icon_scale_min", "0.6", FCVAR_RELEASE | FCVAR_ARCHIVE, "Sets the minimum icon scale. Valid values are 0.4 to 1.0.", true, 0.4f, true, 1.0f );
  168. ConVar cl_radar_fast_transforms( "cl_radar_fast_transforms", "1", FCVAR_DEVELOPMENTONLY, "Faster way of placing icons on the mini map." );
  169. /**********************************************************************
  170. * SFHudRadarIconPackage code
  171. */
  172. SFHudRadar::SFHudRadarIconPackage::SFHudRadarIconPackage()
  173. {
  174. ClearAll();
  175. }
  176. SFHudRadar::SFHudRadarIconPackage::~SFHudRadarIconPackage()
  177. {
  178. }
  179. void SFHudRadar::SFHudRadarIconPackage::ClearAll( void )
  180. {
  181. m_IconPackage = NULL;
  182. m_IconPackageRotate = NULL;
  183. V_memset( m_Icons, 0, sizeof( m_Icons ) );
  184. m_pScaleformUI = NULL;
  185. m_iCurrentVisibilityFlags = 0;
  186. m_fCurrentAlpha = 1.0f;
  187. m_Health = 0;
  188. m_iPlayerType = 0;
  189. m_iIndex = INVALID_INDEX;
  190. m_iEntityID = 0;
  191. m_bIsActive = false;
  192. m_bOffMap = true;
  193. m_bIsSpotted = false;
  194. m_bIsSpottedByFriendsOnly = false;
  195. m_fGhostTime = TIMER_INIT;
  196. m_fLastColorUpdate = TIMER_INIT;
  197. m_bIsDead = false;
  198. m_fDeadTime = TIMER_INIT;
  199. m_fGrenExpireTime = TIMER_INIT;
  200. m_IconPackType = ICON_PACK_PLAYER;
  201. m_bIsRescued = false;
  202. m_bIsOnLocalTeam = false;
  203. m_fRoundStartTime = TIMER_INIT;
  204. m_wcName[0] = 0;
  205. m_Position = vec3_origin;
  206. m_Angle.Init();
  207. m_HudPosition = vec3_origin;
  208. m_HudRotation = 0.0f;
  209. m_HudScale = 1.0f;
  210. m_bIsDefuser = false;
  211. m_bHostageIsUsed = false;
  212. }
  213. void SFHudRadar::SFHudRadarIconPackage::Init( IScaleformUI* pui, SFVALUE iconPackage )
  214. {
  215. m_pScaleformUI = pui;
  216. m_IconPackage = pui->CreateValue( iconPackage );
  217. m_IconPackageRotate = m_pScaleformUI->Value_GetMember( iconPackage, "RotatedLayer" );
  218. for ( int i = 0; i < PI_NUM_ICONS && playerIconNames[i] != NULL; i++ )
  219. {
  220. if ( i < PI_FIRST_ROTATED )
  221. {
  222. m_Icons[i] = pui->Value_GetMember( iconPackage, playerIconNames[i] );
  223. }
  224. else
  225. {
  226. if ( m_IconPackageRotate )
  227. {
  228. m_Icons[i] = pui->Value_GetMember( m_IconPackageRotate, playerIconNames[i] );
  229. }
  230. }
  231. if ( m_Icons[i] )
  232. {
  233. pui->Value_SetVisible( m_Icons[i], ( m_iCurrentVisibilityFlags & ( 1 << i ) ) != 0 );
  234. }
  235. }
  236. ScaleformDisplayInfo displayInfo;
  237. displayInfo.SetAlpha( m_fCurrentAlpha * 100.0f );
  238. displayInfo.SetVisibility( m_iCurrentVisibilityFlags != 0 );
  239. m_pScaleformUI->Value_SetDisplayInfo( m_IconPackage, &displayInfo );
  240. }
  241. void SFHudRadar::SFHudRadarIconPackage::NukeFromOrbit( SFHudRadar* pSFUI )
  242. {
  243. if ( pSFUI->FlashAPIIsValid() )
  244. {
  245. pSFUI->SafeReleaseSFVALUE( m_IconPackage );
  246. pSFUI->SafeReleaseSFVALUE( m_IconPackageRotate );
  247. for ( int i = 0; i < PI_NUM_ICONS; i++ )
  248. {
  249. pSFUI->SafeReleaseSFVALUE( m_Icons[i] );
  250. }
  251. }
  252. ClearAll();
  253. }
  254. void SFHudRadar::SFHudRadarIconPackage::StartRound( void )
  255. {
  256. m_Health = 100;
  257. m_bOffMap = false;
  258. m_bIsSpotted = false;
  259. m_bIsSpottedByFriendsOnly = false;
  260. m_fGhostTime = TIMER_INIT;
  261. m_fLastColorUpdate = TIMER_INIT;
  262. m_bIsDead = false;
  263. m_fDeadTime = TIMER_INIT;
  264. m_fGrenExpireTime = TIMER_INIT;
  265. m_bIsRescued = false;
  266. m_nAboveOrBelow = R_SAMELEVEL;
  267. m_fRoundStartTime = gpGlobals->curtime;
  268. m_Position = vec3_origin;
  269. m_Angle.Init();
  270. SetAlpha( 0 );
  271. SetVisibilityFlags( 0 );
  272. }
  273. bool SFHudRadar::SFHudRadarIconPackage::IsVisible( void )
  274. {
  275. return ( m_fCurrentAlpha != 0 && m_iCurrentVisibilityFlags != 0 );
  276. }
  277. void SFHudRadar::SFHudRadarIconPackage::SetIsPlayer( bool value )
  278. {
  279. m_bIsPlayer = value;
  280. }
  281. void SFHudRadar::SFHudRadarIconPackage::SetIsSelected( bool value )
  282. {
  283. m_bIsSelected = value;
  284. }
  285. void SFHudRadar::SFHudRadarIconPackage::SetIsSpeaking ( bool value )
  286. {
  287. m_bIsSpeaking = value && m_bIsOnLocalTeam;
  288. }
  289. void SFHudRadar::SFHudRadarIconPackage::SetIsOffMap( bool value )
  290. {
  291. m_bOffMap = value;
  292. }
  293. void SFHudRadar::SFHudRadarIconPackage::SetIsAboveOrBelow( int value )
  294. {
  295. m_nAboveOrBelow = value;
  296. }
  297. void SFHudRadar::SFHudRadarIconPackage::SetIsMovingHostage( bool value )
  298. {
  299. m_bIsMovingHostage = value;
  300. }
  301. void SFHudRadar::SFHudRadarIconPackage::SetIsRescued( bool value )
  302. {
  303. m_bIsRescued = value;
  304. }
  305. void SFHudRadar::SFHudRadarIconPackage::SetIsOnLocalTeam( bool value )
  306. {
  307. m_bIsOnLocalTeam = value;
  308. }
  309. void SFHudRadar::SFHudRadarIconPackage::SetIsBot( bool value )
  310. {
  311. m_bIsBot = value;
  312. }
  313. void SFHudRadar::SFHudRadarIconPackage::SetIsControlledBot( void )
  314. {
  315. m_bIsDead = true;
  316. //m_bIsSpotted = false;
  317. m_bIsSpotted = true;
  318. m_fDeadTime = TIMER_INIT;
  319. m_fGhostTime = TIMER_INIT;
  320. m_fLastColorUpdate = TIMER_INIT;
  321. }
  322. void SFHudRadar::SFHudRadarIconPackage::SetIsDead( bool value )
  323. {
  324. if ( value != m_bIsDead )
  325. {
  326. if ( value )
  327. {
  328. // SetIsSpotted( true );
  329. m_fDeadTime = gpGlobals->curtime;
  330. }
  331. else
  332. {
  333. m_fDeadTime = TIMER_INIT;
  334. }
  335. m_bIsDead = value;
  336. }
  337. }
  338. void SFHudRadar::SFHudRadarIconPackage::SetGrenadeExpireTime( float value )
  339. {
  340. if ( value )
  341. {
  342. m_fGrenExpireTime = value;
  343. }
  344. }
  345. void SFHudRadar::SFHudRadarIconPackage::SetIsSpotted( bool value )
  346. {
  347. if ( gpGlobals->curtime - m_fRoundStartTime > 0.25f )
  348. {
  349. if ( value != m_bIsSpotted )
  350. {
  351. if ( !value )
  352. {
  353. m_fGhostTime = gpGlobals->curtime;
  354. }
  355. else
  356. {
  357. m_fGhostTime = TIMER_INIT;
  358. }
  359. m_bIsSpotted = value;
  360. }
  361. }
  362. }
  363. void SFHudRadar::SFHudRadarIconPackage::SetIsSpottedByFriendsOnly( bool value )
  364. {
  365. if ( gpGlobals->curtime - m_fRoundStartTime > 0.25f )
  366. {
  367. m_bIsSpottedByFriendsOnly = value;
  368. }
  369. }
  370. void SFHudRadar::SFHudRadarIconPackage::SetPlayerTeam( int team )
  371. {
  372. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  373. if( pLocalPlayer == NULL )
  374. {
  375. return;
  376. }
  377. int newType;
  378. bool bSpec = ((pLocalPlayer && pLocalPlayer->IsSpectator() ) || engine->IsHLTV());
  379. switch( team )
  380. {
  381. case TEAM_UNASSIGNED:
  382. newType = PI_HOSTAGE;
  383. break;
  384. case TEAM_TERRORIST:
  385. newType = pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST || bSpec ? PI_T : PI_ENEMY;
  386. break;
  387. case TEAM_CT:
  388. newType = pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT || bSpec ? PI_CT : PI_ENEMY;
  389. break;
  390. case TEAM_SPECTATOR:
  391. default:
  392. newType = 0;
  393. break;
  394. }
  395. if ( m_iPlayerType != newType )
  396. {
  397. m_iPlayerType = newType;
  398. SetVisibilityFlags( 0 );
  399. }
  400. }
  401. bool Helper_ShouldShowAssassinationTargetIcon( int iEntIndex )
  402. {
  403. C_CSPlayer *pTarget= (C_CSPlayer*)UTIL_PlayerByIndex( iEntIndex );
  404. C_CS_PlayerResource *pCSPR = GetCSResources();
  405. if ( !pTarget || !pCSPR )
  406. return false;
  407. return ( !pCSPR->IsControllingBot( iEntIndex ) &&
  408. pTarget->IsAssassinationTarget() );
  409. }
  410. void SFHudRadar::SFHudRadarIconPackage::SetupIconsFromStates( void )
  411. {
  412. int flags = 0;
  413. float alpha = 1;
  414. if ( m_iPlayerType != 0 )
  415. {
  416. flags = 1 << m_iPlayerType;
  417. if ( m_bIsPlayer )
  418. {
  419. flags |= 1 << PI_VIEWFRUSTRUM;
  420. }
  421. if ( m_bIsDead )
  422. {
  423. if ( m_Position.x == 0 && m_Position.y == 0 || !m_bIsSpotted )
  424. {
  425. flags = 0;
  426. }
  427. else
  428. {
  429. float deadElapsedTime = gpGlobals->curtime - m_fDeadTime;
  430. if ( deadElapsedTime > DEAD_FADE_TIME )
  431. {
  432. m_fDeadTime = TIMER_INIT;
  433. flags = 0;
  434. }
  435. else
  436. {
  437. alpha = clamp( 1.0f - deadElapsedTime / DEAD_FADE_TIME, 0.0f, 1.0f );
  438. // the shift below changes the icon to be the dead icon ( the X )
  439. // rescued hostages are marked as dead, but we don't want to show
  440. // the X in that case. So if this guy is a hostage and has been resuced
  441. // we want to skip the code that changes the icon to the dead icon.
  442. bool isRescuedNotDead = IsHostageType() && m_bIsRescued;
  443. if ( !isRescuedNotDead )
  444. {
  445. flags <<= 2;
  446. }
  447. }
  448. }
  449. }
  450. else if ( !m_bIsSpotted )
  451. {
  452. float ghostElapsedTime = gpGlobals->curtime - m_fGhostTime;
  453. if ( ghostElapsedTime > GHOST_FADE_TIME )
  454. {
  455. m_fGhostTime = TIMER_INIT;
  456. flags = 0;
  457. }
  458. else
  459. {
  460. alpha = clamp( 1.0f - ghostElapsedTime / GHOST_FADE_TIME, 0.0f, 1.0f );
  461. if ( m_bOffMap )
  462. {
  463. flags <<= 1;
  464. }
  465. else
  466. {
  467. flags <<= 3;
  468. }
  469. }
  470. }
  471. else
  472. {
  473. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  474. bool bSpec = ( ( pLocalPlayer && pLocalPlayer->IsSpectator() ) || engine->IsHLTV());
  475. bool bShowLetters = ( !bSpec && m_iPlayerType != PI_ENEMY && !m_bOffMap && !IsHostageType( ) );
  476. if ( bSpec )
  477. {
  478. flags |= 1 << PI_PLAYER_NUMBER;
  479. }
  480. // this decides if the letter should be shown
  481. if ( bShowLetters || Helper_ShouldShowAssassinationTargetIcon( m_iEntityID ) )
  482. {
  483. flags |= 1 << PI_PLAYER_LETTER;
  484. }
  485. if ( m_bIsMovingHostage )
  486. {
  487. flags |= 1 << PI_HOSTAGE_MOVING;
  488. }
  489. if ( m_bIsSpeaking )
  490. {
  491. flags |= 1 << PI_SPEAKING;
  492. }
  493. if ( m_bIsSelected )
  494. {
  495. flags |= 1 << PI_SELECTED;
  496. }
  497. if ( bSpec == false && m_iPlayerType == PI_ENEMY && (m_bIsSpottedByFriendsOnly == false || pLocalPlayer->IsAlive() == false) )
  498. {
  499. flags |= 1 << PI_ENEMY_SEELOCAL;
  500. }
  501. // this will shift the MOVING and SPEAKING icons to their
  502. // offscreen versions as well ( look at the enum decaration )
  503. if ( m_bOffMap )
  504. {
  505. flags <<= 1;
  506. }
  507. else
  508. {
  509. if ( m_nAboveOrBelow == R_ABOVE )
  510. {
  511. flags |= 1 << PI_ABOVE;
  512. }
  513. else if ( m_nAboveOrBelow == R_BELOW )
  514. {
  515. flags |= 1 << PI_BELOW;
  516. }
  517. else
  518. {
  519. if ( !bSpec && /*!bShowNumbers &&*/ m_iPlayerType != PI_ENEMY && !IsHostageType( ) )
  520. flags |= 1 << PI_DIRECTION_INDICATOR;
  521. }
  522. }
  523. // if ( m_bIsPlayer )
  524. // {
  525. // flags |= 1 << PI_PLAYER_INDICATOR;
  526. // }
  527. }
  528. if ( m_fGrenExpireTime != TIMER_INIT )
  529. {
  530. if ( m_fGrenExpireTime < gpGlobals->curtime )
  531. {
  532. m_fGrenExpireTime = TIMER_INIT;
  533. m_bIsSpotted = false;
  534. }
  535. }
  536. }
  537. else if ( m_bIsDefuser )
  538. {
  539. // only render after we have received a position update
  540. if ( m_Position != vec3_origin )
  541. {
  542. flags |= 1 << PI_DEFUSER;
  543. if ( m_bIsSpotted )
  544. {
  545. m_fGhostTime = TIMER_INIT;
  546. alpha = 1.0f;
  547. }
  548. else
  549. {
  550. float ghostElapsedTime = gpGlobals->curtime - m_fGhostTime;
  551. if ( ghostElapsedTime > GHOST_FADE_TIME )
  552. {
  553. m_fGhostTime = TIMER_INIT;
  554. flags = 0;
  555. }
  556. else
  557. {
  558. alpha = clamp( 1.0f - ghostElapsedTime / GHOST_FADE_TIME, 0.0f, 1.0f );
  559. }
  560. }
  561. }
  562. }
  563. SetAlpha( alpha );
  564. SetVisibilityFlags( flags );
  565. UpdateIconsPostion();
  566. }
  567. void SFHudRadar::SFHudRadarIconPackage::SetVisibilityFlags( int newFlags )
  568. {
  569. newFlags &= ( ( 1 << PI_NUM_ICONS )-1 );
  570. int diffFlags = m_iCurrentVisibilityFlags ^ newFlags;
  571. if ( diffFlags )
  572. {
  573. if ( m_IconPackage )
  574. {
  575. bool wantVisible = ( newFlags != 0 );
  576. if ( ( m_iCurrentVisibilityFlags != 0 ) != wantVisible )
  577. {
  578. m_pScaleformUI->Value_SetVisible( m_IconPackage, wantVisible );
  579. }
  580. for ( int i = 0; i < PI_NUM_ICONS && ( diffFlags != 0 ); i++, diffFlags >>= 1 )
  581. {
  582. if ( (diffFlags & 1) && ( m_Icons[i] ) )
  583. {
  584. Assert( m_Icons[i] );
  585. if ( m_Icons[i] )
  586. {
  587. m_pScaleformUI->Value_SetVisible( m_Icons[i], ( newFlags & ( 1 << i ) ) != 0 );
  588. }
  589. }
  590. }
  591. }
  592. m_iCurrentVisibilityFlags = newFlags;
  593. }
  594. }
  595. void SFHudRadar::SFHudRadarIconPackage::UpdateIconsPostion( void )
  596. {
  597. int visibilityFlags = m_iCurrentVisibilityFlags;
  598. if ( m_IconPackage )
  599. {
  600. for ( int i = 0; i < PI_NUM_ICONS && ( visibilityFlags != 0 ); i++, visibilityFlags >>= 1 )
  601. {
  602. if ( (visibilityFlags & 1) && ( m_Icons[i] ) )
  603. {
  604. Assert( m_Icons[i] );
  605. ScaleformDisplayInfo displayInfo;
  606. if ( cl_radar_fast_transforms.GetBool() )
  607. {
  608. displayInfo.SetX( m_HudPosition.x );
  609. displayInfo.SetY( m_HudPosition.y );
  610. displayInfo.SetXScale( m_HudScale );
  611. displayInfo.SetYScale( m_HudScale );
  612. if ( i >= PI_FIRST_ROTATED )
  613. {
  614. displayInfo.SetRotation( m_HudRotation );
  615. }
  616. }
  617. else
  618. {
  619. displayInfo.SetX( 0.0f );
  620. displayInfo.SetY( 0.0f );
  621. displayInfo.SetXScale( 100.0f );
  622. displayInfo.SetYScale( 100.0f );
  623. displayInfo.SetRotation( 0.0f );
  624. }
  625. m_pScaleformUI->Value_SetDisplayInfo( m_Icons[i], &displayInfo );
  626. }
  627. }
  628. }
  629. }
  630. void SFHudRadar::SFHudRadarIconPackage::SetAlpha( float newAlpha )
  631. {
  632. if ( newAlpha != m_fCurrentAlpha )
  633. {
  634. m_fCurrentAlpha = newAlpha;
  635. if ( m_IconPackage )
  636. {
  637. ScaleformDisplayInfo displayInfo;
  638. displayInfo.SetAlpha( m_fCurrentAlpha * 100.0f );
  639. m_pScaleformUI->Value_SetDisplayInfo( m_IconPackage, &displayInfo );
  640. }
  641. }
  642. }
  643. void SFHudRadar::SFHudRadarIconPackage::SetIsDefuse( bool bValue )
  644. {
  645. m_bIsDefuser = bValue;
  646. }
  647. /**********************************************************************
  648. **********************************************************************
  649. **********************************************************************
  650. **********************************************************************
  651. **********************************************************************
  652. * SFHudHostageIcon
  653. */
  654. SFHudRadar::SFHudRadarHostageIcons::SFHudRadarHostageIcons()
  655. {
  656. m_IconPackage = NULL;
  657. V_memset( m_Icons, 0,sizeof( m_Icons ) );
  658. m_iCurrentIcon = HI_UNUSED;
  659. }
  660. SFHudRadar::SFHudRadarHostageIcons::~SFHudRadarHostageIcons()
  661. {
  662. }
  663. void SFHudRadar::SFHudRadarHostageIcons::Init( IScaleformUI* scaleformui, SFVALUE iconPackage )
  664. {
  665. m_pScaleformUI = scaleformui;
  666. m_IconPackage = scaleformui->CreateValue( iconPackage );
  667. for ( int i = 0; i < HI_NUM_ICONS && hostageIconNames[i] != NULL; i++ )
  668. {
  669. m_Icons[i] = m_pScaleformUI->Value_GetMember( m_IconPackage, hostageIconNames[i] );
  670. if ( m_Icons[i] )
  671. {
  672. m_pScaleformUI->Value_SetVisible( m_Icons[i], m_iCurrentIcon == i );
  673. }
  674. }
  675. m_pScaleformUI->Value_SetVisible( m_IconPackage, m_iCurrentIcon != HI_UNUSED );
  676. }
  677. void SFHudRadar::SFHudRadarHostageIcons::SetStatus( int status )
  678. {
  679. if ( status != m_iCurrentIcon )
  680. {
  681. if ( m_IconPackage )
  682. {
  683. if ( m_iCurrentIcon != HI_UNUSED )
  684. {
  685. assert(m_Icons[m_iCurrentIcon]);
  686. m_pScaleformUI->Value_SetVisible( m_Icons[m_iCurrentIcon], false );
  687. }
  688. else
  689. {
  690. m_pScaleformUI->Value_SetVisible( m_IconPackage, true );
  691. }
  692. m_iCurrentIcon = status;
  693. if ( m_iCurrentIcon != HI_UNUSED )
  694. {
  695. assert(m_Icons[m_iCurrentIcon]);
  696. m_pScaleformUI->Value_SetVisible( m_Icons[m_iCurrentIcon], true );
  697. }
  698. else
  699. {
  700. m_pScaleformUI->Value_SetVisible( m_IconPackage, false );
  701. }
  702. }
  703. }
  704. }
  705. void SFHudRadar::SFHudRadarHostageIcons::ReleaseHandles( SFHudRadar* pradar )
  706. {
  707. if ( m_IconPackage && pradar->FlashAPIIsValid() )
  708. {
  709. pradar->SafeReleaseSFVALUE( m_IconPackage );
  710. for ( int i = 0; i < HI_NUM_ICONS; i++ )
  711. {
  712. pradar->SafeReleaseSFVALUE( m_Icons[i] );
  713. }
  714. }
  715. }
  716. /**********************************************************************
  717. **********************************************************************
  718. **********************************************************************
  719. **********************************************************************
  720. **********************************************************************
  721. * SFHudRadar Code
  722. *
  723. */
  724. SFHudRadar::SFHudRadar( const char *value ) : SFHudFlashInterface( value ),
  725. m_bVisible( false ),
  726. m_fMapSize( 1.0f ),
  727. m_fRadarSize( 1.0f ),
  728. m_fPixelToRadarScale( 1.0f ),
  729. m_fWorldToPixelScale( 1.0f ),
  730. m_fWorldToRadarScale( 1.0f ),
  731. m_RadarModule( NULL ),
  732. m_Radar( NULL ),
  733. m_IconTranslation( NULL ),
  734. m_IconRotation( NULL ),
  735. m_MapRotation( NULL ),
  736. m_MapTranslation( NULL ),
  737. m_iNumGoalIcons( 0 ),
  738. m_iLastPlayerIndex( INVALID_INDEX ),
  739. m_iLastHostageIndex( INVALID_INDEX ),
  740. m_iLastDecoyIndex( INVALID_INDEX ),
  741. m_iLastDefuserIndex( INVALID_INDEX ),
  742. m_RadarViewpointWorld( vec3_origin ),
  743. m_RadarViewpointMap( vec3_origin ),
  744. m_RadarRotation( 0 ),
  745. m_BombPosition( vec3_origin ),
  746. m_DefuserPosition( vec3_origin ),
  747. m_iCurrentVisibilityFlags( 0 ),
  748. m_fBombSeenTime( TIMER_INIT ),
  749. m_fBombAlpha( 0 ),
  750. m_fDefuserSeenTime( TIMER_INIT ),
  751. m_fDefuserAlpha( 0.0f ),
  752. m_LocationText( NULL ),
  753. m_bFlashLoading( false ),
  754. m_bFlashReady( false ),
  755. m_bGotPlayerIcons( false ),
  756. m_bShowingHostageZone( false ),
  757. m_bBombPlanted( false ),
  758. m_bBombDropped( false ),
  759. m_nBombEntIndex( -1 ),
  760. m_nBombHolderUserId( -1 ),
  761. m_bShowBombHighlight( false ),
  762. m_bShowRadar( true ),
  763. m_bShowAll( false ),
  764. m_bShowingDashboard( false ),
  765. m_iObserverMode( OBS_MODE_NONE ),
  766. m_bTrackDefusers( false ),
  767. m_bRound( true )
  768. {
  769. SetHiddenBits( HIDEHUD_RADAR );
  770. m_bWantLateUpdate = true;
  771. m_cDesiredMapName[0] = 0;
  772. m_cLoadedMapName[0] = 0;
  773. m_wcLocationString[0] = 0;
  774. V_memset( m_BombZoneIcons, 0, sizeof( m_BombZoneIcons ) );
  775. V_memset( m_HostageZoneIcons, 0, sizeof( m_HostageZoneIcons ) );
  776. V_memset( m_GoalIcons, 0, sizeof( m_GoalIcons ) );
  777. V_memset( m_HostageStatusIcons, 0, sizeof( m_HostageStatusIcons ) );
  778. V_memset( m_Icons, 0, sizeof( m_Icons ) );
  779. m_EntitySpotted.ClearAll();
  780. m_nCurrentRadarVerticalSection = -1;
  781. m_vecRadarVerticalSections.RemoveAll();
  782. }
  783. SFHudRadar::~SFHudRadar()
  784. {
  785. }
  786. /**************************************
  787. * hud element functions
  788. */
  789. void SFHudRadar::Init( void )
  790. {
  791. // register for events as client listener
  792. const char** pwalk = &desiredMessageNames[0];
  793. while( *pwalk != NULL )
  794. {
  795. ListenForGameEvent( *pwalk );
  796. pwalk++;
  797. }
  798. if ( ! m_messageMap.Count() )
  799. {
  800. const char** pwalk = &desiredMessageNames[0];
  801. int i = 0;
  802. while( *pwalk != NULL )
  803. {
  804. m_messageMap.Insert( *pwalk++, i++ );
  805. }
  806. }
  807. HOOK_HUD_MESSAGE( SFHudRadar, ProcessSpottedEntityUpdate );
  808. }
  809. void SFHudRadar::LevelInit( void )
  810. {
  811. if ( !m_bFlashReady && !m_bFlashLoading )
  812. {
  813. SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFHudRadar, this, Radar );
  814. }
  815. }
  816. void SFHudRadar::LevelShutdown( void )
  817. {
  818. if ( m_bFlashReady || m_bFlashLoading )
  819. {
  820. RemoveFlashElement();
  821. }
  822. }
  823. ConVar cl_drawhud_force_radar( "cl_drawhud_force_radar", "0", FCVAR_RELEASE, "0: default; 1: draw radar even if hud disabled; -1: force no radar" );
  824. bool SFHudRadar::ShouldDraw( void )
  825. {
  826. if ( IsTakingAFreezecamScreenshot() )
  827. return false;
  828. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer( );
  829. if ( !pPlayer )
  830. return false;
  831. bool bSpec = pPlayer->IsSpectator( ) || engine->IsHLTV( );
  832. if ( bSpec == false )
  833. {
  834. // //Don't show the radar while the win panel is up (only look at slot 0 because that is the only "true" Win Panel)
  835. // SFHudWinPanel * pWinPanel = ( SFHudWinPanel* ) ( GetHud( 0 ).FindElement( "SFHudWinPanel" ) );
  836. // if ( pWinPanel && pWinPanel->IsVisible( ) )
  837. // {
  838. // return false;
  839. // }
  840. if ( pPlayer->GetTeamNumber() == TEAM_UNASSIGNED ||
  841. ( pPlayer->GetTeamNumber() == TEAM_UNASSIGNED && pPlayer->GetPendingTeamNumber() != TEAM_SPECTATOR ) )
  842. return false;
  843. }
  844. return m_bShowRadar && ( cl_drawhud_force_radar.GetInt() >= 0 ) && (
  845. ( cl_drawhud_force_radar.GetInt() > 0 ) ||
  846. ( cl_drawhud.GetBool() && cl_draw_only_deathnotices.GetBool() == false )
  847. ) && CHudElement::ShouldDraw();
  848. }
  849. void SFHudRadar::SetActive( bool bActive )
  850. {
  851. if ( bActive != m_bVisible )
  852. Show( bActive );
  853. CHudElement::SetActive( bActive );
  854. }
  855. void SFHudRadar::Show( bool show )
  856. {
  857. if ( !m_pScaleformUI )
  858. return;
  859. WITH_SLOT_LOCKED
  860. {
  861. if ( show )
  862. {
  863. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showPanel", NULL, 0 );
  864. for ( int i = 0; i <= MAX_PLAYERS; ++i )
  865. {
  866. SFHudRadarIconPackage* pPackage = GetRadarPlayer( i );
  867. if ( pPackage )
  868. pPackage->m_fLastColorUpdate = TIMER_INIT;
  869. }
  870. UpdateAllPlayerNumbers();
  871. m_bVisible = true;
  872. }
  873. else
  874. {
  875. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hidePanel", NULL, 0 );
  876. m_bVisible = false;
  877. }
  878. }
  879. }
  880. /**********************************
  881. * initialization code goes here
  882. */
  883. // these overload the ScaleformFlashInterfaceMixin class
  884. void SFHudRadar::FlashLoaded( void )
  885. {
  886. m_RadarModule = m_pScaleformUI->Value_GetMember( m_FlashAPI, "RadarModule" );
  887. if ( !m_RadarModule )
  888. {
  889. return;
  890. }
  891. m_Radar = m_pScaleformUI->Value_GetMember( m_RadarModule, "Radar" );
  892. if ( m_Radar )
  893. {
  894. m_MapRotation = m_pScaleformUI->Value_GetMember( m_Radar, "MapRotation" );
  895. if ( m_MapRotation )
  896. {
  897. m_MapTranslation =m_pScaleformUI->Value_GetMember( m_MapRotation, "MapTranslation" );
  898. }
  899. m_IconRotation = m_pScaleformUI->Value_GetMember( m_Radar, "IconRotation" );
  900. if ( !m_IconRotation )
  901. return;
  902. m_IconTranslation = m_pScaleformUI->Value_GetMember( m_IconRotation, "IconTranslation" );
  903. if ( !m_IconTranslation )
  904. return;
  905. char cHostageZoneIconName[20] = {"HZone0"};
  906. for ( int i = 0; i < MAX_HOSTAGE_RESCUES; i++ )
  907. {
  908. cHostageZoneIconName[5] = '0'+i;
  909. m_HostageZoneIcons[i] = m_pScaleformUI->Value_GetMember( m_IconTranslation, cHostageZoneIconName );
  910. }
  911. m_BombZoneIcons[0] = m_pScaleformUI->Value_GetMember( m_IconTranslation, "BombZoneA" );
  912. m_BombZoneIcons[1] = m_pScaleformUI->Value_GetMember( m_IconTranslation, "BombZoneB" );
  913. }
  914. SFVALUE dashboard = m_pScaleformUI->Value_GetMember( m_RadarModule, "Dashboard" );
  915. m_Icons[RI_DASHBOARD] = dashboard;
  916. if ( !dashboard )
  917. return;
  918. //SFVALUE C4andHostages = m_pScaleformUI->Value_GetMember( m_RadarModule, "C4" );
  919. //if ( !C4andHostages )
  920. // return;
  921. SFVALUE hostageIcons = m_pScaleformUI->Value_GetMember( m_RadarModule, "Hostages" );
  922. char hostageIconName[20] = {"HostageStatusX"};
  923. int index = 0;
  924. SFVALUE hostageIcon;
  925. do
  926. {
  927. hostageIconName[13] = index + '1';
  928. hostageIcon = m_pScaleformUI->Value_GetMember( hostageIcons, hostageIconName );
  929. if ( hostageIcon == NULL )
  930. {
  931. break;
  932. }
  933. else
  934. {
  935. m_HostageStatusIcons[index].Init( m_pScaleformUI, hostageIcon );
  936. SafeReleaseSFVALUE( hostageIcon );
  937. }
  938. } while( ++index < MAX_HOSTAGES );
  939. for ( int i = 0; radarIconNames[i] != NULL; i++ )
  940. {
  941. m_Icons[i] = m_pScaleformUI->Value_GetMember( hostageIcons, radarIconNames[i] );
  942. }
  943. m_LocationText = m_pScaleformUI->TextObject_MakeTextObjectFromMember( dashboard, "Location" );
  944. if ( m_LocationText )
  945. {
  946. m_LocationText->SetText( m_wcLocationString );
  947. }
  948. SafeReleaseSFVALUE( hostageIcons );
  949. }
  950. void SFHudRadar::FlashReady( void )
  951. {
  952. // these aren't ready until after the first frame, so they have to get connected here instead of in
  953. // FlashLoaded()
  954. m_Icons[RI_BOMB_ICON_PACKAGE] = m_pScaleformUI->Value_Invoke( m_IconTranslation, "createBombPack", NULL, 0 );
  955. if ( m_Icons[RI_BOMB_ICON_PACKAGE] )
  956. {
  957. m_Icons[RI_BOMB_ICON_DROPPED] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "DroppedBomb" );
  958. m_Icons[RI_BOMB_ICON_PLANTED] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "PlantedBomb" );
  959. m_Icons[RI_BOMB_ICON_BOMB_CT] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "BombCT" );
  960. m_Icons[RI_BOMB_ICON_BOMB_T] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "BombT" );
  961. m_Icons[RI_BOMB_ICON_BOMB_ABOVE] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "BombAbove" );
  962. m_Icons[RI_BOMB_ICON_BOMB_BELOW] = m_pScaleformUI->Value_GetMember( m_Icons[RI_BOMB_ICON_PACKAGE], "BombBelow" );
  963. }
  964. for ( int i = 0; i < RI_NUM_ICONS; i++ )
  965. {
  966. if ( m_Icons[i] )
  967. {
  968. m_pScaleformUI->Value_SetVisible( m_Icons[i], false );
  969. }
  970. }
  971. m_bFlashLoading = false;
  972. m_bFlashReady = true;
  973. ResetForNewMap();
  974. // there will be a map waiting for us to load
  975. FlashLoadMap( NULL );
  976. //
  977. // if ( m_bActive )
  978. // {
  979. // m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showPanel", NULL, 0 );
  980. // m_bVisible = true;
  981. // }
  982. // else
  983. // {
  984. // m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hidePanel", NULL, 0 );
  985. // m_bVisible = false;
  986. // }
  987. }
  988. void SFHudRadar::LazyCreateGoalIcons( void )
  989. {
  990. if ( m_bGotGoalIcons || !m_bFlashReady )
  991. {
  992. return;
  993. }
  994. // The goal entities don't exist on the client, so we have to get them from the CS Resource.
  995. C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
  996. if ( !pCSPR )
  997. {
  998. return;
  999. }
  1000. m_iNumGoalIcons = 0;
  1001. if ( CSGameRules()->IsBombDefuseMap() )
  1002. {
  1003. Vector bombA = pCSPR->GetBombsiteAPosition();
  1004. if( bombA != vec3_origin )
  1005. {
  1006. m_GoalIcons[m_iNumGoalIcons].m_Position = bombA;
  1007. m_GoalIcons[m_iNumGoalIcons].m_Icon = m_BombZoneIcons[0];
  1008. m_pScaleformUI->Value_SetVisible( m_GoalIcons[m_iNumGoalIcons].m_Icon, true );
  1009. m_iNumGoalIcons++;
  1010. }
  1011. Vector bombB = pCSPR->GetBombsiteBPosition();
  1012. if( bombB != vec3_origin )
  1013. {
  1014. m_GoalIcons[m_iNumGoalIcons].m_Position = bombB;
  1015. m_GoalIcons[m_iNumGoalIcons].m_Icon = m_BombZoneIcons[1];
  1016. m_pScaleformUI->Value_SetVisible( m_GoalIcons[m_iNumGoalIcons].m_Icon, true );
  1017. m_iNumGoalIcons++;
  1018. }
  1019. }
  1020. else if ( CSGameRules()->IsHostageRescueMap() )
  1021. {
  1022. for( int rescueIndex = 0; rescueIndex < MAX_HOSTAGE_RESCUES; rescueIndex++ )
  1023. {
  1024. int hIndex = 0;
  1025. Vector hostageI = pCSPR->GetHostageRescuePosition( rescueIndex );
  1026. if( hostageI != vec3_origin )
  1027. {
  1028. m_GoalIcons[m_iNumGoalIcons].m_Position = hostageI;
  1029. m_GoalIcons[m_iNumGoalIcons].m_Icon = m_HostageZoneIcons[hIndex++];
  1030. m_pScaleformUI->Value_SetVisible( m_GoalIcons[m_iNumGoalIcons].m_Icon, true );
  1031. m_iNumGoalIcons++;
  1032. }
  1033. }
  1034. }
  1035. m_bGotGoalIcons = true;
  1036. }
  1037. bool SFHudRadar::PreUnloadFlash( void )
  1038. {
  1039. if ( m_IconTranslation )
  1040. {
  1041. m_pScaleformUI->Value_InvokeWithoutReturn( m_IconTranslation, "removeBombPack", NULL, 0 );
  1042. }
  1043. for ( int i = 0; i < MAX_BOMB_ZONES; i++ )
  1044. {
  1045. SafeReleaseSFVALUE( m_BombZoneIcons[i] );
  1046. }
  1047. for ( int i = 0; i < MAX_HOSTAGE_RESCUES; i++ )
  1048. {
  1049. SafeReleaseSFVALUE( m_HostageZoneIcons[i] );
  1050. }
  1051. while( m_iLastPlayerIndex >= 0 )
  1052. {
  1053. RemovePlayer( m_iLastPlayerIndex );
  1054. }
  1055. while( m_iLastHostageIndex >= 0 )
  1056. {
  1057. RemoveHostage( m_iLastHostageIndex );
  1058. }
  1059. RemoveAllDefusers();
  1060. RemoveAllDecoys();
  1061. SafeReleaseSFVALUE( m_MapRotation );
  1062. SafeReleaseSFVALUE( m_MapTranslation );
  1063. SafeReleaseSFVALUE( m_RadarModule );
  1064. SafeReleaseSFVALUE( m_Radar );
  1065. SafeReleaseSFVALUE( m_IconTranslation );
  1066. SafeReleaseSFVALUE( m_IconRotation );
  1067. SafeReleaseSFTextObject( m_LocationText );
  1068. int index = 0;
  1069. while( m_HostageStatusIcons[index].m_IconPackage )
  1070. {
  1071. m_HostageStatusIcons[index++].ReleaseHandles( this );
  1072. }
  1073. for ( int i =0 ; i < RI_NUM_ICONS; i++ )
  1074. {
  1075. SafeReleaseSFVALUE( m_Icons[i] );
  1076. }
  1077. m_bFlashReady = false;
  1078. m_cDesiredMapName[0] = 0;
  1079. m_cLoadedMapName[0] = 0;
  1080. m_bActive = false;
  1081. m_bVisible = false;
  1082. return true;
  1083. }
  1084. /*********************************************************
  1085. * set up the background map
  1086. */
  1087. void SFHudRadar::SetMap( const char* pMapName )
  1088. {
  1089. FlashLoadMap( pMapName );
  1090. KeyValues* MapKeyValues = new KeyValues( pMapName );
  1091. char tempfile[MAX_PATH];
  1092. Q_snprintf( tempfile, sizeof( tempfile ), "resource/overviews/%s.txt", pMapName );
  1093. if ( !MapKeyValues->LoadFromFile( g_pFullFileSystem, tempfile, "GAME" ) )
  1094. {
  1095. DevMsg( 1, "Error! CMapOverview::SetMap: couldn't load file %s.\n", tempfile );
  1096. m_MapOrigin.x = 0;
  1097. m_MapOrigin.y = 0;
  1098. return;
  1099. }
  1100. KeyValues* pSections = MapKeyValues->FindKey( "verticalsections" );
  1101. if ( pSections )
  1102. {
  1103. int nIndex = 0;
  1104. for ( KeyValues *kSection = pSections->GetFirstSubKey(); kSection != NULL; kSection = kSection->GetNextKey() )
  1105. {
  1106. float flAltMin = kSection->GetFloat( "AltitudeMin", 0.0f );
  1107. float flAltMax = kSection->GetFloat( "AltitudeMax", 0.0f );
  1108. if ( flAltMin < flAltMax )
  1109. {
  1110. HudRadarLevelVerticalSection_t *pNewSection = &m_vecRadarVerticalSections[ m_vecRadarVerticalSections.AddToTail() ];
  1111. if ( !V_strcmp( kSection->GetName(), "default" ) )
  1112. {
  1113. V_strcpy_safe( pNewSection->m_szSectionName, pMapName );
  1114. }
  1115. else
  1116. {
  1117. V_sprintf_safe( pNewSection->m_szSectionName, "%s_%s", pMapName, kSection->GetName() );
  1118. }
  1119. pNewSection->m_nSectionIndex = nIndex;
  1120. pNewSection->m_flSectionAltitudeFloor = flAltMin;
  1121. pNewSection->m_flSectionAltitudeCeiling = flAltMax;
  1122. nIndex++;
  1123. }
  1124. else
  1125. {
  1126. DevWarning( "Radar vertical section is invalid!\n" );
  1127. }
  1128. }
  1129. if ( m_vecRadarVerticalSections.Count() )
  1130. {
  1131. DevMsg( "Loaded radar vertical section keyvalues.\n" );
  1132. }
  1133. }
  1134. else
  1135. {
  1136. // map doesn't have sections, clear any sections from previous map
  1137. // TODO: Perhaps initialize a single giant vertical section that covers the whole map,
  1138. // to reduce variation in handling radar in downstream code?
  1139. m_vecRadarVerticalSections.Purge();
  1140. }
  1141. // TODO release old texture ?
  1142. m_MapOrigin.x = MapKeyValues->GetInt( "pos_x" );
  1143. m_MapOrigin.y = MapKeyValues->GetInt( "pos_y" );
  1144. m_MapOrigin.z = 0;
  1145. m_fWorldToPixelScale = 1.0f / MapKeyValues->GetFloat( "scale", 1.0f );
  1146. m_fWorldToRadarScale = m_fWorldToPixelScale * m_fPixelToRadarScale;
  1147. MapKeyValues->deleteThis();
  1148. }
  1149. void SFHudRadar::FlashLoadMap( const char* pMapName )
  1150. {
  1151. const char* pMapToLoad = pMapName ? pMapName : m_cDesiredMapName;
  1152. if ( V_strcmp( pMapToLoad, m_cLoadedMapName ) )
  1153. {
  1154. V_strcpy_safe( m_cDesiredMapName, pMapToLoad );
  1155. if ( m_bFlashReady )
  1156. {
  1157. if (!m_vecRadarVerticalSections.Count())
  1158. {
  1159. // Single map
  1160. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 1)
  1161. {
  1162. m_pScaleformUI->ValueArray_SetElement(args, 0, pMapToLoad);
  1163. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "loadMap", args, 1);
  1164. }
  1165. }
  1166. else
  1167. {
  1168. // Multiple map levels
  1169. int numArgs = m_vecRadarVerticalSections.Count() + 1;
  1170. WITH_SFVALUEARRAY_SLOT_LOCKED(args, numArgs)
  1171. {
  1172. m_pScaleformUI->ValueArray_SetElement(args, 0, pMapToLoad);
  1173. FOR_EACH_VEC(m_vecRadarVerticalSections, i)
  1174. {
  1175. m_pScaleformUI->ValueArray_SetElement(args, i + 1, m_vecRadarVerticalSections[i].m_szSectionName);
  1176. }
  1177. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "loadMap2", args, numArgs);
  1178. }
  1179. }
  1180. }
  1181. // Force current map layer to update
  1182. m_nCurrentRadarVerticalSection = -1;
  1183. }
  1184. }
  1185. void SFHudRadar::FlashUpdateMapLayer( int layerIdx )
  1186. {
  1187. if (m_bFlashReady)
  1188. {
  1189. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 1)
  1190. {
  1191. m_pScaleformUI->ValueArray_SetElement(args, 0, layerIdx);
  1192. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "setVisibleLayer", args, 1);
  1193. }
  1194. }
  1195. }
  1196. void SFHudRadar::MapLoaded( SCALEFORM_CALLBACK_ARGS_DECL )
  1197. {
  1198. // flash passes in the scaledsize / image size
  1199. m_fMapSize = 320; //radar_mapsize.GetInt();//( float )pui->Params_GetArgAsNumber( obj, 0 );
  1200. m_fPixelToRadarScale = ( float )pui->Params_GetArgAsNumber( obj, 0 );
  1201. m_fRadarSize = ( float )pui->Params_GetArgAsNumber( obj, 1 );
  1202. m_fWorldToRadarScale = m_fWorldToPixelScale * m_fPixelToRadarScale;
  1203. V_strcpy_safe( m_cLoadedMapName, m_cDesiredMapName );
  1204. }
  1205. /**********************************************
  1206. * reset functions
  1207. */
  1208. void SFHudRadar::ResetForNewMap( void )
  1209. {
  1210. if ( m_bFlashReady )
  1211. {
  1212. for ( int i = 0; i < 2; i++ )
  1213. {
  1214. m_pScaleformUI->Value_SetVisible( m_BombZoneIcons[i], false );
  1215. }
  1216. for ( int i = 0; i < MAX_HOSTAGE_RESCUES; i++ )
  1217. {
  1218. m_pScaleformUI->Value_SetVisible( m_HostageZoneIcons[i], false );
  1219. }
  1220. while( m_iLastHostageIndex >= 0 )
  1221. {
  1222. RemoveHostage( m_iLastHostageIndex );
  1223. }
  1224. int index = 0;
  1225. while( m_HostageStatusIcons[index].m_IconPackage && ( index < MAX_HOSTAGES ) )
  1226. {
  1227. m_HostageStatusIcons[index++].SetStatus( SFHudRadarHostageIcons::HI_UNUSED );
  1228. }
  1229. RemoveAllDecoys();
  1230. RemoveAllDefusers();
  1231. }
  1232. m_iNumGoalIcons = 0;
  1233. m_bGotGoalIcons = false;
  1234. for ( int i = 0; i <= m_iLastPlayerIndex; i++ )
  1235. {
  1236. ResetPlayer( i );
  1237. }
  1238. ResetRoundVariables();
  1239. }
  1240. void SFHudRadar::ResetRoundVariables( bool bResetGlobalStates )
  1241. {
  1242. SetVisibilityFlags( 0 );
  1243. SetLocationText( NULL );
  1244. m_RadarViewpointWorld = vec3_origin;
  1245. m_RadarViewpointMap = vec3_origin;
  1246. m_RadarRotation = 0;
  1247. m_fBombSeenTime = TIMER_INIT;
  1248. m_fBombAlpha = 0.0f;
  1249. m_fDefuserSeenTime = TIMER_INIT;
  1250. m_fDefuserAlpha = 0.0f;
  1251. m_bShowingHostageZone = false;
  1252. m_bShowBombHighlight = false;
  1253. m_bShowingDashboard = false;
  1254. m_bShowAll = false;
  1255. m_iObserverMode = OBS_MODE_NONE;
  1256. ConVarRef mp_defuser_allocation( "mp_defuser_allocation" );
  1257. m_bTrackDefusers = ( mp_defuser_allocation.GetInt() == DefuserAllocation::Random );
  1258. if ( bResetGlobalStates )
  1259. {
  1260. m_nBombEntIndex = -1;
  1261. m_nBombHolderUserId = -1;
  1262. m_BombPosition = vec3_origin;
  1263. m_DefuserPosition = vec3_origin;
  1264. m_bBombIsSpotted = false;
  1265. m_bBombPlanted = false;
  1266. m_bBombDropped = false;
  1267. m_bBombExploded = false;
  1268. m_bBombDefused = false;
  1269. }
  1270. m_EntitySpotted.ClearAll();
  1271. }
  1272. void SFHudRadar::ResetRadar( bool bResetGlobalStates )
  1273. {
  1274. for ( int i = 0; i <= m_iLastPlayerIndex; i++ )
  1275. {
  1276. ResetPlayer( i );
  1277. }
  1278. if ( CSGameRules()->IsHostageRescueMap() )
  1279. {
  1280. RemoveStaleHostages();
  1281. for ( int i = 0; i <= m_iLastHostageIndex; i++ )
  1282. {
  1283. ResetHostage( i );
  1284. }
  1285. int index = 0;
  1286. while( m_HostageStatusIcons[index].m_IconPackage && ( index < MAX_HOSTAGES ) )
  1287. {
  1288. m_HostageStatusIcons[index++].SetStatus( SFHudRadarHostageIcons::HI_UNUSED );
  1289. }
  1290. }
  1291. if ( bResetGlobalStates )
  1292. {
  1293. RemoveAllDecoys();
  1294. RemoveAllDefusers();
  1295. RemoveAllHostages();
  1296. }
  1297. ResetRoundVariables( bResetGlobalStates );
  1298. Show( true );
  1299. }
  1300. void SFHudRadar::ResetRound( void )
  1301. {
  1302. ResetRadar( true );
  1303. }
  1304. /*****************************************************
  1305. * player icon loading / creating
  1306. */
  1307. bool SFHudRadar::LazyUpdateIconArray( SFHudRadarIconPackage* pArray, int lastIndex )
  1308. {
  1309. bool result = true;
  1310. int i;
  1311. SFHudRadarIconPackage* pwalk;
  1312. for ( pwalk = pArray, i = 0; i <= lastIndex; i++, pwalk++ )
  1313. {
  1314. if ( pwalk->m_bIsActive && !pwalk->m_IconPackage )
  1315. {
  1316. if ( !LazyCreateIconPackage( pwalk ) )
  1317. {
  1318. // keep going, but remember that at least one wasn't loaded correctly
  1319. result = false;
  1320. }
  1321. }
  1322. }
  1323. return result;
  1324. }
  1325. void SFHudRadar::LazyCreatePlayerIcons( void )
  1326. {
  1327. if ( !m_bFlashReady || m_bGotPlayerIcons )
  1328. return;
  1329. // the following code looks odd, but it insures that all three of the LazyUpdate calls are made
  1330. // even if m_bGotPlayerIcons becomes false early.
  1331. m_bGotPlayerIcons = LazyUpdateIconArray( m_Players, m_iLastPlayerIndex );
  1332. m_bGotPlayerIcons = LazyUpdateIconArray( m_Hostages, m_iLastHostageIndex ) && m_bGotPlayerIcons;
  1333. m_bGotPlayerIcons = LazyUpdateIconArray( m_Decoys, m_iLastDecoyIndex ) && m_bGotPlayerIcons;
  1334. m_bGotPlayerIcons = LazyUpdateIconArray( m_Defusers, m_iLastDefuserIndex ) && m_bGotPlayerIcons;
  1335. }
  1336. bool SFHudRadar::LazyCreateIconPackage( SFHudRadarIconPackage* pIconPack )
  1337. {
  1338. if ( m_bFlashReady && pIconPack->m_bIsActive && !pIconPack->m_IconPackage )
  1339. {
  1340. SFVALUE result = NULL;
  1341. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 2 )
  1342. {
  1343. m_pScaleformUI->ValueArray_SetElement( args, 0, pIconPack->m_iIndex );
  1344. m_pScaleformUI->ValueArray_SetElement( args, 1, pIconPack->m_IconPackType );
  1345. result = m_pScaleformUI->Value_Invoke( m_IconTranslation, "createIconPack", args, 2 );
  1346. pIconPack->Init( m_pScaleformUI, result );
  1347. if ( result )
  1348. {
  1349. m_pScaleformUI->ReleaseValue( result );
  1350. }
  1351. }
  1352. return true;
  1353. }
  1354. else
  1355. {
  1356. return false;
  1357. }
  1358. }
  1359. void SFHudRadar::InitIconPackage( SFHudRadarIconPackage* pPlayer, int iAbsoluteIndex, ICON_PACK_TYPE iconType )
  1360. {
  1361. if ( pPlayer->m_bIsActive && m_pScaleformUI )
  1362. {
  1363. RemoveIconPackage( pPlayer );
  1364. }
  1365. pPlayer->m_IconPackType = iconType;
  1366. pPlayer->m_iIndex = iAbsoluteIndex;
  1367. pPlayer->m_bIsActive = true;
  1368. pPlayer->StartRound();
  1369. if ( !pPlayer->m_IconPackage && !LazyCreateIconPackage( pPlayer ) )
  1370. {
  1371. m_bGotPlayerIcons = false;
  1372. }
  1373. }
  1374. void SFHudRadar::RemoveIconPackage( SFHudRadarIconPackage* pPackage )
  1375. {
  1376. if ( pPackage->m_bIsActive && m_pScaleformUI )
  1377. {
  1378. if ( m_bFlashReady && pPackage->m_IconPackage )
  1379. {
  1380. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
  1381. {
  1382. m_pScaleformUI->ValueArray_SetElement( args, 0, pPackage->m_IconPackage );
  1383. m_pScaleformUI->Value_InvokeWithoutReturn( m_IconTranslation, "removeIconPack", args, 1 );
  1384. }
  1385. }
  1386. WITH_SLOT_LOCKED
  1387. {
  1388. pPackage->NukeFromOrbit( this );
  1389. }
  1390. }
  1391. }
  1392. /**********************************************
  1393. * player and hostage initialization and creation
  1394. */
  1395. void SFHudRadar::UpdateAllPlayerNumbers( void )
  1396. {
  1397. for ( int i = 0; i <= MAX_PLAYERS; ++i )
  1398. {
  1399. SFHudRadarIconPackage* pPackage = GetRadarPlayer( i );
  1400. if ( pPackage )
  1401. UpdatePlayerNumber( pPackage );
  1402. }
  1403. }
  1404. void SFHudRadar::UpdatePlayerNumber( SFHudRadarIconPackage* pPackage )
  1405. {
  1406. int nMaxPlayers = CCSGameRules::GetMaxPlayers();
  1407. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  1408. if ( !pLocalPlayer )
  1409. return;
  1410. bool bSpec = pLocalPlayer->IsSpectator() || engine->IsHLTV();
  1411. // update the player number
  1412. SFHudTeamCounter* pTeamCounter = GET_HUDELEMENT( SFHudTeamCounter );
  1413. if ( pPackage && pPackage->m_Icons[PI_PLAYER_NUMBER] )
  1414. {
  1415. if ( pTeamCounter )
  1416. {
  1417. int pidx = pTeamCounter->GetPlayerSlotIndex(pPackage->m_iEntityID);
  1418. if ( pidx != -1 )
  1419. {
  1420. if (bSpec)
  1421. {
  1422. pidx += 1;
  1423. if (pidx == 10)
  1424. pidx = 0;
  1425. ISFTextObject* textPanel = g_pScaleformUI->TextObject_MakeTextObjectFromMember(pPackage->m_Icons[PI_PLAYER_NUMBER], "Text");
  1426. if (textPanel)
  1427. {
  1428. WITH_SLOT_LOCKED
  1429. {
  1430. if (nMaxPlayers <= 10)
  1431. {
  1432. textPanel->SetText(pidx);
  1433. }
  1434. else
  1435. {
  1436. textPanel->SetText("");
  1437. }
  1438. }
  1439. SafeReleaseSFTextObject(textPanel);
  1440. }
  1441. }
  1442. else
  1443. {
  1444. bool bShowLetter = false;
  1445. if ((pPackage->m_fLastColorUpdate + 0.5f) < gpGlobals->curtime)
  1446. {
  1447. int nOtherTeamNum = 0;
  1448. if (pPackage->m_iPlayerType == PI_CT)
  1449. nOtherTeamNum = TEAM_CT;
  1450. else if (pPackage->m_iPlayerType == PI_T)
  1451. nOtherTeamNum = TEAM_TERRORIST;
  1452. int nColorID = -1;
  1453. if (pLocalPlayer->ShouldShowTeamPlayerColors(nOtherTeamNum))
  1454. {
  1455. C_CS_PlayerResource* pCSPR = ( C_CS_PlayerResource* )g_PR;
  1456. if ( pCSPR )
  1457. nColorID = pCSPR->GetCompTeammateColor( pPackage->m_iEntityID );
  1458. bShowLetter = pLocalPlayer->ShouldShowTeamPlayerColorLetters( );
  1459. }
  1460. WITH_SLOT_LOCKED
  1461. {
  1462. if (pPackage->m_iPlayerType == PI_CT && pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT)
  1463. {
  1464. // ScaleformDisplayInfo displayInfo;
  1465. // displayInfo.SetAlpha(100.0f);
  1466. // displayInfo.SetVisibility(1);
  1467. // m_pScaleformUI->Value_SetDisplayInfo(pPackage->m_IconPackage, &displayInfo);
  1468. SFVALUE doton = m_pScaleformUI->Value_GetMember(pPackage->m_Icons[PI_CT], "Dot");
  1469. SFVALUE dotoff = m_pScaleformUI->Value_GetMember(pPackage->m_Icons[PI_CT_OFFMAP], "Arrow");
  1470. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
  1471. {
  1472. m_pScaleformUI->ValueArray_SetElement(args, 0, doton);
  1473. m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
  1474. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
  1475. }
  1476. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
  1477. {
  1478. m_pScaleformUI->ValueArray_SetElement(args, 0, dotoff);
  1479. m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
  1480. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
  1481. }
  1482. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
  1483. {
  1484. m_pScaleformUI->ValueArray_SetElement(args, 0, pPackage->m_Icons[PI_CT_DEAD]);
  1485. m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
  1486. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
  1487. }
  1488. SafeReleaseSFVALUE(doton);
  1489. SafeReleaseSFVALUE(dotoff);
  1490. }
  1491. else if (pPackage->m_iPlayerType == PI_T && pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST)
  1492. {
  1493. if (pPackage->m_bIsDead == false && pPackage->m_Health > 0)
  1494. {
  1495. ScaleformDisplayInfo displayInfo;
  1496. displayInfo.SetAlpha(100.0f);
  1497. displayInfo.SetVisibility(1);
  1498. m_pScaleformUI->Value_SetDisplayInfo(pPackage->m_IconPackageRotate, &displayInfo);
  1499. //m_pScaleformUI->Value_SetDisplayInfo(pPackage->m_IconPackage, &displayInfo);
  1500. SFVALUE doton = m_pScaleformUI->Value_GetMember(pPackage->m_Icons[PI_T], "Dot");
  1501. SFVALUE dotoff = m_pScaleformUI->Value_GetMember(pPackage->m_Icons[PI_T_OFFMAP], "Arrow");
  1502. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
  1503. {
  1504. //m_pScaleformUI->Value_SetDisplayInfo(pPackage->m_Icons[PI_T], &displayInfo);
  1505. m_pScaleformUI->ValueArray_SetElement(args, 0, doton);
  1506. m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
  1507. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
  1508. }
  1509. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
  1510. {
  1511. m_pScaleformUI->ValueArray_SetElement(args, 0, dotoff);
  1512. m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
  1513. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
  1514. }
  1515. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
  1516. {
  1517. m_pScaleformUI->ValueArray_SetElement(args, 0, pPackage->m_Icons[PI_T_DEAD]);
  1518. m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
  1519. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
  1520. }
  1521. SafeReleaseSFVALUE(doton);
  1522. SafeReleaseSFVALUE(dotoff);
  1523. }
  1524. }
  1525. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 2 )
  1526. {
  1527. m_pScaleformUI->ValueArray_SetElement( args, 0, pPackage->m_Icons[PI_PLAYER_LETTER] );
  1528. m_pScaleformUI->ValueArray_SetElement( args, 1, bShowLetter ? nColorID : -1 );
  1529. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SetPlayerColorLetter", args, 2 );
  1530. }
  1531. // decide if the target shows the symbol
  1532. // make sure they're no the other team
  1533. if ( pPackage->m_iPlayerType == PI_ENEMY && Helper_ShouldShowAssassinationTargetIcon( pPackage->m_iEntityID ) )
  1534. {
  1535. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 2 )
  1536. {
  1537. // unique number for targets for missions
  1538. int nSpecialTargetID = 10;
  1539. m_pScaleformUI->ValueArray_SetElement( args, 0, pPackage->m_Icons[PI_PLAYER_LETTER] );
  1540. m_pScaleformUI->ValueArray_SetElement( args, 1, nSpecialTargetID );
  1541. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SetPlayerColorLetter", args, 2 );
  1542. }
  1543. }
  1544. }
  1545. pPackage->m_fLastColorUpdate = gpGlobals->curtime;
  1546. }
  1547. }
  1548. }
  1549. }
  1550. }
  1551. }
  1552. SFHudRadar::SFHudRadarIconPackage* SFHudRadar::CreatePlayer( int index )
  1553. {
  1554. SFHudRadarIconPackage* pPackage = GetRadarPlayer( index );
  1555. InitIconPackage( pPackage, index, ICON_PACK_PLAYER );
  1556. m_iLastPlayerIndex = MAX( index, m_iLastPlayerIndex );
  1557. return pPackage;
  1558. }
  1559. void SFHudRadar::ResetPlayer( int index )
  1560. {
  1561. SFHudRadarIconPackage* pPackage = GetRadarPlayer( index );
  1562. if ( pPackage->m_bIsActive )
  1563. {
  1564. pPackage->StartRound();
  1565. UpdatePlayerNumber( pPackage );
  1566. }
  1567. }
  1568. void SFHudRadar::RemovePlayer( int index )
  1569. {
  1570. RemoveIconPackage( GetRadarPlayer( index ) );
  1571. if ( index == m_iLastPlayerIndex )
  1572. {
  1573. while( m_iLastPlayerIndex >= 0 && !m_Players[m_iLastPlayerIndex].m_bIsActive )
  1574. {
  1575. m_iLastPlayerIndex--;
  1576. }
  1577. }
  1578. UpdateAllPlayerNumbers();
  1579. }
  1580. SFHudRadar::SFHudRadarIconPackage* SFHudRadar::CreateHostage( int index )
  1581. {
  1582. SFHudRadarIconPackage* pPackage = GetRadarHostage( index );
  1583. InitIconPackage( pPackage, index, ICON_PACK_HOSTAGE );
  1584. m_iLastHostageIndex = MAX( index, m_iLastHostageIndex );
  1585. return pPackage;
  1586. }
  1587. void SFHudRadar::ResetHostage( int index )
  1588. {
  1589. SFHudRadarIconPackage* pPackage = GetRadarHostage( index );
  1590. if ( pPackage->m_bIsActive )
  1591. {
  1592. pPackage->StartRound();
  1593. }
  1594. }
  1595. void SFHudRadar::RemoveAllHostages( void )
  1596. {
  1597. for ( int index = 0; index < MAX_HOSTAGES; index++ )
  1598. {
  1599. RemoveHostage( index );
  1600. }
  1601. }
  1602. void SFHudRadar::RemoveStaleHostages( void )
  1603. {
  1604. // Remove hostages that are no longer tracked by the player resource (hostages that have died)
  1605. C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
  1606. if ( !pCSPR )
  1607. {
  1608. return;
  1609. }
  1610. for ( int index = 0; index < MAX_HOSTAGES; index++ )
  1611. {
  1612. SFHudRadarIconPackage* pPackage = GetRadarHostage( index );
  1613. if ( pPackage->m_bIsActive )
  1614. {
  1615. bool bRemove = true;
  1616. for( int i = 0; i < MAX_HOSTAGES; i++ )
  1617. {
  1618. if ( pCSPR->GetHostageEntityID( i ) == pPackage->m_iEntityID )
  1619. {
  1620. bRemove = false;
  1621. break;
  1622. }
  1623. }
  1624. if ( bRemove )
  1625. {
  1626. RemoveHostage( index );
  1627. }
  1628. }
  1629. }
  1630. }
  1631. void SFHudRadar::RemoveHostage( int index )
  1632. {
  1633. RemoveIconPackage( GetRadarHostage( index ) );
  1634. if ( index == m_iLastHostageIndex )
  1635. {
  1636. while( m_iLastHostageIndex >= 0 && !m_Hostages[m_iLastHostageIndex].m_bIsActive )
  1637. {
  1638. m_iLastHostageIndex--;
  1639. }
  1640. }
  1641. }
  1642. SFHudRadar::SFHudRadarIconPackage* SFHudRadar::CreateDecoy( int entityID )
  1643. {
  1644. SFHudRadarIconPackage* pPackage = NULL;
  1645. int index = m_iLastDecoyIndex+1;
  1646. for ( int i = 0; i <= m_iLastDecoyIndex; i++ )
  1647. {
  1648. if ( !m_Decoys[i].m_bIsActive )
  1649. {
  1650. index = i;
  1651. break;
  1652. }
  1653. }
  1654. if ( index < MAX_DECOYS )
  1655. {
  1656. pPackage = GetRadarDecoy( index );
  1657. InitIconPackage( pPackage, index, ICON_PACK_DECOY );
  1658. pPackage->m_iEntityID = entityID;
  1659. pPackage->m_fRoundStartTime = TIMER_INIT;
  1660. m_iLastDecoyIndex = MAX( index, m_iLastDecoyIndex );
  1661. }
  1662. return pPackage;
  1663. }
  1664. void SFHudRadar::RemoveAllDecoys( void )
  1665. {
  1666. for ( int i = 0; i <= m_iLastDecoyIndex; i++ )
  1667. {
  1668. if ( m_Decoys[i].m_bIsActive )
  1669. {
  1670. RemoveDecoy( i );
  1671. }
  1672. }
  1673. }
  1674. void SFHudRadar::RemoveDecoy( int index )
  1675. {
  1676. RemoveIconPackage( GetRadarDecoy( index ) );
  1677. if ( index == m_iLastDecoyIndex )
  1678. {
  1679. while( m_iLastDecoyIndex >= 0 && !m_Decoys[m_iLastDecoyIndex].m_bIsActive )
  1680. {
  1681. m_iLastDecoyIndex--;
  1682. }
  1683. }
  1684. }
  1685. SFHudRadar::SFHudRadarIconPackage * SFHudRadar::GetDefuser( int nEntityID, bool bCreateIfNotFound )
  1686. {
  1687. SFHudRadarIconPackage * pResult = NULL;
  1688. int nIndex = GetDefuseIndexFromEntityID( nEntityID );
  1689. if ( nIndex != INVALID_INDEX )
  1690. {
  1691. pResult = GetRadarDefuser( nIndex );
  1692. }
  1693. if ( pResult == NULL && bCreateIfNotFound )
  1694. {
  1695. pResult = CreateDefuser( nEntityID );
  1696. }
  1697. return pResult;
  1698. }
  1699. void SFHudRadar::SetDefuserPos( int nEntityID, int x, int y, int z, int a )
  1700. {
  1701. if ( !m_bTrackDefusers )
  1702. {
  1703. return;
  1704. }
  1705. SFHudRadarIconPackage * pDefuser = GetDefuser( nEntityID, true );
  1706. AssertMsg( pDefuser != NULL, "Defuser not found. Update failed." );
  1707. if ( pDefuser )
  1708. {
  1709. pDefuser->m_Position.Init( x, y, z ) ;
  1710. pDefuser->SetAlpha( 1.0f );
  1711. SetIconPackagePosition( pDefuser );
  1712. }
  1713. }
  1714. // defusers attached to players will update during the PlacePlayer phase
  1715. SFHudRadar::SFHudRadarIconPackage* SFHudRadar::CreateDefuser( int nEntityID )
  1716. {
  1717. if ( !m_bTrackDefusers )
  1718. {
  1719. return NULL;
  1720. }
  1721. SFHudRadarIconPackage* pPackage = NULL;
  1722. int index = m_iLastDefuserIndex+1;
  1723. AssertMsg( GetDefuseIndexFromEntityID( nEntityID ) == INVALID_INDEX, "Defuser entity ID already exists." );
  1724. for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
  1725. {
  1726. if ( !m_Defusers[i].m_bIsActive )
  1727. {
  1728. index = i;
  1729. break;
  1730. }
  1731. }
  1732. if ( index < MAX_PLAYERS )
  1733. {
  1734. pPackage = GetRadarDefuser( index );
  1735. InitIconPackage( pPackage, index, ICON_PACK_DEFUSER );
  1736. pPackage->m_iEntityID = nEntityID;
  1737. pPackage->m_fRoundStartTime = TIMER_INIT;
  1738. pPackage->SetIsSpotted( false );
  1739. pPackage->SetIsDefuse( true );
  1740. pPackage->m_Position = vec3_origin;
  1741. m_iLastDefuserIndex = MAX( index, m_iLastDefuserIndex );
  1742. }
  1743. else
  1744. {
  1745. AssertMsg( false, "m_Defusers array is full" );
  1746. }
  1747. return pPackage;
  1748. }
  1749. void SFHudRadar::RemoveAllDefusers( void )
  1750. {
  1751. for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
  1752. {
  1753. if ( m_Defusers[i].m_bIsActive )
  1754. {
  1755. RemoveDefuser( i );
  1756. }
  1757. }
  1758. }
  1759. void SFHudRadar::RemoveDefuser( int index )
  1760. {
  1761. RemoveIconPackage( GetRadarDefuser( index ) );
  1762. if ( index == m_iLastDefuserIndex )
  1763. {
  1764. while( m_iLastDefuserIndex >= 0 && !m_Defusers[m_iLastDefuserIndex].m_bIsActive )
  1765. {
  1766. m_iLastDefuserIndex--;
  1767. }
  1768. }
  1769. }
  1770. void SFHudRadar::SetPlayerTeam( int index, int team )
  1771. {
  1772. SFHudRadarIconPackage* pPlayer = GetRadarPlayer( index );
  1773. pPlayer->SetPlayerTeam( team );
  1774. }
  1775. int SFHudRadar::GetPlayerIndexFromUserID( int userID )
  1776. {
  1777. int nEntityID = engine->GetPlayerForUserID( userID );
  1778. for ( int i = 0; i <= m_iLastPlayerIndex; i++ )
  1779. {
  1780. if ( m_Players[i].m_bIsActive && m_Players[i].m_iEntityID == nEntityID )
  1781. {
  1782. return i;
  1783. }
  1784. }
  1785. return INVALID_INDEX;
  1786. }
  1787. int SFHudRadar::GetHostageIndexFromHostageEntityID( int entityID )
  1788. {
  1789. for ( int i = 0; i <= m_iLastHostageIndex; i++ )
  1790. {
  1791. if ( m_Hostages[i].m_bIsActive && m_Hostages[i].m_iEntityID == entityID )
  1792. {
  1793. return i;
  1794. }
  1795. }
  1796. return INVALID_INDEX;
  1797. }
  1798. int SFHudRadar::GetDecoyIndexFromEntityID( int entityID )
  1799. {
  1800. for ( int i = 0; i <= m_iLastDecoyIndex; i++ )
  1801. {
  1802. if ( m_Decoys[i].m_bIsActive && m_Decoys[i].m_iEntityID == entityID )
  1803. {
  1804. return i;
  1805. }
  1806. }
  1807. return INVALID_INDEX;
  1808. }
  1809. int SFHudRadar::GetDefuseIndexFromEntityID( int nEntityID )
  1810. {
  1811. for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
  1812. {
  1813. if ( m_Defusers[i].m_bIsActive && m_Defusers[i].m_iEntityID == nEntityID )
  1814. {
  1815. return i;
  1816. }
  1817. }
  1818. return INVALID_INDEX;
  1819. }
  1820. SFHudRadar::SFHudRadarIconPackage* SFHudRadar::GetRadarPlayer( int index )
  1821. {
  1822. return &m_Players[index];
  1823. }
  1824. SFHudRadar::SFHudRadarIconPackage* SFHudRadar::GetRadarHostage( int index )
  1825. {
  1826. return &m_Hostages[index];
  1827. }
  1828. SFHudRadar::SFHudRadarIconPackage* SFHudRadar::GetRadarDecoy( int index )
  1829. {
  1830. return &m_Decoys[index];
  1831. }
  1832. SFHudRadar::SFHudRadarIconPackage* SFHudRadar::GetRadarDefuser( int index )
  1833. {
  1834. return &m_Defusers[index];
  1835. }
  1836. /*************************************************
  1837. * We don't get updates from the server from players
  1838. * that are not in our PVS, so there are separate
  1839. * messages specifically to update the radar
  1840. */
  1841. bool SFHudRadar::MsgFunc_ProcessSpottedEntityUpdate( const CCSUsrMsg_ProcessSpottedEntityUpdate &msg )
  1842. {
  1843. if ( msg.new_update() )
  1844. {
  1845. // new spotting frame. clean up.
  1846. m_bBombIsSpotted = false;
  1847. m_EntitySpotted.ClearAll();
  1848. }
  1849. for ( int i = 0; i < msg.entity_updates_size(); i ++ )
  1850. {
  1851. const CCSUsrMsg_ProcessSpottedEntityUpdate::SpottedEntityUpdate &update = msg.entity_updates(i);
  1852. int nEntityID = update.entity_idx();
  1853. if ( nEntityID < 0 || nEntityID >= MAX_EDICTS )
  1854. continue; // GeekPwn2016 range check
  1855. // non-class specific data
  1856. // read position and angle
  1857. int x = update.origin_x() * 4;
  1858. int y = update.origin_y() * 4;
  1859. int z = update.origin_z() * 4;
  1860. int a = update.angle_y();
  1861. m_EntitySpotted.Set( nEntityID, true );
  1862. const char * szEntityClass = NULL;
  1863. int nClassID = update.class_id();
  1864. for ( ClientClass *pCur = g_pClientClassHead; pCur; pCur=pCur->m_pNext )
  1865. {
  1866. if ( pCur->m_ClassID == nClassID )
  1867. {
  1868. szEntityClass = pCur->GetName();
  1869. break;
  1870. }
  1871. }
  1872. if ( szEntityClass == NULL )
  1873. {
  1874. Warning( "Unknown entity class received in ProcessSpottedEntityUpdate.\n" );
  1875. }
  1876. // Clients are unaware of the defuser class type, so we need to flag defuse entities manually
  1877. if ( update.defuser() )
  1878. {
  1879. SetDefuserPos( nEntityID, x, y, z, a );
  1880. }
  1881. else if ( V_strcmp( "CCSPlayer", szEntityClass ) == 0 )
  1882. {
  1883. SFHudRadarIconPackage* pPlayerIcon = NULL;
  1884. pPlayerIcon = GetRadarPlayer( nEntityID - 1 );
  1885. if ( pPlayerIcon->m_bIsDead )
  1886. continue;
  1887. pPlayerIcon->m_Position.Init( x, y, z );
  1888. pPlayerIcon->m_Angle.Init( 0, a, 0 );
  1889. // has defuser?
  1890. if ( update.player_has_defuser() )
  1891. {
  1892. SetDefuserPos( nEntityID, x, y, z, a );
  1893. }
  1894. // has C4?
  1895. if ( update.player_has_c4() )
  1896. {
  1897. m_bBombIsSpotted = true;
  1898. m_BombPosition.Init( x, y, 0 );
  1899. }
  1900. // The following code should no longer be necessary with the new spotting system
  1901. //C_CSPlayer *pPlayer = ToCSPlayer( UTIL_PlayerByIndex( nEntityID ) );
  1902. //// Only update players that are outside of PVS
  1903. //if ( pPlayer && pPlayer->IsDormant() )
  1904. //{
  1905. // // update origin and angle for players out of my PVS
  1906. // Vector origin = pPlayer->GetAbsOrigin();
  1907. // QAngle angles = pPlayer->GetAbsAngles();
  1908. // origin.x = x;
  1909. // origin.y = y;
  1910. // angles.y = a;
  1911. // pPlayer->SetAbsOrigin( origin );
  1912. // pPlayer->SetAbsAngles( angles );
  1913. //}
  1914. }
  1915. else if ( V_strcmp( "CC4", szEntityClass ) == 0 || V_strcmp( "CPlantedC4", szEntityClass ) == 0 )
  1916. {
  1917. m_bBombIsSpotted = true;
  1918. m_BombPosition.Init( x, y, 0 );
  1919. }
  1920. else if ( V_strcmp( "CHostage", szEntityClass ) == 0 )
  1921. {
  1922. int hostageIndex = GetHostageIndexFromHostageEntityID( nEntityID );
  1923. if ( hostageIndex == INVALID_INDEX )
  1924. {
  1925. for ( int i = 0; i <= m_iLastHostageIndex; i++ )
  1926. {
  1927. RemoveHostage( i );
  1928. }
  1929. }
  1930. else
  1931. {
  1932. SFHudRadarIconPackage* pPackage = GetRadarHostage( hostageIndex );
  1933. if ( pPackage )
  1934. {
  1935. pPackage->m_Position.Init( x, y, z );
  1936. }
  1937. }
  1938. }
  1939. else
  1940. {
  1941. Warning( "Unknown entity update received by ProcessSpottedEntityUpdate: %s.\n", szEntityClass );
  1942. }
  1943. }
  1944. return true;
  1945. }
  1946. // handles all game event messages ( first looks them up in map so there's no long list of strcmps )
  1947. void SFHudRadar::FireGameEvent( IGameEvent *event )
  1948. {
  1949. const char* eventName = event->GetName();
  1950. int elementIndex = m_messageMap.Find( eventName );
  1951. if ( elementIndex == m_messageMap.InvalidIndex() )
  1952. {
  1953. return;
  1954. }
  1955. SF_SPLITSCREEN_PLAYER_GUARD();
  1956. DESIRED_MESSAGE_INDICES messageTypeIndex = ( DESIRED_MESSAGE_INDICES )m_messageMap.Element( elementIndex );
  1957. switch( messageTypeIndex )
  1958. {
  1959. case GAME_NEWMAP:
  1960. ResetForNewMap();
  1961. SetMap( event->GetString( "mapname" ) );
  1962. break;
  1963. case ROUND_POST_START:
  1964. {
  1965. ResetRound();
  1966. UpdateAllPlayerNumbers();
  1967. }
  1968. break;
  1969. case PLAYER_CONNECT:
  1970. case PLAYER_INFO:
  1971. {
  1972. int index = event->GetInt( "index" ); // = entity index - 1
  1973. int userID = index + 1;
  1974. if ( index < 0 || index >= MAX_PLAYERS )
  1975. {
  1976. return;
  1977. }
  1978. SFHudRadarIconPackage* pPackage = CreatePlayer( index );
  1979. if ( messageTypeIndex == PLAYER_CONNECT )
  1980. {
  1981. pPackage->SetPlayerTeam( TEAM_SPECTATOR );
  1982. }
  1983. pPackage->m_iEntityID = userID;
  1984. const char* name = event->GetString( "name","unknown" );
  1985. V_UTF8ToUnicode( name, pPackage->m_wcName, sizeof( pPackage->m_wcName ) );
  1986. }
  1987. break;
  1988. case PLAYER_TEAM:
  1989. {
  1990. int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
  1991. if ( playerIndex == INVALID_INDEX )
  1992. {
  1993. return;
  1994. }
  1995. SFHudRadarIconPackage* pPackage = GetRadarPlayer( playerIndex );
  1996. pPackage->SetPlayerTeam( event->GetInt( "team" ) );
  1997. UpdatePlayerNumber( pPackage );
  1998. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  1999. if ( pLocalPlayer )
  2000. {
  2001. int localID = pLocalPlayer->GetUserID();
  2002. if ( localID == playerIndex )
  2003. {
  2004. ResizeHud();
  2005. }
  2006. }
  2007. }
  2008. break;
  2009. case PLAYER_DEATH:
  2010. {
  2011. int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
  2012. if ( playerIndex == INVALID_INDEX )
  2013. {
  2014. return;
  2015. }
  2016. SFHudRadarIconPackage* pPackage = GetRadarPlayer( playerIndex );
  2017. if ( pPackage->m_bIsActive )
  2018. {
  2019. pPackage->SetIsDead( true );
  2020. pPackage->m_Health = 0;
  2021. }
  2022. int nDefuseIndex = GetDefuseIndexFromEntityID( engine->GetPlayerForUserID( event->GetInt( "userid" ) ) );
  2023. if ( nDefuseIndex != INVALID_INDEX )
  2024. {
  2025. RemoveDefuser( nDefuseIndex );
  2026. }
  2027. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  2028. if ( pLocalPlayer )
  2029. {
  2030. int localID = pLocalPlayer->GetUserID();
  2031. if ( localID == playerIndex )
  2032. {
  2033. ResizeHud();
  2034. }
  2035. }
  2036. }
  2037. break;
  2038. case PLAYER_SPAWN:
  2039. {
  2040. int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
  2041. if ( playerIndex != INVALID_INDEX )
  2042. {
  2043. SFHudRadarIconPackage* pPackage = GetRadarPlayer( playerIndex );
  2044. pPackage->m_Health = 100;
  2045. UpdatePlayerNumber( pPackage );
  2046. }
  2047. }
  2048. break;
  2049. case PLAYER_DISCONNECT:
  2050. {
  2051. int playerIndex = GetPlayerIndexFromUserID( event->GetInt( "userid" ) );
  2052. if ( playerIndex != INVALID_INDEX )
  2053. {
  2054. RemovePlayer( playerIndex );
  2055. }
  2056. }
  2057. break;
  2058. case HOSTAGE_KILLED:
  2059. {
  2060. int hostageIndex = GetHostageIndexFromHostageEntityID( event->GetInt( "hostage" ) );
  2061. if ( hostageIndex == INVALID_INDEX )
  2062. {
  2063. return;
  2064. }
  2065. SFHudRadarIconPackage* pPackage = GetRadarHostage( hostageIndex );
  2066. if ( pPackage->m_bIsActive )
  2067. {
  2068. pPackage->SetIsDead( true );
  2069. }
  2070. }
  2071. break;
  2072. case HOSTAGE_RESCUED:
  2073. {
  2074. int hostageIndex = GetHostageIndexFromHostageEntityID( event->GetInt( "hostage" ) );
  2075. if ( hostageIndex == INVALID_INDEX )
  2076. {
  2077. return;
  2078. }
  2079. SFHudRadarIconPackage* pPackage = GetRadarHostage( hostageIndex );
  2080. if ( pPackage->m_bIsActive )
  2081. {
  2082. pPackage->SetIsRescued( true );
  2083. }
  2084. }
  2085. break;
  2086. case BOMB_DEFUSED:
  2087. {
  2088. m_bBombDefused = true;
  2089. }
  2090. break;
  2091. case BOMB_EXPLODED:
  2092. {
  2093. m_bBombExploded = true;
  2094. }
  2095. break;
  2096. case BOMB_PLANTED:
  2097. {
  2098. m_nBombEntIndex = -1;
  2099. m_bBombPlanted = true;
  2100. m_BombPosition.z = 0;
  2101. m_nBombHolderUserId = -1;
  2102. }
  2103. break;
  2104. case BOMB_PICKUP:
  2105. {
  2106. m_bBombDropped = false;
  2107. m_nBombEntIndex = -1;
  2108. m_nBombHolderUserId = event->GetInt( "userid", -1 );
  2109. }
  2110. break;
  2111. case BOMB_DROPPED:
  2112. {
  2113. m_nBombEntIndex = event->GetInt( "entindex", -1 );
  2114. m_bBombDropped = true;
  2115. m_nBombHolderUserId = -1;
  2116. }
  2117. break;
  2118. case DEFUSER_PICKUP:
  2119. {
  2120. int nDefuseIndex = GetDefuseIndexFromEntityID( event->GetInt( "entityid" ) );
  2121. if ( nDefuseIndex != INVALID_INDEX )
  2122. {
  2123. RemoveDefuser( nDefuseIndex );
  2124. }
  2125. }
  2126. break;
  2127. case DEFUSER_DROPPED:
  2128. {
  2129. int nEntityID = event->GetInt( "entityid" );
  2130. CreateDefuser( nEntityID );
  2131. }
  2132. break;
  2133. case DECOY_STARTED:
  2134. {
  2135. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  2136. if ( pLocalPlayer )
  2137. {
  2138. int userID = event->GetInt( "userid" );
  2139. CBasePlayer* player = UTIL_PlayerByUserId( userID );
  2140. if ( player )
  2141. {
  2142. // the radar only shows the enemy decoys
  2143. if ( pLocalPlayer->IsOtherEnemy( player->entindex() ) )
  2144. {
  2145. int entityID = event->GetInt( "entityid" );
  2146. int teamNumber = player->GetAssociatedTeamNumber();
  2147. SFHudRadarIconPackage* pPackage = CreateDecoy( entityID );
  2148. if ( pPackage )
  2149. {
  2150. pPackage->SetPlayerTeam( teamNumber );
  2151. pPackage->SetIsSpotted( true );
  2152. // this sets the exact moment when the grenade should no longer be visible incase we miss the event
  2153. pPackage->SetGrenadeExpireTime( gpGlobals->curtime + 24 );
  2154. pPackage->m_Position.Init( ( float )event->GetInt( "x" ), ( float )event->GetInt( "y" ), 0.0f );
  2155. pPackage->m_Angle.Init( 0.0f, RandomFloat( 0.0f, 360.0f ), 0.0f );
  2156. SetIconPackagePosition( pPackage );
  2157. }
  2158. }
  2159. }
  2160. }
  2161. }
  2162. break;
  2163. case DECOY_DETONATE:
  2164. {
  2165. int entityID = event->GetInt( "entityid" );
  2166. int i = GetDecoyIndexFromEntityID( entityID );
  2167. if ( i != INVALID_INDEX )
  2168. {
  2169. SFHudRadarIconPackage* pPackage = GetRadarDecoy( i );
  2170. pPackage->SetIsSpotted( false );
  2171. SetIconPackagePosition( pPackage );
  2172. }
  2173. STEAMWORKS_TESTSECRET_AMORTIZE( 31 );
  2174. }
  2175. break;
  2176. case BOT_TAKEOVER:
  2177. {
  2178. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  2179. if ( pLocalPlayer )
  2180. {
  2181. int userID = event->GetInt( "userid" );
  2182. //int playerIndex = GetPlayerIndexFromUserID(event->GetInt("userid"));
  2183. int localID = pLocalPlayer->GetUserID();
  2184. if (localID == userID )
  2185. {
  2186. ResizeHud();
  2187. ResetRadar( false );
  2188. int playerIndex = GetPlayerIndexFromUserID(userID);
  2189. if (playerIndex != INVALID_INDEX)
  2190. {
  2191. SFHudRadarIconPackage* pPackage = GetRadarPlayer(playerIndex);
  2192. UpdatePlayerNumber(pPackage);
  2193. }
  2194. }
  2195. }
  2196. }
  2197. break;
  2198. default:
  2199. break;
  2200. }
  2201. }
  2202. /*****************************************************
  2203. * these set lazy update the icons and text based
  2204. * on the values in the state variables
  2205. */
  2206. void SFHudRadar::SetupIconsFromStates( void )
  2207. {
  2208. int newFlags = 0;
  2209. if ( CSGameRules()->IsBombDefuseMap() )
  2210. {
  2211. if ( m_fBombAlpha > 0.0f )
  2212. {
  2213. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  2214. newFlags |= 1 << RI_BOMB_ICON_PACKAGE;
  2215. if ( m_bShowBombHighlight )
  2216. {
  2217. if ( m_bBombPlanted )
  2218. {
  2219. newFlags |= 1 << RI_BOMB_ICON_PLANTED;
  2220. }
  2221. else
  2222. {
  2223. newFlags |= 1 << RI_BOMB_ICON_DROPPED;
  2224. }
  2225. C_CSPlayer *pLocalOrObserver = NULL;
  2226. if ( pLocalPlayer )
  2227. {
  2228. C_BaseEntity *target = pLocalPlayer->GetObserverTarget();
  2229. if( target && target->IsPlayer() )
  2230. pLocalOrObserver = ToCSPlayer( target );
  2231. else
  2232. pLocalOrObserver = pLocalPlayer;
  2233. }
  2234. if ( pLocalOrObserver )
  2235. {
  2236. if ( m_BombPosition.z > pLocalOrObserver->GetAbsOrigin().z + ABOVE_BELOW_HEIGHT )
  2237. newFlags |= 1 << RI_BOMB_ICON_BOMB_ABOVE;
  2238. else if ( m_BombPosition.z < pLocalOrObserver->GetAbsOrigin().z - ABOVE_BELOW_HEIGHT )
  2239. newFlags |= 1 << RI_BOMB_ICON_BOMB_BELOW;
  2240. }
  2241. }
  2242. if( pLocalPlayer != NULL )
  2243. {
  2244. if ( pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST )
  2245. {
  2246. newFlags |= 1 << RI_BOMB_ICON_BOMB_T;
  2247. }
  2248. else
  2249. {
  2250. newFlags |= 1 << RI_BOMB_ICON_BOMB_CT;
  2251. }
  2252. }
  2253. Vector mapPosition;
  2254. WorldToRadar( m_BombPosition, mapPosition );
  2255. Vector newMapPosition = mapPosition;
  2256. newMapPosition -= m_RadarViewpointMap;
  2257. float dist = newMapPosition.LengthSqr();
  2258. if ( dist >= RADARRADIUS*RADARRADIUS && m_bRound )
  2259. {
  2260. newMapPosition *= sqrt( RADARRADIUS*RADARRADIUS/dist );
  2261. mapPosition = m_RadarViewpointMap;
  2262. mapPosition += newMapPosition;
  2263. }
  2264. ScaleformDisplayInfo displayInfo;
  2265. displayInfo.SetAlpha( m_fBombAlpha * 100.0f );
  2266. if ( cl_radar_fast_transforms.GetBool() )
  2267. {
  2268. Vector hudPos;
  2269. RadarToHud( mapPosition, hudPos );
  2270. displayInfo.SetX( hudPos.x );
  2271. displayInfo.SetY( hudPos.y );
  2272. displayInfo.SetRotation( 0 );
  2273. }
  2274. else
  2275. {
  2276. displayInfo.SetX( mapPosition.x );
  2277. displayInfo.SetY( mapPosition.y );
  2278. bool bRotate = m_bRound ? cl_radar_rotate.GetBool() : false;
  2279. displayInfo.SetRotation( bRotate ? -m_RadarRotation : 0 );
  2280. }
  2281. assert( m_Icons[RI_BOMB_ICON_PACKAGE] );
  2282. m_pScaleformUI->Value_SetDisplayInfo( m_Icons[RI_BOMB_ICON_PACKAGE], &displayInfo );
  2283. SFHudTeamCounter* pTeamCounter = GET_HUDELEMENT( SFHudTeamCounter );
  2284. if (pLocalPlayer && pTeamCounter && m_Icons[RI_BOMB_ICON_PACKAGE])
  2285. {
  2286. int playerIndex = GetPlayerIndexFromUserID( m_nBombHolderUserId ) + 1;
  2287. int pidx = pTeamCounter->GetPlayerSlotIndex( playerIndex );
  2288. int nColorID = 4;
  2289. if (pLocalPlayer->ShouldShowTeamPlayerColors(pLocalPlayer->GetAssociatedTeamNumber()))
  2290. {
  2291. C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
  2292. if ( m_bBombDropped == false && ( pidx > -1 ) && pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST )
  2293. {
  2294. if ( pCSPR )
  2295. nColorID = pCSPR->GetCompTeammateColor( playerIndex );
  2296. }
  2297. else
  2298. nColorID = -1;
  2299. }
  2300. SFVALUE bomb = m_pScaleformUI->Value_GetMember(m_Icons[RI_BOMB_ICON_PACKAGE], "BombT");
  2301. if (bomb)
  2302. {
  2303. SFVALUE bombinner = m_pScaleformUI->Value_GetMember(bomb, "bomb_inner");
  2304. WITH_SFVALUEARRAY_SLOT_LOCKED(args, 2)
  2305. {
  2306. m_pScaleformUI->ValueArray_SetElement(args, 0, bombinner);
  2307. m_pScaleformUI->ValueArray_SetElement(args, 1, nColorID);
  2308. m_pScaleformUI->Value_InvokeWithoutReturn(m_FlashAPI, "SetPlayerObjectColor", args, 2);
  2309. }
  2310. SafeReleaseSFVALUE(bombinner);
  2311. }
  2312. SafeReleaseSFVALUE(bomb);
  2313. }
  2314. }
  2315. }
  2316. else if ( CSGameRules()->IsHostageRescueMap() )
  2317. {
  2318. if ( m_bShowingHostageZone )
  2319. {
  2320. newFlags |= 1 << RI_IN_HOSTAGE_ZONE;
  2321. }
  2322. }
  2323. if ( m_bShowingDashboard )
  2324. newFlags |= 1 << RI_DASHBOARD;
  2325. SetVisibilityFlags( newFlags );
  2326. }
  2327. void SFHudRadar::SetVisibilityFlags( int newFlags )
  2328. {
  2329. newFlags &= ( ( 1 << RI_NUM_ICONS )-1 );
  2330. int diffFlags = m_iCurrentVisibilityFlags ^ newFlags;
  2331. if ( diffFlags )
  2332. {
  2333. for ( int i = 0; i < RI_NUM_ICONS && ( diffFlags != 0 ); i++, diffFlags >>= 1 )
  2334. {
  2335. if ( diffFlags & 1 )
  2336. {
  2337. if ( m_Icons[i] )
  2338. m_pScaleformUI->Value_SetVisible( m_Icons[i], ( newFlags & ( 1 << i ) ) != 0 );
  2339. }
  2340. }
  2341. m_iCurrentVisibilityFlags = newFlags;
  2342. }
  2343. }
  2344. void SFHudRadar::SetLocationText( wchar_t *newText )
  2345. {
  2346. if ( newText == NULL )
  2347. {
  2348. newText = L"";
  2349. }
  2350. if ( V_wcscmp( newText, m_wcLocationString ) )
  2351. {
  2352. V_wcsncpy( m_wcLocationString, newText, sizeof( wchar_t )*MAX_LOCATION_TEXT_LENGTH );
  2353. if ( m_LocationText )
  2354. {
  2355. WITH_SLOT_LOCKED
  2356. {
  2357. m_LocationText->SetText( m_wcLocationString );
  2358. }
  2359. }
  2360. }
  2361. }
  2362. /********************************************
  2363. * "drawing" code. Actually just sets position / alpha
  2364. * of the flash objects
  2365. */
  2366. void SFHudRadar::WorldToRadar( const Vector& ptin, Vector& ptout )
  2367. {
  2368. float fWorldScale = m_fWorldToRadarScale;
  2369. float flMapScaler = 0;
  2370. if ( m_bRound && CSGameRules()->IsPlayingCoopMission() && cl_radar_always_centered.GetBool() )
  2371. flMapScaler = MAX( 0 , (0.75f - fWorldScale) ) * 2.5;
  2372. float fScale = m_bRound ? (cl_radar_scale.GetFloat() + flMapScaler) : ( m_fRadarSize / m_fMapSize ) ;
  2373. fWorldScale *= fScale;
  2374. ptout.x = ( ptin.x - m_MapOrigin.x ) * fWorldScale;
  2375. ptout.y = ( m_MapOrigin.y - ptin.y ) * fWorldScale;
  2376. ptout.z = 0;
  2377. }
  2378. void SFHudRadar::RadarToHud( const Vector& ptin, Vector& ptout )
  2379. {
  2380. VMatrix rot;
  2381. MatrixBuildRotateZ( rot, m_RadarRotation );
  2382. Vector3DMultiply( rot, ptin - m_RadarViewpointMap, ptout );
  2383. }
  2384. //ConVar radar_test( "radar_test", "0" );
  2385. void SFHudRadar::PositionRadarViewpoint( void )
  2386. {
  2387. if ( !m_bFlashReady )
  2388. {
  2389. return;
  2390. }
  2391. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  2392. CBasePlayer * pPlayer = CBasePlayer::GetLocalPlayer();
  2393. if( pPlayer == NULL )
  2394. {
  2395. pPlayer = GetSplitScreenViewPlayer( nSlot );
  2396. }
  2397. bool bRotate;
  2398. float fScale;
  2399. Vector vRadarOffset;
  2400. float fFrustrumRotation;
  2401. Vector vMapCenter = Vector( m_fMapSize / 2, m_fMapSize / 2, 0 );
  2402. if ( m_bRound )
  2403. {
  2404. // [jbright] Using GetLocalOrigin addresses an issue which
  2405. // causes the center player indicator to not stay centered
  2406. // on the radar. This solution causes the radar to go jump
  2407. // around while in observer mode, so in those cases rely on
  2408. // MainViewOrigin.
  2409. if ( pPlayer && m_iObserverMode == OBS_MODE_NONE )
  2410. {
  2411. m_RadarViewpointWorld = pPlayer->GetLocalOrigin();
  2412. }
  2413. else
  2414. {
  2415. m_RadarViewpointWorld = MainViewOrigin( nSlot );
  2416. }
  2417. m_RadarViewpointWorld.z = 0;
  2418. WorldToRadar( m_RadarViewpointWorld, m_RadarViewpointMap );
  2419. float flMapScaler = 0;
  2420. if ( m_bRound && CSGameRules()->IsPlayingCoopMission() && cl_radar_always_centered.GetBool() )
  2421. flMapScaler = MAX( 0, ( 0.75f - m_fWorldToRadarScale ) ) * 2.5;
  2422. fScale = cl_radar_scale.GetFloat() + flMapScaler;
  2423. if ( !cl_radar_always_centered.GetBool() )
  2424. {
  2425. vRadarOffset = ( 1 - fScale ) * ( m_RadarViewpointMap - fScale * ( vMapCenter ) );
  2426. m_RadarViewpointMap -= vRadarOffset;
  2427. }
  2428. bRotate = cl_radar_rotate.GetBool();
  2429. }
  2430. else
  2431. {
  2432. bRotate = false;
  2433. fScale = m_fRadarSize / m_fMapSize;
  2434. m_RadarViewpointMap = fScale * vMapCenter;
  2435. vRadarOffset = Vector( 0, 0, 0 );
  2436. }
  2437. if ( bRotate )
  2438. {
  2439. m_RadarRotation = MainViewAngles( nSlot )[YAW] - 90;
  2440. fFrustrumRotation = 0;
  2441. }
  2442. else
  2443. {
  2444. m_RadarRotation = 0;
  2445. fFrustrumRotation = MainViewAngles( nSlot )[YAW] - 90;
  2446. }
  2447. ScaleformDisplayInfo displayInfo;
  2448. if ( m_MapRotation )
  2449. {
  2450. displayInfo.SetRotation( m_RadarRotation );
  2451. m_pScaleformUI->Value_SetDisplayInfo( m_MapRotation, &displayInfo );
  2452. if ( m_MapTranslation )
  2453. {
  2454. displayInfo.Clear();
  2455. displayInfo.SetX( -m_RadarViewpointMap.x );
  2456. displayInfo.SetY( -m_RadarViewpointMap.y );
  2457. double scale = 100.0f;
  2458. scale *= fScale;
  2459. displayInfo.SetXScale( scale );
  2460. displayInfo.SetYScale( scale );
  2461. m_pScaleformUI->Value_SetDisplayInfo( m_MapTranslation, &displayInfo );
  2462. }
  2463. }
  2464. static bool s_bResetTransform = false;
  2465. if ( m_IconRotation )
  2466. {
  2467. displayInfo.Clear();
  2468. if ( !cl_radar_fast_transforms.GetBool() )
  2469. {
  2470. displayInfo.SetRotation( m_RadarRotation );
  2471. s_bResetTransform = true;
  2472. }
  2473. else if ( s_bResetTransform )
  2474. {
  2475. // Icons are updated individually (do not update parent)
  2476. displayInfo.SetRotation( 0.0f );
  2477. }
  2478. m_pScaleformUI->Value_SetDisplayInfo( m_IconRotation, &displayInfo );
  2479. if ( m_IconTranslation )
  2480. {
  2481. displayInfo.Clear();
  2482. if ( !cl_radar_fast_transforms.GetBool() )
  2483. {
  2484. displayInfo.SetX( -m_RadarViewpointMap.x );
  2485. displayInfo.SetY( -m_RadarViewpointMap.y );
  2486. s_bResetTransform = true;
  2487. }
  2488. else if ( s_bResetTransform )
  2489. {
  2490. // Icons are updated individually (do not update parent)
  2491. displayInfo.SetX( -0.4f );
  2492. displayInfo.SetY( -0.4f );
  2493. }
  2494. m_pScaleformUI->Value_SetDisplayInfo( m_IconTranslation, &displayInfo );
  2495. }
  2496. if ( cl_radar_fast_transforms.GetBool() )
  2497. {
  2498. s_bResetTransform = false;
  2499. }
  2500. }
  2501. if ( m_vecRadarVerticalSections.Count() )
  2502. {
  2503. float flPlayerZ = 0;
  2504. if ( pPlayer && m_iObserverMode == OBS_MODE_NONE )
  2505. {
  2506. flPlayerZ = pPlayer->GetLocalOrigin().z;
  2507. }
  2508. else
  2509. {
  2510. flPlayerZ = MainViewOrigin( nSlot ).z;
  2511. }
  2512. FOR_EACH_VEC( m_vecRadarVerticalSections, i )
  2513. {
  2514. HudRadarLevelVerticalSection_t *pRadarSection = &m_vecRadarVerticalSections[i];
  2515. if ( flPlayerZ >= pRadarSection->m_flSectionAltitudeFloor &&
  2516. flPlayerZ < pRadarSection->m_flSectionAltitudeCeiling &&
  2517. m_nCurrentRadarVerticalSection != pRadarSection->m_nSectionIndex )
  2518. {
  2519. m_nCurrentRadarVerticalSection = pRadarSection->m_nSectionIndex;
  2520. FlashUpdateMapLayer(i);
  2521. break;
  2522. }
  2523. }
  2524. }
  2525. }
  2526. void SFHudRadar::PlaceGoalIcons( void )
  2527. {
  2528. C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
  2529. if ( !pCSPR )
  2530. {
  2531. return;
  2532. }
  2533. SFHudRadarGoalIcon* pwalk = m_GoalIcons;
  2534. Vector mapPosition;
  2535. ScaleformDisplayInfo displayInfo;
  2536. bool bRotate = m_bRound ? cl_radar_rotate.GetBool() : false;
  2537. for ( int i = 0; i < m_iNumGoalIcons; i++ )
  2538. {
  2539. WorldToRadar( pwalk->m_Position, mapPosition );
  2540. if ( pwalk->m_Icon )
  2541. {
  2542. Vector newMapPosition = mapPosition;
  2543. newMapPosition -= m_RadarViewpointMap;
  2544. float dist = newMapPosition.LengthSqr();
  2545. if ( dist > RADARRADIUS*RADARRADIUS && m_bRound )
  2546. {
  2547. newMapPosition *= sqrt( RADARRADIUS*RADARRADIUS/dist );
  2548. mapPosition = m_RadarViewpointMap;
  2549. mapPosition += newMapPosition;
  2550. }
  2551. if ( cl_radar_fast_transforms.GetBool() )
  2552. {
  2553. Vector hudPos;
  2554. RadarToHud(mapPosition, hudPos);
  2555. displayInfo.SetX( hudPos.x );
  2556. displayInfo.SetY( hudPos.y );
  2557. displayInfo.SetRotation( 0.0f );
  2558. }
  2559. else
  2560. {
  2561. displayInfo.SetX( mapPosition.x );
  2562. displayInfo.SetY( mapPosition.y );
  2563. displayInfo.SetRotation( bRotate ? -m_RadarRotation : 0 );
  2564. }
  2565. m_pScaleformUI->Value_SetDisplayInfo( pwalk->m_Icon, &displayInfo );
  2566. }
  2567. pwalk++;
  2568. }
  2569. }
  2570. void SFHudRadar::SetIconPackagePosition( SFHudRadarIconPackage* pPackage )
  2571. {
  2572. if ( !m_bFlashReady )
  2573. return;
  2574. Vector mapPosition;
  2575. float mapAngle;
  2576. WorldToRadar( pPackage->m_Position, mapPosition );
  2577. Vector newMapPosition = mapPosition;
  2578. newMapPosition -= m_RadarViewpointMap;
  2579. float dist = newMapPosition.LengthSqr();
  2580. if ( dist >= RADARRADIUS*RADARRADIUS && m_bRound )
  2581. {
  2582. pPackage->SetIsOffMap( true );
  2583. newMapPosition *= sqrt( RADARRADIUS*RADARRADIUS/dist );
  2584. mapPosition = m_RadarViewpointMap;
  2585. mapPosition += newMapPosition;
  2586. mapAngle = 180.0f*atan2( newMapPosition.y, newMapPosition.x )/3.141592f + 90;
  2587. }
  2588. else
  2589. {
  2590. pPackage->SetIsOffMap( false );
  2591. if ( pPackage->m_bIsDead || !pPackage->m_bIsSpotted || (pPackage->m_nAboveOrBelow != R_SAMELEVEL) || (pPackage->m_iPlayerType == PI_ENEMY && !pPackage->m_bIsSelected) )
  2592. {
  2593. mapAngle = -m_RadarRotation;
  2594. }
  2595. else
  2596. {
  2597. mapAngle = -pPackage->m_Angle[YAW]+90;
  2598. }
  2599. }
  2600. double scale = 100;
  2601. float fIconScale = cl_radar_scale.GetFloat();
  2602. fIconScale = RemapValClamped( fIconScale,
  2603. 0, 1,
  2604. cl_radar_icon_scale_min.GetFloat() , 1 );
  2605. scale *= fIconScale;
  2606. static bool s_bResetTransform = false;
  2607. if ( cl_radar_fast_transforms.GetBool() )
  2608. {
  2609. RadarToHud( mapPosition, pPackage->m_HudPosition );
  2610. if ( pPackage->m_IconPackageRotate )
  2611. {
  2612. bool bRotate = m_bRound ? cl_radar_rotate.GetBool() : false;
  2613. pPackage->m_HudRotation = bRotate ? ( m_RadarRotation + mapAngle ) : mapAngle;
  2614. }
  2615. else
  2616. {
  2617. pPackage->m_HudRotation = 0.0f;
  2618. }
  2619. pPackage->m_HudScale = scale;
  2620. if ( s_bResetTransform )
  2621. {
  2622. ScaleformDisplayInfo displayInfo;
  2623. displayInfo.SetXScale( 100.0f );
  2624. displayInfo.SetYScale( 100.0f );
  2625. displayInfo.SetX( 0.0f );
  2626. displayInfo.SetY( 0.0f );
  2627. m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackage, &displayInfo );
  2628. if ( pPackage->m_IconPackageRotate )
  2629. {
  2630. ScaleformDisplayInfo rotatedDisplayInfo;
  2631. rotatedDisplayInfo.SetRotation( 0.0f );
  2632. m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackageRotate, &rotatedDisplayInfo );
  2633. }
  2634. s_bResetTransform = false;
  2635. }
  2636. }
  2637. else
  2638. {
  2639. ScaleformDisplayInfo displayInfo;
  2640. displayInfo.SetXScale( scale );
  2641. displayInfo.SetYScale( scale );
  2642. displayInfo.SetX( mapPosition.x );
  2643. displayInfo.SetY( mapPosition.y );
  2644. m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackage, &displayInfo );
  2645. if ( pPackage->m_IconPackageRotate )
  2646. {
  2647. ScaleformDisplayInfo rotatedDisplayInfo;
  2648. rotatedDisplayInfo.SetRotation( mapAngle );
  2649. m_pScaleformUI->Value_SetDisplayInfo( pPackage->m_IconPackageRotate, &rotatedDisplayInfo );
  2650. }
  2651. s_bResetTransform = true;
  2652. }
  2653. pPackage->SetupIconsFromStates();
  2654. }
  2655. void SFHudRadar::PlaceHostages( void )
  2656. {
  2657. if ( !m_bFlashReady )
  2658. {
  2659. return;
  2660. }
  2661. if ( !CSGameRules()->IsHostageRescueMap() )
  2662. {
  2663. return;
  2664. }
  2665. C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
  2666. if ( !pCSPR )
  2667. {
  2668. return;
  2669. }
  2670. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  2671. if( pLocalPlayer == NULL )
  2672. {
  2673. return;
  2674. }
  2675. int iNumLiveHostages = 0;
  2676. int iNumDeadHostages = 0;
  2677. int iNumMovingHostages = 0;
  2678. int iNumRescuedHostages = 0;
  2679. /* // Commented out because we want to show hostages on radar to Ts
  2680. bool bIsTerrorist = ( pLocalPlayer->GetTeamNumber() == TEAM_TERRORIST );
  2681. if ( bIsTerrorist )
  2682. {
  2683. // Taking over a bot after switching to the terrorist team results in
  2684. // the hostage indicators remaining visible, so we need to remove them.
  2685. for ( int i = 0; i <= m_iLastHostageIndex; i++ )
  2686. {
  2687. if ( GetRadarHostage( i )->m_bIsActive )
  2688. RemoveHostage( i );
  2689. }
  2690. // we also want to show the number of hostages that are still alive
  2691. // and unrescued
  2692. for( int i=0; i < MAX_HOSTAGES; i++ )
  2693. {
  2694. if( pCSPR->IsHostageAlive( i ) )
  2695. iNumLiveHostages++;
  2696. }
  2697. }
  2698. */
  2699. // T's can now always see basic hostage info (alive, dead) but not moving or rescued status
  2700. /*
  2701. bool bCanShowHostages = m_bShowAll || ( pLocalPlayer->GetTeamNumber() == TEAM_CT );
  2702. if ( !bCanShowHostages )
  2703. {
  2704. return;
  2705. }
  2706. */
  2707. // Update hostage status
  2708. for( int i=0; i < MAX_HOSTAGES; i++ )
  2709. {
  2710. int nEntityID = pCSPR->GetHostageEntityID( i );
  2711. if ( nEntityID > 0 )
  2712. {
  2713. SFHudRadarIconPackage* pHostage = NULL;
  2714. int nHostageIndex = GetHostageIndexFromHostageEntityID( nEntityID );
  2715. if ( nHostageIndex == INVALID_INDEX )
  2716. {
  2717. // Create the hostage in next available slot
  2718. for ( nHostageIndex = 0; nHostageIndex < MAX_HOSTAGES; nHostageIndex++ )
  2719. {
  2720. if ( !m_Hostages[nHostageIndex].m_bIsActive )
  2721. {
  2722. pHostage = CreateHostage( nHostageIndex );
  2723. pHostage->SetPlayerTeam( TEAM_UNASSIGNED );
  2724. pHostage->m_iEntityID = nEntityID;
  2725. break;
  2726. }
  2727. }
  2728. }
  2729. else
  2730. {
  2731. pHostage = GetRadarHostage( nHostageIndex );
  2732. }
  2733. if ( pHostage )
  2734. {
  2735. if( pCSPR->IsHostageAlive( i ) )
  2736. {
  2737. if ( !pHostage->m_bIsActive )
  2738. {
  2739. }
  2740. pHostage->SetIsDead( false );
  2741. if ( pCSPR->IsHostageFollowingSomeone( i ) )
  2742. {
  2743. iNumMovingHostages++;
  2744. pHostage->SetIsMovingHostage( true );
  2745. if ( !pHostage->m_bHostageIsUsed )
  2746. pHostage->m_bHostageIsUsed = true;
  2747. }
  2748. else
  2749. {
  2750. iNumLiveHostages++;
  2751. pHostage->SetIsMovingHostage( false );
  2752. }
  2753. }
  2754. else if ( i <= m_iLastHostageIndex && pHostage->m_bIsActive )
  2755. {
  2756. if ( pHostage->m_bIsRescued )
  2757. {
  2758. iNumRescuedHostages++;
  2759. }
  2760. else
  2761. {
  2762. iNumDeadHostages++;
  2763. }
  2764. pHostage->SetIsDead( true );
  2765. pHostage->SetIsMovingHostage( false );
  2766. }
  2767. }
  2768. }
  2769. }
  2770. // Update hostage positions
  2771. for( int i = 0; i < MAX_HOSTAGES; i++ )
  2772. {
  2773. SFHudRadarIconPackage* pHostage = GetRadarHostage( i );
  2774. if ( pHostage->m_bIsActive )
  2775. {
  2776. C_BaseEntity * pEntity = ClientEntityList().GetBaseEntity( pHostage->m_iEntityID );
  2777. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  2778. // note: !pHostage->m_bHostageIsUsed : T's can always see Hostages until they get +used by CTs
  2779. bool bSpotted = ( !pHostage->m_bHostageIsUsed ||
  2780. pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT ||
  2781. ( pEntity && pEntity->IsSpotted() ) ||
  2782. m_EntitySpotted.Get( pHostage->m_iEntityID ) ||
  2783. m_bShowAll );
  2784. pHostage->SetIsSpotted( bSpotted );
  2785. int nIsAboveOrBelow = R_SAMELEVEL;
  2786. C_CSPlayer *pLocalOrObserver = NULL;
  2787. if ( pLocalPlayer )
  2788. {
  2789. C_BaseEntity *target = pLocalPlayer->GetObserverTarget();
  2790. if( target && target->IsPlayer() )
  2791. pLocalOrObserver = ToCSPlayer( target );
  2792. else
  2793. pLocalOrObserver = pLocalPlayer;
  2794. }
  2795. if ( pLocalOrObserver )
  2796. {
  2797. if ( pHostage->m_Position.z > pLocalOrObserver->GetAbsOrigin().z + ABOVE_BELOW_HEIGHT )
  2798. nIsAboveOrBelow = R_ABOVE;
  2799. else if ( pHostage->m_Position.z < pLocalOrObserver->GetAbsOrigin().z - ABOVE_BELOW_HEIGHT )
  2800. nIsAboveOrBelow = R_BELOW;
  2801. }
  2802. pHostage->SetIsAboveOrBelow( nIsAboveOrBelow );
  2803. SetIconPackagePosition( pHostage );
  2804. bool bRotate = m_bRound ? cl_radar_rotate.GetBool() : false;
  2805. // hostage always faces the same way
  2806. if ( !bRotate )
  2807. pHostage->m_Angle = QAngle( 0, 90, 0 );
  2808. else
  2809. {
  2810. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  2811. pHostage->m_Angle = MainViewAngles( nSlot );
  2812. }
  2813. if ( pEntity && !pEntity->IsDormant() && bSpotted )
  2814. {
  2815. Assert( dynamic_cast<CHostage*>( pEntity ) );
  2816. pHostage->m_Position = pEntity->GetNetworkOrigin();
  2817. }
  2818. }
  2819. }
  2820. int hostageIndex = 0;
  2821. for ( int i = 0; i < iNumDeadHostages; i++ )
  2822. {
  2823. m_HostageStatusIcons[hostageIndex++].SetStatus( SFHudRadarHostageIcons::HI_DEAD );
  2824. }
  2825. for ( int i = 0; i < iNumRescuedHostages; i++ )
  2826. {
  2827. m_HostageStatusIcons[hostageIndex++].SetStatus( SFHudRadarHostageIcons::HI_RESCUED );
  2828. }
  2829. for ( int i = 0; i < iNumMovingHostages; i++ )
  2830. {
  2831. m_HostageStatusIcons[hostageIndex++].SetStatus( SFHudRadarHostageIcons::HI_TRANSIT );
  2832. }
  2833. for ( int i = 0; i < iNumLiveHostages; i++ )
  2834. {
  2835. m_HostageStatusIcons[hostageIndex++].SetStatus( SFHudRadarHostageIcons::HI_ALIVE );
  2836. }
  2837. for ( ; hostageIndex < MAX_HOSTAGES && m_HostageStatusIcons[hostageIndex].m_IconPackage != NULL; hostageIndex++ )
  2838. {
  2839. m_HostageStatusIcons[hostageIndex].SetStatus( SFHudRadarHostageIcons::HI_UNUSED );
  2840. }
  2841. }
  2842. void SFHudRadar::UpdateAllDefusers( void )
  2843. {
  2844. if ( !m_bTrackDefusers )
  2845. {
  2846. return;
  2847. }
  2848. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  2849. if( pLocalPlayer == NULL )
  2850. {
  2851. return;
  2852. }
  2853. for ( int i = 0; i <= m_iLastDefuserIndex; i++ )
  2854. {
  2855. SFHudRadarIconPackage * pPackage = GetRadarDefuser( i );
  2856. if ( pPackage && pPackage->m_bIsActive )
  2857. {
  2858. C_BaseEntity * pEntity = ClientEntityList().GetBaseEntity( pPackage->m_iEntityID );
  2859. bool bSpotted = ( pLocalPlayer->GetAssociatedTeamNumber() == TEAM_CT || ( pEntity && pEntity->IsSpotted() ) || m_EntitySpotted.Get( pPackage->m_iEntityID ) );
  2860. pPackage->SetIsSpotted( bSpotted );
  2861. if ( bSpotted && pEntity && !pEntity->IsDormant() )
  2862. {
  2863. SetDefuserPos( pPackage->m_iEntityID,
  2864. pEntity->GetNetworkOrigin().x,
  2865. pEntity->GetNetworkOrigin().y,
  2866. pEntity->GetNetworkOrigin().z,
  2867. pEntity->GetNetworkAngles().y );
  2868. }
  2869. }
  2870. // update radar position and visibility
  2871. if ( pPackage && pPackage->m_bIsActive )
  2872. {
  2873. SetIconPackagePosition( pPackage );
  2874. }
  2875. }
  2876. }
  2877. void SFHudRadar::PlacePlayers( void )
  2878. {
  2879. if ( !m_bFlashReady )
  2880. {
  2881. return;
  2882. }
  2883. C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
  2884. if ( !pCSPR )
  2885. {
  2886. return;
  2887. }
  2888. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  2889. if( pLocalPlayer == NULL )
  2890. {
  2891. return;
  2892. }
  2893. int localPlayerIndex = pLocalPlayer->entindex()-1;
  2894. if ( localPlayerIndex == INVALID_INDEX )
  2895. return;
  2896. int localTeamNumber = pLocalPlayer->GetAssociatedTeamNumber();
  2897. SFHudRadarIconPackage* pwalk = m_Players;
  2898. int playerIndex;
  2899. for ( int i = 0; i <= m_iLastPlayerIndex; i++, pwalk++ )
  2900. {
  2901. if ( pwalk->m_IconPackage && pwalk->m_bIsActive )
  2902. {
  2903. playerIndex = i+1;
  2904. C_CSPlayer *pPlayer = ToCSPlayer( UTIL_PlayerByIndex( playerIndex ) );
  2905. bool playerIsActive = pPlayer != NULL && !pPlayer->IsDormant();
  2906. int nIsAboveOrBelow = R_SAMELEVEL;
  2907. // we do all the pCSPR stuff because the player may not have been given
  2908. // to us by the server yet. If that's the case, we can't use the player
  2909. // pointer to find anything out, we have to use the PCSPR which keeps some
  2910. // of this data ( like team numbers, spotted, hasC4 etc. The dormant means
  2911. // that it's not in our view
  2912. if ( pPlayer && pCSPR->IsConnected( playerIndex ) )
  2913. {
  2914. pwalk->SetIsBot( pCSPR->IsFakePlayer( playerIndex ) );
  2915. pwalk->m_Health = pCSPR->GetHealth( playerIndex );
  2916. if ( !pCSPR->IsAlive( playerIndex ) )
  2917. {
  2918. pwalk->m_Health = 0;
  2919. if( pCSPR->GetControlledByPlayer( playerIndex ) )
  2920. {
  2921. pwalk->SetIsControlledBot();
  2922. }
  2923. else
  2924. {
  2925. pwalk->SetIsDead( true );
  2926. }
  2927. }
  2928. else
  2929. {
  2930. pwalk->SetIsDead( false );
  2931. //it's hard to figure out if this player has been spotted, and if spotted has enough info to be
  2932. //shown.
  2933. bool bSameTeam = ( localTeamNumber == pCSPR->GetTeam( playerIndex ) );
  2934. bool bIsEnemy = pPlayer->IsOtherEnemy( pLocalPlayer ) && localPlayerIndex != playerIndex;
  2935. bool bHasValidPosition = playerIsActive || ( pwalk->m_Position.x != 0 || pwalk->m_Position.y != 0 );
  2936. bool bPlayerSpotted = ( m_EntitySpotted.Get( playerIndex ) || ( playerIsActive && pPlayer->IsSpotted() ) );
  2937. bool bSpottedByFriends = !bIsEnemy;
  2938. // verify here on the client that we do in fact see the entity how the player would expect to see the entity
  2939. // if the local player is in smoke or if they are looking through smoke, we double check if they can see them on radar
  2940. // use the networked position and not the stored position because the stored one is stale
  2941. Vector vecOtherPos( pPlayer->GetNetworkOrigin( ).x, pPlayer->GetNetworkOrigin( ).y, ( pPlayer->GetNetworkOrigin( ).z + 56 ) );
  2942. if ( bIsEnemy && bPlayerSpotted )
  2943. {
  2944. bSpottedByFriends = pPlayer->IsSpottedByFriends( localPlayerIndex );
  2945. float flDist = ( pLocalPlayer->EyePosition( ) - vecOtherPos ).Length2D( );
  2946. if ( flDist < 1600 && bSpottedByFriends == false &&
  2947. LineGoesThroughSmoke( pLocalPlayer->EyePosition(), vecOtherPos, 1.0f ) )
  2948. {
  2949. bPlayerSpotted = false;
  2950. }
  2951. }
  2952. if ( bHasValidPosition && ( (bSameTeam && !bIsEnemy) || m_bShowAll || bPlayerSpotted ) )
  2953. {
  2954. bool bSpottedByLocalPlayer = bSameTeam ? true : pPlayer->IsSpottedBy( localPlayerIndex );
  2955. pwalk->SetIsSpotted( true );
  2956. pwalk->SetIsSpottedByFriendsOnly( (bSpottedByFriends && !bSpottedByLocalPlayer) );
  2957. if ( playerIsActive && pPlayer->HasDefuser() )
  2958. {
  2959. // attach a defuser icon to this player if one does not already exist
  2960. if ( GetDefuseIndexFromEntityID( playerIndex ) == INVALID_INDEX )
  2961. {
  2962. CreateDefuser( playerIndex );
  2963. }
  2964. }
  2965. if ( playerIsActive && pPlayer->HasC4() )
  2966. {
  2967. m_bBombIsSpotted = true;
  2968. m_BombPosition = pwalk->m_Position;
  2969. m_nBombHolderUserId = pPlayer->GetUserID();
  2970. }
  2971. // set is selected
  2972. C_CSPlayer *pLocalOrObserver = ToCSPlayer( pLocalPlayer->GetObserverTarget() );
  2973. pwalk->SetIsSelected( pLocalOrObserver && pPlayer == pLocalOrObserver );
  2974. }
  2975. else
  2976. {
  2977. pwalk->SetIsSpotted( false );
  2978. }
  2979. }
  2980. pwalk->SetPlayerTeam( pCSPR->GetTeam( playerIndex ) );
  2981. pwalk->SetIsOnLocalTeam( localTeamNumber == pCSPR->GetTeam( playerIndex ) );
  2982. pwalk->SetIsPlayer( i == localPlayerIndex );
  2983. pwalk->SetIsSpeaking( GetClientVoiceMgr()->IsPlayerSpeaking( playerIndex ) && GetClientVoiceMgr()->IsPlayerAudible( playerIndex ) );
  2984. UpdatePlayerNumber( pwalk );
  2985. C_CSPlayer *pLocalOrObserver = NULL;
  2986. if ( pLocalPlayer )
  2987. {
  2988. C_BaseEntity *target = pLocalPlayer->GetObserverTarget();
  2989. if( target && target->IsPlayer() )
  2990. pLocalOrObserver = ToCSPlayer( target );
  2991. else
  2992. pLocalOrObserver = pLocalPlayer;
  2993. }
  2994. if ( pLocalOrObserver )
  2995. {
  2996. if ( pwalk->m_Position.z > pLocalOrObserver->GetAbsOrigin().z + ABOVE_BELOW_HEIGHT )
  2997. nIsAboveOrBelow = R_ABOVE;
  2998. else if ( pwalk->m_Position.z < pLocalOrObserver->GetAbsOrigin().z - ABOVE_BELOW_HEIGHT )
  2999. nIsAboveOrBelow = R_BELOW;
  3000. }
  3001. pwalk->SetIsAboveOrBelow( nIsAboveOrBelow );
  3002. }
  3003. else
  3004. {
  3005. pwalk->SetIsSpotted( false );
  3006. pwalk->SetIsSpeaking( false );
  3007. }
  3008. if ( playerIsActive && pwalk->m_bIsSpotted )
  3009. {
  3010. // when the local player dies the system reports the local players position
  3011. // as the position of the spectator camera. If we let that happen, the player's
  3012. // X migrates from the point they died to follow the camera. Can't have that,
  3013. // so avoid setting the position if we're dead and in observer mode
  3014. if ( m_iObserverMode == OBS_MODE_NONE || i != localPlayerIndex )
  3015. {
  3016. // dkorus and pfreese: Changed from local origin and local angles to last networked version to address jitter issues for pax demo 2011
  3017. if ( !pwalk->m_bIsDead )
  3018. pwalk->m_Position = pPlayer->GetNetworkOrigin();
  3019. // only set the angle of the icon if the player isn't above or below us
  3020. if ( nIsAboveOrBelow != R_SAMELEVEL || pwalk->IsHostageType( ) || ( pwalk->m_iPlayerType == PI_ENEMY && !pwalk->m_bIsSelected ) )
  3021. {
  3022. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  3023. pwalk->m_Angle = MainViewAngles( nSlot );
  3024. }
  3025. else
  3026. pwalk->m_Angle = pPlayer->EyeAngles( );
  3027. if ( pPlayer->HasC4() )
  3028. {
  3029. m_BombPosition = pwalk->m_Position;
  3030. m_nBombHolderUserId = pPlayer->GetUserID();
  3031. }
  3032. }
  3033. }
  3034. SetIconPackagePosition( pwalk );
  3035. }
  3036. }
  3037. }
  3038. void SFHudRadar::UpdateMiscIcons( void )
  3039. {
  3040. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  3041. if ( !pLocalPlayer )
  3042. {
  3043. return;
  3044. }
  3045. // We show the entire dashboard in spectator mode now, so you can see bomb/hostage status, etc.
  3046. m_bShowingDashboard = true;
  3047. // Uncomment this line to disable the radar dashboard in spectator mode:
  3048. // m_bShowingDashboard = ( pLocalPlayer->GetObserverMode() == OBS_MODE_NONE );
  3049. const char *pszLocation = pLocalPlayer->GetLastKnownPlaceName();
  3050. if ( pszLocation )
  3051. {
  3052. SetLocationText( g_pVGuiLocalize->Find( pszLocation ) );
  3053. }
  3054. else
  3055. {
  3056. SetLocationText( NULL );
  3057. }
  3058. C_CS_PlayerResource *pCSPR = ( C_CS_PlayerResource* )GameResources();
  3059. if ( !pCSPR )
  3060. {
  3061. return;
  3062. }
  3063. // show the bomb under the radar if the player has this set
  3064. static ConVarRef cl_hud_bomb_under_radar( "cl_hud_bomb_under_radar" );
  3065. bool bShowBombUnderRadar = ( cl_hud_bomb_under_radar.GetInt( ) == 1 && pLocalPlayer->HasC4() );
  3066. WITH_SFVALUEARRAY( args, 1 )
  3067. {
  3068. g_pScaleformUI->ValueArray_SetElement( args, 0, bShowBombUnderRadar );
  3069. g_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "ShowC4", args, 1 );
  3070. }
  3071. m_fBombAlpha = 0.0f;
  3072. m_fDefuserAlpha = 0.0f;
  3073. if ( CSGameRules()->IsBombDefuseMap() )
  3074. {
  3075. if ( m_bBombPlanted )
  3076. {
  3077. FOR_EACH_VEC( g_PlantedC4s, iBomb )
  3078. {
  3079. C_PlantedC4 * pC4 = g_PlantedC4s[iBomb];
  3080. if ( pC4 && pC4->IsBombActive() )
  3081. {
  3082. bool bLocalPlayerCanSeeBomb =( pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST || m_bShowAll || ( pC4 && !pC4->IsDormant() && pC4->IsSpotted() ) );
  3083. if ( bLocalPlayerCanSeeBomb && pC4 && !pC4->IsDormant() )
  3084. {
  3085. m_bBombIsSpotted = true;
  3086. m_BombPosition = pC4->GetNetworkOrigin();
  3087. m_nBombHolderUserId = -1;
  3088. }
  3089. }
  3090. }
  3091. }
  3092. if ( m_nBombEntIndex != -1 && ( !m_bBombIsSpotted || m_bBombDropped ) )
  3093. {
  3094. C_BaseEntity * pEntity = ClientEntityList().GetBaseEntity( m_nBombEntIndex );
  3095. bool bLocalPlayerCanSeeBomb =( pLocalPlayer->GetAssociatedTeamNumber() == TEAM_TERRORIST || m_bShowAll || ( pEntity && !pEntity->IsDormant() && pEntity->IsSpotted() ) );
  3096. if ( bLocalPlayerCanSeeBomb && pEntity && !pEntity->IsDormant() )
  3097. {
  3098. Assert( pEntity && FClassnameIs( pEntity, "weapon_c4" ) );
  3099. m_bBombIsSpotted = true;
  3100. m_BombPosition = pEntity->GetNetworkOrigin();
  3101. m_nBombHolderUserId = -1;
  3102. }
  3103. }
  3104. float now = gpGlobals->curtime;
  3105. bool drawBomb = false;
  3106. bool bBombPositionIsValid = ( m_BombPosition.x != 0 || m_BombPosition.y != 0 );
  3107. if ( CSGameRules() && CSGameRules()->IsPlayingCoopMission() )
  3108. {
  3109. drawBomb = false;
  3110. }
  3111. else if ( bBombPositionIsValid && !m_bBombExploded && m_bBombIsSpotted )
  3112. {
  3113. drawBomb = true;
  3114. m_fBombSeenTime = now;
  3115. m_fBombAlpha = 1.0f;
  3116. }
  3117. else if ( m_bBombExploded )
  3118. {
  3119. m_fBombAlpha = 0;
  3120. m_fBombSeenTime = TIMER_INIT;
  3121. }
  3122. else
  3123. {
  3124. m_fBombAlpha = clamp( 1.0f - ( now - m_fBombSeenTime )/BOMB_FADE_TIME, 0.0f, 1.0f );
  3125. if ( m_fBombAlpha > 0 )
  3126. {
  3127. drawBomb = true;
  3128. }
  3129. else
  3130. {
  3131. m_fBombSeenTime = TIMER_INIT;
  3132. }
  3133. }
  3134. if ( drawBomb )
  3135. {
  3136. m_bShowBombHighlight = !m_bBombDefused && ( m_bBombPlanted || m_bBombDropped );
  3137. }
  3138. }
  3139. else if ( CSGameRules()->IsHostageRescueMap() )
  3140. {
  3141. m_bShowingHostageZone = pLocalPlayer->IsInHostageRescueZone();
  3142. WITH_SLOT_LOCKED
  3143. {
  3144. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "ShowHostages", NULL, 0 );
  3145. }
  3146. }
  3147. }
  3148. void SFHudRadar::ApplySpectatorModes( void )
  3149. {
  3150. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  3151. if ( !pLocalPlayer )
  3152. return;
  3153. m_bShowAll = false;
  3154. m_iObserverMode = pLocalPlayer->GetObserverMode();
  3155. if ( engine->IsHLTV() || pLocalPlayer->IsSpectator() )
  3156. {
  3157. m_bShowAll = true;
  3158. }
  3159. else if ( m_iObserverMode != OBS_MODE_NONE ) // is not a live player
  3160. {
  3161. // respect mp_forcecamera
  3162. static ConVarRef mp_forcecamera( "mp_forcecamera" );
  3163. m_bShowAll = ( mp_forcecamera.GetInt() == OBS_ALLOW_ALL );
  3164. }
  3165. // mp_radar_showall trumps all
  3166. static ConVarRef mp_radar_showall( "mp_radar_showall" );
  3167. if ( mp_radar_showall.GetInt() && (
  3168. ( pLocalPlayer->GetAssociatedTeamNumber() == mp_radar_showall.GetInt() ) ||
  3169. ( mp_radar_showall.GetInt() == 1 )
  3170. ) )
  3171. {
  3172. m_bShowAll = true;
  3173. }
  3174. // Radar type
  3175. bool bRoundRadar = true;
  3176. IViewPortPanel* panel = GetViewPortInterface()->FindPanelByName( PANEL_SCOREBOARD );
  3177. if ( engine->IsHLTV() || pLocalPlayer->IsSpectator() || (panel->IsVisible() && cl_radar_square_with_scoreboard.GetBool()) )
  3178. bRoundRadar = false;
  3179. else if ( pLocalPlayer->IsAlive() == false &&
  3180. (m_iObserverMode == OBS_MODE_FIXED ||
  3181. m_iObserverMode == OBS_MODE_CHASE ||
  3182. m_iObserverMode == OBS_MODE_ROAMING ||
  3183. m_iObserverMode == OBS_MODE_IN_EYE) )
  3184. {
  3185. bRoundRadar = false;
  3186. }
  3187. SwitchRadarToRound( bRoundRadar );
  3188. }
  3189. void SFHudRadar::UpdateDecoys( void )
  3190. {
  3191. for ( int i = 0; i <= m_iLastDecoyIndex; i++ )
  3192. {
  3193. SFHudRadarIconPackage* pPackage = GetRadarDecoy( i );
  3194. if ( pPackage && pPackage->m_bIsActive )
  3195. {
  3196. SetIconPackagePosition( pPackage );
  3197. if ( !pPackage->IsVisible() )
  3198. {
  3199. RemoveDecoy( i );
  3200. }
  3201. }
  3202. }
  3203. }
  3204. void SFHudRadar::ResizeHud( void )
  3205. {
  3206. if ( !m_pScaleformUI )
  3207. return;
  3208. WITH_SLOT_LOCKED
  3209. {
  3210. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "ForceResizeHud", NULL, 0 );
  3211. }
  3212. }
  3213. void SFHudRadar::ProcessInput( void )
  3214. {
  3215. LazyCreateGoalIcons();
  3216. LazyCreatePlayerIcons();
  3217. ApplySpectatorModes();
  3218. PositionRadarViewpoint();
  3219. PlaceGoalIcons();
  3220. PlacePlayers();
  3221. PlaceHostages();
  3222. UpdateDecoys();
  3223. UpdateAllDefusers();
  3224. UpdateMiscIcons();
  3225. SetupIconsFromStates();
  3226. }
  3227. void SFHudRadar::SwitchRadarToRound( bool toRound )
  3228. {
  3229. if ( !m_bActive || !m_bFlashReady )
  3230. return;
  3231. WITH_SLOT_LOCKED
  3232. {
  3233. if ( m_MapRotation )
  3234. {
  3235. SafeReleaseSFVALUE( m_MapRotation );
  3236. }
  3237. if ( m_MapTranslation )
  3238. {
  3239. SafeReleaseSFVALUE( m_MapTranslation );
  3240. }
  3241. if ( toRound )
  3242. {
  3243. m_bRound = true;
  3244. m_MapRotation = m_pScaleformUI->Value_GetMember( m_Radar, "MapRotation" );
  3245. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SwitchRadarToRound", NULL, 0 );
  3246. }
  3247. else
  3248. {
  3249. m_bRound = false;
  3250. m_MapRotation = m_pScaleformUI->Value_GetMember( m_Radar, "MapRotationSq" );
  3251. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SwitchRadarToSquare", NULL, 0 );
  3252. }
  3253. if ( m_MapRotation )
  3254. {
  3255. m_MapTranslation = m_pScaleformUI->Value_GetMember( m_MapRotation, "MapTranslation" );
  3256. }
  3257. }
  3258. }