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.

2226 lines
70 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "hud.h"
  8. #include "hudelement.h"
  9. #include "hud_element_helper.h"
  10. #include "iclientmode.h"
  11. #include "view.h"
  12. #include "vgui_controls/Controls.h"
  13. #include "vgui/ISurface.h"
  14. #include "ivrenderview.h"
  15. #include "scaleformui/scaleformui.h"
  16. #include "sfhudreticle.h"
  17. #include "vgui/ILocalize.h"
  18. #include "c_cs_hostage.h"
  19. #include "c_cs_player.h"
  20. #include "c_cs_playerresource.h"
  21. #include "engineinterface.h"
  22. #include "interfaces/interfaces.h"
  23. #include "matchmaking/imatchframework.h"
  24. #include "matchmaking/iplayermanager.h"
  25. #include "gameui_util.h"
  26. #include "c_plantedc4.h"
  27. #include "sfhudfreezepanel.h"
  28. #include "inputsystem/iinputsystem.h"
  29. #include "voice_status.h"
  30. #include "basepanel.h"
  31. #include "cs_shareddefs.h"
  32. #include "hltvcamera.h"
  33. #include "cs_hud_weaponselection.h"
  34. #include "HUD/sfhud_teamcounter.h"
  35. #include "hltvreplaysystem.h"
  36. #if !defined (NO_STEAM)
  37. #include "steam/steam_api.h"
  38. #endif
  39. #ifdef SIXENSE
  40. #include "sixense/in_sixense.h"
  41. #endif
  42. // memdbgon must be the last include file in a .cpp file!!!
  43. #include "tier0/memdbgon.h"
  44. //ConVar sfcrosshair( "sfcrosshair", "1", FCVAR_ARCHIVE | FCVAR_SS );
  45. ConVar crosshair( "crosshair", "1", FCVAR_ARCHIVE | FCVAR_SS );
  46. ConVar cl_observercrosshair( "cl_observercrosshair", "1", FCVAR_ARCHIVE | FCVAR_SS );
  47. ConVar cl_fixedcrosshairgap( "cl_fixedcrosshairgap", "3", FCVAR_ARCHIVE | FCVAR_SS, "How big to make the gap between the pips in the fixed crosshair" );
  48. ConVar lockMoveControllerRet( "lockMoveControllerRet", "0", FCVAR_ARCHIVE );
  49. static ConVar hud_showtargetid( "hud_showtargetid", "1", FCVAR_ARCHIVE | FCVAR_SS, "Enables display of target names" );
  50. //extern ConVar cl_dynamiccrosshair;
  51. extern ConVar cl_teamid_overhead;
  52. extern ConVar cl_teamid_overhead_maxdist;
  53. extern ConVar cl_teamid_overhead_maxdist_spec;
  54. extern ConVar voice_icons_method;
  55. extern ConVar cl_crosshairstyle;
  56. extern ConVar spec_show_xray;
  57. extern ConVar cl_draw_only_deathnotices;
  58. extern ConVar mp_hostages_takedamage;
  59. static ConVar cl_teamid_overhead_name_alpha( "cl_teamid_overhead_name_alpha", "100", FCVAR_ARCHIVE | FCVAR_SS, "The max alpha the overhead ID names will draw as." );
  60. static ConVar cl_teamid_overhead_name_fadetime( "cl_teamid_overhead_name_fadetime", "1.0", FCVAR_ARCHIVE | FCVAR_SS, "How long it takes for the overhad name to fade out once your crosshair has left the target." );
  61. static ConVar mc_use_recoil_on_cursor( "mc_use_recoil_on_cursor", "0", 0 );
  62. void fnTeamIDOverheadAlwaysCallback( IConVar *pConVar, const char *pOldValue, float flOldValue )
  63. {
  64. ConVarRef var( pConVar );
  65. ( GET_HUDELEMENT( SFHudReticle ) )->ToggleTeamEquipmentVisibility( var.GetInt() == 2 );
  66. }
  67. static ConVar cl_teamid_overhead_always( "cl_teamid_overhead_always", "0", FCVAR_ARCHIVE | FCVAR_RELEASE,"Always show team id over teammates. 1 = pips; 2 = pips, name, and equipment", fnTeamIDOverheadAlwaysCallback );
  68. #define MAX_PLAYER_NAME_ID_PANELS 16
  69. enum ID_TEXT_INDEX
  70. {
  71. IDTEXT_NONE,
  72. IDTEXT_FOE,
  73. IDTEXT_FRIEND,
  74. IDTEXT_HOSTAGE
  75. };
  76. DECLARE_HUDELEMENT( SFHudReticle );
  77. void IN_ShowTeamEquipmentDown( const CCommand &args )
  78. {
  79. ( GET_HUDELEMENT( SFHudReticle ) )->ToggleTeamEquipmentVisibility( true );
  80. }
  81. void IN_ShowTeamEquipmentUp( const CCommand &args )
  82. {
  83. ( GET_HUDELEMENT( SFHudReticle ) )->ToggleTeamEquipmentVisibility( false );
  84. }
  85. static ConCommand ShowAllTargetIDs( "+cl_show_team_equipment", IN_ShowTeamEquipmentDown );
  86. static ConCommand UnShowAllTargetIDs( "-cl_show_team_equipment", IN_ShowTeamEquipmentUp );
  87. SFUI_BEGIN_GAME_API_DEF
  88. SFUI_DECL_METHOD_AS( OnSwapReticle, "SwapReticle" ),
  89. SFUI_END_GAME_API_DEF( SFHudReticle, Reticle );
  90. SFHudReticle::SFHudReticle( const char *value ) : SFHudFlashInterface( value ),
  91. m_WeaponCrosshairHandle( NULL ),
  92. m_TopPip( NULL ),
  93. m_BottomPip( NULL ),
  94. m_LeftPip( NULL ),
  95. m_RightPip( NULL ),
  96. m_topCrosshairArc( NULL ),
  97. m_rightCrosshairArc( NULL ),
  98. m_leftCrosshairArc( NULL ),
  99. m_bottomCrosshairArc( NULL ),
  100. m_FriendCrosshair( NULL ),
  101. m_crosshairDot( NULL ),
  102. m_blackRing( NULL ),
  103. m_IDText( NULL ),
  104. m_IDMovie( NULL ),
  105. m_FlashedIcon( NULL ),
  106. m_fIDTimer( 0.0f ),
  107. m_bTextIDVisible( false ),
  108. m_iReticleMode( RETICLE_MODE_NONE ),
  109. m_bFriendlyCrosshairVisible( true ),
  110. m_bEnemyCrosshairVisible( false ),
  111. m_bFlashedIconFadingOut(true),
  112. m_iLastGap( -1 ),
  113. m_iLastSpread( -1 ),
  114. m_dotX( 0.0f ),
  115. m_dotY( 0.0f ),
  116. m_blackRingX( 0.0f ),
  117. m_blackRingY( 0.0f ),
  118. m_friendIndicatorX( 0.0f ),
  119. m_friendIndicatorY( 0.0f ),
  120. m_IDMovieX( 0.0f ),
  121. m_IDMovieY( 0.0f ),
  122. m_bCrosshairPositionsInitialized( false )
  123. {
  124. // TODO Auto-generated constructor stub
  125. SetHiddenBits( HIDEHUD_PLAYERDEAD | HIDEHUD_CROSSHAIR );
  126. m_wcIDString[0] = 0;
  127. m_bWantLateUpdate = true;
  128. }
  129. SFHudReticle::~SFHudReticle()
  130. {
  131. // TODO Auto-generated destructor stub
  132. }
  133. void SFHudReticle::ShowReticle( RETICLE_MODE mode, bool value )
  134. {
  135. SFVALUE handle = 0;
  136. switch( mode )
  137. {
  138. case RETICLE_MODE_WEAPON:
  139. handle = m_WeaponCrosshairHandle;
  140. break;
  141. case RETICLE_MODE_OBSERVER:
  142. handle = m_ObserverCrosshairHandle;
  143. break;
  144. default:
  145. break;
  146. }
  147. if ( handle )
  148. {
  149. m_pScaleformUI->Value_SetVisible( handle, value );
  150. }
  151. }
  152. void SFHudReticle::LockSlot( bool wantItLocked, bool& currentlyLocked )
  153. {
  154. if ( currentlyLocked != wantItLocked )
  155. {
  156. if ( wantItLocked )
  157. LockScaleformSlot();
  158. else
  159. UnlockScaleformSlot();
  160. currentlyLocked = wantItLocked;
  161. }
  162. }
  163. extern ConVar weapon_debug_spread_show;
  164. void SFHudReticle::ProcessInput( void )
  165. {
  166. if ( !FlashAPIIsValid() )
  167. return;
  168. SF_SPLITSCREEN_PLAYER_GUARD();
  169. bool bShowFriendlyCrosshair = false;
  170. RETICLE_MODE iDesiredReticleMode = RETICLE_MODE_NONE;
  171. wchar_t wcNewString[ TEXTFIELD_LENGTH ];
  172. wcNewString[0] = 0;
  173. C_CSPlayer *pCSPlayer = GetHudPlayer();
  174. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  175. // do crosshair calculations first because they can affect the
  176. // display of the target id
  177. bool bWantWeaponShown = false;
  178. bool bHasWeapon = false;
  179. bool bPlayerInInputMode = false;
  180. bool bShowCrosshair = false;
  181. bool bShowFriendEnemyDesignation = false;
  182. bool bFriendlyCrosshairOkay = false;
  183. bool bShowDroppedWeaponNames = false;
  184. bool bCheckWeaponRange = false;
  185. bool bWantEnemyCrosshair = false;
  186. int iDesiredGap = -1;
  187. int iDesiredSpread = -1;
  188. float fDesiredFishtail = 0.0f;
  189. int iObsMode = OBS_MODE_NONE;
  190. /************************************
  191. * the logic below is complicated, but here's what it means:
  192. * 1 - If we're not in spectator mode, then only show a crosshair if we're not in an input mode
  193. * and we have a weapon ( normally true ) and the weapon wants a crosshair.
  194. * 2 - If we're in spectator in eye mode, show a crosshair if the weapon wants it
  195. * but don't show the friendly target icon
  196. * 3 - If we're in spectator roaming mode, show the spectator crosshair
  197. * 4 - Otherwise show no crosshair
  198. */
  199. if ( pLocalPlayer && crosshair.GetBool() )
  200. {
  201. iObsMode = pLocalPlayer->GetObserverMode();
  202. switch( iObsMode )
  203. {
  204. case OBS_MODE_IN_EYE:
  205. case OBS_MODE_ROAMING:
  206. bShowCrosshair = true;
  207. break;
  208. case OBS_MODE_NONE:
  209. bFriendlyCrosshairOkay = true;
  210. bShowDroppedWeaponNames = true;
  211. bShowCrosshair = true;
  212. bShowFriendEnemyDesignation = true;
  213. break;
  214. default:
  215. bShowCrosshair = false;
  216. break;
  217. }
  218. #ifdef IRONSIGHT
  219. CWeaponCSBase *pCSWeapon = pLocalPlayer->GetActiveCSWeapon();
  220. if ( pCSWeapon && pCSWeapon->GetIronSightController() && !weapon_debug_spread_show.GetBool() )
  221. {
  222. bShowCrosshair = !pCSWeapon->GetIronSightController()->ShouldHideCrossHair();
  223. }
  224. #endif //IRONSIGHT
  225. if ( bShowCrosshair && iObsMode != OBS_MODE_ROAMING )
  226. {
  227. if ( pLocalPlayer->IsInVGuiInputMode() || pLocalPlayer->IsInViewModelVGuiInputMode() )
  228. bPlayerInInputMode = true;
  229. else
  230. {
  231. CWeaponCSBase *pWeapon = ( CWeaponCSBase* )pCSPlayer->GetActiveWeapon();
  232. if ( pWeapon )
  233. {
  234. bHasWeapon = true;
  235. if ( pWeapon->WantReticleShown() )
  236. {
  237. if ( pWeapon->GetCSWeaponID() == WEAPON_TASER )
  238. {
  239. // When using the taser we don't want to change the reticle color until the
  240. // target is in range.
  241. bCheckWeaponRange = true;
  242. }
  243. bWantWeaponShown = true;
  244. iDesiredSpread = pWeapon->GetReticleWeaponSpread();
  245. iDesiredGap = pWeapon->GetReticleCrosshairGap();
  246. fDesiredFishtail = pWeapon->GetAccuracyFishtail();
  247. }
  248. }
  249. }
  250. }
  251. // the reticle mode is defaulted to NONE above (outside this clause) so
  252. // we don't have to explicitly sent none
  253. if ( bShowCrosshair )
  254. {
  255. if ( iObsMode == OBS_MODE_ROAMING )
  256. {
  257. iDesiredReticleMode = RETICLE_MODE_OBSERVER;
  258. }
  259. else if ( pLocalPlayer && !bPlayerInInputMode && bHasWeapon && bWantWeaponShown )
  260. {
  261. iDesiredReticleMode = RETICLE_MODE_WEAPON;
  262. }
  263. }
  264. }
  265. bool bShowBlankXHairID = false;
  266. bool bIsHostage = false;
  267. bool bLocalIsSpectatorViewer = CanSeeSpectatorOnlyTools();
  268. bool bForceShowCenterID = false;
  269. bool displayingTargetID = false;
  270. bool bIsFullyBlinded = pCSPlayer && pCSPlayer->m_flFlashOverlayAlpha >= 180.0f;
  271. bool bIsFlashed = pCSPlayer && pCSPlayer->m_flFlashBangTime > ( gpGlobals->curtime+0.5 );
  272. if ( m_FlashedIcon && !cl_draw_only_deathnotices.GetBool() )
  273. {
  274. if ( pCSPlayer->m_flFlashOverlayAlpha > 0 && bLocalIsSpectatorViewer )
  275. {
  276. float flFlashFrac = 1.0 - clamp( pCSPlayer->m_flFlashOverlayAlpha / 210, 0, 1 );
  277. // show flashed
  278. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
  279. {
  280. m_pScaleformUI->ValueArray_SetElement( args, 0, flFlashFrac );
  281. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "FlashFade", args, 1 );
  282. }
  283. m_bFlashedIconFadingOut = true;
  284. }
  285. else if ( m_bFlashedIconFadingOut )
  286. {
  287. WITH_SLOT_LOCKED
  288. {
  289. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "Hide", NULL, 0 );
  290. }
  291. m_bFlashedIconFadingOut = false;
  292. }
  293. }
  294. if ( hud_showtargetid.GetBool() )
  295. {
  296. // if we're still blinded, then leave everything just like it is
  297. if ( !bLocalIsSpectatorViewer && bIsFlashed )
  298. return;
  299. // if we're spectating and the player we're observing is fully blind, say so in the target id
  300. if ( iObsMode == OBS_MODE_IN_EYE && bIsFullyBlinded && !cl_draw_only_deathnotices.GetBool() )
  301. {
  302. displayingTargetID = true;
  303. g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( "#SFUIHUD_targetid_FLASHED" ), 0 );
  304. }
  305. else if ( ( iDesiredReticleMode != RETICLE_MODE_NONE ) || ( pCSPlayer->GetFOV() != pCSPlayer->GetDefaultFOV() ) )
  306. {
  307. // Get our target's ent index
  308. int iEntIndex = hud_showtargetid.GetBool() ? pCSPlayer->GetIDTarget() : 0;
  309. if ( iEntIndex )
  310. {
  311. C_CSPlayer *pPlayer = static_cast<C_CSPlayer*>( cl_entitylist->GetEnt( iEntIndex ) );
  312. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  313. const char *printFormatString = NULL;
  314. wchar_t wszClanTag[ MAX_PLAYER_NAME_LENGTH ];
  315. wchar_t wszPlayerName[ MAX_DECORATED_PLAYER_NAME_LENGTH ];
  316. wchar_t wszHealthText[ 10 ];
  317. bool bShowHealth = false;
  318. bool bShowPlayerName = false;
  319. // Some entities we always want to check, cause the text may change
  320. // even while we're looking at it
  321. // Is it a player?
  322. if ( IsPlayerIndex( iEntIndex ) )
  323. {
  324. // check player because they may have been endeadend
  325. if ( pPlayer )
  326. {
  327. bShowPlayerName = true;
  328. if ( pPlayer->IsOtherSameTeam( pLocalPlayer->GetTeamNumber() ) && !pPlayer->IsOtherEnemy( pLocalPlayer->entindex() ) )
  329. {
  330. printFormatString = ( bShowFriendEnemyDesignation ) ? "#SFUIHUD_playerid_sameteam" : "#SFUIHUD_playerid_specteam";
  331. bShowFriendlyCrosshair = bFriendlyCrosshairOkay;
  332. bShowHealth = true;
  333. }
  334. else if ( pLocalPlayer->GetTeamNumber() != TEAM_CT && pLocalPlayer->GetTeamNumber() != TEAM_TERRORIST )
  335. {
  336. printFormatString = "#SFUIHUD_playerid_noteam";
  337. bShowFriendlyCrosshair = bFriendlyCrosshairOkay;
  338. bShowHealth = true;
  339. }
  340. else
  341. {
  342. printFormatString = ( bShowFriendEnemyDesignation ) ? "#SFUIHUD_playerid_diffteam" : "#SFUIHUD_playerid_specteam";
  343. bShowFriendlyCrosshair = false;
  344. bWantEnemyCrosshair = bShowFriendEnemyDesignation;
  345. if ( bWantEnemyCrosshair && bCheckWeaponRange )
  346. {
  347. CWeaponCSBase *pWeapon = ( CWeaponCSBase* )pCSPlayer->GetActiveWeapon();
  348. if ( pWeapon )
  349. {
  350. float flWeaponRange = pWeapon->GetCSWpnData().GetRange();
  351. vec_t length = VectorLength( pPlayer->WorldSpaceCenter() - pLocalPlayer->Weapon_ShootPosition() );
  352. bWantEnemyCrosshair = ( length <= flWeaponRange );
  353. }
  354. }
  355. }
  356. // only get the name and health if necessary
  357. if ( !( cl_teamid_overhead.GetInt() && bShowFriendlyCrosshair ) )
  358. {
  359. C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
  360. if ( cs_PR )
  361. {
  362. cs_PR->GetDecoratedPlayerName( iEntIndex, wszPlayerName, sizeof( wszPlayerName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
  363. }
  364. else
  365. {
  366. wszPlayerName[0] = L'\0';
  367. }
  368. if ( bShowHealth )
  369. {
  370. float flHealth = MAX( 0.0f, ( float )pPlayer->GetHealth() );
  371. V_snwprintf( wszHealthText, ARRAYSIZE( wszHealthText ) - 1, L"%.0f%%", ( flHealth / ( float )pPlayer->GetMaxHealth() ) * 100 );
  372. wszHealthText[ ARRAYSIZE( wszHealthText )-1 ] = '\0';
  373. }
  374. }
  375. else
  376. {
  377. wszPlayerName[0] = L'\0';
  378. }
  379. }
  380. }
  381. else
  382. {
  383. C_BaseEntity *pEnt = cl_entitylist->GetEnt( iEntIndex );
  384. //Hostages!
  385. C_CHostage *pHostage = NULL;
  386. for( int i=0;i<g_Hostages.Count();i++ )
  387. {
  388. // compare entity pointers
  389. if( g_Hostages[i] == pEnt )
  390. {
  391. pHostage = g_Hostages[i];
  392. break;
  393. }
  394. }
  395. if( pHostage != NULL )
  396. {
  397. float flHealth = MAX( 0.0f, ( float )pPlayer->GetHealth() );
  398. V_snwprintf( wszHealthText, ARRAYSIZE( wszHealthText ) - 1, L"%.0f%%", ( flHealth / ( float )pHostage->GetMaxHealth() ) * 100 );
  399. wszHealthText[ ARRAYSIZE( wszHealthText )-1 ] = '\0';
  400. bShowFriendlyCrosshair = bFriendlyCrosshairOkay;
  401. bShowHealth = mp_hostages_takedamage.GetBool();
  402. bIsHostage = true;
  403. Vector forward, up;
  404. pLocalPlayer->EyeVectors( &forward, NULL, &up );
  405. trace_t tr;
  406. // Search for objects in a sphere (tests for entities that are not solid, yet still useable)
  407. Vector searchCenter = pLocalPlayer->EyePosition();
  408. int useableContents = MASK_NPCSOLID_BRUSHONLY | MASK_OPAQUE_AND_NPCS;
  409. UTIL_TraceLine( searchCenter, searchCenter + forward * 1024, useableContents, pLocalPlayer, COLLISION_GROUP_NONE, &tr );
  410. if ( tr.m_pEnt )
  411. {
  412. CConfigurationForHighPriorityUseEntity_t cfgUseHostageRule;
  413. bool bValidHostageRule = pLocalPlayer->GetUseConfigurationForHighPriorityUseEntity( pHostage, cfgUseHostageRule );
  414. // if we're outside use range, we're a terrorist or the hostage has a leader and it's not the player...
  415. if ( !bValidHostageRule || !cfgUseHostageRule.UseByPlayerNow( pLocalPlayer, cfgUseHostageRule.k_EPlayerUseType_Start ) ||
  416. pLocalPlayer->GetTeamNumber() == TEAM_TERRORIST || (pHostage->GetLeader() && pHostage->GetLeader() != pLocalPlayer) ||
  417. (HOSTAGE_RULE_CAN_PICKUP && pLocalPlayer->m_hCarriedHostage != NULL) )
  418. {
  419. if ( pHostage->GetLeader() && pHostage->GetLeader() != pLocalPlayer)
  420. {
  421. if ( !bShowHealth )
  422. printFormatString = "#SFUIHUD_hostageid_nh_following";
  423. else
  424. printFormatString = "#SFUIHUD_hostageid_following";
  425. C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
  426. char szClan[MAX_PLAYER_NAME_LENGTH];
  427. g_pVGuiLocalize->ConvertANSIToUnicode( szClan, wszClanTag, sizeof( wszClanTag ) );
  428. if ( cs_PR )
  429. {
  430. cs_PR->GetDecoratedPlayerName( pHostage->GetLeader()->entindex(), wszPlayerName, sizeof( wszPlayerName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
  431. }
  432. else
  433. {
  434. wszPlayerName[0] = L'\0';
  435. }
  436. bShowPlayerName = true;
  437. }
  438. else
  439. {
  440. if ( !bShowHealth )
  441. {
  442. //SFUIHUD_hostagename_nh
  443. if ( CSGameRules()->IsPlayingCooperativeGametype() )
  444. {
  445. bShowPlayerName = true;
  446. g_pVGuiLocalize->ConstructString( wszPlayerName, sizeof( wszPlayerName ), g_pVGuiLocalize->Find( pHostage->GetCustomHostageNameForMap( engine->GetLevelNameShort() ) ), 0 );
  447. printFormatString = "#SFUIHUD_hostagename_nh";
  448. }
  449. else
  450. printFormatString = "#SFUIHUD_hostageid_nh";
  451. }
  452. else
  453. printFormatString = "#SFUIHUD_hostageid";
  454. }
  455. }
  456. else
  457. {
  458. if ( pHostage->GetLeader() == pLocalPlayer )
  459. {
  460. // if ( !bShowHealth )
  461. // printFormatString = "#SFUIHUD_hostageid_nh_use_leave";
  462. // else
  463. // printFormatString = "#SFUIHUD_hostageid_use_leave";
  464. }
  465. else if ( !pHostage->GetLeader() )
  466. {
  467. if ( !bShowHealth )
  468. printFormatString = "#SFUIHUD_hostageid_nh_use_lead";
  469. else
  470. printFormatString = "#SFUIHUD_hostageid_use_lead";
  471. }
  472. }
  473. }
  474. }
  475. }
  476. if ( printFormatString )
  477. {
  478. if ( cl_teamid_overhead.GetInt() && bShowFriendlyCrosshair && !bIsHostage )
  479. {
  480. Vector vDelta = pPlayer->EyePosition() - pLocalPlayer->EyePosition();
  481. float flDistance = vDelta.Length();
  482. if ( pPlayer->IsOtherSameTeam( pLocalPlayer->GetTeamNumber() ) && !pPlayer->IsOtherEnemy( pLocalPlayer->entindex() )
  483. && pPlayer->IsBot() && pPlayer->HasC4() && flDistance < PLAYER_USE_BOT_RADIUS )
  484. {
  485. g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( "#SFUIHUD_botid_request_bomb" ), 0 );
  486. bForceShowCenterID = true;
  487. }
  488. else
  489. {
  490. V_snwprintf( wcNewString, ARRAYSIZE( wcNewString ), L"" );
  491. bShowBlankXHairID = true;
  492. }
  493. displayingTargetID = true;
  494. }
  495. else
  496. {
  497. displayingTargetID = true;
  498. if ( bShowPlayerName && bShowHealth )
  499. {
  500. g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 2, wszPlayerName, wszHealthText );
  501. }
  502. else if ( bShowPlayerName )
  503. {
  504. g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 1, wszPlayerName );
  505. }
  506. else if ( bShowHealth )
  507. {
  508. g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 1, wszHealthText );
  509. }
  510. else
  511. {
  512. g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 0 );
  513. }
  514. }
  515. }
  516. }
  517. if ( !displayingTargetID && bShowDroppedWeaponNames )
  518. {
  519. int weaponEntIndex = pCSPlayer->GetTargetedWeapon();
  520. if ( weaponEntIndex > 0 ) //0 is a valid entity index, but will never be used for a weapon
  521. {
  522. C_BaseEntity *pEnt = cl_entitylist->GetEnt( weaponEntIndex );
  523. C_PlantedC4 *pC4 = dynamic_cast<C_PlantedC4*>( pEnt );
  524. if ( !pC4 )
  525. {
  526. CWeaponCSBase* weapon = static_cast<CWeaponCSBase*>( pEnt );
  527. bool isWeaponAllowed = ( weapon && ( !weapon->IsA(WEAPON_TASER) /* || weapon->HasAnyAmmo()*/ ) ); // we allow players to pick up guns without ammo --mtw
  528. CEconItemView *pItem = weapon->GetEconItemView();
  529. wchar_t wcTargetWeaponFormatted[128];
  530. if ( pItem && pItem->IsValid() )
  531. {
  532. const CEconItemRarityDefinition* pRarity = GetItemSchema()->GetRarityDefinition( pItem->GetRarity() );
  533. const int kColorBufSize = 128;
  534. wchar_t rwchColor[kColorBufSize];
  535. Q_UTF8ToUnicode( GetHexColorForAttribColor( pRarity->GetAttribColor() ), rwchColor, kColorBufSize );
  536. // Update target name
  537. V_snwprintf( wcTargetWeaponFormatted, ARRAYSIZE( wcTargetWeaponFormatted ), L"<font color=\"" PRI_WS_FOR_WS L"\">" PRI_WS_FOR_WS L"</font>", rwchColor, pItem->GetItemName( true ) );
  538. }
  539. else
  540. {
  541. V_snwprintf( wcTargetWeaponFormatted, ARRAYSIZE( wcTargetWeaponFormatted ), PRI_WS_FOR_WS, g_pVGuiLocalize->Find( weapon->GetPrintName() ) );
  542. }
  543. //const char* szWeaponPrintName = ( pItem ? pItem->GetItemDefinition()->GetItemBaseName() : weapon->GetPrintName() );
  544. if ( isWeaponAllowed && wcTargetWeaponFormatted )
  545. {
  546. displayingTargetID = true;
  547. CSWeaponType nType = weapon->GetWeaponType();
  548. if ( pCSPlayer->IsPrimaryOrSecondaryWeapon( nType ) )
  549. {
  550. // check to see if we are swapping weapons or if we are just filling in an empty weapon slot
  551. bool bSwap = false;
  552. if ( (nType == WEAPONTYPE_PISTOL && pCSPlayer->Weapon_GetSlot( WEAPON_SLOT_PISTOL )) || ( nType != WEAPONTYPE_PISTOL && pCSPlayer->Weapon_GetSlot( WEAPON_SLOT_RIFLE ) ) )
  553. bSwap = true;
  554. if ( bSwap )
  555. {
  556. //const wchar_t* wszWeaponText = g_pVGuiLocalize->Find( szWeaponPrintName );
  557. g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( "#SFUIHUD_weaponid_pickup" ), 1, wcTargetWeaponFormatted );
  558. }
  559. else
  560. {
  561. V_snwprintf( wcNewString, ARRAYSIZE( wcNewString ), PRI_WS_FOR_WS, wcTargetWeaponFormatted );
  562. }
  563. }
  564. else
  565. {
  566. V_snwprintf( wcNewString, ARRAYSIZE( wcNewString ), PRI_WS_FOR_WS, wcTargetWeaponFormatted );
  567. displayingTargetID = true;
  568. }
  569. }
  570. }
  571. }
  572. }
  573. }
  574. }
  575. // player ID
  576. FOR_EACH_VEC( m_playerIDs, i )
  577. {
  578. m_playerIDs[i].bActive = false;
  579. }
  580. {
  581. MDLCACHE_CRITICAL_SECTION();
  582. bool bIsPauseMenuActive = ( BasePanel() && BasePanel()->IsScaleformPauseMenuActive() );
  583. bool bShowAllNamesForSpec = (bLocalIsSpectatorViewer && spec_show_xray.GetInt());
  584. for ( int i = 1; i <= gpGlobals->maxClients; i++ )
  585. {
  586. if ( bIsPauseMenuActive )
  587. break;
  588. //TODO: check whether they are an enemy as well
  589. CCSPlayer* pOtherPlayer = ToCSPlayer( UTIL_PlayerByIndex( i ) );
  590. bool bTurnedOff = false;
  591. if ( cl_teamid_overhead.GetBool() == false || cl_draw_only_deathnotices.GetBool() == true )
  592. bTurnedOff = true;
  593. if ( bTurnedOff || !pLocalPlayer || !pOtherPlayer || !pOtherPlayer->IsAlive( ) || !pOtherPlayer->IsVisible( ) || ( pOtherPlayer == pCSPlayer && !input->CAM_IsThirdPersonOverview( ) ) )
  594. continue;
  595. if ( g_HltvReplaySystem.GetHltvReplayDelay() )
  596. continue; // in replay, there's a clear indication of "You". People seem to not care about the other labels that add to visual noise.
  597. static ConVarRef sv_show_voip_indicator_for_enemies( "sv_show_voip_indicator_for_enemies" );
  598. if ( bShowAllNamesForSpec || (pCSPlayer->IsOtherSameTeam( pOtherPlayer->GetTeamNumber() ) && !pCSPlayer->IsOtherEnemy( pOtherPlayer ) ) || ( sv_show_voip_indicator_for_enemies.GetBool() && pOtherPlayer->IsPlayerTalkingOverVOIP() ) )
  599. {
  600. bool bSameTeam = pLocalPlayer->InSameTeam( pOtherPlayer );
  601. bool bIsEnemy = pLocalPlayer->IsOtherEnemy( pOtherPlayer );
  602. Vector vDelta = pOtherPlayer->EyePosition() - pCSPlayer->EyePosition();
  603. float flDistance = vDelta.Length();
  604. // get our spectator target
  605. int nTargetSpec = g_bEngineIsHLTV ? HLTVCamera()->GetCurrentOrLastTarget() : (pLocalPlayer->GetObserverTarget() ? pLocalPlayer->GetObserverTarget()->entindex() : -1);
  606. // max distance to draw the names is different depending on whether we are on team spectator or not
  607. float flMaxDrawDist = bShowAllNamesForSpec ? cl_teamid_overhead_maxdist_spec.GetInt() : cl_teamid_overhead_maxdist.GetInt();
  608. // always show the name for the player who is our target when roaming
  609. if ( bShowAllNamesForSpec && nTargetSpec == pOtherPlayer->entindex() && (pLocalPlayer->GetObserverMode() == OBS_MODE_FIXED || pLocalPlayer->GetObserverMode() == OBS_MODE_ROAMING) )
  610. flMaxDrawDist = 99999.9f;
  611. if ( flDistance <= flMaxDrawDist )
  612. {
  613. Vector vecOtherPlayerEyes = pOtherPlayer->EyePosition() + Vector( 0, 0, 3 );
  614. // other player is close enough, now make sure the local player is facing the other player.
  615. Vector vecOtherPlayerPos = pOtherPlayer->EyePosition();
  616. Vector forward;
  617. AngleVectors(pCSPlayer->EyeAngles(), &forward, NULL, NULL);
  618. Vector toAimSpot = vecOtherPlayerEyes - pCSPlayer->EyePosition();
  619. float rangeToEnemy = toAimSpot.NormalizeInPlace();
  620. float flTargetIDCone = DotProduct( toAimSpot, forward );
  621. const float flViewCone = 0.5f;
  622. bool bPlayerIsNotVisible = false;
  623. // trace against world for enemies or if client doesn't want team id everywhere+
  624. {
  625. // if we can't trace to the player or if they are obscured by smoke, skip them
  626. CBasePlayer *lastPlayerHit = NULL;
  627. trace_t tr;
  628. if ( pCSPlayer->IsAlive( ) && ( flTargetIDCone > flViewCone ) && !bShowAllNamesForSpec )
  629. {
  630. if ( LineGoesThroughSmoke( pCSPlayer->EyePosition(), vecOtherPlayerEyes, 1.0f ) )
  631. {
  632. if ( !ShouldShowAllFriendlyTargetIDs() || pCSPlayer->IsOtherEnemy( pOtherPlayer ) )
  633. {
  634. continue;
  635. }
  636. else
  637. {
  638. bPlayerIsNotVisible = true;
  639. }
  640. }
  641. UTIL_TraceLine( pCSPlayer->EyePosition(), vecOtherPlayerEyes, MASK_VISIBLE, pCSPlayer, COLLISION_GROUP_DEBRIS, &tr );
  642. {
  643. CTraceFilterSkipTwoEntities filter( pCSPlayer, lastPlayerHit, COLLISION_GROUP_DEBRIS );
  644. // Check for player hitboxes extending outside their collision bounds
  645. const float rayExtension = 40.0f;
  646. UTIL_ClipTraceToPlayers( pCSPlayer->EyePosition(), vecOtherPlayerEyes + forward * rayExtension, MASK_VISIBLE, &filter, &tr );
  647. if ( tr.fraction < 1 )
  648. {
  649. if ( !ShouldShowAllFriendlyTargetIDs() || pCSPlayer->IsOtherEnemy( pOtherPlayer ) )
  650. {
  651. continue;
  652. }
  653. else
  654. {
  655. bPlayerIsNotVisible = true;
  656. }
  657. }
  658. }
  659. }
  660. }
  661. // aiming tolerance depends on how close the target is - closer targets subtend larger angles
  662. float aimTolerance = 0.6f; //(float)cos( atan( 256 / rangeToEnemy ) );
  663. int index = 0;
  664. bool bExists = false;
  665. // let's do this!
  666. if ( bShowAllNamesForSpec || flTargetIDCone > flViewCone )
  667. {
  668. FOR_EACH_VEC( m_playerIDs, j )
  669. {
  670. if ( m_playerIDs[j].hPlayer.Get() == pOtherPlayer )
  671. {
  672. index = j;
  673. bExists = true;
  674. m_playerIDs[j].bActive = true;
  675. break;
  676. }
  677. }
  678. int nIDIndex = pCSPlayer->GetIDTarget();
  679. //Msg( "ID Index = %d\n", nIDIndex );
  680. C_BaseEntity *pIDEnt = cl_entitylist->GetEnt( nIDIndex );
  681. bool bShowIDName = CSGameRules()->IsFreezePeriod() || bShowAllNamesForSpec || ((pIDEnt == pOtherPlayer || !pCSPlayer->IsAlive()) && bSameTeam && !bIsEnemy);
  682. if ( !bExists )
  683. {
  684. index = m_playerIDs.Count();
  685. bExists = true;
  686. bool bFriend = false;
  687. C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
  688. if ( cs_PR )
  689. {
  690. XUID nOtherXUID = cs_PR->GetXuid( pOtherPlayer->entindex() );
  691. if ( g_pMatchFramework->GetMatchSystem()->GetPlayerManager()->GetFriendByXUID( nOtherXUID ) )
  692. {
  693. bFriend = true;
  694. }
  695. }
  696. AddNewPlayerID( pOtherPlayer, bShowIDName, bFriend );
  697. }
  698. if ( m_playerIDs.Count() > 0 && index < m_playerIDs.Count() )
  699. {
  700. // update the team number
  701. m_playerIDs[index].nTeam = pOtherPlayer->GetTeamNumber();
  702. bool bFlashedChanged = bLocalIsSpectatorViewer ? (m_playerIDs[index].bFlashedAmt != pOtherPlayer->m_flFlashOverlayAlpha) : false;
  703. bool bHealthChanged = (m_playerIDs[index].nHealth != pOtherPlayer->GetHealth());
  704. bool bUpdateNow = (m_playerIDs[index].flUpdateAt != 0 && m_playerIDs[index].flUpdateAt <= gpGlobals->curtime );
  705. if ( bExists && ( /*CSGameRules()->IsFreezePeriod() ||*/ bUpdateNow || bHealthChanged || bFlashedChanged || m_playerIDs[index].bShowName != bShowIDName) )
  706. {
  707. if ( bShowIDName == false && m_playerIDs[index].bShowName == true )
  708. {
  709. m_playerIDs[index].flLastHighlightTime = gpGlobals->curtime;
  710. }
  711. if ( CSGameRules()->IsFreezePeriod() ) // update again in a bit if we're still in freeze time
  712. m_playerIDs[index].flUpdateAt = gpGlobals->curtime + 0.5f;
  713. else
  714. m_playerIDs[index].flUpdateAt = 0;
  715. m_playerIDs[index].bShowName = bShowIDName;
  716. m_playerIDs[index].nHealth = pOtherPlayer->GetHealth();
  717. UpdatePlayerID( pOtherPlayer, index, true );
  718. }
  719. WITH_SLOT_LOCKED
  720. {
  721. float flScale = clamp( (float)atan( 512 / (rangeToEnemy*1.0) ), 0.6, 2 );
  722. float flAlp = clamp( 1 - (rangeToEnemy / (flMaxDrawDist*0.75)), 0.25, 1 );
  723. //Msg( "scale = %f, rangeToEnemy = %f\n", flScale, rangeToEnemy );
  724. // adjust scale by the screen size
  725. flScale *= clamp( 1-(600.0f/(float)ScreenHeight()), 0.25, 1 );
  726. float flFadeRangeClose = 160;
  727. if ( rangeToEnemy < flFadeRangeClose && !bShowIDName )
  728. {
  729. flAlp *= MAX( 0.25, (rangeToEnemy-(flFadeRangeClose*0.35))/(flFadeRangeClose*0.55) );
  730. }
  731. float flFadeEdge = (1-aimTolerance)*0.4;
  732. if ( flTargetIDCone < (aimTolerance+flFadeEdge) && !bShowAllNamesForSpec )
  733. {
  734. float flFadeEdgeCur = flTargetIDCone - aimTolerance;
  735. flAlp *= MAX( 0.3, flFadeEdgeCur/flFadeEdge );
  736. }
  737. if ( input->CAM_IsThirdPersonOverview() )
  738. {
  739. flScale = 0.8f;
  740. flAlp = 1.0f;
  741. }
  742. // need to make sure that not only do we have a valid handle, but that the handle is of the correct type for GetType to handle it. Otherwise Scaleform just crashes.....
  743. if ( m_playerIDs[index].panel && m_pScaleformUI->Value_GetType( m_playerIDs[index].panel ) == IScaleformUI::VT_DisplayObject )
  744. {
  745. // if the player is talking, hide the arrow and just show the talk icon
  746. if ( m_playerIDs[index].arrowA && m_playerIDs[index].arrowB && m_playerIDs[index].arrowF && m_playerIDs[index].voiceIcon && m_playerIDs[index].defuseIcon )
  747. {
  748. bool bIsFriend = m_playerIDs[index].bFriend;
  749. bool bVoiceActive = !bPlayerIsNotVisible && ( pOtherPlayer->IsPlayerTalkingOverVOIP( ) && ( ( bSameTeam && !bIsEnemy ) || sv_show_voip_indicator_for_enemies.GetBool( ) ) && voice_icons_method.GetInt( ) == 2 );
  750. bool bIsDefusing = !bPlayerIsNotVisible && pOtherPlayer->m_bIsDefusing;
  751. int flags = 0;
  752. flags |= bIsFriend ? 1<<0 : 0;
  753. flags |= bVoiceActive ? 1<<1 : 0;
  754. flags |= bIsDefusing ? 1<<2 : 0;
  755. if ( m_playerIDs[index].iconsFlag != flags )
  756. {
  757. ScaleformDisplayInfo dinfoA;
  758. ScaleformDisplayInfo dinfoB;
  759. ScaleformDisplayInfo dinfoF;
  760. ScaleformDisplayInfo dinfoV;
  761. ScaleformDisplayInfo dinfoD;
  762. dinfoA.SetVisibility( !bVoiceActive && !bIsDefusing );
  763. dinfoB.SetVisibility( !bVoiceActive && /*!bIsFriend &&*/ !bIsDefusing );
  764. dinfoF.SetVisibility( !bVoiceActive && bIsFriend && !bIsDefusing );
  765. dinfoV.SetVisibility( bVoiceActive );
  766. dinfoD.SetVisibility( bIsDefusing && !bVoiceActive );
  767. m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].arrowA, &dinfoA );
  768. m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].arrowB, &dinfoB );
  769. m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].arrowF, &dinfoF );
  770. m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].voiceIcon, &dinfoV );
  771. m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].defuseIcon, &dinfoD );
  772. m_playerIDs[index].iconsFlag = flags;
  773. }
  774. }
  775. // put the indicator right over their head
  776. bool bHaveHeadBone = true;
  777. // Make sure he's all the way on screen so his bone is correct
  778. int iBIndex = -1;
  779. {
  780. iBIndex = pOtherPlayer->LookupBone( "ValveBiped.Bip01_Head" );
  781. }
  782. if( ( iBIndex == -1 ) || !pOtherPlayer->GetBaseAnimating()->isBoneAvailableForRead( iBIndex ) )
  783. {
  784. bHaveHeadBone = false;
  785. }
  786. Vector vecBone;
  787. if ( bHaveHeadBone )
  788. {
  789. QAngle angBone;
  790. pOtherPlayer->GetBonePosition( iBIndex, vecBone, angBone );
  791. }
  792. else
  793. {
  794. vecBone = (pOtherPlayer->EyePosition() - pOtherPlayer->GetAbsOrigin()) + Vector( 0.0f, 0.0f, 20 );
  795. }
  796. int iX, iY;
  797. GetVectorInScreenSpace( vecBone + Vector( 0, 0, 9 ), iX, iY );
  798. //GetTargetInScreenSpace( pFoundEnt, iX, iY );
  799. ScaleformDisplayInfo dinfo;
  800. dinfo.SetVisibility( true );
  801. dinfo.SetAlpha( 140 * flAlp );
  802. dinfo.SetX( iX );
  803. dinfo.SetY( iY );
  804. dinfo.SetXScale( 240 * flScale );
  805. dinfo.SetYScale( 240 * flScale );
  806. m_pScaleformUI->Value_SetDisplayInfo( m_playerIDs[index].panel, &dinfo );
  807. }
  808. }
  809. }
  810. }
  811. }
  812. }
  813. }
  814. } // End MDLCACHE_CRITICAL_SECTION()
  815. // Don't remove players at this point in order to void adding them again (causing spikes)
  816. FOR_EACH_VEC( m_playerIDs, k )
  817. {
  818. if ( m_playerIDs[ k ].bActive == false )
  819. {
  820. //RemoveID( k );
  821. m_pScaleformUI->Value_SetVisible( m_playerIDs[ k ].panel, false );
  822. }
  823. }
  824. if ( !ShouldShowAllFriendlyEquipment() )
  825. {
  826. FOR_EACH_VEC( m_playerIDs, l )
  827. {
  828. float flTimeToFadeOut = cl_teamid_overhead_name_fadetime.GetFloat();
  829. float flExpireTime = m_playerIDs[l].flLastHighlightTime + flTimeToFadeOut;
  830. int nMaxAlpha = cl_teamid_overhead_name_alpha.GetInt();
  831. if ( m_playerIDs[l].bActive && m_playerIDs[l].bShowName == false && m_playerIDs[l].flNameAlpha > 0 )
  832. {
  833. float frac = ( flExpireTime - gpGlobals->curtime ) / flTimeToFadeOut;
  834. int alpha = frac * nMaxAlpha;
  835. SFVALUE animatedID = m_pScaleformUI->Value_GetMember( m_playerIDs[l].panel, "IDClip" );
  836. SFVALUE textBG = m_pScaleformUI->Value_GetMember( m_playerIDs[l].panel, "IDTextBG" );
  837. if ( animatedID /*&& animatedIDDrop*/ && textBG )
  838. {
  839. SFVALUE textmovie = m_pScaleformUI->Value_GetMember( animatedID, "IDTextMovie" );
  840. if ( textmovie /*&& textDrop*/ )
  841. {
  842. ScaleformDisplayInfo dinfo;
  843. ScaleformDisplayInfo dinfo2;
  844. dinfo.SetAlpha( alpha );
  845. dinfo2.SetAlpha( alpha/7 );
  846. if ( alpha <= 0 || frac <= 0 )
  847. {
  848. alpha = 0;
  849. dinfo.SetVisibility( false );
  850. dinfo2.SetVisibility( false );
  851. }
  852. m_playerIDs[l].flNameAlpha = MAX( 0, alpha );
  853. m_pScaleformUI->Value_SetDisplayInfo( textmovie, &dinfo );
  854. m_pScaleformUI->Value_SetDisplayInfo( textBG, &dinfo2 );
  855. SafeReleaseSFVALUE( textmovie );
  856. }
  857. SafeReleaseSFVALUE( animatedID );
  858. SafeReleaseSFVALUE( textBG );
  859. }
  860. }
  861. }
  862. }
  863. // now do all the stuff that might lock the slot
  864. //0 = default
  865. //1 = default static
  866. //2 = classic standard
  867. //3 = classic dynamic
  868. //4 = classic static
  869. if ( cl_crosshairstyle.GetInt() >= 2 )
  870. //if ( !sfcrosshair.GetBool() )
  871. {
  872. iDesiredReticleMode = RETICLE_MODE_NONE;
  873. }
  874. bool bSlotIsLocked = false;
  875. if ( displayingTargetID && (wcNewString[0] || bShowBlankXHairID) )
  876. {
  877. // this updates the text if necessary
  878. if ( V_wcscmp( wcNewString, m_wcIDString ) )
  879. {
  880. LockSlot( true, bSlotIsLocked );
  881. m_pScaleformUI->Value_SetTextHTML( m_IDText, m_pScaleformUI->ReplaceGlyphKeywordsWithHTML( wcNewString ) );
  882. V_wcsncpy( m_wcIDString, wcNewString, TEXTFIELD_LENGTH*sizeof( wchar_t ) );
  883. }
  884. // this shows/hides the friendly crosshair
  885. if ( m_FriendCrosshair && ( bShowFriendlyCrosshair != m_bFriendlyCrosshairVisible ) )
  886. {
  887. LockSlot( true, bSlotIsLocked );
  888. m_pScaleformUI->Value_SetVisible( m_FriendCrosshair, bShowFriendlyCrosshair );
  889. m_bFriendlyCrosshairVisible = bShowFriendlyCrosshair;
  890. }
  891. // update the timer ( which turns the text field off after quarter a second
  892. m_fIDTimer = gpGlobals->curtime + 0.25f;
  893. // call the text field's show animation if it isn't already visible
  894. if ( !m_bTextIDVisible && (bForceShowCenterID || cl_teamid_overhead.GetInt() == 0 || (cl_teamid_overhead.GetInt() > 0 && !bShowFriendlyCrosshair) || bIsHostage) )
  895. {
  896. LockSlot( true, bSlotIsLocked );
  897. m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "Show", NULL, 0 );
  898. m_bTextIDVisible = true;
  899. }
  900. }
  901. else
  902. {
  903. // hide the friendly crosshair since we're not looking at anything anymore
  904. if ( m_bFriendlyCrosshairVisible )
  905. {
  906. LockSlot( true, bSlotIsLocked );
  907. m_pScaleformUI->Value_SetVisible( m_FriendCrosshair, false );
  908. m_bFriendlyCrosshairVisible = false;
  909. }
  910. // once our timer has run out, call the hide animation for the text
  911. if ( m_bTextIDVisible && gpGlobals->curtime >= m_fIDTimer )
  912. {
  913. LockSlot( true, bSlotIsLocked );
  914. m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "Hide", NULL, 0 );
  915. m_bTextIDVisible = false;
  916. }
  917. }
  918. if ( bWantEnemyCrosshair != m_bEnemyCrosshairVisible )
  919. {
  920. m_bEnemyCrosshairVisible = bWantEnemyCrosshair;
  921. float colorIndex = 99;
  922. if ( !bWantEnemyCrosshair )
  923. {
  924. ConVarRef convar( "cl_crosshaircolor" );
  925. colorIndex = convar.GetFloat();
  926. }
  927. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
  928. {
  929. m_pScaleformUI->ValueArray_SetElement( args, 0, colorIndex );
  930. g_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "onUpdateColor", args, 1 );
  931. }
  932. }
  933. if ( iDesiredReticleMode != m_iReticleMode )
  934. {
  935. LockSlot( true, bSlotIsLocked );
  936. ShowReticle( m_iReticleMode, false );
  937. ShowReticle( iDesiredReticleMode, true );
  938. m_iReticleMode = iDesiredReticleMode;
  939. }
  940. if ( m_iReticleMode == RETICLE_MODE_WEAPON )
  941. {
  942. float x = 0.0f;
  943. float y = 0.0f;
  944. #ifdef SIXENSE
  945. if( g_pSixenseInput->IsEnabled() &&
  946. C_BasePlayer::GetLocalPlayer() &&
  947. ( C_BasePlayer::GetLocalPlayer()->GetObserverMode()==OBS_MODE_NONE ) &&
  948. lockMoveControllerRet.GetBool() == false )
  949. #else
  950. if ( inputsystem->MotionControllerActive() &&
  951. C_BasePlayer::GetLocalPlayer() &&
  952. ( C_BasePlayer::GetLocalPlayer()->GetObserverMode()==OBS_MODE_NONE ) &&
  953. lockMoveControllerRet.GetBool() == false )
  954. #endif
  955. {
  956. Vector aimDirection;
  957. if ( mc_use_recoil_on_cursor.GetBool())
  958. {
  959. AngleVectors(pCSPlayer->GetFinalAimAngle(), &aimDirection);
  960. }
  961. else
  962. {
  963. aimDirection = pCSPlayer->GetAimDirection();
  964. }
  965. Vector screen;
  966. Vector point;
  967. VectorAdd( CurrentViewOrigin(), aimDirection, point );
  968. ScreenTransform( point, screen );
  969. x = 0.5f * screen[0] * ScreenWidth() + 0.5f;
  970. y = -0.5f * screen[1] * ScreenHeight() + 0.5f;
  971. }
  972. //0 = default
  973. //1 = default static
  974. //2 = classic standard
  975. //3 = classic dynamic
  976. //4 = classic static
  977. if ( cl_crosshairstyle.GetInt() == 1 )
  978. {
  979. fDesiredFishtail = 0;
  980. }
  981. SetReticlePosition( iDesiredSpread, iDesiredGap, x, y, ( fDesiredFishtail / 200.0f ) * ( ScreenWidth() * 0.5f ) );
  982. }
  983. LockSlot( false, bSlotIsLocked );
  984. }
  985. void SFHudReticle::ToggleTeamEquipmentVisibility( bool bShow )
  986. {
  987. m_bForceShowAllTeammateTargetIDs = bShow;
  988. for ( int i = 1; i <= gpGlobals->maxClients; i++ )
  989. {
  990. CCSPlayer* pCSPlayer = ToCSPlayer( UTIL_PlayerByIndex( i ) );
  991. FOR_EACH_VEC( m_playerIDs, j )
  992. {
  993. if ( m_playerIDs[ j ].hPlayer.Get( ) == pCSPlayer )
  994. {
  995. UpdatePlayerID( pCSPlayer, j );
  996. }
  997. }
  998. }
  999. }
  1000. void SFHudReticle::AddNewPlayerID( CBaseEntity *player, bool bShowName, bool bFriend )
  1001. {
  1002. if ( !FlashAPIIsValid() )
  1003. return;
  1004. if ( !player || m_playerIDs.Count() >= MAX_PLAYER_NAME_ID_PANELS )
  1005. return;
  1006. SFVALUE newPanelHandle = NULL;
  1007. WITH_SLOT_LOCKED
  1008. {
  1009. //Create new panel
  1010. newPanelHandle = m_pScaleformUI->Value_Invoke( m_FlashAPI, "AddNewPlayerID", NULL, 0 );
  1011. }
  1012. if ( newPanelHandle )
  1013. {
  1014. //Put the new panel in the list
  1015. PlayerIDPanel newPanel;
  1016. newPanel.hPlayer = player;
  1017. newPanel.panel = newPanelHandle;
  1018. newPanel.bActive = true;
  1019. newPanel.bFriend = bFriend;
  1020. newPanel.nHealth = player->GetHealth();
  1021. newPanel.nTeam = player->GetTeamNumber();
  1022. newPanel.flNameAlpha = 0;
  1023. newPanel.flLastHighlightTime = 0;
  1024. newPanel.bShowName = false;
  1025. newPanel.flUpdateAt = 0;
  1026. newPanel.iconsFlag = -1;
  1027. newPanel.bFlashedAmt = -1;// we will hide the panel immediately
  1028. if ( m_pScaleformUI->Value_GetType( newPanelHandle ) == IScaleformUI::VT_DisplayObject )
  1029. {
  1030. newPanel.arrowA = m_pScaleformUI->Value_GetMember( newPanelHandle, "IDArrow" );
  1031. newPanel.arrowB = m_pScaleformUI->Value_GetMember( newPanelHandle, "IDArrowBorder" );
  1032. newPanel.arrowF = m_pScaleformUI->Value_GetMember( newPanelHandle, "IDArrowFriend" );
  1033. newPanel.voiceIcon = m_pScaleformUI->Value_GetMember( newPanelHandle, "iconChat" );
  1034. newPanel.defuseIcon = m_pScaleformUI->Value_GetMember( newPanelHandle, "DefuseKitIcon" );
  1035. }
  1036. else
  1037. {
  1038. newPanel.arrowA = NULL;
  1039. newPanel.arrowB = NULL;
  1040. newPanel.arrowF = NULL;
  1041. newPanel.voiceIcon = NULL;
  1042. newPanel.defuseIcon = NULL;
  1043. }
  1044. m_playerIDs.AddToTail( newPanel );
  1045. UpdatePlayerID( player, m_playerIDs.Count()-1 );
  1046. }
  1047. }
  1048. void SFHudReticle::UpdatePlayerID( CBaseEntity *player, int slot, bool bHealthAndNameOnly )
  1049. {
  1050. if ( !FlashAPIIsValid() )
  1051. return;
  1052. C_CSPlayer *pCSPlayer = C_CSPlayer::GetLocalCSPlayer();
  1053. if ( !pCSPlayer || !player || m_playerIDs.Count() >= MAX_PLAYER_NAME_ID_PANELS || slot >= m_playerIDs.Count() )
  1054. return;
  1055. bool bDidSetName = false;
  1056. if ( !m_playerIDs[slot].panel )
  1057. {
  1058. Warning( "AddNewPlayerID called and updated in sfhudreticle, but m_playerIDs[slot].panel is null!!\n" );
  1059. return;
  1060. }
  1061. C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
  1062. if ( !bHealthAndNameOnly )
  1063. {
  1064. int playerIndex = 0;
  1065. for ( int i = 0; i <= MAX_PLAYERS; i++ )
  1066. {
  1067. CBasePlayer* pCheckPlayer = UTIL_PlayerByIndex( i );
  1068. if ( pCheckPlayer && pCheckPlayer == player )
  1069. playerIndex = i;
  1070. }
  1071. int nColorID = -1;
  1072. if ( cs_PR && pCSPlayer->ShouldShowTeamPlayerColors( player->GetTeamNumber() ) )
  1073. nColorID = cs_PR->GetCompTeammateColor( playerIndex );
  1074. // set the color of the icon, need to do it by calling the script
  1075. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 4 )
  1076. {
  1077. m_pScaleformUI->ValueArray_SetElement( args, 0, m_playerIDs[slot].panel );
  1078. m_pScaleformUI->ValueArray_SetElement( args, 1, m_playerIDs[slot].nTeam );
  1079. m_pScaleformUI->ValueArray_SetElement( args, 2, m_playerIDs[slot].bFriend );
  1080. m_pScaleformUI->ValueArray_SetElement( args, 3, nColorID );
  1081. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "setIDTeamColor", args, 4 );
  1082. }
  1083. }
  1084. if ( !cs_PR )
  1085. {
  1086. Warning( "AddNewPlayerID called and updated in sfhudreticle, but C_CS_PlayerResource is null!!\n" );
  1087. return;
  1088. }
  1089. SFVALUE animatedID = m_pScaleformUI->Value_GetMember( m_playerIDs[slot].panel, "IDClip" );
  1090. SFVALUE textBG = m_pScaleformUI->Value_GetMember( m_playerIDs[slot].panel, "IDTextBG" );
  1091. if ( !animatedID /*&& animatedIDDrop*/ || !textBG )
  1092. {
  1093. Warning( "AddNewPlayerID called and updated in sfhudreticle, but IDClip and IDTextBG objects are null!!\n" );
  1094. return;
  1095. }
  1096. SFVALUE textmovie = m_pScaleformUI->Value_GetMember( animatedID, "IDTextMovie" );
  1097. if ( !textmovie /*&& textDrop*/ )
  1098. {
  1099. Warning( "AddNewPlayerID called and updated in sfhudreticle, but IDTextMovie object is null!!\n" );
  1100. return;
  1101. }
  1102. SFVALUE text = m_pScaleformUI->Value_GetMember( textmovie, "IDText" );
  1103. if ( !text /*&& textDrop*/ )
  1104. {
  1105. Warning( "AddNewPlayerID called and updated in sfhudreticle, but IDText object is null!!\n" );
  1106. return;
  1107. }
  1108. //IDWeaponTextParent
  1109. SFVALUE wepIconParent = m_pScaleformUI->Value_GetMember( textmovie, "IDWeaponTextParent" );
  1110. if ( !wepIconParent )
  1111. return;
  1112. SFVALUE wepIcons = m_pScaleformUI->Value_GetMember( wepIconParent, "IDWeaponText" );
  1113. if ( !wepIcons )
  1114. {
  1115. Warning( "AddNewPlayerID called and updated in sfhudreticle, but IDWeaponText object is null!!\n" );
  1116. return;
  1117. }
  1118. wchar_t wszHealthText[ 10 ];
  1119. float flHealth = 0.0f;
  1120. C_CSPlayer *pTargetPlayer = static_cast<C_CSPlayer*>( player );
  1121. bool bLocalIsSpectatorViewer = CanSeeSpectatorOnlyTools();
  1122. bool bShowMoneyInsteadOfHealth = CSGameRules( )->CanSpendMoneyInMap( ) && CSGameRules( )->IsFreezePeriod( ) && !bLocalIsSpectatorViewer;
  1123. if ( bShowMoneyInsteadOfHealth ) // we show money in the place of health during freeze time
  1124. flHealth = pTargetPlayer->GetAccount( );
  1125. else
  1126. flHealth = ( MAX( 0.0f, ( float ) player->GetHealth( ) ) / ( float ) player->GetMaxHealth( ) );
  1127. // show the main equipped weapon, grenades and money during freezetime or if ShouldShowAllFriendlyEquipment
  1128. if ( ( !bLocalIsSpectatorViewer && ( CSGameRules( )->IsFreezePeriod( ) ) || ShouldShowAllFriendlyEquipment() ) )
  1129. {
  1130. CHudWeaponSelection *pHudSelection = (CHudWeaponSelection *)GET_HUDELEMENT( CHudWeaponSelection );
  1131. if ( !pHudSelection )
  1132. return;
  1133. wchar_t wszWeaponIcons[ MAX_DECORATED_PLAYER_NAME_LENGTH ] = { L"" };
  1134. // weapons are only shown in freeze time.
  1135. bool bShowWeapons = CSGameRules( )->IsFreezePeriod( ) || ShouldShowAllFriendlyEquipment();
  1136. bool bShowDefuser = ShouldShowAllFriendlyEquipment();
  1137. bool bShowC4 = ShouldShowAllFriendlyEquipment();
  1138. CSWeaponID nPrimaryWeaponID = WEAPON_KNIFE;
  1139. if ( bShowWeapons )
  1140. {
  1141. if ( pTargetPlayer && pTargetPlayer->GetActiveCSWeapon( ) )
  1142. {
  1143. if ( !IsPrimaryWeapon( nPrimaryWeaponID )/* && CSGameRules()->IsFreezePeriod()*/ )
  1144. {
  1145. // While in the freeze period we want to show their primary weapon if they have one
  1146. for ( int i = 0; i < MAX_WEAPONS; i++ )
  1147. {
  1148. C_WeaponCSBase *pWeapon = assert_cast< C_WeaponCSBase* >( pTargetPlayer->GetWeapon( i ) );
  1149. if ( !pWeapon )
  1150. continue;
  1151. CSWeaponID nIDTemp = pWeapon->GetCSWeaponID( );
  1152. if ( IsPrimaryWeapon( nIDTemp ) )
  1153. {
  1154. // Found a primary
  1155. nPrimaryWeaponID = nIDTemp;
  1156. break;
  1157. }
  1158. else if ( IsSecondaryWeapon( nIDTemp ) )
  1159. {
  1160. // Fall back to secondary if non-primary and non-secondary is active
  1161. nPrimaryWeaponID = nIDTemp;
  1162. }
  1163. }
  1164. }
  1165. }
  1166. }
  1167. // let's wait on showing armor and defuse kits
  1168. // int nArmor = cs_PR->GetArmor( pTargetPlayer->entindex() );
  1169. // bool bHasHelmet = cs_PR->HasHelmet( pTargetPlayer->entindex() );
  1170. //
  1171. // if ( nArmor > 0 )
  1172. // {
  1173. // const char *szWeapon = "armor";
  1174. // if ( bHasHelmet )
  1175. // szWeapon = "armor_helmet";
  1176. //
  1177. // wchar_t wszWeapon[64];
  1178. // V_UTF8ToUnicode( szWeapon, wszWeapon, sizeof( wszWeapon ) );
  1179. // wchar_t szWeaponHTML[64];
  1180. // GetIconHTML( wszWeapon, szWeaponHTML, ARRAYSIZE( szWeaponHTML ), true );
  1181. // Q_wcsncat( wszWeaponIcons, szWeaponHTML, sizeof( wszWeaponIcons ), COPY_ALL_CHARACTERS );
  1182. // }
  1183. //
  1184. if ( bShowDefuser )
  1185. {
  1186. bool bHasDef = cs_PR->HasDefuser( pTargetPlayer->entindex( ) );
  1187. if ( bHasDef )
  1188. {
  1189. wchar_t wszWeapon[ 64 ];
  1190. V_UTF8ToUnicode( "defuser", wszWeapon, sizeof( wszWeapon ) );
  1191. wchar_t szWeaponHTML[ 64 ];
  1192. GetIconHTML( wszWeapon, szWeaponHTML, ARRAYSIZE( szWeaponHTML ), true );
  1193. Q_wcsncat( wszWeaponIcons, szWeaponHTML, sizeof( wszWeaponIcons ), COPY_ALL_CHARACTERS );
  1194. }
  1195. }
  1196. if ( bShowC4 )
  1197. {
  1198. bool bHasC4 = cs_PR->HasC4( pTargetPlayer->entindex( ) );
  1199. if ( bHasC4 )
  1200. {
  1201. wchar_t wszWeapon[ 64 ];
  1202. V_UTF8ToUnicode( "bomb-holder", wszWeapon, sizeof( wszWeapon ) );
  1203. wchar_t szWeaponHTML[ 64 ];
  1204. GetIconHTML( wszWeapon, szWeaponHTML, ARRAYSIZE( szWeaponHTML ), true );
  1205. Q_wcsncat( wszWeaponIcons, szWeaponHTML, sizeof( wszWeaponIcons ), COPY_ALL_CHARACTERS );
  1206. }
  1207. }
  1208. for ( int slot = MAX_WEAPON_SLOTS; slot >= 0; slot-- )
  1209. {
  1210. for ( int pos = MAX_WEAPON_POSITIONS; pos >= 0; pos-- )
  1211. {
  1212. C_WeaponCSBase *pWeapon = assert_cast< C_WeaponCSBase* >( pHudSelection->GetWeaponInSlotForTarget( pTargetPlayer, slot, pos ) );
  1213. // if we dont have a weapon OR if the found weapon is our selected weapon, skip it
  1214. if ( !pWeapon )
  1215. continue;
  1216. // if we're not showing weapons ignore anything that isn't utility
  1217. if ( !bShowWeapons && !pWeapon->IsKindOf( WEAPONTYPE_GRENADE ) )
  1218. {
  1219. continue;
  1220. }
  1221. // if we are showing weapons then we're only showing primary or utility
  1222. else if ( pWeapon->GetCSWeaponID( ) == nPrimaryWeaponID || pWeapon->IsKindOf( WEAPONTYPE_GRENADE ) )
  1223. {
  1224. CEconItemView *pItem = pWeapon->GetEconItemView( );
  1225. const char *szWeapon = ( ( pItem && pItem->IsValid() && pItem->GetItemIndex() && pItem->GetItemDefinition() )
  1226. ? pItem->GetItemDefinition( )->GetDefinitionName( )
  1227. : pWeapon->GetClassname( ) );
  1228. if ( IsWeaponClassname( szWeapon ) )
  1229. {
  1230. szWeapon += WEAPON_CLASSNAME_PREFIX_LENGTH;
  1231. }
  1232. if ( Q_strcmp( "knife", szWeapon ) == 0 )
  1233. {
  1234. if ( pTargetPlayer && pTargetPlayer->GetTeamNumber( ) == TEAM_CT )
  1235. {
  1236. szWeapon = "knife_default_ct";
  1237. }
  1238. else
  1239. {
  1240. szWeapon = "knife_default_t";
  1241. }
  1242. }
  1243. wchar_t wszWeapon[ 64 ];
  1244. V_UTF8ToUnicode( szWeapon, wszWeapon, sizeof( wszWeapon ) );
  1245. wchar_t szWeaponHTML[ 64 ];
  1246. GetIconHTML( wszWeapon, szWeaponHTML, ARRAYSIZE( szWeaponHTML ), true );
  1247. int nCount = 1;
  1248. if ( pWeapon->IsKindOf( WEAPONTYPE_GRENADE ) )
  1249. nCount = pWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY );
  1250. for ( int nGren = 0; nGren < nCount; nGren++ )
  1251. {
  1252. Q_wcsncat( wszWeaponIcons, szWeaponHTML, sizeof( wszWeaponIcons ), COPY_ALL_CHARACTERS );
  1253. }
  1254. }
  1255. }
  1256. }
  1257. m_pScaleformUI->Value_SetTextHTML( wepIcons, wszWeaponIcons );
  1258. }
  1259. else
  1260. {
  1261. m_pScaleformUI->Value_SetTextHTML( wepIcons, "" );
  1262. }
  1263. // bool bIsFullyBlinded = pCSPlayer->m_flFlashOverlayAlpha >= 180.0f;
  1264. // bool bIsFlashed = pCSPlayer->m_flFlashBangTime > ( gpGlobals->curtime + 0.5 );
  1265. if ( pTargetPlayer )
  1266. {
  1267. float flFlashFrac = 1.0 - clamp( pTargetPlayer->m_flFlashOverlayAlpha / 150, 0, 1 );
  1268. if ( pTargetPlayer->m_flFlashOverlayAlpha > 0 )
  1269. m_playerIDs[ slot ].bFlashedAmt = pTargetPlayer->m_flFlashOverlayAlpha;
  1270. if ( m_playerIDs[ slot ].bFlashedAmt != 0 )
  1271. {
  1272. if ( pTargetPlayer->m_flFlashOverlayAlpha <= 0 || m_playerIDs[ slot ].bFlashedAmt == -1 )
  1273. {
  1274. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
  1275. {
  1276. m_pScaleformUI->ValueArray_SetElement( args, 0, m_playerIDs[ slot ].panel );
  1277. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hideFlashIcon", args, 1 );
  1278. }
  1279. m_playerIDs[ slot ].bFlashedAmt = 0;
  1280. }
  1281. else if ( CanSeeSpectatorOnlyTools( ) )
  1282. {
  1283. // show flashed
  1284. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 2 )
  1285. {
  1286. m_pScaleformUI->ValueArray_SetElement( args, 0, m_playerIDs[ slot ].panel );
  1287. m_pScaleformUI->ValueArray_SetElement( args, 1, flFlashFrac );
  1288. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "setFlashIcon", args, 2 );
  1289. }
  1290. }
  1291. }
  1292. }
  1293. WITH_SLOT_LOCKED
  1294. {
  1295. wchar_t wcNewString[ TEXTFIELD_LENGTH ];
  1296. wchar_t wszPlayerName[ MAX_DECORATED_PLAYER_NAME_LENGTH ];
  1297. const char *printFormatString = "#SFUIHUD_playerid_specteam";
  1298. // if ( pCSPlayer->ShouldShowTeamPlayerColors( player->GetTeamNumber() ) )
  1299. // {
  1300. // if ( bShowOverheadWeapons && CSGameRules()->CanSpendMoneyInMap() )
  1301. // printFormatString = "#SFUIHUD_playerid_overhead_money";
  1302. // else if ( flHealth < 0.25f )
  1303. // printFormatString = "#SFUIHUD_playerid_overhead_lowhealth";
  1304. // else
  1305. // printFormatString = "#SFUIHUD_playerid_overhead";
  1306. // }
  1307. // else if ( m_playerIDs[slot].nTeam == TEAM_CT )
  1308. if ( m_playerIDs[slot].nTeam == TEAM_CT )
  1309. {
  1310. if ( bShowMoneyInsteadOfHealth )
  1311. printFormatString = "#SFUIHUD_playerid_overhead_ct_money";
  1312. else if ( flHealth < 0.25f )
  1313. printFormatString = "#SFUIHUD_playerid_overhead_ct_lowhealth";
  1314. else
  1315. printFormatString = "#SFUIHUD_playerid_overhead_ct";
  1316. }
  1317. else
  1318. {
  1319. if ( bShowMoneyInsteadOfHealth )
  1320. printFormatString = "#SFUIHUD_playerid_overhead_t_money";
  1321. else if ( flHealth < 0.25f )
  1322. printFormatString = "#SFUIHUD_playerid_overhead_t_lowhealth";
  1323. else
  1324. printFormatString = "#SFUIHUD_playerid_overhead_t";
  1325. }
  1326. if ( printFormatString )
  1327. {
  1328. if ( bShowMoneyInsteadOfHealth )
  1329. {
  1330. V_snwprintf( wszHealthText, ARRAYSIZE( wszHealthText ) - 1, L"$%d", (int)flHealth );
  1331. }
  1332. else
  1333. {
  1334. V_snwprintf( wszHealthText, ARRAYSIZE( wszHealthText ) - 1, L"%.0f%%", flHealth * 100 );
  1335. }
  1336. wszHealthText[ ARRAYSIZE( wszHealthText )-1 ] = '\0';
  1337. cs_PR->GetDecoratedPlayerName( player->entindex(), wszPlayerName, sizeof( wszPlayerName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
  1338. g_pVGuiLocalize->ConstructString( wcNewString, sizeof( wcNewString ), g_pVGuiLocalize->Find( printFormatString ), 2, wszPlayerName, wszHealthText );
  1339. }
  1340. m_pScaleformUI->Value_SetTextHTML( text, wcNewString );
  1341. bool bSetVisible = ShouldShowAllFriendlyEquipment() || m_playerIDs[ slot ].bShowName || m_playerIDs[ slot ].flLastHighlightTime == 0;
  1342. ScaleformDisplayInfo dinfo;
  1343. ScaleformDisplayInfo dinfo2;
  1344. m_pScaleformUI->Value_GetDisplayInfo( textmovie, &dinfo );
  1345. m_pScaleformUI->Value_GetDisplayInfo( textBG, &dinfo2 );
  1346. bool bShowAllNamesForSpec = ( bLocalIsSpectatorViewer && spec_show_xray.GetInt() );
  1347. float flMaxDrawDist = bShowAllNamesForSpec ? cl_teamid_overhead_maxdist_spec.GetInt() : cl_teamid_overhead_maxdist.GetInt();
  1348. Vector vecOtherPlayerEyes = pTargetPlayer->EyePosition() + Vector( 0, 0, 3 );
  1349. Vector toAimSpot = vecOtherPlayerEyes - pCSPlayer->EyePosition();
  1350. float rangeToEnemy = toAimSpot.NormalizeInPlace();
  1351. float flAlp = RemapValClamped( rangeToEnemy,
  1352. 500.0f, flMaxDrawDist,
  1353. 100.0f, 50.0f );
  1354. m_playerIDs[ slot ].flNameAlpha = bLocalIsSpectatorViewer ? cl_teamid_overhead_name_alpha.GetInt() : flAlp;
  1355. dinfo.SetAlpha( m_playerIDs[slot].flNameAlpha );
  1356. dinfo2.SetAlpha( m_playerIDs[slot].flNameAlpha/7 );
  1357. dinfo.SetVisibility( bSetVisible );
  1358. dinfo2.SetVisibility( bSetVisible );
  1359. m_pScaleformUI->Value_SetDisplayInfo( textmovie, &dinfo );
  1360. m_pScaleformUI->Value_SetDisplayInfo( textBG, &dinfo2 );
  1361. bDidSetName = true;
  1362. }
  1363. WITH_SLOT_LOCKED
  1364. {
  1365. SafeReleaseSFVALUE( wepIconParent );
  1366. SafeReleaseSFVALUE( wepIcons );
  1367. SafeReleaseSFVALUE( textmovie );
  1368. SafeReleaseSFVALUE( text );
  1369. WITH_SFVALUEARRAY( args, 1 )
  1370. {
  1371. m_pScaleformUI->ValueArray_SetElement( args, 0, m_playerIDs[slot].panel );
  1372. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "UpdateBGSize", args, 1 );
  1373. }
  1374. SafeReleaseSFVALUE( animatedID );
  1375. SafeReleaseSFVALUE( textBG );
  1376. }
  1377. if ( !bDidSetName )
  1378. {
  1379. Warning( "AddNewPlayerID called and updated in sfhudreticle, but no name was displayed!!!!\n" );
  1380. }
  1381. }
  1382. void SFHudReticle::GetIconHTML( const wchar_t * szIcon, wchar_t * szBuffer, int nBufferSize, bool bSelected )
  1383. {
  1384. if ( bSelected )
  1385. V_snwprintf( szBuffer, nBufferSize, HUDRET_WEPICON_SELECTED_IMG_STRING, szIcon );
  1386. else
  1387. V_snwprintf( szBuffer, nBufferSize, HUDRET_WEPICON_IMG_STRING, szIcon );
  1388. }
  1389. bool SFHudReticle::ShouldShowAllFriendlyTargetIDs( void )
  1390. {
  1391. extern ConVar sv_teamid_overhead_always_prohibit;
  1392. if ( sv_teamid_overhead_always_prohibit.GetBool() )
  1393. return false;
  1394. return ( m_bForceShowAllTeammateTargetIDs || cl_teamid_overhead_always.GetInt() >= 1 );
  1395. }
  1396. bool SFHudReticle::ShouldShowAllFriendlyEquipment( void )
  1397. {
  1398. extern ConVar sv_show_team_equipment_prohibit;
  1399. if ( sv_show_team_equipment_prohibit.GetBool() )
  1400. return false;
  1401. return ( m_bForceShowAllTeammateTargetIDs || cl_teamid_overhead_always.GetInt() == 2 );
  1402. }
  1403. bool SFHudReticle::SetReticlePosition( int distance, int crosshairGap, int offsetX, int offsetY, int nDesiredFishtail )
  1404. {
  1405. bool bMadeChanges = false;
  1406. bool bSlotIsLocked = false;
  1407. if ( m_WeaponCrosshairHandle )
  1408. {
  1409. ScaleformDisplayInfo dinfo;
  1410. LockSlot( true, bSlotIsLocked );
  1411. //0 = default
  1412. //1 = default static
  1413. //2 = classic standard
  1414. //3 = classic dynamic
  1415. //4 = classic static
  1416. if ( cl_crosshairstyle.GetInt() == 0 )
  1417. //if ( cl_dynamiccrosshair.GetBool() )
  1418. {
  1419. // setting this once here will make all of these become visible
  1420. dinfo.SetVisibility( true );
  1421. if ( m_crosshairDot )
  1422. {
  1423. ScaleformDisplayInfo dotDisplayInfo;
  1424. dotDisplayInfo.SetX( offsetX + m_dotX - nDesiredFishtail );
  1425. dotDisplayInfo.SetY( offsetY + m_dotY - nDesiredFishtail );
  1426. m_pScaleformUI->Value_SetDisplayInfo( m_crosshairDot, &dotDisplayInfo );
  1427. }
  1428. if ( m_blackRing )
  1429. {
  1430. ScaleformDisplayInfo blackRingDisplayInfo;
  1431. blackRingDisplayInfo.SetX( offsetX + m_blackRingX );
  1432. blackRingDisplayInfo.SetY( offsetY + m_blackRingY );
  1433. m_pScaleformUI->Value_SetDisplayInfo( m_blackRing, &blackRingDisplayInfo );
  1434. }
  1435. if ( m_FriendCrosshair )
  1436. {
  1437. ScaleformDisplayInfo friendlyCrossHairDisplayInfo;
  1438. friendlyCrossHairDisplayInfo.SetX( offsetX + m_friendIndicatorX - nDesiredFishtail );
  1439. friendlyCrossHairDisplayInfo.SetY( offsetY + m_friendIndicatorY - nDesiredFishtail );
  1440. m_pScaleformUI->Value_SetDisplayInfo( m_FriendCrosshair, &friendlyCrossHairDisplayInfo );
  1441. }
  1442. //Hide the arcs if we get the sentinel value as the desired distance
  1443. if ( distance == -1 )
  1444. {
  1445. ScaleformDisplayInfo hideArcsDisplayInfo;
  1446. hideArcsDisplayInfo.SetVisibility( false );
  1447. m_pScaleformUI->Value_SetDisplayInfo( m_topCrosshairArc, &hideArcsDisplayInfo );
  1448. m_pScaleformUI->Value_SetDisplayInfo( m_bottomCrosshairArc, &hideArcsDisplayInfo );
  1449. m_pScaleformUI->Value_SetDisplayInfo( m_leftCrosshairArc, &hideArcsDisplayInfo );
  1450. m_pScaleformUI->Value_SetDisplayInfo( m_rightCrosshairArc, &hideArcsDisplayInfo );
  1451. }
  1452. else
  1453. {
  1454. dinfo.SetX( offsetX - nDesiredFishtail );
  1455. dinfo.SetY( - distance + offsetY );
  1456. m_pScaleformUI->Value_SetDisplayInfo( m_topCrosshairArc, &dinfo );
  1457. dinfo.SetX( distance + offsetX - nDesiredFishtail );
  1458. dinfo.SetY( offsetY );
  1459. m_pScaleformUI->Value_SetDisplayInfo( m_rightCrosshairArc, &dinfo );
  1460. dinfo.SetX( - distance + offsetX - nDesiredFishtail );
  1461. dinfo.SetY( offsetY );
  1462. m_pScaleformUI->Value_SetDisplayInfo( m_leftCrosshairArc, &dinfo );
  1463. dinfo.SetX( offsetX - nDesiredFishtail );
  1464. dinfo.SetY( distance + offsetY );
  1465. m_pScaleformUI->Value_SetDisplayInfo( m_bottomCrosshairArc, &dinfo );
  1466. }
  1467. if ( crosshairGap == -1 )
  1468. {
  1469. ScaleformDisplayInfo hidePipsDisplayInfo;
  1470. hidePipsDisplayInfo.SetVisibility( false );
  1471. m_pScaleformUI->Value_SetDisplayInfo( m_TopPip, &hidePipsDisplayInfo );
  1472. m_pScaleformUI->Value_SetDisplayInfo( m_BottomPip, &hidePipsDisplayInfo );
  1473. m_pScaleformUI->Value_SetDisplayInfo( m_LeftPip, &hidePipsDisplayInfo );
  1474. m_pScaleformUI->Value_SetDisplayInfo( m_RightPip, &hidePipsDisplayInfo );
  1475. }
  1476. else
  1477. {
  1478. dinfo.SetX( offsetX - nDesiredFishtail );
  1479. dinfo.SetY( m_TopPipY - crosshairGap + offsetY);
  1480. m_pScaleformUI->Value_SetDisplayInfo( m_TopPip, &dinfo );
  1481. dinfo.SetX( offsetX + 1 - nDesiredFishtail );
  1482. dinfo.SetY( m_BottomPipY + crosshairGap + offsetY+1);
  1483. m_pScaleformUI->Value_SetDisplayInfo( m_BottomPip, &dinfo );
  1484. dinfo.SetY(offsetY+1);
  1485. dinfo.SetX( m_LeftPipX - crosshairGap + offsetX - nDesiredFishtail );
  1486. m_pScaleformUI->Value_SetDisplayInfo( m_LeftPip, &dinfo );
  1487. dinfo.SetY(offsetY);
  1488. dinfo.SetX( m_RightPipX + crosshairGap + offsetX + 1 - nDesiredFishtail );
  1489. m_pScaleformUI->Value_SetDisplayInfo( m_RightPip, &dinfo );
  1490. }
  1491. }
  1492. else
  1493. {
  1494. // make the arcs invisible
  1495. dinfo.SetVisibility( false );
  1496. m_pScaleformUI->Value_SetDisplayInfo( m_topCrosshairArc, &dinfo );
  1497. m_pScaleformUI->Value_SetDisplayInfo( m_rightCrosshairArc, &dinfo );
  1498. m_pScaleformUI->Value_SetDisplayInfo( m_leftCrosshairArc, &dinfo );
  1499. m_pScaleformUI->Value_SetDisplayInfo( m_bottomCrosshairArc, &dinfo );
  1500. dinfo.SetVisibility( true );
  1501. float cg = cl_fixedcrosshairgap.GetFloat();
  1502. dinfo.SetX( offsetX - nDesiredFishtail );
  1503. dinfo.SetY( m_TopPipY - cg + offsetY);
  1504. m_pScaleformUI->Value_SetDisplayInfo( m_TopPip, &dinfo );
  1505. dinfo.SetX( offsetX + 1 - nDesiredFishtail );
  1506. dinfo.SetY( m_BottomPipY + cg + offsetY+1);
  1507. m_pScaleformUI->Value_SetDisplayInfo( m_BottomPip, &dinfo );
  1508. dinfo.SetY(offsetY+1);
  1509. dinfo.SetX( m_LeftPipX - cg + offsetX - nDesiredFishtail );
  1510. m_pScaleformUI->Value_SetDisplayInfo( m_LeftPip, &dinfo );
  1511. dinfo.SetY(offsetY);
  1512. dinfo.SetX( m_RightPipX + cg + offsetX + 1 - nDesiredFishtail );
  1513. m_pScaleformUI->Value_SetDisplayInfo( m_RightPip, &dinfo );
  1514. }
  1515. m_iLastSpread = distance;
  1516. m_iLastGap = crosshairGap;
  1517. bMadeChanges = true;
  1518. }
  1519. // Update the position of the text.
  1520. if ( m_bTextIDVisible && m_IDMovie && m_IDText )
  1521. {
  1522. LockSlot( true, bSlotIsLocked );
  1523. // text movie
  1524. ScaleformDisplayInfo displayInfo;
  1525. displayInfo.SetX( offsetX + m_IDMovieX );
  1526. displayInfo.SetY( offsetY + m_IDMovieY );
  1527. m_pScaleformUI->Value_SetDisplayInfo( m_IDMovie, &displayInfo );
  1528. bMadeChanges = true;
  1529. }
  1530. LockSlot( false, bSlotIsLocked );
  1531. return bMadeChanges;
  1532. }
  1533. void SFHudReticle::FlashReady( void )
  1534. {
  1535. m_ObserverCrosshairHandle = m_pScaleformUI->Value_GetMember( m_FlashAPI, "Observer" );
  1536. PerformSwapReticle( "Crosshair1" );
  1537. m_IDMovie = m_pScaleformUI->Value_GetMember( m_FlashAPI, "TargetID" );
  1538. if ( m_IDMovie )
  1539. {
  1540. SFVALUE animatedID = m_pScaleformUI->Value_GetMember( m_IDMovie, "IDAnimated" );
  1541. if ( animatedID )
  1542. {
  1543. m_IDText = m_pScaleformUI->Value_GetMember( animatedID, "TextBox" );
  1544. m_pScaleformUI->Value_SetTextHTML( m_IDText, " " );
  1545. SafeReleaseSFVALUE( animatedID );
  1546. }
  1547. }
  1548. m_FlashedIcon = m_pScaleformUI->Value_GetMember( m_FlashAPI, "FlashedBlind" );
  1549. // // Update the position of the text.
  1550. // if ( m_FlashedIcon )
  1551. // {
  1552. // LockSlot( true, bSlotIsLocked );
  1553. //
  1554. // // text movie
  1555. // ScaleformDisplayInfo displayInfo;
  1556. // m_pScaleformUI->Value_GetDisplayInfo( m_FlashedIcon, &displayInfo );
  1557. // displayInfo.SetX( offsetX + m_IDMovieX );
  1558. // displayInfo.SetY( offsetY + m_IDMovieY );
  1559. // m_pScaleformUI->Value_SetDisplayInfo( m_IDMovie, &displayInfo );
  1560. //
  1561. // bMadeChanges = true;
  1562. // }
  1563. ResetDisplay();
  1564. ListenForGameEvent( "item_pickup" );
  1565. ListenForGameEvent( "ammo_pickup" );
  1566. ListenForGameEvent( "player_death" );
  1567. ListenForGameEvent( "round_start" );
  1568. ListenForGameEvent( "round_end" );
  1569. ListenForGameEvent( "round_freeze_end" );
  1570. ListenForGameEvent( "bomb_planted" );
  1571. ListenForGameEvent( "defuser_pickup" );
  1572. ListenForGameEvent( "bomb_dropped" );
  1573. ListenForGameEvent( "bomb_pickup" );
  1574. ListenForGameEvent( "grenade_thrown" );
  1575. }
  1576. bool SFHudReticle::PreUnloadFlash( void )
  1577. {
  1578. SafeReleaseSFVALUE( m_WeaponCrosshairHandle );
  1579. SafeReleaseSFVALUE( m_ObserverCrosshairHandle );
  1580. SafeReleaseSFVALUE( m_TopPip );
  1581. SafeReleaseSFVALUE( m_BottomPip );
  1582. SafeReleaseSFVALUE( m_LeftPip );
  1583. SafeReleaseSFVALUE( m_RightPip );
  1584. SafeReleaseSFVALUE( m_topCrosshairArc );
  1585. SafeReleaseSFVALUE( m_rightCrosshairArc );
  1586. SafeReleaseSFVALUE( m_leftCrosshairArc );
  1587. SafeReleaseSFVALUE( m_bottomCrosshairArc );
  1588. SafeReleaseSFVALUE( m_FriendCrosshair );
  1589. SafeReleaseSFVALUE( m_crosshairDot );
  1590. SafeReleaseSFVALUE( m_blackRing );
  1591. SafeReleaseSFVALUE( m_IDMovie );
  1592. SafeReleaseSFVALUE( m_IDText );
  1593. SafeReleaseSFVALUE( m_FlashedIcon );
  1594. RemoveAllIDs();
  1595. return true;
  1596. }
  1597. void SFHudReticle::ResetDisplay( void )
  1598. {
  1599. // hide everything we don't want / need;
  1600. WITH_SLOT_LOCKED
  1601. {
  1602. if ( m_IDMovie )
  1603. {
  1604. m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "HideNow", NULL, 0 );
  1605. }
  1606. if ( m_FlashedIcon )
  1607. {
  1608. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "Hide", NULL, 0 );
  1609. m_bFlashedIconFadingOut = false;
  1610. }
  1611. if ( m_FriendCrosshair )
  1612. {
  1613. m_pScaleformUI->Value_SetVisible( m_FriendCrosshair, false );
  1614. }
  1615. ShowReticle( RETICLE_MODE_WEAPON, false );
  1616. ShowReticle( RETICLE_MODE_OBSERVER, false );
  1617. }
  1618. m_fIDTimer = 0;
  1619. m_bTextIDVisible = false;
  1620. m_bFriendlyCrosshairVisible = false;
  1621. m_iReticleMode = RETICLE_MODE_NONE;
  1622. RemoveAllIDs();
  1623. }
  1624. void SFHudReticle::LevelInit( void )
  1625. {
  1626. if ( !FlashAPIIsValid() )
  1627. {
  1628. SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFHudReticle, this, Reticle );
  1629. }
  1630. else
  1631. {
  1632. ResetDisplay();
  1633. }
  1634. }
  1635. void SFHudReticle::LevelShutdown( void )
  1636. {
  1637. if ( FlashAPIIsValid() )
  1638. {
  1639. RemoveFlashElement();
  1640. }
  1641. }
  1642. bool SFHudReticle::ShouldDraw( void )
  1643. {
  1644. if ( IsTakingAFreezecamScreenshot() )
  1645. return false;
  1646. C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
  1647. if ( !pPlayer )
  1648. return false;
  1649. if ( pPlayer->GetObserverInterpState() == C_CSPlayer::OBSERVER_INTERP_TRAVELING )
  1650. return false;
  1651. bool bNeedsDraw = false;
  1652. if ( (pPlayer->GetObserverMode() == OBS_MODE_ROAMING) || (pPlayer->GetObserverMode() == OBS_MODE_FIXED) )
  1653. bNeedsDraw = true;
  1654. return cl_drawhud.GetBool() && (bNeedsDraw || CHudElement::ShouldDraw());
  1655. }
  1656. void SFHudReticle::SetActive( bool bActive )
  1657. {
  1658. if ( !FlashAPIIsValid() )
  1659. return;
  1660. SF_SPLITSCREEN_PLAYER_GUARD();
  1661. if ( !bActive && m_bActive )
  1662. {
  1663. ResetDisplay();
  1664. }
  1665. else if ( bActive && !m_bActive )
  1666. {
  1667. SplitScreenSlottedConVarRef convar( GET_ACTIVE_SPLITSCREEN_SLOT(), "cl_crosshaircolor" );
  1668. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 1 )
  1669. {
  1670. g_pScaleformUI->ValueArray_SetElement( args, 0, convar.GetFloat() );
  1671. g_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "onUpdateColor", args, 1 );
  1672. }
  1673. }
  1674. CHudElement::SetActive( bActive );
  1675. }
  1676. void SFHudReticle::OnSwapReticle( SCALEFORM_CALLBACK_ARGS_DECL )
  1677. {
  1678. SF_SPLITSCREEN_PLAYER_GUARD();
  1679. PerformSwapReticle( m_pScaleformUI->Params_GetArgAsString( obj, 0 ) );
  1680. }
  1681. void SFHudReticle::PerformSwapReticle( const char * szReticleName )
  1682. {
  1683. SafeReleaseSFVALUE( m_WeaponCrosshairHandle );
  1684. SafeReleaseSFVALUE( m_FriendCrosshair );
  1685. SafeReleaseSFVALUE( m_crosshairDot );
  1686. SafeReleaseSFVALUE( m_blackRing );
  1687. SafeReleaseSFVALUE( m_TopPip );
  1688. SafeReleaseSFVALUE( m_BottomPip );
  1689. SafeReleaseSFVALUE( m_LeftPip );
  1690. SafeReleaseSFVALUE( m_RightPip );
  1691. SafeReleaseSFVALUE( m_topCrosshairArc );
  1692. SafeReleaseSFVALUE( m_rightCrosshairArc );
  1693. SafeReleaseSFVALUE( m_leftCrosshairArc );
  1694. SafeReleaseSFVALUE( m_bottomCrosshairArc );
  1695. m_WeaponCrosshairHandle = m_pScaleformUI->Value_GetMember( m_FlashAPI, szReticleName );
  1696. if ( m_WeaponCrosshairHandle )
  1697. {
  1698. ScaleformDisplayInfo dinfo;
  1699. m_FriendCrosshair = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "FriendCrosshair" );
  1700. m_crosshairDot = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "Dot" );
  1701. m_blackRing = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "BlackRing" );
  1702. if ( !m_bCrosshairPositionsInitialized )
  1703. {
  1704. m_bCrosshairPositionsInitialized = true;
  1705. if ( m_FriendCrosshair )
  1706. {
  1707. m_pScaleformUI->Value_GetDisplayInfo( m_FriendCrosshair, &dinfo );
  1708. m_friendIndicatorX = dinfo.GetX();
  1709. m_friendIndicatorY = dinfo.GetY();
  1710. }
  1711. if ( m_crosshairDot )
  1712. {
  1713. m_pScaleformUI->Value_GetDisplayInfo( m_crosshairDot, &dinfo );
  1714. m_dotX = dinfo.GetX();
  1715. m_dotY = dinfo.GetY();
  1716. }
  1717. if ( m_blackRing )
  1718. {
  1719. m_pScaleformUI->Value_GetDisplayInfo( m_blackRing, &dinfo );
  1720. m_blackRingX = dinfo.GetX();
  1721. m_blackRingY = dinfo.GetY();
  1722. }
  1723. }
  1724. m_TopPip = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "TopPip" );
  1725. if ( m_TopPip )
  1726. {
  1727. m_TopPipY = 0;
  1728. }
  1729. m_BottomPip = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "BottomPip" );
  1730. if ( m_BottomPip )
  1731. {
  1732. m_BottomPipY = 0;
  1733. }
  1734. m_LeftPip = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "LeftPip" );
  1735. if ( m_LeftPip )
  1736. {
  1737. m_LeftPipX = 0;
  1738. }
  1739. m_RightPip = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "RightPip" );
  1740. if ( m_RightPip )
  1741. {
  1742. m_RightPipX = 0;
  1743. }
  1744. m_topCrosshairArc = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "TopArc" );
  1745. m_rightCrosshairArc = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "RightArc" );
  1746. m_leftCrosshairArc = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "LeftArc" );
  1747. m_bottomCrosshairArc = m_pScaleformUI->Value_GetMember( m_WeaponCrosshairHandle, "BottomArc" );
  1748. }
  1749. if ( m_FriendCrosshair )
  1750. {
  1751. m_pScaleformUI->Value_SetVisible( m_FriendCrosshair, false );
  1752. }
  1753. if ( m_IDMovie )
  1754. {
  1755. ScaleformDisplayInfo dinfo;
  1756. m_pScaleformUI->Value_GetDisplayInfo( m_IDMovie, &dinfo );
  1757. m_IDMovieX = dinfo.GetX();
  1758. m_IDMovieY = dinfo.GetY();
  1759. }
  1760. // set these here because the flash code makes them invisible
  1761. m_bFriendlyCrosshairVisible = false;
  1762. m_iReticleMode = RETICLE_MODE_NONE;
  1763. m_iLastSpread = -1;
  1764. m_iLastGap = -1;
  1765. }
  1766. void SFHudReticle::RemoveID( int index )
  1767. {
  1768. SFVALUE panel = m_playerIDs[ index ].panel;
  1769. SafeReleaseSFVALUE( m_playerIDs[ index ].arrowA );
  1770. SafeReleaseSFVALUE( m_playerIDs[ index ].arrowB );
  1771. SafeReleaseSFVALUE( m_playerIDs[ index ].arrowF );
  1772. SafeReleaseSFVALUE( m_playerIDs[ index ].voiceIcon );
  1773. SafeReleaseSFVALUE( m_playerIDs[ index ].defuseIcon );
  1774. m_playerIDs.Remove( index );
  1775. WITH_SFVALUEARRAY_SLOT_LOCKED( data, 1 )
  1776. {
  1777. m_pScaleformUI->ValueArray_SetElement( data, 0, panel );
  1778. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "RemovePlayerID", data, 1 );
  1779. }
  1780. SafeReleaseSFVALUE( panel );
  1781. }
  1782. void SFHudReticle::RemoveAllIDs( void )
  1783. {
  1784. if ( m_pScaleformUI )
  1785. {
  1786. WITH_SLOT_LOCKED
  1787. {
  1788. //Remove all items before we exit
  1789. while( m_playerIDs.Count() > 0 )
  1790. {
  1791. RemoveID( 0 );
  1792. }
  1793. }
  1794. }
  1795. }
  1796. void SFHudReticle::FireGameEvent( IGameEvent *event )
  1797. {
  1798. const char *type = event->GetName();
  1799. int nUserId = event->GetInt( "userid" );
  1800. C_BasePlayer *pPlayer = UTIL_PlayerByUserId( nUserId );
  1801. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  1802. if ( !V_strcmp( type, "player_death" ) )
  1803. {
  1804. // if we were the one that died or the player we are spectating, remove all the stuff!
  1805. if ( pPlayer && (pPlayer->entindex() == pLocalPlayer->entindex() || (pLocalPlayer->GetObserverTarget() && pPlayer == pLocalPlayer->GetObserverTarget())) )
  1806. {
  1807. RemoveAllIDs();
  1808. if ( m_IDMovie )
  1809. {
  1810. WITH_SLOT_LOCKED
  1811. {
  1812. m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "HideNow", NULL, 0 );
  1813. }
  1814. }
  1815. if ( m_FlashedIcon )
  1816. {
  1817. WITH_SLOT_LOCKED
  1818. {
  1819. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "Hide", NULL, 0 );
  1820. m_bFlashedIconFadingOut = false;
  1821. }
  1822. }
  1823. }
  1824. }
  1825. else if ( !V_strcmp( type, "round_end" ) )
  1826. {
  1827. RemoveAllIDs();
  1828. }
  1829. else if ( !V_strcmp( type, "round_start" ) )
  1830. {
  1831. RemoveAllIDs();
  1832. if ( m_IDMovie && FlashAPIIsValid() )
  1833. {
  1834. WITH_SLOT_LOCKED
  1835. {
  1836. m_pScaleformUI->Value_InvokeWithoutReturn( m_IDMovie, "HideNow", NULL, 0 );
  1837. }
  1838. }
  1839. if ( m_FlashedIcon )
  1840. {
  1841. WITH_SLOT_LOCKED
  1842. {
  1843. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashedIcon, "Hide", NULL, 0 );
  1844. m_bFlashedIconFadingOut = false;
  1845. }
  1846. }
  1847. }
  1848. else if ( !V_strcmp( type, "item_pickup" ) ||
  1849. !V_strcmp( type, "ammo_pickup" ) ||
  1850. !V_strcmp( type, "bomb_planted" ) ||
  1851. !V_strcmp( type, "defuser_pickup" ) ||
  1852. !V_strcmp( type, "bomb_dropped" ) ||
  1853. !V_strcmp( type, "bomb_pickup" ) ||
  1854. !V_strcmp( type, "grenade_thrown" ) )
  1855. {
  1856. if ( pLocalPlayer )
  1857. {
  1858. FOR_EACH_VEC( m_playerIDs, j )
  1859. {
  1860. if ( m_playerIDs[j].hPlayer.Get() == pPlayer )
  1861. {
  1862. m_playerIDs[j].flUpdateAt = (gpGlobals->curtime + 0.1f);
  1863. break;
  1864. }
  1865. }
  1866. }
  1867. }
  1868. else if ( !V_strcmp( type, "round_freeze_end" ) )
  1869. {
  1870. if ( pLocalPlayer )
  1871. {
  1872. FOR_EACH_VEC( m_playerIDs, j )
  1873. {
  1874. m_playerIDs[j].flUpdateAt = (gpGlobals->curtime + 0.1f);
  1875. }
  1876. }
  1877. }
  1878. }