Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

796 lines
22 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "weapon_selection.h"
  8. #include "iclientmode.h"
  9. #include "history_resource.h"
  10. #include <KeyValues.h>
  11. #include <vgui/IScheme.h>
  12. #include <vgui/ISurface.h>
  13. #include <vgui/ISystem.h>
  14. #include <vgui_controls/AnimationController.h>
  15. #include <vgui_controls/Panel.h>
  16. #include <string.h>
  17. #include "weapon_dodbase.h"
  18. float GetScale( int nIconWidth, int nIconHeight, int nWidth, int nHeight );
  19. //-----------------------------------------------------------------------------
  20. // Purpose: cstrike weapon selection hud element
  21. //-----------------------------------------------------------------------------
  22. class CHudWeaponSelection : public CBaseHudWeaponSelection, public vgui::Panel
  23. {
  24. DECLARE_CLASS_SIMPLE( CHudWeaponSelection, vgui::Panel );
  25. public:
  26. CHudWeaponSelection( const char *pElementName );
  27. virtual void VidInit();
  28. virtual bool ShouldDraw();
  29. virtual void OnWeaponPickup( C_BaseCombatWeapon *pWeapon );
  30. virtual void CycleToNextWeapon( void );
  31. virtual void CycleToPrevWeapon( void );
  32. virtual C_BaseCombatWeapon *GetWeaponInSlot( int iSlot, int iSlotPos );
  33. virtual void SelectWeaponSlot( int iSlot );
  34. virtual C_BaseCombatWeapon *GetSelectedWeapon( void )
  35. {
  36. return m_hSelectedWeapon;
  37. }
  38. virtual void OpenSelection( void );
  39. virtual void HideSelection( void );
  40. virtual void LevelInit();
  41. virtual void SelectWeapon( void );
  42. virtual void CancelWeaponSelection( void );
  43. virtual bool IsHudMenuPreventingWeaponSelection() { return false; }
  44. protected:
  45. virtual void OnThink();
  46. virtual void Paint();
  47. virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
  48. virtual bool IsWeaponSelectable()
  49. {
  50. if ( IsInSelectionMode() )
  51. {
  52. return true;
  53. }
  54. return false;
  55. }
  56. private:
  57. C_BaseCombatWeapon *FindNextWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition);
  58. C_BaseCombatWeapon *FindPrevWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition);
  59. virtual void SetSelectedWeapon( C_BaseCombatWeapon *pWeapon )
  60. {
  61. m_hSelectedWeapon = pWeapon;
  62. }
  63. void DrawBox( int x, int y, int wide, int tall, int type, int number, int valid );
  64. private:
  65. int m_iBackgroundTexture;
  66. CPanelAnimationVarAliasType( float, m_flSmallBoxWide, "SmallBoxWide", "108", "proportional_float" );
  67. CPanelAnimationVarAliasType( float, m_flSmallBoxTall, "SmallBoxTall", "72", "proportional_float" );
  68. CPanelAnimationVarAliasType( float, m_flSmallBoxCutSize, "SmallBoxCutSize", "5", "proportional_float" );
  69. CPanelAnimationVarAliasType( float, m_flLargeBoxWide, "LargeBoxWide", "108", "proportional_float" );
  70. CPanelAnimationVarAliasType( float, m_flLargeBoxTall, "LargeBoxTall", "72", "proportional_float" );
  71. CPanelAnimationVarAliasType( float, m_flLargeBoxCutSize, "LargeBoxCutSize", "5", "proportional_float" );
  72. CPanelAnimationVarAliasType( float, m_flBoxGap, "BoxGap", "8", "proportional_float" );
  73. CPanelAnimationVarAliasType( float, m_flSelectionNumberXPos, "SelectionNumberXPos", "4", "proportional_float" );
  74. CPanelAnimationVarAliasType( float, m_flSelectionNumberYPos, "SelectionNumberYPos", "4", "proportional_float" );
  75. CPanelAnimationVarAliasType( float, m_flIconXPos, "IconXPos", "16", "proportional_float" );
  76. CPanelAnimationVarAliasType( float, m_flIconYPos, "IconYPos", "8", "proportional_float" );
  77. CPanelAnimationVarAliasType( float, m_flTextYPos, "TextYPos", "54", "proportional_float" );
  78. CPanelAnimationVar( float, m_flAlphaOverride, "Alpha", "255" );
  79. CPanelAnimationVar( float, m_flSelectionAlphaOverride, "SelectionAlpha", "255" );
  80. CPanelAnimationVar( Color, m_ActiveTextColor, "ActiveTextColor", "255 255 255 255" );
  81. CPanelAnimationVar( Color, m_InactiveTextColor, "InactiveTextColor", "80 80 80 255" );
  82. CPanelAnimationVar( vgui::HFont, m_hNumberFont, "NumberFont", "HudSelectionNumbers" );
  83. CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "HudSelectionText" );
  84. CPanelAnimationVar( Color, m_TextColor, "TextColor", "SelectionTextFg" );
  85. CPanelAnimationVar( Color, m_NumberColor, "NumberColor", "SelectionNumberFg" );
  86. CPanelAnimationVar( Color, m_EmptyBoxColor, "EmptyBoxColor", "SelectionEmptyBoxBg" );
  87. CPanelAnimationVar( Color, m_BoxColor, "BoxColor", "SelectionBoxBg" );
  88. CPanelAnimationVar( Color, m_SelectedBoxColor, "SelectedBoxClor", "SelectionSelectedBoxBg" );
  89. CPanelAnimationVar( float, m_flWeaponPickupGrowTime, "SelectionGrowTime", "0.1" );
  90. CPanelAnimationVar( float, m_flTextScan, "TextScan", "1.0" );
  91. CPanelAnimationVar( int, m_iMaxSlots, "MaxSlots", "6" );
  92. CPanelAnimationVar( bool, m_bPlaySelectionSounds, "PlaySelectSounds", "1" );
  93. CPanelAnimationVar( Color, m_ActiveBoxColor, "ActiveBoxColor", "255 255 255 255" );
  94. CPanelAnimationVar( Color, m_ActiveBoxBorder, "ActiveBoxBorder", "255 255 255 255" );
  95. CPanelAnimationVar( Color, m_InactiveBoxColor, "InactiveBoxColor", "0 0 0 0" );
  96. CPanelAnimationVar( Color, m_InactiveBoxBorder, "InactiveBoxBorder", "255 255 255 255" );
  97. CPanelAnimationVar( Color, m_NotUseableColor, "NotUseableColor", "0 0 0 0" );
  98. };
  99. DECLARE_HUDELEMENT( CHudWeaponSelection );
  100. //-----------------------------------------------------------------------------
  101. // Purpose: Constructor
  102. //-----------------------------------------------------------------------------
  103. CHudWeaponSelection::CHudWeaponSelection( const char *pElementName ) : CBaseHudWeaponSelection(pElementName), BaseClass(NULL, "HudWeaponSelection")
  104. {
  105. vgui::Panel *pParent = g_pClientMode->GetViewport();
  106. SetParent( pParent );
  107. SetHiddenBits( HIDEHUD_WEAPONSELECTION | HIDEHUD_PLAYERDEAD );
  108. m_iBackgroundTexture = vgui::surface()->DrawGetTextureId( "vgui/white" );
  109. if ( m_iBackgroundTexture == -1 )
  110. {
  111. m_iBackgroundTexture = vgui::surface()->CreateNewTextureID();
  112. }
  113. vgui::surface()->DrawSetTextureFile( m_iBackgroundTexture, "vgui/white" , true, true );
  114. }
  115. void CHudWeaponSelection::VidInit(void)
  116. {
  117. // If we've already loaded weapons, let's get new sprites
  118. gWR.LoadAllWeaponSprites();
  119. Reset();
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Purpose: sets up display for showing weapon pickup
  123. //-----------------------------------------------------------------------------
  124. void CHudWeaponSelection::OnWeaponPickup( C_BaseCombatWeapon *pWeapon )
  125. {
  126. // show tnt pickup panel
  127. C_WeaponDODBase *pDODWpn = dynamic_cast<C_WeaponDODBase *>( pWeapon );
  128. if ( pDODWpn && pDODWpn->GetDODWpnData().m_WeaponType == WPN_TYPE_BOMB )
  129. {
  130. IGameEvent *event = gameeventmanager->CreateEvent( "dod_tnt_pickup" );
  131. if ( event )
  132. {
  133. gameeventmanager->FireEventClientSide( event );
  134. }
  135. }
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Purpose: updates animation status
  139. //-----------------------------------------------------------------------------
  140. void CHudWeaponSelection::OnThink()
  141. {
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Purpose: returns true if the panel should draw
  145. //-----------------------------------------------------------------------------
  146. bool CHudWeaponSelection::ShouldDraw()
  147. {
  148. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  149. if ( !pPlayer )
  150. {
  151. if ( IsInSelectionMode() )
  152. {
  153. HideSelection();
  154. }
  155. return false;
  156. }
  157. bool bret = CBaseHudWeaponSelection::ShouldDraw();
  158. if ( !bret )
  159. {
  160. return false;
  161. }
  162. return ( m_bSelectionVisible ) ? true : false;
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Purpose:
  166. //-----------------------------------------------------------------------------
  167. void CHudWeaponSelection::LevelInit()
  168. {
  169. CHudElement::LevelInit();
  170. m_iMaxSlots = clamp( m_iMaxSlots, 0, MAX_WEAPON_SLOTS );
  171. }
  172. //-------------------------------------------------------------------------
  173. // Purpose: draws the selection area
  174. //-------------------------------------------------------------------------
  175. void CHudWeaponSelection::Paint(void)
  176. {
  177. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  178. if ( !pPlayer )
  179. {
  180. return;
  181. }
  182. // find and display our current selection
  183. C_BaseCombatWeapon *pSelectedWeapon = GetSelectedWeapon();
  184. if ( !pSelectedWeapon )
  185. {
  186. return;
  187. }
  188. int x, y, w, h;
  189. GetBounds( x, y, w, h );
  190. int xpos = 0;
  191. int ypos = h;
  192. int nType = 0;
  193. Color bright( 255,255,255,255 );
  194. // iterate over all the weapon slots
  195. for ( int iSlot = m_iMaxSlots - 1; iSlot >=0; iSlot-- )
  196. {
  197. for( int iPos = 0; iPos < MAX_WEAPON_POSITIONS; iPos++ )
  198. {
  199. C_BaseCombatWeapon *pWeapon = GetWeaponInSlot(iSlot, iPos);
  200. if ( !pWeapon )
  201. {
  202. continue;
  203. }
  204. if ( !pWeapon->CanBeSelected() )
  205. {
  206. continue;
  207. }
  208. if ( pWeapon->GetSpriteActive() )
  209. {
  210. const CHudTexture *pWpnSprite = pWeapon->GetSpriteActive();
  211. Color finalColor;
  212. Assert( pWpnSprite );
  213. float finalBoxWide, finalBoxTall;
  214. if ( pWeapon == pSelectedWeapon )
  215. {
  216. finalBoxWide = m_flLargeBoxWide;
  217. finalBoxTall = m_flLargeBoxTall;
  218. finalColor = m_ActiveBoxColor;
  219. nType = 1;
  220. }
  221. else
  222. {
  223. finalBoxWide = m_flSmallBoxWide;
  224. finalBoxTall = m_flSmallBoxTall;
  225. finalColor = m_InactiveBoxColor;
  226. nType = 0;
  227. }
  228. xpos = ( w / 2.0 ) - ( finalBoxWide / 2.0f );
  229. ypos -= finalBoxTall;
  230. int sprBoxWidth = finalBoxWide - XRES(4); // minus 4 (2 left, 2 right)
  231. int sprBoxHeight = finalBoxTall - YRES(4); // minus 4 (2 top, 2 bottom)
  232. int sprWidth = pWpnSprite->Width();
  233. int sprHeight = pWpnSprite->Height();
  234. float scale = GetScale( sprWidth, sprHeight, sprBoxWidth, sprBoxHeight );
  235. sprWidth = sprWidth * scale;
  236. sprHeight = sprHeight * scale;
  237. int wpnX = xpos + ( finalBoxWide - sprWidth ) / 2;
  238. int wpnY = ypos + ( finalBoxTall - sprHeight ) / 2;
  239. bool bHasAmmo = true;
  240. if ( pWeapon->UsesClipsForAmmo1() )
  241. {
  242. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  243. if ( pPlayer )
  244. {
  245. int ammo = pWeapon->Clip1() + pPlayer->GetAmmoCount( pWeapon->GetPrimaryAmmoType() );
  246. if ( ammo <= 0 )
  247. {
  248. bHasAmmo = false;
  249. }
  250. }
  251. }
  252. DrawBox( xpos, ypos, finalBoxWide, finalBoxTall, nType, iSlot + 1, ( pWeapon->CanDeploy() && bHasAmmo ) ) ;
  253. pWpnSprite->DrawSelf( wpnX, wpnY, sprWidth, sprHeight, bright );
  254. ypos -= m_flBoxGap;
  255. }
  256. }
  257. }
  258. }
  259. //-----------------------------------------------------------------------------
  260. // Purpose: draws a selection box
  261. //-----------------------------------------------------------------------------
  262. void CHudWeaponSelection::DrawBox( int x, int y, int wide, int tall, int type, int number, int valid )
  263. {
  264. vgui::Vertex_t verts[5];
  265. int nwide = wide - 1;
  266. int ntall = tall - 1;
  267. int nCutSize;
  268. vgui::surface()->DrawSetTexture( m_iBackgroundTexture );
  269. if ( type == 1 )
  270. {
  271. nCutSize = m_flLargeBoxCutSize;
  272. vgui::surface()->DrawSetColor( Color( m_ActiveBoxColor ) );
  273. }
  274. else
  275. {
  276. nCutSize = m_flSmallBoxCutSize;
  277. vgui::surface()->DrawSetColor( Color( m_InactiveBoxColor ) );
  278. }
  279. if ( !valid )
  280. {
  281. vgui::surface()->DrawSetColor( Color( m_NotUseableColor ) );
  282. }
  283. verts[0].Init( Vector2D( x, y ) );
  284. verts[1].Init( Vector2D( x + nwide - nCutSize, y ) );
  285. verts[2].Init( Vector2D( x + nwide, y + nCutSize ) );
  286. verts[3].Init( Vector2D( x + nwide, y + ntall ) );
  287. verts[4].Init( Vector2D( x, y + ntall ) );
  288. vgui::surface()->DrawTexturedPolygon( 5, verts );
  289. if ( type == 1 )
  290. {
  291. vgui::surface()->DrawSetColor( Color( m_ActiveBoxBorder ) );
  292. }
  293. else
  294. {
  295. vgui::surface()->DrawSetColor( Color( m_InactiveBoxBorder ) );
  296. }
  297. vgui::surface()->DrawTexturedPolyLine( verts, 5 );
  298. // draw the number
  299. if ( number >= 0 )
  300. {
  301. vgui::surface()->DrawSetTextFont( m_hNumberFont );
  302. if ( type == 1 )
  303. {
  304. vgui::surface()->DrawSetTextColor( Color( m_ActiveTextColor ) );
  305. }
  306. else
  307. {
  308. vgui::surface()->DrawSetTextColor( Color( m_InactiveTextColor ) );
  309. }
  310. wchar_t wch = '0' + number;
  311. vgui::surface()->DrawSetTextPos( x + m_flSelectionNumberXPos, y + ntall - m_flSelectionNumberYPos );
  312. vgui::surface()->DrawUnicodeChar( wch );
  313. }
  314. }
  315. //-----------------------------------------------------------------------------
  316. // Purpose: hud scheme settings
  317. //-----------------------------------------------------------------------------
  318. void CHudWeaponSelection::ApplySchemeSettings( vgui::IScheme *pScheme )
  319. {
  320. BaseClass::ApplySchemeSettings( pScheme );
  321. SetPaintBackgroundEnabled( false );
  322. }
  323. //-----------------------------------------------------------------------------
  324. // Purpose: Opens weapon selection control
  325. //-----------------------------------------------------------------------------
  326. void CHudWeaponSelection::OpenSelection( void )
  327. {
  328. Assert( !IsInSelectionMode() );
  329. CBaseHudWeaponSelection::OpenSelection();
  330. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "OpenWeaponSelectionMenu" );
  331. }
  332. //-----------------------------------------------------------------------------
  333. // Purpose: Closes weapon selection control
  334. //-----------------------------------------------------------------------------
  335. void CHudWeaponSelection::HideSelection( void )
  336. {
  337. CBaseHudWeaponSelection::HideSelection();
  338. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "CloseWeaponSelectionMenu" );
  339. }
  340. //-----------------------------------------------------------------------------
  341. // Purpose: Returns the next available weapon item in the weapon selection
  342. //-----------------------------------------------------------------------------
  343. C_BaseCombatWeapon *CHudWeaponSelection::FindNextWeaponInWeaponSelection( int iCurrentSlot, int iCurrentPosition )
  344. {
  345. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  346. if ( !pPlayer )
  347. {
  348. return NULL;
  349. }
  350. C_BaseCombatWeapon *pNextWeapon = NULL;
  351. // search all the weapons looking for the closest next
  352. int iLowestNextSlot = MAX_WEAPON_SLOTS;
  353. int iLowestNextPosition = MAX_WEAPON_POSITIONS;
  354. for ( int i = 0; i < MAX_WEAPONS; i++ )
  355. {
  356. C_BaseCombatWeapon *pWeapon = pPlayer->GetWeapon( i );
  357. if ( !pWeapon )
  358. {
  359. continue;
  360. }
  361. if ( pWeapon->CanBeSelected() )
  362. {
  363. int weaponSlot = pWeapon->GetSlot(), weaponPosition = pWeapon->GetPosition();
  364. // see if this weapon is further ahead in the selection list
  365. if ( weaponSlot > iCurrentSlot || ( weaponSlot == iCurrentSlot && weaponPosition > iCurrentPosition ) )
  366. {
  367. // see if this weapon is closer than the current lowest
  368. if ( weaponSlot < iLowestNextSlot || ( weaponSlot == iLowestNextSlot && weaponPosition < iLowestNextPosition ) )
  369. {
  370. iLowestNextSlot = weaponSlot;
  371. iLowestNextPosition = weaponPosition;
  372. pNextWeapon = pWeapon;
  373. }
  374. }
  375. }
  376. }
  377. return pNextWeapon;
  378. }
  379. //-----------------------------------------------------------------------------
  380. // Purpose: Returns the prior available weapon item in the weapon selection
  381. //-----------------------------------------------------------------------------
  382. C_BaseCombatWeapon *CHudWeaponSelection::FindPrevWeaponInWeaponSelection( int iCurrentSlot, int iCurrentPosition )
  383. {
  384. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  385. if ( !pPlayer )
  386. {
  387. return NULL;
  388. }
  389. C_BaseCombatWeapon *pPrevWeapon = NULL;
  390. // search all the weapons looking for the closest next
  391. int iLowestPrevSlot = -1;
  392. int iLowestPrevPosition = -1;
  393. for ( int i = 0; i < MAX_WEAPONS; i++ )
  394. {
  395. C_BaseCombatWeapon *pWeapon = pPlayer->GetWeapon( i );
  396. if ( !pWeapon )
  397. {
  398. continue;
  399. }
  400. if ( pWeapon->CanBeSelected() )
  401. {
  402. int weaponSlot = pWeapon->GetSlot(), weaponPosition = pWeapon->GetPosition();
  403. // see if this weapon is further ahead in the selection list
  404. if ( weaponSlot < iCurrentSlot || (weaponSlot == iCurrentSlot && weaponPosition < iCurrentPosition) )
  405. {
  406. // see if this weapon is closer than the current lowest
  407. if ( weaponSlot > iLowestPrevSlot || (weaponSlot == iLowestPrevSlot && weaponPosition > iLowestPrevPosition) )
  408. {
  409. iLowestPrevSlot = weaponSlot;
  410. iLowestPrevPosition = weaponPosition;
  411. pPrevWeapon = pWeapon;
  412. }
  413. }
  414. }
  415. }
  416. return pPrevWeapon;
  417. }
  418. //-----------------------------------------------------------------------------
  419. // Purpose: Moves the selection to the next item in the menu
  420. //-----------------------------------------------------------------------------
  421. void CHudWeaponSelection::CycleToNextWeapon( void )
  422. {
  423. // Get the local player.
  424. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  425. if ( !pPlayer )
  426. {
  427. return;
  428. }
  429. C_BaseCombatWeapon *pNextWeapon = NULL;
  430. if ( IsInSelectionMode() )
  431. {
  432. // find the next selection spot
  433. C_BaseCombatWeapon *pWeapon = GetSelectedWeapon();
  434. if ( !pWeapon )
  435. {
  436. return;
  437. }
  438. pNextWeapon = FindNextWeaponInWeaponSelection( pWeapon->GetSlot(), pWeapon->GetPosition() );
  439. }
  440. else
  441. {
  442. // open selection at the current place
  443. pNextWeapon = pPlayer->GetActiveWeapon();
  444. if ( pNextWeapon )
  445. {
  446. pNextWeapon = FindNextWeaponInWeaponSelection( pNextWeapon->GetSlot(), pNextWeapon->GetPosition() );
  447. }
  448. }
  449. if ( !pNextWeapon )
  450. {
  451. // wrap around back to start
  452. pNextWeapon = FindNextWeaponInWeaponSelection( -1, -1 );
  453. }
  454. if ( pNextWeapon )
  455. {
  456. SetSelectedWeapon( pNextWeapon );
  457. if ( hud_fastswitch.GetInt() > 0 )
  458. {
  459. SelectWeapon();
  460. }
  461. else if ( !IsInSelectionMode() )
  462. {
  463. OpenSelection();
  464. }
  465. // Play the "cycle to next weapon" sound
  466. if ( m_bPlaySelectionSounds )
  467. {
  468. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  469. }
  470. }
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Purpose: Moves the selection to the previous item in the menu
  474. //-----------------------------------------------------------------------------
  475. void CHudWeaponSelection::CycleToPrevWeapon( void )
  476. {
  477. // Get the local player.
  478. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  479. if ( !pPlayer )
  480. {
  481. return;
  482. }
  483. C_BaseCombatWeapon *pNextWeapon = NULL;
  484. if ( IsInSelectionMode() )
  485. {
  486. // find the next selection spot
  487. C_BaseCombatWeapon *pWeapon = GetSelectedWeapon();
  488. if ( !pWeapon )
  489. {
  490. return;
  491. }
  492. pNextWeapon = FindPrevWeaponInWeaponSelection( pWeapon->GetSlot(), pWeapon->GetPosition() );
  493. }
  494. else
  495. {
  496. // open selection at the current place
  497. pNextWeapon = pPlayer->GetActiveWeapon();
  498. if ( pNextWeapon )
  499. {
  500. pNextWeapon = FindPrevWeaponInWeaponSelection( pNextWeapon->GetSlot(), pNextWeapon->GetPosition() );
  501. }
  502. }
  503. if ( !pNextWeapon )
  504. {
  505. // wrap around back to end of weapon list
  506. pNextWeapon = FindPrevWeaponInWeaponSelection( MAX_WEAPON_SLOTS, MAX_WEAPON_POSITIONS );
  507. }
  508. if ( pNextWeapon )
  509. {
  510. SetSelectedWeapon( pNextWeapon );
  511. if( hud_fastswitch.GetInt() > 0 )
  512. {
  513. SelectWeapon();
  514. }
  515. else if ( !IsInSelectionMode() )
  516. {
  517. OpenSelection();
  518. }
  519. // Play the "cycle to next weapon" sound
  520. if( m_bPlaySelectionSounds )
  521. {
  522. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  523. }
  524. }
  525. }
  526. //-----------------------------------------------------------------------------
  527. // Purpose: returns the weapon in the specified slot
  528. //-----------------------------------------------------------------------------
  529. C_BaseCombatWeapon *CHudWeaponSelection::GetWeaponInSlot( int iSlot, int iSlotPos )
  530. {
  531. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  532. if ( !player )
  533. {
  534. return NULL;
  535. }
  536. for ( int i = 0; i < MAX_WEAPONS; i++ )
  537. {
  538. C_BaseCombatWeapon *pWeapon = player->GetWeapon( i );
  539. if ( pWeapon == NULL )
  540. {
  541. continue;
  542. }
  543. if ( pWeapon->GetSlot() == iSlot && pWeapon->GetPosition() == iSlotPos )
  544. {
  545. return pWeapon;
  546. }
  547. }
  548. return NULL;
  549. }
  550. //-----------------------------------------------------------------------------
  551. // Purpose: Moves selection to the specified slot
  552. //-----------------------------------------------------------------------------
  553. void CHudWeaponSelection::SelectWeaponSlot( int iSlot )
  554. {
  555. // iSlot is one higher than it should be, since it's the number key, not the 0-based index into the weapons
  556. --iSlot;
  557. // Get the local player.
  558. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  559. if ( !pPlayer )
  560. {
  561. return;
  562. }
  563. // Don't try and read past our possible number of slots
  564. if ( iSlot > MAX_WEAPON_SLOTS )
  565. {
  566. return;
  567. }
  568. // Make sure the player's allowed to switch weapons
  569. if ( pPlayer->IsAllowedToSwitchWeapons() == false )
  570. {
  571. return;
  572. }
  573. int slotPos = 0;
  574. C_BaseCombatWeapon *pActiveWeapon = GetSelectedWeapon();
  575. // start later in the list
  576. if ( IsInSelectionMode() && pActiveWeapon && pActiveWeapon->GetSlot() == iSlot )
  577. {
  578. slotPos = pActiveWeapon->GetPosition() + 1;
  579. }
  580. // find the weapon in this slot
  581. pActiveWeapon = GetNextActivePos( iSlot, slotPos );
  582. if ( !pActiveWeapon )
  583. {
  584. pActiveWeapon = GetNextActivePos( iSlot, 0 );
  585. }
  586. if ( pActiveWeapon != NULL )
  587. {
  588. // Mark the change
  589. SetSelectedWeapon( pActiveWeapon );
  590. if( hud_fastswitch.GetInt() > 0 )
  591. {
  592. SelectWeapon();
  593. }
  594. else if ( !IsInSelectionMode() )
  595. {
  596. // open the weapon selection
  597. OpenSelection();
  598. }
  599. }
  600. if ( m_bPlaySelectionSounds )
  601. {
  602. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  603. }
  604. }
  605. //-----------------------------------------------------------------------------
  606. // Purpose: Player has chosen to draw the currently selected weapon
  607. //-----------------------------------------------------------------------------
  608. void CHudWeaponSelection::SelectWeapon( void )
  609. {
  610. if ( !GetSelectedWeapon() )
  611. {
  612. engine->ClientCmd( "cancelselect\n" );
  613. return;
  614. }
  615. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  616. if ( !player )
  617. {
  618. return;
  619. }
  620. // Don't allow selections of weapons that can't be selected (out of ammo, etc)
  621. if ( GetSelectedWeapon()->CanBeSelected() )
  622. {
  623. SetWeaponSelected();
  624. m_hSelectedWeapon = NULL;
  625. engine->ClientCmd( "cancelselect\n" );
  626. }
  627. }
  628. //-----------------------------------------------------------------------------
  629. // Purpose: Abort selecting a weapon
  630. //-----------------------------------------------------------------------------
  631. void CHudWeaponSelection::CancelWeaponSelection( void )
  632. {
  633. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  634. if ( !player )
  635. {
  636. return;
  637. }
  638. // Fastswitches happen in a single frame, so the Weapon Selection HUD Element isn't visible
  639. // yet, but it's going to be next frame. We need to ask it if it thinks it's going to draw,
  640. // instead of checking it's IsActive flag.
  641. if ( ShouldDraw() )
  642. {
  643. HideSelection();
  644. m_hSelectedWeapon = NULL;
  645. }
  646. else
  647. {
  648. engine->ClientCmd("escape");
  649. }
  650. }