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.

1416 lines
46 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Weapon selection hud
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "sfweaponselection.h"
  9. #include "hud_macros.h"
  10. #include <vgui/ILocalize.h>
  11. #include <vgui/ISurface.h>
  12. #include "iclientmode.h"
  13. #include "hud.h"
  14. #include "hudelement.h"
  15. #include "hud_element_helper.h"
  16. #include "iclientmode.h"
  17. #include "scaleformui/scaleformui.h"
  18. #include "weapon_selection.h"
  19. #include "weapon_basecsgrenade.h"
  20. #include "hltvreplaysystem.h"
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. extern ConVar hud_drawhistory_time;
  24. DECLARE_HUDELEMENT( SFWeaponSelection );
  25. //
  26. SFUI_BEGIN_GAME_API_DEF
  27. SFUI_END_GAME_API_DEF( SFWeaponSelection, WeaponSelected );
  28. void showloadoutCallBack( IConVar *var, const char *pOldString, float flOldValue );
  29. ConVar cl_showloadout( "cl_showloadout", "1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE | FCVAR_SS , "Toggles display of current loadout.", showloadoutCallBack );
  30. ConVar cl_loadout_colorweaponnames( "cl_loadout_colorweaponnames", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE | FCVAR_SS , "If set to true, the weapon names are colored in the weapon loadout to match their rarity." );
  31. ConVar cl_inv_showdividerline( "cl_inv_showdividerline", "0", FCVAR_ARCHIVE | FCVAR_SS , "If 1, will show a divider line above the grenades in the inventory panel." );
  32. extern ConVar cl_draw_only_deathnotices;
  33. void showloadoutCallBack( IConVar *var, const char *pOldString, float flOldValue )
  34. {
  35. if ( !C_BasePlayer::GetLocalPlayer() || !engine->IsLocalPlayerResolvable() )
  36. return;
  37. SFWeaponSelection *pHudWS = GET_HUDELEMENT( SFWeaponSelection );
  38. if ( pHudWS )
  39. {
  40. pHudWS->SetAlwaysShow( cl_showloadout.GetBool( ) );
  41. }
  42. }
  43. CON_COMMAND_F( show_loadout_toggle, "Toggles loadout display", FCVAR_CLIENTCMD_CAN_EXECUTE )
  44. {
  45. cl_showloadout.SetValue( !cl_showloadout.GetBool() );
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Purpose: Constructor
  49. //-----------------------------------------------------------------------------
  50. SFWeaponSelection::SFWeaponSelection( const char *value ) : SFHudFlashInterface( value ),
  51. m_bVisible( false ),
  52. m_anchorPanel( NULL )
  53. {
  54. SetHiddenBits( HIDEHUD_PLAYERDEAD | HIDEHUD_MISCSTATUS | HIDEHUD_WEAPONSELECTION );
  55. m_flFadeStartTime = 0;
  56. m_nPrevWepAlignSlot = -1;
  57. m_nPrevOccupiedWepSlot = -1;
  58. m_nOrigXPos = 0;
  59. m_nOrigYPos = 0;
  60. m_bInitPos = false;
  61. m_bInitialized = false;
  62. m_bC4IsVisible = false;
  63. m_bAlwaysShow = cl_showloadout.GetBool();
  64. m_bCreatedNextPanel = false;
  65. m_ggNextPanel.handle = NULL;
  66. m_nLastTRKills = 0;
  67. m_nLastGGWepIndex = 0;
  68. m_bUpdateGGNextPanel = false;
  69. m_flUpdateInventoryAt = -1;
  70. m_bUpdateInventoryReset = false;
  71. m_bSpectatorTargetIndex = -1;
  72. V_memset( m_weaponPanels, 0, sizeof( m_weaponPanels ) );
  73. }
  74. C_CSPlayer* SFWeaponSelection::GetLocalOrHudPlayer( void )
  75. {
  76. if ( !g_HltvReplaySystem.GetHltvReplayDelay() )
  77. {
  78. int nMaxPlayers = CCSGameRules::GetMaxPlayers();
  79. if ( C_CSPlayer::GetLocalCSPlayer() && C_CSPlayer::GetLocalCSPlayer()->GetObserverTarget() && ( nMaxPlayers <= 10 || C_CSPlayer::GetLocalCSPlayer()->IsHLTV() ) )
  80. {
  81. return C_CSPlayer::GetLocalCSPlayer();
  82. }
  83. }
  84. return GetHudPlayer();
  85. }
  86. void SFWeaponSelection::AddWeapon( C_BaseCombatWeapon *pWeapon, bool bSelected )
  87. {
  88. if ( !pWeapon || !C_CSPlayer::GetLocalCSPlayer() )
  89. return;
  90. int nWepSlot = pWeapon->GetSlot();
  91. int nWepPos = pWeapon->GetPosition();
  92. SFVALUE panelHandle = NULL;
  93. CEconItemView *pItem = pWeapon->GetEconItemView();
  94. CWeaponCSBase *pCSWeapon = ( CWeaponCSBase* )pWeapon;
  95. C_BasePlayer *pPlayer = GetLocalOrHudPlayer();
  96. if ( !pCSWeapon || !pPlayer || !pCSWeapon->GetPlayerOwner() || pCSWeapon->GetPlayerOwner() != pPlayer )
  97. return;
  98. bool bShowWeaponColor = ( pItem && pItem->IsValid() && pItem->GetItemID() > 0 && !pCSWeapon->IsKindOf( WEAPONTYPE_GRENADE ) );
  99. WITH_SLOT_LOCKED
  100. {
  101. WITH_SFVALUEARRAY( data, 4 )
  102. {
  103. const int kColorBufSize = 128;
  104. wchar_t rwchColor[kColorBufSize];
  105. if ( bShowWeaponColor )
  106. {
  107. const CEconItemRarityDefinition *pRarity = GetItemSchema()->GetRarityDefinition( pItem->GetRarity() );
  108. Q_UTF8ToUnicode( GetHexColorForAttribColor( pRarity->GetAttribColor() ), rwchColor, kColorBufSize );
  109. }
  110. m_pScaleformUI->ValueArray_SetElement( data, 0, m_weaponPanels[nWepSlot][nWepPos].handle );
  111. m_pScaleformUI->ValueArray_SetElement( data, 1, (pCSWeapon && pCSWeapon->GetPlayerOwner()) ? pCSWeapon->GetPlayerOwner()->GetTeamNumber() : 0 );
  112. m_pScaleformUI->ValueArray_SetElement( data, 2, ((pItem && pItem->IsValid()) ? pItem->GetItemDefinition()->GetDefinitionName() : pWeapon->GetName()) );
  113. m_pScaleformUI->ValueArray_SetElement( data, 3, (bShowWeaponColor ? rwchColor : L"") );
  114. panelHandle = m_pScaleformUI->Value_Invoke( m_FlashAPI, "AddWeaponData", data, 4 );
  115. }
  116. }
  117. if ( panelHandle && m_pScaleformUI->Value_GetType( panelHandle ) == IScaleformUI::VT_DisplayObject )
  118. {
  119. //Put the new panel in the list
  120. SafeReleaseSFVALUE( m_weaponPanels[nWepSlot][nWepPos].handle );
  121. m_weaponPanels[nWepSlot][nWepPos].handle = panelHandle;
  122. m_weaponPanels[nWepSlot][nWepPos].alpha = 255;
  123. m_weaponPanels[nWepSlot][nWepPos].hWeapon = pWeapon;
  124. m_weaponPanels[nWepSlot][nWepPos].bSelected = bSelected;
  125. m_weaponPanels[nWepSlot][nWepPos].bJustPickedUp = !C_CSPlayer::GetLocalCSPlayer()->GetObserverTarget();
  126. m_weaponPanels[nWepSlot][nWepPos].fLastBlinkTime = gpGlobals->curtime;
  127. m_weaponPanels[nWepSlot][nWepPos].fEndBlinkTime = gpGlobals->curtime + WEAPON_SELECTION_FADE_DELAY;
  128. ScaleformDisplayInfo dinfo;
  129. m_pScaleformUI->Value_GetDisplayInfo( panelHandle, &dinfo );
  130. dinfo.SetVisibility( true );
  131. m_pScaleformUI->Value_SetDisplayInfo( panelHandle, &dinfo );
  132. }
  133. if ( CSGameRules() && CSGameRules()->IsPlayingGunGameProgressive() )
  134. {
  135. if ( !m_bCreatedNextPanel )
  136. {
  137. CreateGGNextPanel();
  138. }
  139. UpdateGGNextPanel();
  140. }
  141. // force a weapon switch to catch where we got a user message but not the network update, yet
  142. m_flUpdateInventoryAt = gpGlobals->curtime + 0.1;
  143. }
  144. void SFWeaponSelection::UpdateGGNextPanel( bool bForceShowForTRBomb, bool bKnifeReached )
  145. {
  146. // check if it already exists
  147. if ( m_ggNextPanel.handle == NULL || !m_bCreatedNextPanel )
  148. {
  149. CreateGGNextPanel();
  150. }
  151. if ( !FlashAPIIsValid() || m_pScaleformUI->Value_GetType( m_ggNextPanel.handle ) != IScaleformUI::VT_DisplayObject )
  152. return;
  153. bool bIsSpectating = !!(C_CSPlayer::GetLocalCSPlayer()->GetObserverTarget());
  154. // use the spectator target if we have one, otherwise use the local player
  155. C_CSPlayer *pPlayer = (C_CSPlayer::GetLocalCSPlayer() && bIsSpectating) ? dynamic_cast<C_CSPlayer*>(C_CSPlayer::GetLocalCSPlayer()->GetObserverTarget()) : C_CSPlayer::GetLocalCSPlayer();
  156. if ( !pPlayer )
  157. return;
  158. bool bIsPlayingProgressive = CSGameRules()->IsPlayingGunGameProgressive();
  159. int nCurrentIndex = pPlayer->GetPlayerGunGameWeaponIndex();
  160. int nIndexOffset = 0;
  161. if ( bIsPlayingProgressive )
  162. nIndexOffset = -1;
  163. //GetPlayerGunGameWeaponIndex( void ) { return m_iGunGameProgressiveWeaponIndex; }
  164. int nextWeaponID = CSGameRules()->GetNextGunGameWeapon( MAX( 0, nCurrentIndex+nIndexOffset ), pPlayer->GetTeamNumber() );
  165. int nextWeaponID1 = CSGameRules()->GetNextGunGameWeapon( nCurrentIndex+1+nIndexOffset, pPlayer->GetTeamNumber() );
  166. int nextWeaponID2 = CSGameRules()->GetNextGunGameWeapon( nCurrentIndex+2+nIndexOffset, pPlayer->GetTeamNumber() );
  167. int nextWeaponID3 = CSGameRules()->GetNextGunGameWeapon( nCurrentIndex+3+nIndexOffset, pPlayer->GetTeamNumber() );
  168. int nextWeaponID4 = CSGameRules()->GetNextGunGameWeapon( nCurrentIndex + 4 + nIndexOffset, pPlayer->GetTeamNumber() );
  169. int nextWeaponID5 = CSGameRules()->GetNextGunGameWeapon( nCurrentIndex + 5 + nIndexOffset, pPlayer->GetTeamNumber() );
  170. const CEconItemDefinition *pNextWeaponDef = GetItemSchema()->GetItemDefinition( nextWeaponID );
  171. const CEconItemDefinition *pNextWeapon1Def = nextWeaponID1 >= 0 ? GetItemSchema()->GetItemDefinition( nextWeaponID1 ) : NULL;
  172. //if ( !pNextWeapon1Def || pNextWeapon1Def->GetDefinitionIndex() <= 0 )
  173. const CEconItemDefinition *pNextWeapon2Def = nextWeaponID2 >= 0 ? GetItemSchema()->GetItemDefinition( nextWeaponID2 ) : NULL;
  174. const CEconItemDefinition *pNextWeapon3Def = nextWeaponID3 >= 0 ? GetItemSchema()->GetItemDefinition( nextWeaponID3 ) : NULL;
  175. const CEconItemDefinition *pNextWeapon4Def = nextWeaponID4 >= 0 ? GetItemSchema()->GetItemDefinition( nextWeaponID4 ) : NULL;
  176. const CEconItemDefinition *pNextWeapon5Def = nextWeaponID5 >= 0 ? GetItemSchema()->GetItemDefinition( nextWeaponID5 ) : NULL;
  177. bool bVisible = true;
  178. int nMaxIndex = CSGameRules()->GetNumProgressiveGunGameWeapons( pPlayer->GetTeamNumber() )-1;
  179. int nCurIndex = bKnifeReached ? nMaxIndex : (float)pPlayer->GetPlayerGunGameWeaponIndex();
  180. int nCurTRKills = pPlayer->GetNumGunGameTRKillPoints();
  181. if ( nCurIndex == nMaxIndex || ( CSGameRules()->IsPlayingGunGameTRBomb() && !bForceShowForTRBomb ) )
  182. bVisible = false;
  183. const char *szGrenName = NULL;
  184. if ( bForceShowForTRBomb )
  185. {
  186. int nBonusGrenade = CSGameRules()->GetGunGameTRBonusGrenade( pPlayer );
  187. if ( nBonusGrenade == WEAPON_MOLOTOV || nBonusGrenade == WEAPON_INCGRENADE )
  188. {
  189. if ( pPlayer->GetTeamNumber() == TEAM_CT )
  190. szGrenName = "weapon_incgrenade";
  191. else
  192. szGrenName = "weapon_molotov";
  193. }
  194. else if ( nBonusGrenade == WEAPON_FLASHBANG )
  195. {
  196. szGrenName = "weapon_flashbang";
  197. }
  198. else if ( nBonusGrenade == WEAPON_HEGRENADE )
  199. {
  200. szGrenName = "weapon_hegrenade";
  201. }
  202. }
  203. //float flProgressFrac = (float)nCurIndex / (float)nMaxIndex;
  204. WITH_SLOT_LOCKED
  205. {
  206. if ( bVisible )
  207. {
  208. SFVALUE panelHandle = NULL;
  209. WITH_SFVALUEARRAY( data, 13 )
  210. {
  211. m_pScaleformUI->ValueArray_SetElement( data, 0, m_ggNextPanel.handle );
  212. m_pScaleformUI->ValueArray_SetElement( data, 1, pNextWeaponDef ? pNextWeaponDef->GetDefinitionName() : "" );
  213. m_pScaleformUI->ValueArray_SetElement( data, 2, pPlayer ? pPlayer->GetTeamNumber() : 0 );
  214. m_pScaleformUI->ValueArray_SetElement( data, 3, nCurIndex );
  215. m_pScaleformUI->ValueArray_SetElement( data, 4, nMaxIndex );
  216. m_pScaleformUI->ValueArray_SetElement( data, 5, szGrenName );
  217. m_pScaleformUI->ValueArray_SetElement( data, 6, !bIsSpectating && bIsPlayingProgressive ); // show the gun drop animation in progressive
  218. m_pScaleformUI->ValueArray_SetElement( data, 7, !bIsSpectating && (m_nLastGGWepIndex != nCurIndex || m_nLastTRKills != nCurTRKills) ); // show the animation if the new weapon is different from the last
  219. m_pScaleformUI->ValueArray_SetElement( data, 8, (pNextWeapon1Def && pNextWeapon1Def->GetDefinitionIndex() > 0) ? pNextWeapon1Def->GetDefinitionName() : ((nextWeaponID1 >= 0) ? WeaponIdAsString((CSWeaponID)nextWeaponID1) : "") );
  220. m_pScaleformUI->ValueArray_SetElement( data, 9, (pNextWeapon2Def && pNextWeapon2Def->GetDefinitionIndex() > 0) ? pNextWeapon2Def->GetDefinitionName() : ((nextWeaponID2 >= 0) ? WeaponIdAsString((CSWeaponID)nextWeaponID2) : "") );
  221. m_pScaleformUI->ValueArray_SetElement( data, 10, (pNextWeapon3Def && pNextWeapon3Def->GetDefinitionIndex() > 0) ? pNextWeapon3Def->GetDefinitionName() : ((nextWeaponID3 >= 0) ? WeaponIdAsString((CSWeaponID)nextWeaponID3) : "") );
  222. m_pScaleformUI->ValueArray_SetElement( data, 11, (pNextWeapon4Def && pNextWeapon4Def->GetDefinitionIndex() > 0) ? pNextWeapon4Def->GetDefinitionName() : ((nextWeaponID4 >= 0) ? WeaponIdAsString((CSWeaponID)nextWeaponID4) : "") );
  223. m_pScaleformUI->ValueArray_SetElement( data, 12, (pNextWeapon5Def && pNextWeapon5Def->GetDefinitionIndex() > 0) ? pNextWeapon5Def->GetDefinitionName() : ((nextWeaponID5 >= 0) ? WeaponIdAsString((CSWeaponID)nextWeaponID5) : "") );
  224. panelHandle = m_pScaleformUI->Value_Invoke( m_FlashAPI, "AddNextWeaponData", data, 13 );
  225. }
  226. if ( panelHandle )
  227. {
  228. //Put the new panel in the list
  229. SafeReleaseSFVALUE( m_ggNextPanel.handle );
  230. m_ggNextPanel.handle = panelHandle;
  231. m_ggNextPanel.alpha = 255;
  232. m_ggNextPanel.hWeapon = NULL;
  233. m_ggNextPanel.bSelected = false;
  234. m_ggNextPanel.bJustPickedUp = !bIsSpectating;
  235. m_ggNextPanel.fLastBlinkTime = gpGlobals->curtime;
  236. m_ggNextPanel.fEndBlinkTime = gpGlobals->curtime + WEAPON_SELECTION_FADE_DELAY;
  237. SFVALUE root = g_pScaleformUI->Value_GetMember( m_ggNextPanel.handle, "Panel" );
  238. if ( root )
  239. {
  240. ISFTextObject* textPanel = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "TextPanel" );
  241. wchar_t *tempString = g_pVGuiLocalize->Find( (bIsPlayingProgressive && pNextWeapon1Def) ? pNextWeapon1Def->GetItemBaseName() : (pNextWeaponDef ? pNextWeaponDef->GetItemBaseName() : "" ) );
  242. if ( textPanel && tempString )
  243. {
  244. if ( CSGameRules()->IsPlayingGunGameTRBomb() )
  245. {
  246. textPanel->SetText( "" );
  247. }
  248. else
  249. {
  250. textPanel->SetText( tempString );
  251. }
  252. SafeReleaseSFTextObject( textPanel );
  253. }
  254. SFVALUE bgPanel = g_pScaleformUI->Value_GetMember( root, "bgPanel" );
  255. if ( bgPanel )
  256. {
  257. ScaleformDisplayInfo dinfobg;
  258. m_pScaleformUI->Value_GetDisplayInfo( bgPanel, &dinfobg );
  259. if ( CSGameRules()->IsPlayingGunGameTRBomb() )
  260. dinfobg.SetVisibility( false );
  261. else
  262. dinfobg.SetVisibility( true );
  263. m_pScaleformUI->Value_SetDisplayInfo( bgPanel, &dinfobg );
  264. SafeReleaseSFVALUE( bgPanel );
  265. }
  266. ISFTextObject* titlePanel = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "TitlePanel" );
  267. wchar_t *tempString2 = NULL;
  268. if ( CSGameRules()->IsPlayingGunGameTRBomb() )
  269. tempString2 = g_pVGuiLocalize->Find( "#SFUI_WS_GG_AwardNextRound" );
  270. else
  271. tempString2 = g_pVGuiLocalize->Find( "#SFUI_WS_GG_NextWep" );
  272. if ( titlePanel && tempString2 )
  273. {
  274. titlePanel->SetText( tempString2 );
  275. SafeReleaseSFTextObject( titlePanel );
  276. }
  277. SafeReleaseSFVALUE( root );
  278. }
  279. }
  280. }
  281. ScaleformDisplayInfo dinfo;
  282. m_pScaleformUI->Value_GetDisplayInfo( m_ggNextPanel.handle, &dinfo );
  283. dinfo.SetVisibility( bVisible );
  284. m_pScaleformUI->Value_SetDisplayInfo( m_ggNextPanel.handle, &dinfo );
  285. }
  286. m_nLastTRKills = nCurTRKills;
  287. m_nLastGGWepIndex = nCurIndex;
  288. }
  289. void SFWeaponSelection::HideWeapon( int nSlot, int nPos )
  290. {
  291. if ( !m_weaponPanels[nSlot][nPos].handle || m_pScaleformUI->Value_GetType( m_weaponPanels[nSlot][nPos].handle ) != IScaleformUI::VT_DisplayObject )
  292. return;
  293. ScaleformDisplayInfo dinfo;
  294. if ( m_weaponPanels[nSlot][nPos].hWeapon.Get() )
  295. {
  296. m_pScaleformUI->Value_GetDisplayInfo( m_weaponPanels[nSlot][nPos].handle, &dinfo );
  297. dinfo.SetVisibility( false );
  298. m_pScaleformUI->Value_SetDisplayInfo( m_weaponPanels[nSlot][nPos].handle, &dinfo );
  299. }
  300. }
  301. void SFWeaponSelection::RemoveWeapon( int nSlot, int nPos )
  302. {
  303. if ( nSlot< 0 || nSlot >= MAX_WEP_SELECT_PANELS )
  304. return;
  305. if ( m_weaponPanels[nSlot][nPos].handle && m_pScaleformUI->Value_GetType( m_weaponPanels[nSlot][nPos].handle ) == IScaleformUI::VT_DisplayObject )
  306. {
  307. m_weaponPanels[nSlot][nPos].hWeapon = NULL;
  308. ScaleformDisplayInfo dinfo;
  309. m_pScaleformUI->Value_GetDisplayInfo( m_weaponPanels[nSlot][nPos].handle, &dinfo );
  310. dinfo.SetVisibility( false );
  311. m_pScaleformUI->Value_SetDisplayInfo( m_weaponPanels[nSlot][nPos].handle, &dinfo );
  312. }
  313. // force a weapon switch to catch where we got a user message but not the network update, yet
  314. m_flUpdateInventoryAt = gpGlobals->curtime + 0.1;
  315. }
  316. WeaponSelectPanel SFWeaponSelection::CreateNewPanel( C_BaseCombatWeapon *pWeapon, bool bSelected )
  317. {
  318. WeaponSelectPanel newPanel;
  319. if ( pWeapon == NULL || C_CSPlayer::GetLocalCSPlayer() == NULL )
  320. {
  321. bSelected = false;
  322. }
  323. SFVALUE newPanelHandle = NULL;
  324. WITH_SLOT_LOCKED
  325. {
  326. newPanelHandle = m_pScaleformUI->Value_Invoke( m_FlashAPI, "AddPanel", NULL, 0 );
  327. }
  328. if ( newPanelHandle && m_pScaleformUI->Value_GetType( newPanelHandle ) == IScaleformUI::VT_DisplayObject )
  329. {
  330. //Put the new panel in the list
  331. newPanel.handle = newPanelHandle;
  332. newPanel.alpha = 255;
  333. newPanel.hWeapon = pWeapon;
  334. newPanel.bSelected = bSelected;
  335. newPanel.bJustPickedUp = !C_CSPlayer::GetLocalCSPlayer()->GetObserverTarget();
  336. newPanel.fLastBlinkTime = gpGlobals->curtime;
  337. newPanel.fEndBlinkTime = gpGlobals->curtime + WEAPON_SELECTION_FADE_DELAY;
  338. }
  339. return newPanel;
  340. }
  341. void SFWeaponSelection::CreateGGNextPanel( void )
  342. {
  343. // check if it already exists
  344. if ( !FlashAPIIsValid() || m_ggNextPanel.handle != NULL )
  345. return;
  346. WeaponSelectPanel newPanel;
  347. SFVALUE newPanelHandle = NULL;
  348. WITH_SLOT_LOCKED
  349. {
  350. newPanelHandle = m_pScaleformUI->Value_Invoke( m_FlashAPI, "AddNextPanel", NULL, 0 );
  351. }
  352. if ( newPanelHandle && m_pScaleformUI->Value_GetType( newPanelHandle ) == IScaleformUI::VT_DisplayObject )
  353. {
  354. //Put the new panel in the list
  355. newPanel.handle = newPanelHandle;
  356. newPanel.alpha = 255;
  357. newPanel.hWeapon = NULL;
  358. newPanel.bSelected = false;
  359. newPanel.bJustPickedUp = false;
  360. newPanel.fLastBlinkTime = gpGlobals->curtime;
  361. newPanel.fEndBlinkTime = gpGlobals->curtime + WEAPON_SELECTION_FADE_DELAY;
  362. }
  363. m_ggNextPanel = newPanel;
  364. m_bCreatedNextPanel = true;
  365. }
  366. void SFWeaponSelection::ShowAndUpdateSelection( int nType, C_BaseCombatWeapon *pWeapon, bool bGiveInitial )
  367. {
  368. if ( !m_pScaleformUI )
  369. return;
  370. if ( !pWeapon || pWeapon->IsMarkedForDeletion() )
  371. {
  372. pWeapon = NULL;
  373. nType = WEPSELECT_SWITCH;
  374. }
  375. C_BasePlayer *pPlayer = GetLocalOrHudPlayer();
  376. if ( !pPlayer || !engine->IsLocalPlayerResolvable() )
  377. return;
  378. if ( !m_bInitialized )
  379. {
  380. for ( int i=0; i < MAX_WEP_SELECT_PANELS; i++ )
  381. {
  382. for ( int j=0; j < MAX_WEP_SELECT_POSITIONS; j++ )
  383. {
  384. WeaponSelectPanel panel = CreateNewPanel();
  385. if ( panel.handle && m_pScaleformUI->Value_GetType( panel.handle ) == IScaleformUI::VT_DisplayObject )
  386. {
  387. WITH_SLOT_LOCKED
  388. {
  389. panel.hWeapon = NULL;
  390. ScaleformDisplayInfo dinfo;
  391. m_pScaleformUI->Value_GetDisplayInfo( panel.handle, &dinfo );
  392. dinfo.SetVisibility( false );
  393. m_pScaleformUI->Value_SetDisplayInfo( panel.handle, &dinfo );
  394. m_weaponPanels[i][j] = panel;
  395. }
  396. }
  397. }
  398. }
  399. m_bInitialized = true;
  400. }
  401. CHudWeaponSelection *pHudSelection = (CHudWeaponSelection *)GET_HUDELEMENT( CHudWeaponSelection );
  402. if ( !pHudSelection )
  403. return;
  404. m_hSelectedWeapon = (pWeapon && nType == WEPSELECT_SWITCH) ? pWeapon : pPlayer->GetActiveWeapon();
  405. C_WeaponCSBase *pNextWeapon= NULL;
  406. switch ( nType )
  407. {
  408. default:
  409. case WEPSELECT_SWITCH :
  410. {
  411. bool bFoundSelectedItem = false;
  412. // loop through all of our slots and update differences
  413. for ( int i=0; i < MAX_WEP_SELECT_PANELS; i++ )
  414. {
  415. for ( int j=0; j < MAX_WEP_SELECT_POSITIONS; j++ )
  416. {
  417. C_WeaponCSBase *pPanelWeapon = dynamic_cast<C_WeaponCSBase*>(m_weaponPanels[i][j].hWeapon.Get());
  418. pNextWeapon = dynamic_cast<C_WeaponCSBase*>(pHudSelection->GetWeaponInSlotForTarget( pPlayer, i, j ));
  419. CBaseCSGrenade *pGrenade = NULL;
  420. // we have a weapon in our list, but we don't have it in our inventory, remove it
  421. if ( pPanelWeapon && !pNextWeapon )
  422. {
  423. RemoveWeapon( i, j );
  424. }
  425. else if ( pNextWeapon && !pPanelWeapon )
  426. {
  427. if ( IsGrenadeWeapon( pNextWeapon->GetCSWeaponID() ) )
  428. {
  429. pGrenade = static_cast<CBaseCSGrenade*>( pNextWeapon );
  430. }
  431. // this is an edge case where this happens when the very first round starts
  432. // but we can't add grenades back after they've been thrown because they are set as thrown before they've left our inventory.....
  433. // if it's not a grenade, OR if its a grenade and hasn't been thrown, add it back
  434. // we are awarded bonus grenades late during gun gun arsenal mode, so we have to catch them here
  435. if ( !pGrenade || (pGrenade && !pGrenade->IsPinPulled() && !pGrenade->IsBeingThrown()) )
  436. {
  437. AddWeapon( pNextWeapon, (GetSelectedWeapon() == pNextWeapon) );
  438. }
  439. }
  440. if ( pPanelWeapon && pNextWeapon && pPanelWeapon == pNextWeapon )
  441. {
  442. bool bJustRemovedGrenade = false;
  443. if ( IsGrenadeWeapon( pPanelWeapon->GetCSWeaponID() ) )
  444. {
  445. pGrenade = static_cast<CBaseCSGrenade*>( pPanelWeapon );
  446. bool bShouldRemove = true;
  447. if ( pPanelWeapon && IsGrenadeWeapon( pPanelWeapon->GetCSWeaponID() ) )
  448. {
  449. int ammo = pPanelWeapon->UsesPrimaryAmmo() ? pPanelWeapon->Clip1() : 0;
  450. if ( ammo < 0 )
  451. ammo = pPanelWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY );
  452. if ( ammo > 0 )
  453. bShouldRemove = false;
  454. }
  455. if ( bShouldRemove )
  456. {
  457. RemoveWeapon( i, j );
  458. bJustRemovedGrenade = true;
  459. }
  460. // pGrenade = static_cast<CBaseCSGrenade*>( pPanelWeapon );
  461. // if ( pGrenade && pGrenade->GetIsThrown() && pGrenade->IsPinPulled() )
  462. // {
  463. // RemoveWeapon( i, j );
  464. // bJustRemovedGrenade = true;
  465. // }
  466. }
  467. // if we just removed the panel because we just threw the grenade, don't count it as selected because it's about to be removed
  468. if ( GetSelectedWeapon() == pPanelWeapon && !bJustRemovedGrenade )
  469. bFoundSelectedItem = true;
  470. m_weaponPanels[i][j].bSelected = (GetSelectedWeapon() == pPanelWeapon);
  471. }
  472. }
  473. }
  474. // if we didn't find the item selected, try again in a short while
  475. if ( bFoundSelectedItem == false )
  476. {
  477. m_flUpdateInventoryAt = gpGlobals->curtime + 0.1;
  478. }
  479. break;
  480. }
  481. case WEPSELECT_PICKUP :
  482. {
  483. if ( pWeapon )
  484. {
  485. int nWepSlot = pWeapon->GetSlot();
  486. int nWepPos = pWeapon->GetPosition();
  487. bool bSelected = (pWeapon == GetSelectedWeapon());
  488. if ( m_weaponPanels[nWepSlot][nWepPos].handle != NULL && m_pScaleformUI->Value_GetType( m_weaponPanels[nWepSlot][nWepPos].handle ) == IScaleformUI::VT_DisplayObject )
  489. {
  490. m_weaponPanels[nWepSlot][nWepPos].bSelected = bSelected;
  491. ScaleformDisplayInfo dinfo;
  492. m_pScaleformUI->Value_GetDisplayInfo( m_weaponPanels[nWepSlot][nWepPos].handle, &dinfo );
  493. AddWeapon( pWeapon, bSelected );
  494. }
  495. }
  496. break;
  497. }
  498. case WEPSELECT_DROP :
  499. {
  500. for ( int i=0; i < MAX_WEP_SELECT_PANELS; i++ )
  501. {
  502. for ( int j=0; j < MAX_WEP_SELECT_POSITIONS; j++ )
  503. {
  504. C_WeaponCSBase *pPanelWeapon = dynamic_cast<C_WeaponCSBase*>(m_weaponPanels[i][j].hWeapon.Get());
  505. // we're dropping a weapon so just find it, remove it and be done
  506. if ( pPanelWeapon && pWeapon && pPanelWeapon == pWeapon )
  507. {
  508. bool bShouldRemove = true;
  509. if ( pPanelWeapon && IsGrenadeWeapon( pPanelWeapon->GetCSWeaponID() ) )
  510. {
  511. int ammo = pPanelWeapon->UsesPrimaryAmmo() ? pPanelWeapon->Clip1() : 0;
  512. if ( ammo < 0 )
  513. ammo = pPanelWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY );
  514. if ( ammo > 0 )
  515. bShouldRemove = false;
  516. }
  517. if ( bShouldRemove )
  518. RemoveWeapon( i, j );
  519. // force a weapon switch to catch where we got a user message but not the network update, yet
  520. m_flUpdateInventoryAt = gpGlobals->curtime + 0.1;
  521. }
  522. }
  523. }
  524. break;
  525. }
  526. }
  527. UpdatePanelPositions();
  528. float flStartFadeTime = gpGlobals->curtime + WEAPON_SELECTION_FADE_DELAY;
  529. if ( nType == WEPSELECT_DROP )
  530. flStartFadeTime -= WEAPON_SELECTION_FADE_DELAY/2;
  531. m_flFadeStartTime = flStartFadeTime;
  532. }
  533. void SFWeaponSelection::UpdatePanelPositions( void )
  534. {
  535. int nYPos = 0;
  536. int nXPos = 0;
  537. bool bFirstTime = true;
  538. int nStartWepSlot = -1;
  539. int nStartWepSlotPos = -1;
  540. bool bReverse = true;
  541. if ( bReverse )
  542. {
  543. nStartWepSlot = MAX_WEAPON_SLOTS;
  544. nStartWepSlotPos = MAX_WEAPON_POSITIONS;
  545. }
  546. if ( !C_BasePlayer::GetLocalPlayer() || !engine->IsLocalPlayerResolvable() )
  547. return;
  548. CHudWeaponSelection *pHudSelection = (CHudWeaponSelection *)GET_HUDELEMENT( CHudWeaponSelection );
  549. if ( !pHudSelection )
  550. return;
  551. C_CSPlayer *pPlayer = GetLocalOrHudPlayer();
  552. if ( !pPlayer )
  553. return;
  554. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  555. if ( !pLocalPlayer )
  556. return;
  557. bool bUsingKeyboard = ( false == m_pScaleformUI->IsSetToControllerUI( SF_FULL_SCREEN_SLOT ) );
  558. // update whether we should always show
  559. m_bAlwaysShow = cl_showloadout.GetBool();
  560. bool bIsSpectating = (pLocalPlayer != pPlayer);
  561. C_WeaponCSBase *pNextWeapon = NULL;
  562. for ( int i=MAX_WEP_SELECT_PANELS-1; i >= 0; i-- )
  563. {
  564. for ( int j=0; j < MAX_WEP_SELECT_POSITIONS; j++ )
  565. {
  566. C_WeaponCSBase *pPanelWeapon = static_cast<C_WeaponCSBase*>(m_weaponPanels[i][j].hWeapon.Get());
  567. pNextWeapon = static_cast<C_WeaponCSBase*>( pHudSelection->GetWeaponInSlotForTarget( pPlayer, i, j ) );
  568. // little hack checking knives because we remove the first knife given on initial spawn and the panel doesn't pick up the change until next update, so the knife isn't shown on initial spawn int eh first map
  569. if ( pPanelWeapon && pNextWeapon && (pPanelWeapon == pNextWeapon || (pPanelWeapon->IsA(WEAPON_KNIFE) && pNextWeapon->IsA(WEAPON_KNIFE) ) ) )
  570. {
  571. bool bSelected = m_weaponPanels[i][j].bSelected;
  572. //bool bBuyOpen = pPlayer->IsBuyMenuOpen();
  573. m_weaponPanels[i][j].alpha = 255;
  574. // testing
  575. // if ( pPanelWeapon->GetCSWeaponID() == WEAPON_C4 )
  576. // m_weaponPanels[i][j].alpha = 0;
  577. if ( bSelected )
  578. {
  579. m_selectedPanel = m_weaponPanels[i][j];
  580. }
  581. ScaleformDisplayInfo dinfo;
  582. m_pScaleformUI->Value_GetDisplayInfo( m_weaponPanels[i][j].handle, &dinfo );
  583. bool bShowCountNumber = false;
  584. int nSlot = pPanelWeapon->GetSlot();
  585. if ( nSlot == 3 || (nSlot == 5 && pPanelWeapon->IsKindOf( WEAPONTYPE_STACKABLEITEM ) ) )
  586. bShowCountNumber = true;
  587. if ( bFirstTime )
  588. {
  589. if ( m_bInitPos == false )
  590. {
  591. m_nOrigXPos = dinfo.GetX();
  592. m_nOrigYPos = dinfo.GetY();;
  593. m_bInitPos = true;
  594. }
  595. nXPos = m_nOrigXPos;
  596. if ( pPlayer && pPlayer->HasDefuser() )
  597. {
  598. nYPos = m_nOrigYPos - WEAPON_SELECT_PANEL_HEIGHT;
  599. }
  600. else
  601. {
  602. nYPos = m_nOrigYPos;
  603. }
  604. bFirstTime = false;
  605. }
  606. else
  607. {
  608. bool bShiftLeft = false;
  609. if ( m_nPrevWepAlignSlot == nSlot )
  610. {
  611. bShiftLeft = true;
  612. }
  613. else
  614. {
  615. nXPos = m_nOrigXPos;
  616. }
  617. if ( bShiftLeft )
  618. {
  619. // grenades are 3
  620. if ( nSlot == 3 )
  621. nXPos -= WEAPON_SELECT_PANEL_HEIGHT*0.75;
  622. else
  623. nXPos -= WEAPON_SELECT_PANEL_HEIGHT*1.25;
  624. }
  625. else
  626. {
  627. nYPos -= WEAPON_SELECT_PANEL_HEIGHT;
  628. // if the previous was the grenade (or item) slot, put a gap here to make sense of the controls
  629. if ( (((m_nPrevOccupiedWepSlot == 3 || m_nPrevOccupiedWepSlot == 2) && cl_inv_showdividerline.GetInt() == 1) || m_nPrevOccupiedWepSlot == cl_inv_showdividerline.GetInt()) && !bUsingKeyboard )
  630. nYPos -= WEAPON_SELECT_PANEL_HEIGHT/4;
  631. }
  632. }
  633. WITH_SLOT_LOCKED
  634. {
  635. const CCSWeaponInfo* pWeaponInfo = GetWeaponInfo( pPanelWeapon->GetCSWeaponID() );
  636. CEconItemView *pItem = pPanelWeapon->GetEconItemView();
  637. SFVALUE root = g_pScaleformUI->Value_GetMember( m_weaponPanels[i][j].handle, "Panel" );
  638. if ( root && pWeaponInfo )
  639. {
  640. SFVALUE iconS = g_pScaleformUI->Value_GetMember( root, "iconSelected" );
  641. if ( iconS )
  642. {
  643. ScaleformDisplayInfo dinfo2;
  644. m_pScaleformUI->Value_GetDisplayInfo( iconS, &dinfo2 );
  645. dinfo2.SetVisibility(bSelected);
  646. m_pScaleformUI->Value_SetDisplayInfo( iconS, &dinfo2 );
  647. SafeReleaseSFVALUE( iconS );
  648. }
  649. SFVALUE iconNS = g_pScaleformUI->Value_GetMember( root, "iconNotSelected" );
  650. if ( iconNS )
  651. {
  652. ScaleformDisplayInfo dinfo2;
  653. m_pScaleformUI->Value_GetDisplayInfo( iconNS, &dinfo2 );
  654. dinfo2.SetVisibility(!bSelected);
  655. m_pScaleformUI->Value_SetDisplayInfo( iconNS, &dinfo2 );
  656. SafeReleaseSFVALUE( iconNS );
  657. }
  658. // find the first panel in our row
  659. WeaponSelectPanel firstBGPanel;
  660. for ( int k=0; k < MAX_WEP_SELECT_POSITIONS; k++ )
  661. {
  662. // find the first panel in use in our "position" list and that'll be our background
  663. // and show the key binding
  664. if ( m_weaponPanels[nSlot][k].hWeapon.Get() )
  665. {
  666. firstBGPanel = m_weaponPanels[nSlot][k];
  667. break;
  668. }
  669. }
  670. SFVALUE bgPanel = g_pScaleformUI->Value_GetMember( root, "bgPanel" );
  671. SFVALUE divPanel = g_pScaleformUI->Value_GetMember( root, "PanelDivider" );
  672. if ( bgPanel && divPanel )
  673. {
  674. ScaleformDisplayInfo dinfo2;
  675. m_pScaleformUI->Value_GetDisplayInfo( bgPanel, &dinfo2 );
  676. dinfo2.SetVisibility( false );
  677. m_pScaleformUI->Value_SetDisplayInfo( bgPanel, &dinfo2 );
  678. SafeReleaseSFVALUE( bgPanel );
  679. // divider
  680. ScaleformDisplayInfo dinfo2a;
  681. m_pScaleformUI->Value_GetDisplayInfo( divPanel, &dinfo2a );
  682. dinfo2a.SetVisibility( false );
  683. m_pScaleformUI->Value_SetDisplayInfo( divPanel, &dinfo2a );
  684. SafeReleaseSFVALUE( divPanel );
  685. if ( firstBGPanel.handle && m_pScaleformUI->Value_GetType( firstBGPanel.handle ) == IScaleformUI::VT_DisplayObject )
  686. {
  687. SFVALUE root2 = g_pScaleformUI->Value_GetMember( firstBGPanel.handle, "Panel" );
  688. if ( root2 )
  689. {
  690. if ( bSelected )
  691. {
  692. SFVALUE bgPanel2 = g_pScaleformUI->Value_GetMember( root2, "bgPanel" );
  693. if ( bgPanel2 )
  694. {
  695. ScaleformDisplayInfo dinfo3;
  696. m_pScaleformUI->Value_GetDisplayInfo( bgPanel2, &dinfo3 );
  697. dinfo3.SetVisibility( true );
  698. m_pScaleformUI->Value_SetDisplayInfo( bgPanel2, &dinfo3 );
  699. SafeReleaseSFVALUE( bgPanel2 );
  700. }
  701. }
  702. SFVALUE divPanel = g_pScaleformUI->Value_GetMember( root2, "PanelDivider" );
  703. if ( divPanel )
  704. {
  705. // if we're the first panel in the horizontal list of grenade panels and we aren't using the keyboard, show the divider
  706. ScaleformDisplayInfo dinfo3;
  707. m_pScaleformUI->Value_GetDisplayInfo( divPanel, &dinfo3 );
  708. dinfo3.SetVisibility( !bUsingKeyboard && (((nSlot == 3 || nSlot == 2) && cl_inv_showdividerline.GetInt() == 1) || nSlot == cl_inv_showdividerline.GetInt()) );
  709. m_pScaleformUI->Value_SetDisplayInfo( divPanel, &dinfo3 );
  710. SafeReleaseSFVALUE( divPanel );
  711. }
  712. SafeReleaseSFVALUE( root2 );
  713. }
  714. }
  715. }
  716. bool bWeaponIsItem = (pItem && pItem->IsValid());
  717. wchar_t wcTargetWeaponFormatted[128];
  718. if ( bWeaponIsItem )
  719. {
  720. if ( cl_loadout_colorweaponnames.GetBool() && pItem->GetItemID() > 0 )
  721. {
  722. const int kColorBufSize = 128;
  723. wchar_t rwchColor[kColorBufSize];
  724. const CEconItemRarityDefinition *pRarity = GetItemSchema()->GetRarityDefinition( pItem->GetRarity() );
  725. Q_UTF8ToUnicode( GetHexColorForAttribColor( pRarity->GetAttribColor() ), rwchColor, kColorBufSize );
  726. V_snwprintf( wcTargetWeaponFormatted, ARRAYSIZE( wcTargetWeaponFormatted ), L"<font color=\"" PRI_WS_FOR_WS L"\">" PRI_WS_FOR_WS L"</font>", rwchColor, pItem->GetItemName() );
  727. }
  728. else
  729. {
  730. V_snwprintf( wcTargetWeaponFormatted, ARRAYSIZE( wcTargetWeaponFormatted ), PRI_WS_FOR_WS, pItem->GetItemName() );
  731. }
  732. }
  733. else
  734. {
  735. V_snwprintf( wcTargetWeaponFormatted, ARRAYSIZE( wcTargetWeaponFormatted ), PRI_WS_FOR_WS, g_pVGuiLocalize->Find( pWeaponInfo->szPrintName ) );
  736. }
  737. wchar_t wcTargetWeaponPossessed[128] = { 0 };
  738. WITH_SFVALUEARRAY( data, 5 )
  739. {
  740. m_pScaleformUI->ValueArray_SetElement( data, 0, root );
  741. m_pScaleformUI->ValueArray_SetElement( data, 1, bWeaponIsItem );
  742. m_pScaleformUI->ValueArray_SetElement( data, 2, bSelected );
  743. m_pScaleformUI->ValueArray_SetElement( data, 3, bShowCountNumber );
  744. m_pScaleformUI->ValueArray_SetElement( data, 4, StringIsEmpty( wcTargetWeaponPossessed ) ? wcTargetWeaponFormatted : wcTargetWeaponPossessed );
  745. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "SetWeaponName", data, 5 );
  746. }
  747. ISFTextObject* countPanel = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "CountPanel" );
  748. if ( countPanel && pPanelWeapon )
  749. {
  750. int ammo = pPanelWeapon->UsesPrimaryAmmo() ? pPanelWeapon->Clip1() : 0;
  751. if ( ammo < 0 )
  752. ammo = pPanelWeapon->GetReserveAmmoCount( AMMO_POSITION_PRIMARY );
  753. countPanel->SetVisible( bShowCountNumber && ammo > 1 );
  754. wchar_t buf[32];
  755. V_snwprintf( buf, ARRAYSIZE( buf ), L"(%d)", ammo );
  756. countPanel->SetText( buf );
  757. SafeReleaseSFTextObject( countPanel );
  758. }
  759. ISFTextObject* bindPanel = g_pScaleformUI->TextObject_MakeTextObjectFromMember( root, "BindingPanel" );
  760. if ( bindPanel )
  761. {
  762. if ( !bIsSpectating && bUsingKeyboard && firstBGPanel.handle && firstBGPanel.handle == m_weaponPanels[i][j].handle && m_pScaleformUI->Value_GetType( firstBGPanel.handle ) == IScaleformUI::VT_DisplayObject )
  763. {
  764. wchar_t wzFinal[32] = L"";
  765. wchar_t buf[32];
  766. V_snwprintf( buf, ARRAYSIZE( buf ), L"%%slot%d%%", i+1 );
  767. //g_pVGuiLocalize->ConstructString( buf, sizeof( buf ), "\%slot%d\%", 1, i );
  768. if ( bindPanel && buf )
  769. {
  770. UTIL_ReplaceKeyBindings( buf, 0, wzFinal, sizeof( wzFinal ) );
  771. bindPanel->SetVisible( true );
  772. bindPanel->SetText( wzFinal );
  773. }
  774. else
  775. {
  776. bindPanel->SetVisible( false );
  777. }
  778. }
  779. else
  780. {
  781. bindPanel->SetVisible( false );
  782. }
  783. SafeReleaseSFTextObject( bindPanel );
  784. }
  785. SafeReleaseSFVALUE( root );
  786. m_nPrevOccupiedWepSlot = nSlot;
  787. }
  788. }
  789. dinfo.SetY( nYPos );
  790. dinfo.SetX( nXPos );
  791. dinfo.SetVisibility( true );
  792. dinfo.SetAlpha( 255 );
  793. m_pScaleformUI->Value_SetDisplayInfo( m_weaponPanels[i][j].handle, &dinfo );
  794. m_nPrevWepAlignSlot = nSlot;
  795. }
  796. }
  797. }
  798. if ( CSGameRules() && (CSGameRules()->IsPlayingGunGameTRBomb() || CSGameRules()->IsPlayingGunGameProgressive()) )
  799. {
  800. if ( m_ggNextPanel.handle && m_pScaleformUI->Value_GetType( m_ggNextPanel.handle ) == IScaleformUI::VT_DisplayObject )
  801. {
  802. ScaleformDisplayInfo dinfo;
  803. m_pScaleformUI->Value_GetDisplayInfo( m_ggNextPanel.handle, &dinfo );
  804. nYPos -= WEAPON_SELECT_PANEL_HEIGHT * 1.2f;
  805. dinfo.SetY( nYPos );
  806. dinfo.SetX( nXPos );
  807. //dinfo.SetVisibility( true );
  808. dinfo.SetAlpha( 255 );
  809. m_pScaleformUI->Value_SetDisplayInfo( m_ggNextPanel.handle, &dinfo );
  810. // hide the progress bar in the TRbomb mode
  811. SFVALUE root = g_pScaleformUI->Value_GetMember( m_ggNextPanel.handle, "Panel" );
  812. if ( root )
  813. {
  814. SFVALUE progress = g_pScaleformUI->Value_GetMember( root, "Progress" );
  815. if ( progress )
  816. {
  817. ScaleformDisplayInfo dinfo2;
  818. m_pScaleformUI->Value_GetDisplayInfo( progress, &dinfo2 );
  819. dinfo2.SetVisibility( !CSGameRules()->IsPlayingGunGameTRBomb() );
  820. m_pScaleformUI->Value_SetDisplayInfo( progress, &dinfo2 );
  821. SafeReleaseSFVALUE( progress );
  822. }
  823. SafeReleaseSFVALUE( root );
  824. }
  825. }
  826. }
  827. }
  828. void SFWeaponSelection::ProcessInput( void )
  829. {
  830. if ( !m_pScaleformUI )
  831. return;
  832. C_CSPlayer *pPlayer = GetLocalOrHudPlayer();
  833. if ( !pPlayer )
  834. return;
  835. int nKillValue = pPlayer->GetNumGunGameTRKillPoints();
  836. // we need to delay this a frame to allow the next network update to happen
  837. // if we update it now, the data hasn't been networked down yet
  838. if ( m_bUpdateGGNextPanel && m_nLastTRKills < nKillValue )
  839. {
  840. m_bUpdateGGNextPanel = false;
  841. UpdateGGNextPanel( true );
  842. UpdatePanelPositions();
  843. }
  844. if ( m_flUpdateInventoryAt > 0 && m_flUpdateInventoryAt < gpGlobals->curtime )
  845. {
  846. if ( m_bUpdateInventoryReset )
  847. {
  848. RemoveAllItems();
  849. m_bUpdateInventoryReset = false;
  850. }
  851. ShowAndUpdateSelection( WEPSELECT_SWITCH );
  852. m_flUpdateInventoryAt = -1;
  853. }
  854. if ( ( CSGameRules() && CSGameRules()->IsPlayingGunGameProgressive() ) &&
  855. pPlayer->GetObserverTarget() && pPlayer->GetObserverTarget()->entindex() != m_bSpectatorTargetIndex )
  856. {
  857. m_bSpectatorTargetIndex = pPlayer->GetObserverTarget()->entindex();
  858. C_CSPlayer *pTargetPlayer = dynamic_cast<C_CSPlayer*>(C_CSPlayer::GetLocalCSPlayer()->GetObserverTarget());
  859. if ( pTargetPlayer )
  860. UpdateGGNextPanel();
  861. }
  862. // fade each panel
  863. float deltaTime = gpGlobals->curtime - m_lastUpdate;
  864. m_lastUpdate = gpGlobals->curtime;
  865. m_bC4IsVisible = false;
  866. for ( int i=0; i < MAX_WEP_SELECT_PANELS; i++ )
  867. {
  868. for ( int j=0; j < MAX_WEP_SELECT_POSITIONS; j++ )
  869. {
  870. if ( m_weaponPanels[i][j].handle == NULL || m_pScaleformUI->Value_GetType( m_weaponPanels[i][j].handle ) != IScaleformUI::VT_DisplayObject )
  871. continue;
  872. ScaleformDisplayInfo dinfo;
  873. m_pScaleformUI->Value_GetDisplayInfo( m_weaponPanels[i][j].handle, &dinfo );
  874. C_CSPlayer *pLocalPlayer = GetLocalOrHudPlayer();
  875. if ( pLocalPlayer && !pLocalPlayer->IsAlive() )
  876. {
  877. m_weaponPanels[i][j].alpha = 0;
  878. }
  879. else
  880. {
  881. C_WeaponCSBase *pPanelWeapon = static_cast<C_WeaponCSBase*>(m_weaponPanels[i][j].hWeapon.Get());
  882. if ( !pPanelWeapon && m_weaponPanels[i][j].alpha > 0 && dinfo.GetVisibility() )
  883. {
  884. dinfo.SetVisibility( false );
  885. }
  886. if ( m_selectedPanel.alpha <= 0 && !m_bAlwaysShow && !( CSGameRules() && CSGameRules()->IsPlayingGunGameProgressive() ) )
  887. {
  888. ScaleformDisplayInfo dinfo2;
  889. m_pScaleformUI->Value_GetDisplayInfo( m_weaponPanels[i][j].handle, &dinfo2 );
  890. if ( dinfo2.GetVisibility() )
  891. {
  892. dinfo2.SetVisibility( false );
  893. m_pScaleformUI->Value_SetDisplayInfo( m_weaponPanels[i][j].handle, &dinfo2 );
  894. }
  895. }
  896. else
  897. {
  898. if ( pPanelWeapon && pPanelWeapon->IsKindOf( WEAPONTYPE_C4 ) && m_weaponPanels[i][j].alpha > 0 )
  899. m_bC4IsVisible = true;
  900. if ( gpGlobals->curtime >= m_flFadeStartTime )
  901. {
  902. if ( m_bAlwaysShow || ( CSGameRules() && CSGameRules()->IsPlayingGunGameProgressive() ) )
  903. {
  904. m_weaponPanels[i][j].alpha = 255;
  905. }
  906. else
  907. {
  908. m_weaponPanels[i][j].alpha -= deltaTime * WEAPON_SELECTION_FADE_SPEED;
  909. m_weaponPanels[i][j].alpha = MAX( 0, m_weaponPanels[i][j].alpha );
  910. }
  911. }
  912. if ( m_weaponPanels[i][j].fEndBlinkTime <= gpGlobals->curtime && m_weaponPanels[i][j].bJustPickedUp )
  913. {
  914. m_weaponPanels[i][j].alpha = 255;
  915. m_weaponPanels[i][j].bJustPickedUp = false;
  916. }
  917. else if ( m_weaponPanels[i][j].bJustPickedUp )
  918. {
  919. if ( m_weaponPanels[i][j].fLastBlinkTime + (WEAPON_SELECTION_FADE_DELAY/7) <= gpGlobals->curtime )
  920. {
  921. if ( m_weaponPanels[i][j].alpha == 255 )
  922. m_weaponPanels[i][j].alpha = 50;
  923. else
  924. m_weaponPanels[i][j].alpha = 255;
  925. m_weaponPanels[i][j].fLastBlinkTime = gpGlobals->curtime;
  926. }
  927. }
  928. }
  929. }
  930. dinfo.SetAlpha( m_weaponPanels[i][j].alpha );
  931. m_pScaleformUI->Value_SetDisplayInfo(m_weaponPanels[i][j].handle, &dinfo );
  932. }
  933. }
  934. }
  935. void SFWeaponSelection::LevelInit( void )
  936. {
  937. if ( !FlashAPIIsValid() )
  938. {
  939. SFUI_REQUEST_ELEMENT( SF_SS_SLOT( GET_ACTIVE_SPLITSCREEN_SLOT() ), g_pScaleformUI, SFWeaponSelection, this, WeaponSelected );
  940. }
  941. }
  942. void SFWeaponSelection::LevelShutdown( void )
  943. {
  944. if ( FlashAPIIsValid() )
  945. {
  946. WITH_SLOT_LOCKED
  947. {
  948. for ( int i=0; i < MAX_WEP_SELECT_PANELS; i++ )
  949. {
  950. for ( int j=0; j < MAX_WEP_SELECT_POSITIONS; j++ )
  951. {
  952. //Remove all items before we exit
  953. RemoveItem(i,j);
  954. }
  955. }
  956. }
  957. V_memset( m_weaponPanels, 0, sizeof( m_weaponPanels ) );
  958. m_bInitialized = false;
  959. RemoveFlashElement();
  960. }
  961. }
  962. bool SFWeaponSelection::ShouldDraw( void )
  963. {
  964. return cl_drawhud.GetBool() && cl_draw_only_deathnotices.GetBool() == false && CHudElement::ShouldDraw();
  965. }
  966. void SFWeaponSelection::SetActive( bool bActive )
  967. {
  968. if ( FlashAPIIsValid() )
  969. {
  970. if ( bActive != m_bVisible )
  971. {
  972. ShowPanel( bActive );
  973. }
  974. }
  975. if ( bActive == false && m_bActive == true )
  976. {
  977. // We want to continue to run ProcessInput while the HUD element is hidden
  978. // so that the notifications continue advancing down the screen
  979. return;
  980. }
  981. CHudElement::SetActive( bActive );
  982. }
  983. void SFWeaponSelection::SetAlwaysShow( bool bAlwaysShow )
  984. {
  985. if ( bAlwaysShow != m_bAlwaysShow )
  986. {
  987. if ( bAlwaysShow )
  988. {
  989. UpdatePanelPositions();
  990. }
  991. else
  992. {
  993. // reset the update timer so it begins to fade
  994. m_flFadeStartTime = gpGlobals->curtime;
  995. }
  996. m_bAlwaysShow = bAlwaysShow;
  997. }
  998. }
  999. void SFWeaponSelection::FlashReady( void )
  1000. {
  1001. m_lastUpdate = gpGlobals->curtime;
  1002. if ( m_FlashAPI && m_pScaleformUI )
  1003. {
  1004. m_anchorPanel = m_pScaleformUI->Value_GetMember( m_FlashAPI, "Anchor" );
  1005. ListenForGameEvent( "round_prestart" );
  1006. ListenForGameEvent( "round_start" );
  1007. ListenForGameEvent( "player_death" );
  1008. ListenForGameEvent( "gg_player_impending_upgrade" );
  1009. ListenForGameEvent( "ggprogressive_player_levelup" );
  1010. ListenForGameEvent( "bot_takeover" );
  1011. ListenForGameEvent( "buymenu_open" );
  1012. ListenForGameEvent( "buymenu_close" );
  1013. ListenForGameEvent( "spec_mode_updated" );
  1014. ListenForGameEvent( "spec_target_updated" );
  1015. ListenForGameEvent( "hltv_changed_mode" );
  1016. }
  1017. }
  1018. bool SFWeaponSelection::PreUnloadFlash( void )
  1019. {
  1020. SafeReleaseSFVALUE( m_anchorPanel );
  1021. if ( m_ggNextPanel.handle && m_pScaleformUI->Value_GetType( m_ggNextPanel.handle ) == IScaleformUI::VT_DisplayObject )
  1022. {
  1023. SafeReleaseSFVALUE( m_ggNextPanel.handle );
  1024. m_bCreatedNextPanel = false;
  1025. }
  1026. for ( int i=0; i < MAX_WEP_SELECT_PANELS; i++ )
  1027. {
  1028. for ( int j=0; j < MAX_WEP_SELECT_POSITIONS; j++ )
  1029. {
  1030. if ( m_weaponPanels[i][j].handle )
  1031. SafeReleaseSFVALUE( m_weaponPanels[i][j].handle );
  1032. }
  1033. }
  1034. return true;
  1035. }
  1036. void SFWeaponSelection::FireGameEvent( IGameEvent *event )
  1037. {
  1038. const char *type = event->GetName();
  1039. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  1040. if ( !pLocalPlayer )
  1041. return;
  1042. int nPlayerUserID = pLocalPlayer->GetUserID();
  1043. int nEventUserID = event->GetInt( "userid" );
  1044. bool bLocalPlayerDeath = false;
  1045. if ( StringHasPrefix( type, "player_death" ) && nPlayerUserID == nEventUserID )
  1046. bLocalPlayerDeath = true;
  1047. if ( StringHasPrefix( type, "round_start" ) )
  1048. {
  1049. ShowAndUpdateSelection( WEPSELECT_SWITCH );
  1050. m_nLastTRKills = 0;
  1051. if ( CSGameRules()->IsPlayingGunGameProgressive() )
  1052. {
  1053. UpdateGGNextPanel( CSGameRules()->IsPlayingGunGameTRBomb(), false );
  1054. }
  1055. }
  1056. if ( CSGameRules() && (CSGameRules()->IsPlayingGunGameTRBomb() || CSGameRules()->IsPlayingGunGameProgressive()) )
  1057. {
  1058. if ( bLocalPlayerDeath || (Q_strcmp( "bot_takeover", type ) == 0 || Q_strcmp( "spec_target_updated", type ) == 0) && nPlayerUserID == nEventUserID )
  1059. {
  1060. UpdateGGNextPanel( false );
  1061. ShowAndUpdateSelection( WEPSELECT_SWITCH );
  1062. }
  1063. if ( Q_strcmp( "round_prestart", type ) == 0 || ((Q_strcmp( "bot_takeover", type ) == 0) && ( nEventUserID == nPlayerUserID )) )
  1064. {
  1065. // update the inventory
  1066. m_flUpdateInventoryAt = gpGlobals->curtime + 0.1;
  1067. UpdateGGNextPanel( false );
  1068. if ( FlashAPIIsValid() && m_ggNextPanel.handle && m_pScaleformUI->Value_GetType( m_ggNextPanel.handle ) == IScaleformUI::VT_DisplayObject )
  1069. {
  1070. ScaleformDisplayInfo dinfo;
  1071. m_pScaleformUI->Value_GetDisplayInfo( m_ggNextPanel.handle, &dinfo );
  1072. dinfo.SetVisibility( false );
  1073. m_pScaleformUI->Value_SetDisplayInfo( m_ggNextPanel.handle, &dinfo );
  1074. }
  1075. }
  1076. if ( Q_strcmp( "gg_player_impending_upgrade", type ) == 0 && nPlayerUserID == nEventUserID )
  1077. {
  1078. // Let the local player know a level-up is impending
  1079. DisplayLevelUpNextWeapon();
  1080. }
  1081. else if ( Q_strcmp( "ggprogressive_player_levelup", type ) == 0 && nPlayerUserID == nEventUserID )
  1082. {
  1083. if ( Q_strcmp( "weapon_knifegg", event->GetString( "weaponname" ) ) == 0 )
  1084. {
  1085. UpdateGGNextPanel( false, true );
  1086. }
  1087. }
  1088. /*else if ( Q_strcmp( "player_death", type ) == 0 )
  1089. {
  1090. int iPlayerIndexKiller = (engine->GetPlayerForUserID( event->GetInt( "attacker" ) )) + 1;
  1091. // Let the local player know a level-up is impending
  1092. DisplayLevelUpNextWeapon();
  1093. }*/
  1094. }
  1095. else
  1096. {
  1097. if ( (!Q_strcmp( "buymenu_open", type ) || !Q_strcmp( "buymenu_close", type )) && nPlayerUserID == nEventUserID )
  1098. {
  1099. ShowAndUpdateSelection( WEPSELECT_SWITCH );
  1100. m_flUpdateInventoryAt = gpGlobals->curtime + 0.1;
  1101. }
  1102. else if ( ((Q_strcmp( "bot_takeover", type ) == 0 || Q_strcmp( "spec_target_updated", type ) == 0) && nPlayerUserID == nEventUserID) )
  1103. {
  1104. ShowAndUpdateSelection( WEPSELECT_SWITCH );
  1105. m_flUpdateInventoryAt = gpGlobals->curtime + 0.1;
  1106. m_bUpdateInventoryReset = true;
  1107. }
  1108. else if ( (Q_strcmp( "spec_mode_updated", type ) == 0 && nPlayerUserID == nEventUserID) || Q_strcmp( "hltv_changed_mode", type ) == 0 )
  1109. {
  1110. ShowAndUpdateSelection( WEPSELECT_SWITCH );
  1111. m_flUpdateInventoryAt = gpGlobals->curtime + 0.1;
  1112. }
  1113. }
  1114. }
  1115. void SFWeaponSelection::DisplayLevelUpNextWeapon()
  1116. {
  1117. if ( !m_bCreatedNextPanel )
  1118. {
  1119. CreateGGNextPanel();
  1120. }
  1121. // we need to delay this a frame to allow the next network update to happen
  1122. // if we update it now, the data hasn't been networked down yet
  1123. m_bUpdateGGNextPanel = true;
  1124. }
  1125. ////////////////////////////////////////////////////////////////////////////////
  1126. // NOTE: This function is not threadsafe. If it is not called from ActionScript,
  1127. // it needs to be called within a lock.
  1128. ////////////////////////////////////////////////////////////////////////////////
  1129. void SFWeaponSelection::RemoveItem( int nSlot, int nPos )
  1130. {
  1131. if ( !m_weaponPanels[nSlot][nPos].handle || m_pScaleformUI->Value_GetType( m_weaponPanels[nSlot][nPos].handle ) != IScaleformUI::VT_DisplayObject )
  1132. return;
  1133. WITH_SLOT_LOCKED
  1134. {
  1135. WITH_SFVALUEARRAY( data, 1 )
  1136. {
  1137. m_pScaleformUI->ValueArray_SetElement( data, 0, m_weaponPanels[nSlot][nPos].handle );
  1138. m_pScaleformUI->Value_InvokeWithoutReturn( m_FlashAPI, "RemovePanel", data, 1 );
  1139. }
  1140. SafeReleaseSFVALUE( m_weaponPanels[nSlot][nPos].handle );
  1141. }
  1142. }
  1143. void SFWeaponSelection::RemoveAllItems( void )
  1144. {
  1145. if ( FlashAPIIsValid() )
  1146. {
  1147. WITH_SLOT_LOCKED
  1148. {
  1149. //Remove all items before we exit
  1150. for ( int i=0; i < MAX_WEP_SELECT_PANELS; i++ )
  1151. {
  1152. for ( int j=0; j < MAX_WEP_SELECT_POSITIONS; j++ )
  1153. {
  1154. //Remove all items before we exit
  1155. RemoveItem(i,j);
  1156. }
  1157. }
  1158. }
  1159. V_memset( m_weaponPanels, 0, sizeof( m_weaponPanels ) );
  1160. m_bInitialized = false;
  1161. }
  1162. }
  1163. void SFWeaponSelection::Show( void )
  1164. {
  1165. m_bVisible = true;
  1166. if ( m_anchorPanel && m_pScaleformUI && m_pScaleformUI->Value_GetType( m_anchorPanel ) == IScaleformUI::VT_DisplayObject )
  1167. {
  1168. m_pScaleformUI->Value_SetVisible( m_anchorPanel, true );
  1169. }
  1170. }
  1171. void SFWeaponSelection::Hide( void )
  1172. {
  1173. m_bVisible = false;
  1174. if ( m_anchorPanel && m_pScaleformUI && m_pScaleformUI->Value_GetType( m_anchorPanel ) == IScaleformUI::VT_DisplayObject )
  1175. {
  1176. m_pScaleformUI->Value_SetVisible( m_anchorPanel, false );
  1177. }
  1178. }
  1179. void SFWeaponSelection::ShowPanel( const bool bShow )
  1180. {
  1181. if ( m_FlashAPI )
  1182. {
  1183. if ( bShow )
  1184. {
  1185. Show();
  1186. }
  1187. else
  1188. {
  1189. Hide();
  1190. }
  1191. }
  1192. }