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.

682 lines
20 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 "vgui/ILocalize.h"
  17. #include <string.h>
  18. //-----------------------------------------------------------------------------
  19. // Purpose: cstrike weapon selection hud element
  20. //-----------------------------------------------------------------------------
  21. class CHudWeaponSelection : public CBaseHudWeaponSelection, public vgui::Panel
  22. {
  23. DECLARE_CLASS_SIMPLE( CHudWeaponSelection, vgui::Panel );
  24. public:
  25. CHudWeaponSelection(const char *pElementName );
  26. virtual bool ShouldDraw();
  27. virtual void OnWeaponPickup( C_BaseCombatWeapon *pWeapon );
  28. virtual void CycleToNextWeapon( void );
  29. virtual void CycleToPrevWeapon( void );
  30. virtual C_BaseCombatWeapon *GetWeaponInSlot( int iSlot, int iSlotPos );
  31. virtual void SelectWeaponSlot( int iSlot );
  32. virtual C_BaseCombatWeapon *GetSelectedWeapon( void )
  33. {
  34. return m_hSelectedWeapon;
  35. }
  36. virtual void OpenSelection( void );
  37. virtual void HideSelection( void );
  38. virtual void LevelInit();
  39. protected:
  40. virtual void OnThink();
  41. virtual void Paint();
  42. virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
  43. virtual bool IsWeaponSelectable()
  44. {
  45. if (IsInSelectionMode())
  46. return true;
  47. return false;
  48. }
  49. private:
  50. C_BaseCombatWeapon *FindNextWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition);
  51. C_BaseCombatWeapon *FindPrevWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition);
  52. virtual void SetSelectedWeapon( C_BaseCombatWeapon *pWeapon )
  53. {
  54. m_hSelectedWeapon = pWeapon;
  55. }
  56. void DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, int number);
  57. CPanelAnimationVar( vgui::HFont, m_hNumberFont, "NumberFont", "HudSelectionNumbers" );
  58. CPanelAnimationVar( vgui::HFont, m_hTextFont, "TextFont", "HudSelectionText" );
  59. CPanelAnimationVarAliasType( float, m_flSmallBoxSize, "SmallBoxSize", "32", "proportional_float" );
  60. CPanelAnimationVarAliasType( float, m_flLargeBoxWide, "LargeBoxWide", "108", "proportional_float" );
  61. CPanelAnimationVarAliasType( float, m_flLargeBoxTall, "LargeBoxTall", "72", "proportional_float" );
  62. CPanelAnimationVarAliasType( float, m_flBoxGap, "BoxGap", "12", "proportional_float" );
  63. CPanelAnimationVarAliasType( float, m_flSelectionNumberXPos, "SelectionNumberXPos", "4", "proportional_float" );
  64. CPanelAnimationVarAliasType( float, m_flSelectionNumberYPos, "SelectionNumberYPos", "4", "proportional_float" );
  65. CPanelAnimationVarAliasType( float, m_flIconXPos, "IconXPos", "16", "proportional_float" );
  66. CPanelAnimationVarAliasType( float, m_flIconYPos, "IconYPos", "8", "proportional_float" );
  67. CPanelAnimationVarAliasType( float, m_flTextYPos, "TextYPos", "54", "proportional_float" );
  68. CPanelAnimationVar( float, m_flAlphaOverride, "Alpha", "255" );
  69. CPanelAnimationVar( float, m_flSelectionAlphaOverride, "SelectionAlpha", "255" );
  70. CPanelAnimationVar( Color, m_TextColor, "TextColor", "SelectionTextFg" );
  71. CPanelAnimationVar( Color, m_NumberColor, "NumberColor", "SelectionNumberFg" );
  72. CPanelAnimationVar( Color, m_EmptyBoxColor, "EmptyBoxColor", "SelectionEmptyBoxBg" );
  73. CPanelAnimationVar( Color, m_BoxColor, "BoxColor", "SelectionBoxBg" );
  74. CPanelAnimationVar( Color, m_SelectedBoxColor, "SelectedBoxClor", "SelectionSelectedBoxBg" );
  75. CPanelAnimationVar( float, m_flWeaponPickupGrowTime, "SelectionGrowTime", "0.1" );
  76. CPanelAnimationVar( float, m_flTextScan, "TextScan", "1.0" );
  77. CPanelAnimationVar( int, m_iMaxSlots, "MaxSlots", "6" );
  78. CPanelAnimationVar( bool, m_bPlaySelectionSounds, "PlaySelectSounds", "1" );
  79. };
  80. DECLARE_HUDELEMENT( CHudWeaponSelection );
  81. using namespace vgui;
  82. //-----------------------------------------------------------------------------
  83. // Purpose: Constructor
  84. //-----------------------------------------------------------------------------
  85. CHudWeaponSelection::CHudWeaponSelection( const char *pElementName ) : CBaseHudWeaponSelection(pElementName), BaseClass(NULL, "HudWeaponSelection")
  86. {
  87. vgui::Panel *pParent = g_pClientMode->GetViewport();
  88. SetParent( pParent );
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose: sets up display for showing weapon pickup
  92. //-----------------------------------------------------------------------------
  93. void CHudWeaponSelection::OnWeaponPickup( C_BaseCombatWeapon *pWeapon )
  94. {
  95. // add to pickup history
  96. CHudHistoryResource *pHudHR = GET_HUDELEMENT( CHudHistoryResource );
  97. if( pHudHR )
  98. {
  99. pHudHR->AddToHistory( HISTSLOT_WEAP, pWeapon );
  100. }
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose: updates animation status
  104. //-----------------------------------------------------------------------------
  105. void CHudWeaponSelection::OnThink()
  106. {
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Purpose: returns true if the panel should draw
  110. //-----------------------------------------------------------------------------
  111. bool CHudWeaponSelection::ShouldDraw()
  112. {
  113. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  114. if ( !pPlayer )
  115. {
  116. if ( IsInSelectionMode() )
  117. {
  118. HideSelection();
  119. }
  120. return false;
  121. }
  122. bool bret = CBaseHudWeaponSelection::ShouldDraw();
  123. if ( !bret )
  124. return false;
  125. return ( m_bSelectionVisible ) ? true : false;
  126. }
  127. //-----------------------------------------------------------------------------
  128. // Purpose:
  129. //-----------------------------------------------------------------------------
  130. void CHudWeaponSelection::LevelInit()
  131. {
  132. CHudElement::LevelInit();
  133. m_iMaxSlots = clamp( m_iMaxSlots, 0, MAX_WEAPON_SLOTS );
  134. }
  135. //-------------------------------------------------------------------------
  136. // Purpose: draws the selection area
  137. //-------------------------------------------------------------------------
  138. void CHudWeaponSelection::Paint()
  139. {
  140. if (!ShouldDraw())
  141. return;
  142. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  143. if ( !pPlayer )
  144. return;
  145. // find and display our current selection
  146. C_BaseCombatWeapon *pSelectedWeapon = GetSelectedWeapon();
  147. if ( !pSelectedWeapon )
  148. return;
  149. int iActiveSlot = (pSelectedWeapon ? pSelectedWeapon->GetSlot() : -1);
  150. // interpolate the selected box size between the small box size and the large box size
  151. // interpolation has been removed since there is no weapon pickup animation anymore, so it's all at the largest size
  152. float percentageDone = 1.0f; //min(1.0f, (gpGlobals->curtime - m_flPickupStartTime) / m_flWeaponPickupGrowTime);
  153. int largeBoxWide = m_flSmallBoxSize + ((m_flLargeBoxWide - m_flSmallBoxSize) * percentageDone);
  154. int largeBoxTall = m_flSmallBoxSize + ((m_flLargeBoxTall - m_flSmallBoxSize) * percentageDone);
  155. Color selectedColor;
  156. {for (int i = 0; i < 4; i++)
  157. {
  158. selectedColor[i] = m_BoxColor[i] + ((m_SelectedBoxColor[i] - m_BoxColor[i]) * percentageDone);
  159. }}
  160. // calculate where to start drawing
  161. int width = (m_iMaxSlots - 1) * (m_flSmallBoxSize + m_flBoxGap) + largeBoxWide;
  162. int xpos = (GetWide() - width) / 2;
  163. int ypos = 0;
  164. // iterate over all the weapon slots
  165. for ( int i = 0; i < m_iMaxSlots; i++ )
  166. {
  167. if ( i == iActiveSlot )
  168. {
  169. bool bFirstItem = true;
  170. for (int slotpos = 0; slotpos < MAX_WEAPON_POSITIONS; slotpos++)
  171. {
  172. C_BaseCombatWeapon *pWeapon = GetWeaponInSlot(i, slotpos);
  173. if ( !pWeapon )
  174. continue;
  175. // draw selected weapon
  176. DrawBox(xpos, ypos, largeBoxWide, largeBoxTall, selectedColor, m_flSelectionAlphaOverride, bFirstItem ? i + 1 : -1);
  177. // draw icon
  178. Color col = GetFgColor();
  179. // icons use old system, drawing in screen space
  180. if ( pWeapon->GetSpriteActive() )
  181. {
  182. if (!pWeapon->CanBeSelected())
  183. {
  184. // unselectable weapon, display as such
  185. col = Color(255, 0, 0, col[3]);
  186. }
  187. else if (pWeapon == pSelectedWeapon)
  188. {
  189. // currently selected weapon, display brighter
  190. col[3] = m_flSelectionAlphaOverride;
  191. }
  192. pWeapon->GetSpriteActive()->DrawSelf( xpos + m_flIconXPos, ypos + m_flIconYPos, col );
  193. }
  194. // draw text
  195. col = m_TextColor;
  196. const FileWeaponInfo_t &weaponInfo = pWeapon->GetWpnData();
  197. if (pWeapon == pSelectedWeapon)
  198. {
  199. wchar_t text[128];
  200. wchar_t *tempString = g_pVGuiLocalize->Find(weaponInfo.szPrintName);
  201. // setup our localized string
  202. if ( tempString )
  203. {
  204. #ifdef WIN32
  205. _snwprintf(text, sizeof(text)/sizeof(wchar_t) - 1, L"%s", tempString);
  206. #else
  207. _snwprintf(text, sizeof(text)/sizeof(wchar_t) - 1, L"%S", tempString);
  208. #endif
  209. text[sizeof(text)/sizeof(wchar_t) - 1] = 0;
  210. }
  211. else
  212. {
  213. // string wasn't found by g_pVGuiLocalize->Find()
  214. g_pVGuiLocalize->ConvertANSIToUnicode(weaponInfo.szPrintName, text, sizeof(text));
  215. }
  216. surface()->DrawSetTextColor( col );
  217. surface()->DrawSetTextFont( m_hTextFont );
  218. // count the position
  219. int slen = 0, charCount = 0, maxslen = 0;
  220. {
  221. for (wchar_t *pch = text; *pch != 0; pch++)
  222. {
  223. if (*pch == '\n')
  224. {
  225. // newline character, drop to the next line
  226. if (slen > maxslen)
  227. {
  228. maxslen = slen;
  229. }
  230. slen = 0;
  231. }
  232. else if (*pch == '\r')
  233. {
  234. // do nothing
  235. }
  236. else
  237. {
  238. slen += surface()->GetCharacterWidth( m_hTextFont, *pch );
  239. charCount++;
  240. }
  241. }
  242. }
  243. if (slen > maxslen)
  244. {
  245. maxslen = slen;
  246. }
  247. int tx = xpos + ((largeBoxWide - maxslen) / 2);
  248. int ty = ypos + (int)m_flTextYPos;
  249. surface()->DrawSetTextPos( tx, ty );
  250. // adjust the charCount by the scan amount
  251. charCount *= m_flTextScan;
  252. for (wchar_t *pch = text; charCount > 0; pch++)
  253. {
  254. if (*pch == '\n')
  255. {
  256. // newline character, move to the next line
  257. surface()->DrawSetTextPos( xpos + ((largeBoxWide - slen) / 2), ty + (surface()->GetFontTall(m_hTextFont) * 1.1f));
  258. }
  259. else if (*pch == '\r')
  260. {
  261. // do nothing
  262. }
  263. else
  264. {
  265. surface()->DrawUnicodeChar(*pch);
  266. charCount--;
  267. }
  268. }
  269. }
  270. ypos += (largeBoxTall + m_flBoxGap);
  271. bFirstItem = false;
  272. }
  273. xpos += largeBoxWide;
  274. }
  275. else
  276. {
  277. // check to see if there is a weapons in this bucket
  278. if ( GetFirstPos( i ) )
  279. {
  280. // draw has weapon in slot
  281. DrawBox(xpos, ypos, m_flSmallBoxSize, m_flSmallBoxSize, m_BoxColor, m_flAlphaOverride, i + 1);
  282. }
  283. else
  284. {
  285. // draw empty slot
  286. DrawBox(xpos, ypos, m_flSmallBoxSize, m_flSmallBoxSize, m_EmptyBoxColor, m_flAlphaOverride, -1);
  287. }
  288. xpos += m_flSmallBoxSize;
  289. }
  290. // reset position
  291. ypos = 0;
  292. xpos += m_flBoxGap;
  293. }
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Purpose: draws a selection box
  297. //-----------------------------------------------------------------------------
  298. void CHudWeaponSelection::DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, int number)
  299. {
  300. BaseClass::DrawBox( x, y, wide, tall, color, normalizedAlpha / 255.0f );
  301. // draw the number
  302. if (number >= 0)
  303. {
  304. Color numberColor = m_NumberColor;
  305. numberColor[3] *= normalizedAlpha / 255.0f;
  306. surface()->DrawSetTextColor(numberColor);
  307. surface()->DrawSetTextFont(m_hNumberFont);
  308. wchar_t wch = '0' + number;
  309. surface()->DrawSetTextPos(x + m_flSelectionNumberXPos, y + m_flSelectionNumberYPos);
  310. surface()->DrawUnicodeChar(wch);
  311. }
  312. }
  313. //-----------------------------------------------------------------------------
  314. // Purpose: hud scheme settings
  315. //-----------------------------------------------------------------------------
  316. void CHudWeaponSelection::ApplySchemeSettings(vgui::IScheme *pScheme)
  317. {
  318. BaseClass::ApplySchemeSettings(pScheme);
  319. SetPaintBackgroundEnabled(false);
  320. // set our size
  321. int screenWide, screenTall;
  322. int x, y;
  323. GetPos(x, y);
  324. GetHudSize(screenWide, screenTall);
  325. SetBounds(0, y, screenWide, screenTall - y);
  326. }
  327. //-----------------------------------------------------------------------------
  328. // Purpose: Opens weapon selection control
  329. //-----------------------------------------------------------------------------
  330. void CHudWeaponSelection::OpenSelection( void )
  331. {
  332. Assert(!IsInSelectionMode());
  333. CBaseHudWeaponSelection::OpenSelection();
  334. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("OpenWeaponSelectionMenu");
  335. }
  336. //-----------------------------------------------------------------------------
  337. // Purpose: Closes weapon selection control
  338. //-----------------------------------------------------------------------------
  339. void CHudWeaponSelection::HideSelection( void )
  340. {
  341. CBaseHudWeaponSelection::HideSelection();
  342. g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("CloseWeaponSelectionMenu");
  343. }
  344. //-----------------------------------------------------------------------------
  345. // Purpose: Returns the next available weapon item in the weapon selection
  346. //-----------------------------------------------------------------------------
  347. C_BaseCombatWeapon *CHudWeaponSelection::FindNextWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition)
  348. {
  349. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  350. if ( !pPlayer )
  351. return NULL;
  352. C_BaseCombatWeapon *pNextWeapon = NULL;
  353. // search all the weapons looking for the closest next
  354. int iLowestNextSlot = MAX_WEAPON_SLOTS;
  355. int iLowestNextPosition = MAX_WEAPON_POSITIONS;
  356. for ( int i = 0; i < MAX_WEAPONS; i++ )
  357. {
  358. C_BaseCombatWeapon *pWeapon = pPlayer->GetWeapon(i);
  359. if ( !pWeapon )
  360. continue;
  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. return NULL;
  387. C_BaseCombatWeapon *pPrevWeapon = NULL;
  388. // search all the weapons looking for the closest next
  389. int iLowestPrevSlot = -1;
  390. int iLowestPrevPosition = -1;
  391. for ( int i = 0; i < MAX_WEAPONS; i++ )
  392. {
  393. C_BaseCombatWeapon *pWeapon = pPlayer->GetWeapon(i);
  394. if ( !pWeapon )
  395. continue;
  396. if ( pWeapon->CanBeSelected() )
  397. {
  398. int weaponSlot = pWeapon->GetSlot(), weaponPosition = pWeapon->GetPosition();
  399. // see if this weapon is further ahead in the selection list
  400. if ( weaponSlot < iCurrentSlot || (weaponSlot == iCurrentSlot && weaponPosition < iCurrentPosition) )
  401. {
  402. // see if this weapon is closer than the current lowest
  403. if ( weaponSlot > iLowestPrevSlot || (weaponSlot == iLowestPrevSlot && weaponPosition > iLowestPrevPosition) )
  404. {
  405. iLowestPrevSlot = weaponSlot;
  406. iLowestPrevPosition = weaponPosition;
  407. pPrevWeapon = pWeapon;
  408. }
  409. }
  410. }
  411. }
  412. return pPrevWeapon;
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Purpose: Moves the selection to the next item in the menu
  416. //-----------------------------------------------------------------------------
  417. void CHudWeaponSelection::CycleToNextWeapon( void )
  418. {
  419. // Get the local player.
  420. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  421. if ( !pPlayer )
  422. return;
  423. C_BaseCombatWeapon *pNextWeapon = NULL;
  424. if ( IsInSelectionMode() )
  425. {
  426. // find the next selection spot
  427. C_BaseCombatWeapon *pWeapon = GetSelectedWeapon();
  428. if ( !pWeapon )
  429. return;
  430. pNextWeapon = FindNextWeaponInWeaponSelection( pWeapon->GetSlot(), pWeapon->GetPosition() );
  431. }
  432. else
  433. {
  434. // open selection at the current place
  435. pNextWeapon = pPlayer->GetActiveWeapon();
  436. if ( pNextWeapon )
  437. {
  438. pNextWeapon = FindNextWeaponInWeaponSelection( pNextWeapon->GetSlot(), pNextWeapon->GetPosition() );
  439. }
  440. }
  441. if ( !pNextWeapon )
  442. {
  443. // wrap around back to start
  444. pNextWeapon = FindNextWeaponInWeaponSelection(-1, -1);
  445. }
  446. if ( pNextWeapon )
  447. {
  448. SetSelectedWeapon( pNextWeapon );
  449. if( hud_fastswitch.GetInt() > 0 )
  450. {
  451. SelectWeapon();
  452. }
  453. else if ( !IsInSelectionMode() )
  454. {
  455. OpenSelection();
  456. }
  457. // Play the "cycle to next weapon" sound
  458. if( m_bPlaySelectionSounds )
  459. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  460. }
  461. }
  462. //-----------------------------------------------------------------------------
  463. // Purpose: Moves the selection to the previous item in the menu
  464. //-----------------------------------------------------------------------------
  465. void CHudWeaponSelection::CycleToPrevWeapon( void )
  466. {
  467. // Get the local player.
  468. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  469. if ( !pPlayer )
  470. return;
  471. C_BaseCombatWeapon *pNextWeapon = NULL;
  472. if ( IsInSelectionMode() )
  473. {
  474. // find the next selection spot
  475. C_BaseCombatWeapon *pWeapon = GetSelectedWeapon();
  476. if ( !pWeapon )
  477. return;
  478. pNextWeapon = FindPrevWeaponInWeaponSelection( pWeapon->GetSlot(), pWeapon->GetPosition() );
  479. }
  480. else
  481. {
  482. // open selection at the current place
  483. pNextWeapon = pPlayer->GetActiveWeapon();
  484. if ( pNextWeapon )
  485. {
  486. pNextWeapon = FindPrevWeaponInWeaponSelection( pNextWeapon->GetSlot(), pNextWeapon->GetPosition() );
  487. }
  488. }
  489. if ( !pNextWeapon )
  490. {
  491. // wrap around back to end of weapon list
  492. pNextWeapon = FindPrevWeaponInWeaponSelection(MAX_WEAPON_SLOTS, MAX_WEAPON_POSITIONS);
  493. }
  494. if ( pNextWeapon )
  495. {
  496. SetSelectedWeapon( pNextWeapon );
  497. if( hud_fastswitch.GetInt() > 0 )
  498. {
  499. SelectWeapon();
  500. }
  501. else if ( !IsInSelectionMode() )
  502. {
  503. OpenSelection();
  504. }
  505. // Play the "cycle to next weapon" sound
  506. if( m_bPlaySelectionSounds )
  507. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  508. }
  509. }
  510. //-----------------------------------------------------------------------------
  511. // Purpose: returns the weapon in the specified slot
  512. //-----------------------------------------------------------------------------
  513. C_BaseCombatWeapon *CHudWeaponSelection::GetWeaponInSlot( int iSlot, int iSlotPos )
  514. {
  515. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  516. if ( !player )
  517. return NULL;
  518. for ( int i = 0; i < MAX_WEAPONS; i++ )
  519. {
  520. C_BaseCombatWeapon *pWeapon = player->GetWeapon(i);
  521. if ( pWeapon == NULL )
  522. continue;
  523. if ( pWeapon->GetSlot() == iSlot && pWeapon->GetPosition() == iSlotPos )
  524. return pWeapon;
  525. }
  526. return NULL;
  527. }
  528. //-----------------------------------------------------------------------------
  529. // Purpose: Moves selection to the specified slot
  530. //-----------------------------------------------------------------------------
  531. void CHudWeaponSelection::SelectWeaponSlot( int iSlot )
  532. {
  533. // iSlot is one higher than it should be, since it's the number key, not the 0-based index into the weapons
  534. --iSlot;
  535. // Get the local player.
  536. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  537. if ( !pPlayer )
  538. return;
  539. // Don't try and read past our possible number of slots
  540. if ( iSlot > MAX_WEAPON_SLOTS )
  541. return;
  542. // Make sure the player's allowed to switch weapons
  543. if ( pPlayer->IsAllowedToSwitchWeapons() == false )
  544. return;
  545. int slotPos = 0;
  546. C_BaseCombatWeapon *pActiveWeapon = GetSelectedWeapon();
  547. // start later in the list
  548. if ( IsInSelectionMode() && pActiveWeapon && pActiveWeapon->GetSlot() == iSlot )
  549. {
  550. slotPos = pActiveWeapon->GetPosition() + 1;
  551. }
  552. // find the weapon in this slot
  553. pActiveWeapon = GetNextActivePos( iSlot, slotPos );
  554. if ( !pActiveWeapon )
  555. {
  556. pActiveWeapon = GetNextActivePos( iSlot, 0 );
  557. }
  558. if ( pActiveWeapon != NULL )
  559. {
  560. // Mark the change
  561. SetSelectedWeapon( pActiveWeapon );
  562. if( hud_fastswitch.GetInt() > 0 )
  563. {
  564. SelectWeapon();
  565. }
  566. else if ( !IsInSelectionMode() )
  567. {
  568. // open the weapon selection
  569. OpenSelection();
  570. }
  571. }
  572. if( m_bPlaySelectionSounds )
  573. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  574. }