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.

1271 lines
39 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #if defined( INCLUDE_SCALEFORM )
  9. #include "sfhudfreezepanel.h"
  10. #include "view.h"
  11. //#include "iviewrender.h"
  12. #include "hud_macros.h"
  13. #include <vgui/ILocalize.h>
  14. #include <vgui/ISurface.h>
  15. #include "iclientmode.h"
  16. #include "hud.h"
  17. #include "hudelement.h"
  18. #include "hud_element_helper.h"
  19. #include "iclientmode.h"
  20. #include "scaleformui/scaleformui.h"
  21. #include "c_cs_playerresource.h"
  22. #include "gameui_util.h"
  23. #include "vstdlib/vstrtools.h"
  24. #include "sfhudwinpanel.h"
  25. #include "viewrender.h"
  26. #include "steam/steam_api.h"
  27. #include "inputsystem/iinputsystem.h"
  28. #include "sfhudinfopanel.h"
  29. #include "hltvreplaysystem.h"
  30. // memdbgon must be the last include file in a .cpp file!!!
  31. #include "tier0/memdbgon.h"
  32. extern float g_flFreezeFlash[ MAX_SPLITSCREEN_PLAYERS ];
  33. extern ConVar cl_draw_only_deathnotices;
  34. ConVar spec_freeze_panel_replay_position( "spec_freeze_panel_replay_position", "0.75", FCVAR_CLIENTDLL );
  35. float g_flFreezecamScreenshotFrameTimeStarted = 0;
  36. bool g_bFreezecamScreenshotFrameNumAssigned = false;
  37. #define NUM_FREEZE_CAM_BORDER_IMAGES 4
  38. bool IsTakingAFreezecamScreenshot( void )
  39. {
  40. // Don't draw in freezecam, or when the game's not running
  41. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  42. bool bInFreezeCam = ( pPlayer && pPlayer->GetObserverMode() == OBS_MODE_FREEZECAM );
  43. if ( bInFreezeCam && g_bFreezecamScreenshotFrameNumAssigned &&
  44. ( gpGlobals->curtime - g_flFreezecamScreenshotFrameTimeStarted < 1.0f ) && engine->IsTakingScreenshot() )
  45. return true;
  46. SFHudFreezePanel *pPanel = GET_HUDELEMENT( SFHudFreezePanel );
  47. if ( pPanel )
  48. {
  49. if ( pPanel->IsHoldingAfterScreenShot() )
  50. return true;
  51. }
  52. if ( g_bFreezecamScreenshotFrameNumAssigned )
  53. g_bFreezecamScreenshotFrameNumAssigned = false;
  54. return false;
  55. }
  56. void CS_FreezePanel_OnTimeJump()
  57. {
  58. SFHudFreezePanel *pPanel = GET_HUDELEMENT( SFHudFreezePanel );
  59. if ( pPanel )
  60. {
  61. pPanel->OnTimeJump();
  62. }
  63. }
  64. void CS_FreezePanel_ResetDamageText( int iPlayerIndexKiller, int iPlayerIndexVictim )
  65. {
  66. SFHudFreezePanel *pPanel = GET_HUDELEMENT( SFHudFreezePanel );
  67. if ( pPanel )
  68. {
  69. pPanel->ResetDamageText( iPlayerIndexKiller, iPlayerIndexVictim );
  70. }
  71. }
  72. void CS_FreezePanel_OnHltvReplayButtonStateChanged()
  73. {
  74. SFHudFreezePanel *pPanel = GET_HUDELEMENT( SFHudFreezePanel );
  75. if ( pPanel )
  76. {
  77. pPanel->OnHltvReplayButtonStateChanged();
  78. }
  79. }
  80. DECLARE_HUDELEMENT( SFHudFreezePanel );
  81. ConVar cl_disablefreezecam(
  82. "cl_disablefreezecam",
  83. "0",
  84. FCVAR_ARCHIVE,
  85. "Turn on/off freezecam on client"
  86. );
  87. ConVar cl_freezecampanel_position_dynamic(
  88. "cl_freezecampanel_position_dynamic",
  89. "1",
  90. FCVAR_ARCHIVE,
  91. "Turn on/off freezecam's kill panel dynamic Y movement"
  92. );
  93. SFUI_BEGIN_GAME_API_DEF
  94. SFUI_END_GAME_API_DEF( SFHudFreezePanel, FreezePanel );
  95. #define FREEZECAM_SCREENSHOT_STRING "got the upper hand!"
  96. //-----------------------------------------------------------------------------
  97. // Purpose: Constructor
  98. //-----------------------------------------------------------------------------
  99. SFHudFreezePanel::SFHudFreezePanel( const char *value ) : SFHudFlashInterface( value )
  100. {
  101. SetHiddenBits( HIDEHUD_MISCSTATUS );
  102. for ( int i = 0 ; i < DominationIconMax ; ++i )
  103. {
  104. m_dominationIcons[i] = NULL;
  105. }
  106. m_dominationText1 = NULL;
  107. m_dominationText2 = NULL;
  108. m_killerName = NULL;
  109. m_freezePanel = NULL;
  110. m_FollowEntity = NULL;
  111. m_iKillerIndex = 0;
  112. m_navigationText = NULL;
  113. m_weaponInfoText1 = NULL;
  114. m_weaponInfoText2 = NULL;
  115. // screenshot
  116. m_ssDescText = NULL;
  117. m_ssNameText = NULL;
  118. m_PosX = 0;
  119. m_PosY = 0;
  120. g_flFreezeFlash[ GetSplitScreenPlayerSlot() ] = 0.0f;
  121. m_bDominationIconVisible = false;
  122. m_bIsVisible = false;
  123. m_bIsCancelPanelVisible = false;
  124. m_bFreezePanelStateRelevant = false;
  125. }
  126. void SFHudFreezePanel::LevelInit( void )
  127. {
  128. Assert( !m_bFreezePanelStateRelevant );
  129. if ( !FlashAPIIsValid() )
  130. {
  131. SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFHudFreezePanel, this, FreezePanel );
  132. }
  133. }
  134. void SFHudFreezePanel::LevelShutdown( void )
  135. {
  136. if ( FlashAPIIsValid() )
  137. {
  138. RemoveFlashElement();
  139. }
  140. }
  141. bool SFHudFreezePanel::ShouldDraw( void )
  142. {
  143. return m_bIsVisible && cl_drawhud.GetBool() && cl_draw_only_deathnotices.GetBool() == false && CHudElement::ShouldDraw();
  144. }
  145. void SFHudFreezePanel::SetActive( bool bActive )
  146. {
  147. CHudElement::SetActive( bActive );
  148. }
  149. void SFHudFreezePanel::FlashReady( void )
  150. {
  151. if ( !m_FlashAPI )
  152. {
  153. return;
  154. }
  155. m_freezePanel = g_pScaleformUI->Value_GetMember( m_FlashAPI, "FreezePanel" );
  156. if ( !m_freezePanel )
  157. {
  158. return;
  159. }
  160. SFVALUE root = g_pScaleformUI->Value_GetMember( m_freezePanel, "FreezePanel" );
  161. //SafeReleaseSFVALUE( innerPanel );
  162. if ( !root )
  163. {
  164. return;
  165. }
  166. m_dominationText1 = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "DescriptionText" );
  167. m_dominationText2 = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "DescriptionTextTitle" );
  168. m_killerName = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "NameText" );
  169. m_dominationIcons[Nemesis] = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "NemesisIcon" );
  170. m_dominationIcons[Revenge] = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "RevengeIcon" );
  171. m_navigationText = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "Navigation" );
  172. m_weaponInfoText1 = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "WeaponInfoText" );
  173. m_weaponInfoText2 = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "WeaponCustomText" );
  174. SafeReleaseSFVALUE( root );
  175. // screenshot panel
  176. m_ssFreezePanel = g_pScaleformUI->Value_GetMember( m_FlashAPI, "FreezePanelSS" );
  177. if ( !m_ssFreezePanel )
  178. {
  179. return;
  180. }
  181. else
  182. {
  183. m_ssDescText = g_pScaleformUI->TextObject_MakeTextObjectFromMember( m_ssFreezePanel, "DescriptionText" );
  184. m_ssNameText = g_pScaleformUI->TextObject_MakeTextObjectFromMember( m_ssFreezePanel, "NameText" );
  185. }
  186. SetIcon( None );
  187. // listen for events
  188. ListenForGameEvent( "show_freezepanel" );
  189. ListenForGameEvent( "hide_freezepanel" );
  190. ListenForGameEvent( "player_death" );
  191. ListenForGameEvent( "player_spawn" );
  192. WITH_SLOT_LOCKED
  193. {
  194. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hide", NULL, 0 );
  195. ScaleformDisplayInfo dinfo;
  196. m_pScaleformUI->Value_GetDisplayInfo( m_ssFreezePanel, &dinfo );
  197. dinfo.SetVisibility( false );
  198. m_pScaleformUI->Value_SetDisplayInfo( m_ssFreezePanel, &dinfo );
  199. }
  200. g_pScaleformUI->AddDeviceDependentObject( this );
  201. }
  202. bool SFHudFreezePanel::PreUnloadFlash( void )
  203. {
  204. StopListeningForAllEvents();
  205. for ( int i = 0 ; i < DominationIconMax ; ++i )
  206. {
  207. SafeReleaseSFTextObject( m_dominationIcons[i] );
  208. }
  209. SafeReleaseSFTextObject( m_dominationText1 );
  210. SafeReleaseSFTextObject( m_dominationText2 );
  211. SafeReleaseSFTextObject( m_killerName );
  212. SafeReleaseSFVALUE( m_freezePanel );
  213. SafeReleaseSFTextObject( m_navigationText );
  214. SafeReleaseSFTextObject( m_weaponInfoText1 );
  215. SafeReleaseSFTextObject( m_weaponInfoText2 );
  216. SafeReleaseSFTextObject( m_ssDescText );
  217. SafeReleaseSFTextObject( m_ssNameText );
  218. SafeReleaseSFVALUE( m_ssFreezePanel );
  219. g_pScaleformUI->RemoveDeviceDependentObject( this );
  220. return true;
  221. }
  222. void SFHudFreezePanel::FireGameEvent( IGameEvent* event )
  223. {
  224. const char *pEventName = event->GetName();
  225. if ( Q_strcmp( "player_death", pEventName ) == 0 )
  226. {
  227. m_bDominationIconVisible = false;
  228. // see if the local player died
  229. int iPlayerIndexVictim = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
  230. int iPlayerIndexKiller = engine->GetPlayerForUserID( event->GetInt( "attacker" ) );
  231. SF_SPLITSCREEN_PLAYER_GUARD();
  232. C_BasePlayer *pVictimPlayer = UTIL_PlayerByIndex( iPlayerIndexVictim ), *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  233. CCSPlayer* pKiller = ToCSPlayer( ClientEntityList().GetBaseEntity( iPlayerIndexKiller ) );
  234. m_FollowEntity = pKiller;
  235. CEconItemView *pItem = NULL;
  236. extern ConVar spec_replay_others_experimental;
  237. if ( !g_HltvReplaySystem.GetHltvReplayDelay() && ( spec_replay_others_experimental.GetBool() || ( pLocalPlayer && iPlayerIndexVictim == pLocalPlayer->entindex() ) ) )
  238. {
  239. // we need to notify the replay system that the replay is available before some other calls that happen on this very event, so it would not be reliable to just have replay system listen to player_death event
  240. m_bHoldingAfterScreenshot = false;
  241. bool bShowItem = false;
  242. const char * szWeapon = event->GetString( "weapon" );
  243. // wchar_t *szWeaponHTML = 0;
  244. wchar_t wszWeaponNameHTML[64];
  245. wchar_t wszLocalizedString[256];
  246. if ( szWeapon && szWeapon[0] != 0 )
  247. {
  248. // if ( Q_strcmp( "knifegg", szWeapon ) == 0 )
  249. // szWeapon = "knife";
  250. //
  251. // char szWeaponTemp[64];
  252. // if ( Q_strcmp( "knife", szWeapon ) == 0 )
  253. // {
  254. // if ( pKiller && pKiller->GetTeamNumber() == TEAM_CT )
  255. // {
  256. // szWeapon = "knife_default_ct";
  257. // }
  258. // else
  259. // {
  260. // szWeapon = "knife_default_t";
  261. // }
  262. // }
  263. // else
  264. // {
  265. // V_snprintf( szWeaponTemp, sizeof(szWeaponTemp), "%s", szWeapon );
  266. // }
  267. //
  268. // wchar_t wszWeapon[64];
  269. // V_UTF8ToUnicode( szWeaponTemp, wszWeapon, sizeof( wszWeapon ) );
  270. // wchar_t wszTempWeaponIcon[64];
  271. // V_snwprintf( wszTempWeaponIcon, 64, L"<img src='icon-%s.png'/>", wszWeapon );
  272. // szWeaponHTML = wszTempWeaponIcon;
  273. // pKiller = C_CSPlayer::GetLocalCSPlayer();
  274. // if ( CSInventoryManager() && CSInventoryManager()->GetLocalInventory() )
  275. // pItem = CSInventoryManager()->GetItemInLoadoutForTeam( pKiller->GetTeamNumber(), LOADOUT_POSITION_RIFLE3 );
  276. //get weapon name and custom name for the weapon info panel
  277. const char* szEventWeaponItemID = event->GetString( "weapon_itemid" );
  278. uint64 itemid = Q_atoui64( szEventWeaponItemID );
  279. const char* szEventWeaponFauxItemID = event->GetString( "weapon_fauxitemid" );
  280. uint64 fauxitemid = Q_atoui64( szEventWeaponFauxItemID );
  281. const char* szEventWeaponOriginalOwnerXuid = event->GetString( "weapon_originalowner_xuid" );
  282. uint64 ullWeaponOriginalOwnerXuid = Q_atoui64( szEventWeaponOriginalOwnerXuid );
  283. if ( pKiller )
  284. {
  285. if ( !StringIsEmpty( szEventWeaponItemID ) )
  286. {
  287. // Get the real item if it's still in in the SO cache,
  288. pItem = CEconItemView::FindOrCreateEconItemViewForItemID( itemid );
  289. // if we don't have the item, see if the killer still has the item equiped and use that instead
  290. if ( !pItem && pKiller->GetActiveCSWeapon() && pKiller->GetActiveCSWeapon()->GetEconItemView() && pKiller->GetActiveCSWeapon()->GetEconItemView()->GetItemID() == itemid )
  291. {
  292. pItem = pKiller->GetActiveCSWeapon()->GetEconItemView();
  293. }
  294. // otherwise fallback to the faux version
  295. if ( !pItem )
  296. {
  297. pItem = CEconItemView::FindOrCreateEconItemViewForItemID( fauxitemid );
  298. }
  299. }
  300. // char szWeapon_Weapon[128];
  301. // V_sprintf_safe( szWeapon_Weapon, "weapon_%s", event->GetString( "weapon" ) );
  302. //
  303. // // collapse the various knives into the definition base name ( "knife_default_ct", ... )
  304. // if ( !V_strncmp( szWeapon_Weapon, "weapon_knife", 12 ) )
  305. // {
  306. // V_sprintf_safe( szWeapon_Weapon, "weapon_knife" );
  307. // }
  308. const char *pszLocString = NULL;
  309. if ( pItem && pItem->IsValid() )
  310. {
  311. const CEconItemRarityDefinition *pRarity = GetItemSchema()->GetRarityDefinition( pItem->GetRarity() );
  312. enum { kColorBufSize = 128 };
  313. wchar_t rwchColor[kColorBufSize];
  314. Q_UTF8ToUnicode( GetHexColorForAttribColor( pRarity->GetAttribColor() ), rwchColor, kColorBufSize );
  315. V_swprintf_safe( wszWeaponNameHTML, L"<font color=\"" PRI_WS_FOR_WS L"\">" PRI_WS_FOR_WS L"</font>", rwchColor, pItem->GetItemName() );
  316. bShowItem = ( pItem->GetItemID() != 0 );
  317. }
  318. else // we have no econitemview. Print generic message.
  319. {
  320. const char * szWeapon = event->GetString( "weapon" );
  321. //pszLocString = "FreezePanel_Killer1_Weapon";
  322. if ( StringHasPrefixCaseSensitive( szWeapon, "prop_exploding_barrel" ) ) //"prop_exploding_barrel"
  323. {
  324. V_swprintf_safe( wszWeaponNameHTML, L"" PRI_WS_FOR_WS, g_pVGuiLocalize->Find( "#SFUI_WPNHUD_Exploding_Barrel" ) );
  325. }
  326. else
  327. {
  328. if ( StringHasPrefixCaseSensitive( szWeapon, "hegrenade" ) )
  329. {
  330. V_swprintf_safe( wszWeaponNameHTML, L"" PRI_WS_FOR_WS, g_pVGuiLocalize->Find( "#SFUI_WPNHUD_HE_Grenade" ) );
  331. }
  332. else if ( StringHasPrefixCaseSensitive( szWeapon, "flashbang" ) )
  333. {
  334. V_swprintf_safe( wszWeaponNameHTML, L"" PRI_WS_FOR_WS, g_pVGuiLocalize->Find( "#SFUI_WPNHUD_Flashbang" ) );
  335. }
  336. else if ( StringHasPrefixCaseSensitive( szWeapon, "decoy" ) )
  337. {
  338. V_swprintf_safe( wszWeaponNameHTML, L"" PRI_WS_FOR_WS, g_pVGuiLocalize->Find( "#SFUI_WPNHUD_Decoy" ) );
  339. }
  340. else if ( StringHasPrefixCaseSensitive( szWeapon, "smokegrenade" ) )
  341. {
  342. V_swprintf_safe( wszWeaponNameHTML, L"" PRI_WS_FOR_WS, g_pVGuiLocalize->Find( "#SFUI_WPNHUD_Smoke_Grenade" ) );
  343. }
  344. else if ( StringHasPrefixCaseSensitive( szWeapon, "incgrenade" ) )
  345. {
  346. V_swprintf_safe( wszWeaponNameHTML, L"" PRI_WS_FOR_WS, g_pVGuiLocalize->Find( "#SFUI_WPNHUD_IncGrenade" ) );
  347. }
  348. else if ( StringHasPrefixCaseSensitive( szWeapon, "molotov" ) )
  349. {
  350. V_swprintf_safe( wszWeaponNameHTML, L"" PRI_WS_FOR_WS, g_pVGuiLocalize->Find( "#SFUI_WPNHUD_Molotov" ) );
  351. }
  352. else if ( !V_strcmp( szWeapon, "inferno" ) )
  353. {
  354. pszLocString = "FreezePanel_Killer1_Weapon_Plural";
  355. V_swprintf_safe( wszWeaponNameHTML, L"" PRI_WS_FOR_WS, g_pVGuiLocalize->Find( "#SFUI_Inferno" ) );
  356. }
  357. else
  358. {
  359. g_pVGuiLocalize->ConvertANSIToUnicode( szWeapon, wszWeaponNameHTML, sizeof( wszWeaponNameHTML ) );
  360. }
  361. }
  362. bShowItem = false;
  363. }
  364. CSteamID pKillerID;
  365. pKiller->GetSteamID( &pKillerID );
  366. CSteamID pVictimID = steamapicontext->SteamUser()->GetSteamID();
  367. if ( !pszLocString )
  368. {
  369. if ( pVictimID.ConvertToUint64( ) == ullWeaponOriginalOwnerXuid )
  370. {
  371. pszLocString = "FreezePanel_Killer1_YourWeapon"; // Victim's weapon
  372. }
  373. else if ( pKillerID.ConvertToUint64( ) == ullWeaponOriginalOwnerXuid ||
  374. ( ( ullWeaponOriginalOwnerXuid == 0 ) && pKiller->IsBot( ) ) )
  375. {
  376. pszLocString = "FreezePanel_Killer1_KillerWeapon"; // Killer's weapon
  377. }
  378. else if ( ullWeaponOriginalOwnerXuid != 0 )
  379. {
  380. pszLocString = "FreezePanel_Killer1_OthersWeapon"; // Someone else's weapon
  381. }
  382. else
  383. {
  384. pszLocString = "FreezePanel_Killer1_Weapon";
  385. }
  386. }
  387. if ( pszLocString && ullWeaponOriginalOwnerXuid )
  388. {
  389. /* Removed for partner depot */
  390. {
  391. pszLocString = "FreezePanel_Killer1_Weapon";
  392. g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), g_pVGuiLocalize->Find(pszLocString), 1, wszWeaponNameHTML );
  393. }
  394. }
  395. else
  396. {
  397. g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), g_pVGuiLocalize->Find(pszLocString), 1, wszWeaponNameHTML );
  398. }
  399. }
  400. }
  401. // the local player is dead, see if this is a new nemesis or a revenge
  402. if ( event->GetInt( "dominated" ) > 0 )
  403. {
  404. PopulateDominationInfo( Nemesis, "#FreezePanel_NewNemesis1", "#FreezePanel_NewNemesis2", L"" );
  405. }
  406. // was the killer your pre-existing nemesis?
  407. else if ( pKiller && pKiller->IsPlayerDominated( iPlayerIndexVictim ) )
  408. {
  409. PopulateDominationInfo( Nemesis, "#FreezePanel_OldNemesis1", "#FreezePanel_OldNemesis2", L"" );
  410. }
  411. else if ( event->GetInt( "revenge" ) > 0 )
  412. {
  413. PopulateDominationInfo( Revenge, "#FreezePanel_Revenge1", "#FreezePanel_Revenge2", L"" );
  414. }
  415. else if ( pKiller == pVictimPlayer || pKiller == NULL )
  416. {
  417. PopulateDominationInfo( None, "#FreezePanel_KilledSelf", "#FreezePanel_Killer2", L"" );
  418. }
  419. else
  420. {
  421. PopulateDominationInfo( None, "", "", wszLocalizedString );
  422. }
  423. // TODO: this is not the correct thing to do! This assumes that the player's active weapon is the weapon that killed the other player, this is not always true!!!
  424. // this set the item panel
  425. {
  426. static char itemIDStr[256] = { 0 };
  427. itemIDStr[0] = 0;
  428. V_snprintf( itemIDStr, sizeof( itemIDStr ), "%llu", (pItem && pItem->IsValid() && pItem->GetItemID() > 0) ? pItem->GetItemID() : 0ull );
  429. C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
  430. if (!cs_PR)
  431. return;
  432. static char xuidAsText[256] = { 0 };
  433. xuidAsText[0] = 0;
  434. if ( pKiller )
  435. cs_PR->FillXuidText( pKiller->entindex(), xuidAsText, sizeof( xuidAsText ) );
  436. static char szFauxItemId[255] = { 0 };
  437. itemid_t ullFauxItemId;
  438. if ( bShowItem && pItem )
  439. {
  440. ullFauxItemId = CombinedItemIdMakeFromDefIndexAndPaint( pItem->GetItemDefinition()->GetDefinitionIndex(), pItem->GetCustomPaintKitIndex() );
  441. }
  442. else
  443. {
  444. ullFauxItemId = 0ull;
  445. }
  446. V_snprintf( szFauxItemId, ARRAYSIZE(szFauxItemId), "%llu", ullFauxItemId );
  447. WITH_SFVALUEARRAY_SLOT_LOCKED( args, 4 )
  448. {
  449. m_pScaleformUI->ValueArray_SetElement( args, 0, bShowItem );
  450. m_pScaleformUI->ValueArray_SetElement( args, 1, itemIDStr );
  451. m_pScaleformUI->ValueArray_SetElement( args, 2, szFauxItemId );
  452. m_pScaleformUI->ValueArray_SetElement( args, 3, xuidAsText );
  453. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SetKillerItem", args, 4 );
  454. }
  455. }
  456. PopulateNavigationText();
  457. }
  458. }
  459. else if ( Q_strcmp( "player_spawn", pEventName ) == 0 )
  460. {
  461. int iUserid = engine->GetPlayerForUserID( event->GetInt( "userid" ) );
  462. SF_SPLITSCREEN_PLAYER_GUARD();
  463. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  464. if ( pLocalPlayer && iUserid == pLocalPlayer->entindex() )
  465. {
  466. WITH_SLOT_LOCKED
  467. {
  468. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "HideFreezeFrameBorder", NULL, 0 );
  469. }
  470. }
  471. }
  472. else if ( Q_strcmp( "hide_freezepanel", pEventName ) == 0 )
  473. {
  474. g_bFreezecamScreenshotFrameNumAssigned = false;
  475. m_bFreezePanelStateRelevant = false;
  476. if ( m_FlashAPI )
  477. {
  478. ShowPanel( false );
  479. m_bHoldingAfterScreenshot = false;
  480. }
  481. }
  482. else if ( Q_strcmp( "show_freezepanel", pEventName ) == 0 )
  483. {
  484. g_bFreezecamScreenshotFrameNumAssigned = true;
  485. g_flFreezecamScreenshotFrameTimeStarted = gpGlobals->curtime;
  486. SF_SPLITSCREEN_PLAYER_GUARD();
  487. int iVictimIndex = event->GetInt( "victim" );
  488. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  489. if ( pLocalPlayer && ( iVictimIndex == pLocalPlayer->entindex() ) )
  490. {
  491. C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
  492. if ( !cs_PR )
  493. return;
  494. if ( m_FlashAPI )
  495. {
  496. bool bPauseBeforeAutoreplay = g_HltvReplaySystem.IsDelayedReplayRequestPending();
  497. ShowPanel( !bPauseBeforeAutoreplay );
  498. ShowCancelPanel( bPauseBeforeAutoreplay );
  499. m_bFreezePanelStateRelevant = true;
  500. }
  501. // Get the entity who killed us
  502. m_iKillerIndex = event->GetInt( "killer" );
  503. CCSPlayer* pKiller = ToCSPlayer( ClientEntityList().GetBaseEntity( m_iKillerIndex ) );
  504. m_FollowEntity = pKiller;
  505. if ( pKiller )
  506. {
  507. int iKillerHealth = pKiller->GetHealth();
  508. if ( mp_forcecamera.GetInt() != OBS_ALLOW_ALL )
  509. {
  510. // we don't want to show the killer's health unless player can spectate killer
  511. // -1 lets the script know what we should hide it
  512. iKillerHealth = -1;
  513. }
  514. else if ( !pKiller->IsAlive() )
  515. {
  516. iKillerHealth = 0;
  517. }
  518. wchar_t wszkillerName[MAX_DECORATED_PLAYER_NAME_LENGTH];
  519. wszkillerName[0] = '\0';
  520. cs_PR->GetDecoratedPlayerName( m_iKillerIndex, wszkillerName, sizeof( wszkillerName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
  521. if ( FlashAPIIsValid() )
  522. {
  523. if ( m_killerName && m_ssNameText )
  524. {
  525. // // Truncate killer name
  526. // wchar_t wszTruncatedKillerName[MAX_DECORATED_PLAYER_NAME_LENGTH];
  527. // V_wcscpy_safe( wszTruncatedKillerName, wszkillerName );
  528. // if ( m_bDominationIconVisible )
  529. // TruncatePlayerName( wszTruncatedKillerName, ARRAYSIZE( wszTruncatedKillerName ), FREEZE_PANEL_NAME_TRUNCATE_AT_SHORT );
  530. // else
  531. // TruncatePlayerName( wszTruncatedKillerName, ARRAYSIZE( wszTruncatedKillerName ), FREEZE_PANEL_NAME_TRUNCATE_AT_LONG );
  532. WITH_SLOT_LOCKED
  533. {
  534. m_killerName->SetTextHTML( wszkillerName );
  535. m_ssNameText->SetTextHTML( wszkillerName );
  536. }
  537. WITH_SLOT_LOCKED
  538. {
  539. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "NameTextUpdated", NULL, 0 );
  540. }
  541. }
  542. char xuidAsText[256] = { 0 };
  543. g_PR->FillXuidText( m_iKillerIndex, xuidAsText, sizeof( xuidAsText ) );
  544. int nHitsTaken = 0;
  545. int nDamTaken = 0;
  546. int nHitsGiven = 0;
  547. int nDamGiven = 0;
  548. static ConVarRef sv_damage_print_enable( "sv_damage_print_enable" );
  549. if ( sv_damage_print_enable.GetBool() )
  550. {
  551. nHitsTaken = event->GetInt( "hits_taken", 0 );
  552. nDamTaken = event->GetInt( "damage_taken", 0 );
  553. nHitsGiven = event->GetInt( "hits_given", 0 );
  554. nDamGiven = event->GetInt( "damage_given", 0 );
  555. }
  556. WITH_SFVALUEARRAY( avatarData, 8 )
  557. {
  558. m_pScaleformUI->ValueArray_SetElement( avatarData, 0, xuidAsText );
  559. m_pScaleformUI->ValueArray_SetElement( avatarData, 1, pKiller->GetTeamNumber() == TEAM_CT );
  560. m_pScaleformUI->ValueArray_SetElement( avatarData, 2, wszkillerName );
  561. m_pScaleformUI->ValueArray_SetElement( avatarData, 3, nDamTaken );
  562. m_pScaleformUI->ValueArray_SetElement( avatarData, 4, nHitsTaken );
  563. m_pScaleformUI->ValueArray_SetElement( avatarData, 5, nDamGiven );
  564. m_pScaleformUI->ValueArray_SetElement( avatarData, 6, nHitsGiven );
  565. m_pScaleformUI->ValueArray_SetElement( avatarData, 7, iKillerHealth );
  566. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showAvatar", avatarData, 8 );
  567. }
  568. }
  569. m_PosY = 0;
  570. bool bShouldShowBorder = false;
  571. int nNumBorderScreens = NUM_FREEZE_CAM_BORDER_IMAGES;
  572. if ( bShouldShowBorder )
  573. {
  574. int nIndex = (pKiller->entindex()%nNumBorderScreens) + 1;
  575. WITH_SFVALUEARRAY( data, 1 )
  576. {
  577. m_pScaleformUI->ValueArray_SetElement( data, 0, nIndex );
  578. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "ShowFreezeFrameBorder", data, 1 );
  579. }
  580. }
  581. else
  582. {
  583. WITH_SLOT_LOCKED
  584. {
  585. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "HideFreezeFrameBorder", NULL, 0 );
  586. }
  587. }
  588. }
  589. else
  590. {
  591. // No specific killer (falling suicide can cause this), so set killer info to victim info
  592. if ( FlashAPIIsValid() )
  593. {
  594. wchar_t wszvictimName[MAX_DECORATED_PLAYER_NAME_LENGTH];
  595. wszvictimName[0] = '\0';
  596. cs_PR->GetDecoratedPlayerName( iVictimIndex, wszvictimName, sizeof( wszvictimName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
  597. char xuidAsText[256] = { 0 };
  598. g_PR->FillXuidText( iVictimIndex, xuidAsText, sizeof( xuidAsText ) );
  599. CCSPlayer* pVictim = ToCSPlayer( ClientEntityList().GetBaseEntity( iVictimIndex ) );
  600. WITH_SLOT_LOCKED
  601. {
  602. if ( m_killerName && m_ssNameText )
  603. {
  604. m_killerName->SetTextHTML( wszvictimName );
  605. m_ssNameText->SetTextHTML( wszvictimName );
  606. }
  607. if ( pVictim )
  608. {
  609. WITH_SFVALUEARRAY( avatarData, 3 )
  610. {
  611. m_pScaleformUI->ValueArray_SetElement( avatarData, 0, xuidAsText );
  612. m_pScaleformUI->ValueArray_SetElement( avatarData, 1, pVictim->GetTeamNumber() == TEAM_CT );
  613. m_pScaleformUI->ValueArray_SetElement( avatarData, 2, wszvictimName );
  614. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showAvatar", avatarData, 3 );
  615. }
  616. }
  617. }
  618. }
  619. }
  620. }
  621. }
  622. }
  623. void SFHudFreezePanel::ShowPanel( bool bShow )
  624. {
  625. if ( !m_FlashAPI )
  626. return;
  627. if ( bShow == false && m_bIsVisible )
  628. {
  629. // hide it
  630. WITH_SLOT_LOCKED
  631. {
  632. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "hide", NULL, 0 );
  633. ScaleformDisplayInfo dinfo_freeze;
  634. m_pScaleformUI->Value_GetDisplayInfo( m_freezePanel, &dinfo_freeze );
  635. dinfo_freeze.SetVisibility( false );
  636. m_pScaleformUI->Value_SetDisplayInfo( m_freezePanel, &dinfo_freeze );
  637. ScaleformDisplayInfo dinfo;
  638. m_pScaleformUI->Value_GetDisplayInfo( m_ssFreezePanel, &dinfo );
  639. dinfo.SetVisibility( false );
  640. m_pScaleformUI->Value_SetDisplayInfo( m_ssFreezePanel, &dinfo );
  641. }
  642. m_bIsVisible = false;
  643. }
  644. else if ( bShow && m_bIsVisible == false )
  645. {
  646. // show it
  647. WITH_SLOT_LOCKED
  648. {
  649. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "show", NULL, 0 );
  650. ScaleformDisplayInfo dinfo_freeze;
  651. m_pScaleformUI->Value_GetDisplayInfo( m_freezePanel, &dinfo_freeze );
  652. dinfo_freeze.SetVisibility( true );
  653. m_pScaleformUI->Value_SetDisplayInfo( m_freezePanel, &dinfo_freeze );
  654. ScaleformDisplayInfo dinfo;
  655. m_pScaleformUI->Value_GetDisplayInfo( m_ssFreezePanel, &dinfo );
  656. dinfo.SetVisibility( false );
  657. m_pScaleformUI->Value_SetDisplayInfo( m_ssFreezePanel, &dinfo );
  658. }
  659. m_bIsVisible = true;
  660. }
  661. }
  662. void SFHudFreezePanel::ShowCancelPanel( bool bShow )
  663. {
  664. if ( bShow != m_bIsCancelPanelVisible )
  665. {
  666. WITH_SLOT_LOCKED
  667. {
  668. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, bShow ? "ShowCancelText" : "HideCancelText", NULL, 0 );
  669. }
  670. m_bIsCancelPanelVisible = bShow;
  671. }
  672. }
  673. void SFHudFreezePanel::PopulateDominationInfo( DominationIconType iconType, const char* localizationToken1, const char* localizationToken2, wchar_t *szWeaponHTML )
  674. {
  675. WITH_SLOT_LOCKED
  676. {
  677. SetIcon( iconType );
  678. if ( m_dominationText1 )
  679. {
  680. wchar_t wszCombined[256];
  681. V_snwprintf( wszCombined,
  682. ARRAYSIZE( wszCombined ),
  683. #if defined(_PS3) || defined(POSIX)
  684. L"%ls %ls %ls",
  685. #else
  686. L"%s %s %s",
  687. #endif
  688. g_pScaleformUI->Translate( localizationToken1, NULL ),
  689. g_pScaleformUI->Translate( localizationToken2, NULL ),
  690. szWeaponHTML ? szWeaponHTML : L""
  691. );
  692. m_dominationText1->SetTextHTML( wszCombined );
  693. /* Removed for partner depot */
  694. {
  695. m_ssDescText->SetTextHTML( wszCombined );
  696. }
  697. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "HideFreezeFrameBorder", NULL, 0 );
  698. }
  699. }
  700. }
  701. void SFHudFreezePanel::PopulateNavigationText( void )
  702. {
  703. WITH_SLOT_LOCKED
  704. {
  705. if ( m_navigationText )
  706. {
  707. if ( IsTakingAFreezecamScreenshot() )
  708. {
  709. m_navigationText->SetTextHTML( "" );
  710. }
  711. else
  712. {
  713. if ( IsGameConsole() )
  714. {
  715. if ( g_pInputSystem->GetCurrentInputDevice() == INPUT_DEVICE_SHARPSHOOTER )
  716. {
  717. m_navigationText->SetTextHTML( "#SFUI_Freeze_Skip_Trigger" );
  718. }
  719. else
  720. {
  721. m_navigationText->SetTextHTML( "#SFUI_Freeze_Skip" );
  722. }
  723. }
  724. else
  725. {
  726. if ( g_HltvReplaySystem.GetHltvReplayDelay() )
  727. {
  728. if ( wchar_t *wzCancelReplay = g_pVGuiLocalize->Find( "#SFUI_Freeze_Cancel_Replay" ) )
  729. {
  730. m_navigationText->SetTextHTML( m_pScaleformUI->ReplaceGlyphKeywordsWithHTML( wzCancelReplay ) );
  731. }
  732. }
  733. else
  734. {
  735. wchar_t wzBind[ 16 ] = L"";
  736. wchar_t navBarText[ 256 ] = L"";
  737. UTIL_ReplaceKeyBindings( L"%jpeg%", 0, wzBind, sizeof( wzBind ) );
  738. g_pVGuiLocalize->ConstructString( navBarText, sizeof( navBarText ), g_pVGuiLocalize->Find( "#SFUI_Freeze_Snapshot" ), 1, wzBind );
  739. if ( g_HltvReplaySystem.IsHltvReplayButtonEnabled() && !g_HltvReplaySystem.IsDelayedReplayRequestPending() ) // no need to show "press F5 for replay" if we're about to show replay anyway
  740. {
  741. // we can also start replay right now out of freezecam
  742. if ( wchar_t *wcReplayLastKill = g_pVGuiLocalize->Find( "#SFUIHUD_Spectate_Navigation_Replay_Death" ) )
  743. {
  744. if ( wcReplayLastKill[ 0 ] != L'\0' )
  745. {
  746. V_wcscat( navBarText, L" ", sizeof( navBarText ) );
  747. V_wcscat( navBarText, wcReplayLastKill, sizeof( navBarText ) );
  748. }
  749. }
  750. }
  751. m_navigationText->SetTextHTML( m_pScaleformUI->ReplaceGlyphKeywordsWithHTML( navBarText ) );
  752. }
  753. }
  754. }
  755. }
  756. }
  757. }
  758. void SFHudFreezePanel::OnTimeJump( void )
  759. {
  760. if ( m_FlashAPI )
  761. {
  762. WITH_SLOT_LOCKED
  763. {
  764. if ( g_HltvReplaySystem.GetHltvReplayDelay() )
  765. {
  766. if ( g_HltvReplaySystem.IsReplayingFinalKillOfRound() )
  767. {
  768. //m_ssDescText->SetTextHTML( g_pVGuiLocalize->Find( "FreezePanel_FinalKillOfTheRound" ) );
  769. //m_navigationText->SetTextHTML( g_pVGuiLocalize->Find( "FreezePanel_FinalKillOfTheRound" ) );
  770. m_dominationText1->SetTextHTML( g_pVGuiLocalize->Find( "FreezePanel_FinalKillOfTheRound" ) );
  771. }
  772. ShowPanel( true );
  773. }
  774. PopulateNavigationText();
  775. }
  776. }
  777. }
  778. void SFHudFreezePanel::ResetDamageText( int iPlayerIndexKiller, int iPlayerIndexVictim )
  779. {
  780. C_BasePlayer *pKiller = UTIL_PlayerByIndex( iPlayerIndexKiller );
  781. C_BasePlayer *pVictim = UTIL_PlayerByIndex( iPlayerIndexVictim );
  782. if ( !pVictim || !pKiller )
  783. return;
  784. C_CS_PlayerResource *cs_PR = dynamic_cast<C_CS_PlayerResource *>( g_PR );
  785. if ( !cs_PR )
  786. return;
  787. char xuidAsText[ 256 ] = { 0 };
  788. g_PR->FillXuidText( m_iKillerIndex, xuidAsText, sizeof( xuidAsText ) );
  789. int nHitsTaken = pVictim->m_nLastKillerHitsTaken;
  790. int nDamTaken = pVictim->m_nLastKillerDamageTaken;
  791. int nHitsGiven = pVictim->m_nLastKillerHitsGiven;
  792. int nDamGiven = pVictim->m_nLastKillerDamageGiven;
  793. wchar_t wszkillerName[ MAX_DECORATED_PLAYER_NAME_LENGTH ];
  794. wszkillerName[ 0 ] = '\0';
  795. cs_PR->GetDecoratedPlayerName( m_iKillerIndex, wszkillerName, sizeof( wszkillerName ), k_EDecoratedPlayerNameFlag_AddBotToNameIfControllingBot );
  796. WITH_SFVALUEARRAY( avatarData, 8 )
  797. {
  798. m_pScaleformUI->ValueArray_SetElement( avatarData, 0, xuidAsText );
  799. m_pScaleformUI->ValueArray_SetElement( avatarData, 1, pKiller->GetTeamNumber() == TEAM_CT );
  800. m_pScaleformUI->ValueArray_SetElement( avatarData, 2, wszkillerName );
  801. m_pScaleformUI->ValueArray_SetElement( avatarData, 3, nDamTaken );
  802. m_pScaleformUI->ValueArray_SetElement( avatarData, 4, nHitsTaken );
  803. m_pScaleformUI->ValueArray_SetElement( avatarData, 5, nDamGiven );
  804. m_pScaleformUI->ValueArray_SetElement( avatarData, 6, nHitsGiven );
  805. m_pScaleformUI->ValueArray_SetElement( avatarData, 7, pKiller->GetHealth() );
  806. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "showAvatar", avatarData, 8 );
  807. }
  808. }
  809. void SFHudFreezePanel::OnHltvReplayButtonStateChanged( void )
  810. {
  811. if ( m_FlashAPI )
  812. {
  813. WITH_SLOT_LOCKED
  814. {
  815. PopulateNavigationText();
  816. bool bPauseBeforeAutoreplay = !g_HltvReplaySystem.GetHltvReplayDelay() && g_HltvReplaySystem.IsDelayedReplayRequestPending();
  817. ShowPanel( m_bFreezePanelStateRelevant && !bPauseBeforeAutoreplay );
  818. ShowCancelPanel( m_bFreezePanelStateRelevant && bPauseBeforeAutoreplay );
  819. }
  820. }
  821. }
  822. ////////////////////////////////////////////////////////////////////////////////
  823. // NOTE: This function is not threadsafe. If it is not called from ActionScript,
  824. // it needs to be called within a lock.
  825. ////////////////////////////////////////////////////////////////////////////////
  826. void SFHudFreezePanel::SetIcon( DominationIconType iconType )
  827. {
  828. for ( int i = 0 ; i < DominationIconMax ; ++i )
  829. {
  830. ISFTextObject* pIcon = m_dominationIcons[i];
  831. if ( pIcon )
  832. {
  833. pIcon->SetVisible( i == iconType );
  834. m_bDominationIconVisible = (iconType != 0);
  835. }
  836. }
  837. }
  838. void SFHudFreezePanel::DeviceReset( void *pDevice, void *pPresentParameters, void *pHWnd )
  839. {
  840. if ( FlashAPIIsValid() )
  841. {
  842. WITH_SLOT_LOCKED
  843. {
  844. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "RefreshAvatarImage", NULL, 0 );
  845. }
  846. }
  847. }
  848. void SFHudFreezePanel::ProcessInput( void )
  849. {
  850. PositionPanel();
  851. }
  852. void SFHudFreezePanel::PositionPanel( void )
  853. {
  854. if ( !m_freezePanel )
  855. return;
  856. ScaleformDisplayInfo dinfo;
  857. m_pScaleformUI->Value_GetDisplayInfo( m_freezePanel, &dinfo );
  858. if ( !dinfo.GetVisibility() || dinfo.GetAlpha() <= 0 )
  859. return;
  860. if ( cl_freezecampanel_position_dynamic.GetInt() > 0 )
  861. {
  862. SF_SPLITSCREEN_PLAYER_GUARD();
  863. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  864. C_CSPlayer *pPlayer = ToCSPlayer( C_BasePlayer::GetLocalPlayer() );
  865. if ( pPlayer == NULL )
  866. return;
  867. // TODO: get panels that this might overlap with, get their height and make sure they don't overlap
  868. // need to be able to get the height/width of a panel for this work to be done
  869. bool bWinPanelVisible = false;
  870. SFHudWinPanel * pWinPanel = GET_HUDELEMENT( SFHudWinPanel );
  871. if ( pWinPanel && pWinPanel->IsVisible() )
  872. {
  873. bWinPanelVisible = true;
  874. }
  875. float flInterp = pPlayer->GetFreezeFrameInterpolant();
  876. if ( g_HltvReplaySystem.GetHltvReplayDelay() )
  877. {
  878. // we're in replay, position the panel so that it plays nicely with the Replay framing
  879. m_PosX = ScreenWidth() / 2;
  880. m_PosY = ScreenHeight() * spec_freeze_panel_replay_position.GetFloat();
  881. }
  882. else if ( flInterp < 1.0f )
  883. {
  884. // Reposition the callout based on our target's position
  885. Vector vecTarget = pPlayer->GetRenderOrigin();
  886. CCSPlayer *pKiller = dynamic_cast<CCSPlayer*>( m_FollowEntity.Get() );
  887. if ( pKiller )
  888. {
  889. vecTarget = pKiller->EyePosition();
  890. vecTarget.z -= 50;
  891. }
  892. Vector vDelta = vecTarget - MainViewOrigin( nSlot );
  893. //float flDistance = vDelta.Length();
  894. VectorNormalize( vDelta ); // Only necessary so we can use it as part of our alpha calculation
  895. // Is the target visible on screen?
  896. int iX, iY;
  897. bool bOnscreen = GetVectorInScreenSpace( vecTarget, iX, iY );
  898. m_PosX = iX;
  899. bool bMsgBoxVisible = false;
  900. SFHudInfoPanel *pElement = dynamic_cast<SFHudInfoPanel*>( GetHud().FindElement( "SFHudInfoPanel" ) );
  901. if ( pElement )
  902. bMsgBoxVisible = pElement->IsVisible();
  903. // some nasty hardcoded numbers until we can get the height/width of the panels surrounding it
  904. int nMaxY = ScreenHeight() * 0.8;
  905. if ( bMsgBoxVisible )
  906. {
  907. m_PosY = ( ScreenHeight()*0.75 );
  908. }
  909. else if ( bWinPanelVisible || !bOnscreen )
  910. {
  911. m_PosY = (ScreenHeight()*0.5);
  912. }
  913. else
  914. {
  915. m_PosY = clamp( iY, ScreenHeight()*0.55, nMaxY );
  916. }
  917. }
  918. int nPrevY = dinfo.GetY();
  919. int nCurY = Lerp( flInterp, nPrevY, m_PosY );
  920. //float flRot = Lerp( flInterp, 0.0f, -pPlayer->GetFreezeFrameTilt() );
  921. dinfo.SetY( nCurY );
  922. //dinfo.SetRotation( flRot );
  923. m_pScaleformUI->Value_SetDisplayInfo( m_freezePanel, &dinfo );
  924. }
  925. else
  926. {
  927. // let the script handle it
  928. WITH_SFVALUEARRAY_SLOT_LOCKED( panelData, 1 )
  929. {
  930. m_pScaleformUI->ValueArray_SetElement( panelData, 0, m_freezePanel );
  931. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "positionDeathPanel", panelData, 1 );
  932. }
  933. }
  934. }
  935. const char *SFHudFreezePanel::GetFilesafePlayerName( const char *pszOldName )
  936. {
  937. if ( !pszOldName )
  938. return "";
  939. static char szSafeName[ MAX_PLAYER_NAME_LENGTH ];
  940. int nSafeNameBufSize = sizeof( szSafeName );
  941. int nNewPos = 0;
  942. for( const char *p = pszOldName; *p != 0 && nNewPos < nSafeNameBufSize-1; p++ )
  943. {
  944. if( *p == '.' )
  945. {
  946. szSafeName[ nNewPos ] = '-';
  947. }
  948. else if( *p == '/' )
  949. {
  950. szSafeName[ nNewPos ] = '-';
  951. }
  952. else if( *p == '\\' )
  953. {
  954. szSafeName[ nNewPos ] = '-';
  955. }
  956. else if( *p == ':' )
  957. {
  958. szSafeName[ nNewPos ] = '-';
  959. }
  960. else
  961. {
  962. szSafeName[ nNewPos ] = *p;
  963. }
  964. nNewPos++;
  965. }
  966. szSafeName[ nNewPos ] = 0;
  967. return szSafeName;
  968. }
  969. void SFHudFreezePanel::TakeFreezeShot( void )
  970. {
  971. if ( ShouldDraw() )
  972. {
  973. // Establish the frame when we are starting freezecam shot
  974. g_bFreezecamScreenshotFrameNumAssigned = true;
  975. g_flFreezecamScreenshotFrameTimeStarted = gpGlobals->curtime;
  976. WITH_SLOT_LOCKED
  977. {
  978. //C_CSPlayer *pLocalPlayer = ToCSPlayer( C_BasePlayer::GetLocalPlayer() );
  979. //if ( EconHolidays_IsHolidayActive( kHoliday_Christmas ) && pLocalPlayer && pLocalPlayer->GetObserverTarget() && ( pLocalPlayer->GetObserverTarget() != pLocalPlayer ) )
  980. //{
  981. // m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "ShowFreezeFrameBorder", NULL, 0 );
  982. //}
  983. // hide the main freeze panel
  984. ScaleformDisplayInfo dinfo_freeze;
  985. m_pScaleformUI->Value_GetDisplayInfo( m_freezePanel, &dinfo_freeze );
  986. dinfo_freeze.SetVisibility( false );
  987. m_pScaleformUI->Value_SetDisplayInfo( m_freezePanel, &dinfo_freeze );
  988. ScaleformDisplayInfo dinfo;
  989. m_pScaleformUI->Value_GetDisplayInfo( m_ssFreezePanel, &dinfo );
  990. dinfo.SetVisibility( true );
  991. // move the target id to the corner
  992. if ( m_ssFreezePanel && dinfo.GetVisibility() && dinfo.GetAlpha() > 0 )
  993. {
  994. if ( cl_freezecampanel_position_dynamic.GetInt() > 0 )
  995. {
  996. // we don't know how big the panels are.......
  997. //m_pBasePanel->SetPos( ScreenWidth() - w, ScreenHeight() - h );
  998. C_CSPlayer *pPlayer = ToCSPlayer( C_BasePlayer::GetLocalPlayer() );
  999. if ( pPlayer == NULL )
  1000. return;
  1001. float flRot = -pPlayer->GetFreezeFrameTilt();
  1002. dinfo.SetRotation( flRot );
  1003. m_PosY = ScreenHeight() - (ScreenHeight() * 0.3);
  1004. if ( flRot > 0 )
  1005. m_PosY -= (ScreenHeight() * 0.2);
  1006. dinfo.SetY( m_PosY );
  1007. int nXPos = -(ScreenWidth() * 0.05);
  1008. // widescreen
  1009. if ( ScreenHeight()/ScreenWidth() < 0.75 )
  1010. nXPos = -(ScreenWidth() * 0.01);
  1011. dinfo.SetX( -(ScreenWidth() * 0.02) );
  1012. dinfo.SetXScale( 200.0f * ((float)ScreenWidth()/1920.0f) );
  1013. dinfo.SetYScale( 200.0f * ((float)ScreenWidth()/1920.0f) );
  1014. m_pScaleformUI->Value_SetDisplayInfo( m_ssFreezePanel, &dinfo );
  1015. }
  1016. else
  1017. {
  1018. // let the script handle it
  1019. WITH_SFVALUEARRAY( panelData, 1 )
  1020. {
  1021. m_pScaleformUI->ValueArray_SetElement( panelData, 0, m_ssFreezePanel );
  1022. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "positionScreenshotPanel", panelData, 1 );
  1023. }
  1024. }
  1025. }
  1026. }
  1027. // Get the local player.
  1028. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  1029. if ( pPlayer )
  1030. {
  1031. //Do effects
  1032. g_flFreezeFlash[ GetSplitScreenPlayerSlot() ] = gpGlobals->curtime + 0.75f;
  1033. pPlayer->EmitSound( "FreezeShot.TakeScreenshot" );
  1034. //Extend Freezecam by a couple more seconds.
  1035. engine->ClientCmd( "extendfreeze" );
  1036. view->FreezeFrame( 3.0f );
  1037. m_bHoldingAfterScreenshot = true;
  1038. /*
  1039. // Hide everything?
  1040. if ( hud_freezecamhide.GetBool() )
  1041. {
  1042. SetVisible( false );
  1043. DeleteCalloutPanels();
  1044. }
  1045. */
  1046. //Set the screenshot name
  1047. if ( m_iKillerIndex <= MAX_PLAYERS )
  1048. {
  1049. const char *pszKillerName = g_PR->GetPlayerName( m_iKillerIndex );
  1050. if ( pszKillerName )
  1051. {
  1052. ConVarRef cl_screenshotname( "cl_screenshotname" );
  1053. if ( cl_screenshotname.IsValid() )
  1054. {
  1055. char szScreenShotName[512];
  1056. Q_snprintf( szScreenShotName, sizeof( szScreenShotName ), "%s %s", GetFilesafePlayerName( pszKillerName ), FREEZECAM_SCREENSHOT_STRING );
  1057. cl_screenshotname.SetValue( szScreenShotName );
  1058. }
  1059. }
  1060. // clear the navigation text (space to skip)
  1061. PopulateNavigationText();
  1062. C_CSPlayer *pKiller = ToCSPlayer( UTIL_PlayerByIndex( m_iKillerIndex ) );
  1063. if ( pKiller && !pKiller->IsBot() )
  1064. {
  1065. CSteamID steamID;
  1066. if ( pKiller->GetSteamID( &steamID ) && steamID.IsValid() )
  1067. {
  1068. ConVarRef cl_screenshotusertag( "cl_screenshotusertag" );
  1069. if ( cl_screenshotusertag.IsValid() )
  1070. {
  1071. cl_screenshotusertag.SetValue( (int)steamID.GetAccountID() );
  1072. }
  1073. }
  1074. }
  1075. }
  1076. }
  1077. }
  1078. }
  1079. #endif // INCLUDE_SCALEFORM