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.

683 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Weapon selection handling
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "weapon_selection.h"
  9. #include "hud_macros.h"
  10. #include "history_resource.h"
  11. #include "menu.h"
  12. #include "in_buttons.h"
  13. #include <KeyValues.h>
  14. #include "filesystem.h"
  15. #include "iinput.h"
  16. #include "inputsystem/iinputsystem.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. #define HISTORY_DRAW_TIME "5"
  20. ConVar hud_drawhistory_time( "hud_drawhistory_time", HISTORY_DRAW_TIME, 0 );
  21. ConVar hud_fastswitch( "hud_fastswitch", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX );
  22. //-----------------------------------------------------------------------------
  23. // Purpose: Weapon Selection commands
  24. //-----------------------------------------------------------------------------
  25. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot1, "CHudWeaponSelection");
  26. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot2, "CHudWeaponSelection");
  27. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot3, "CHudWeaponSelection");
  28. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot4, "CHudWeaponSelection");
  29. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot5, "CHudWeaponSelection");
  30. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot6, "CHudWeaponSelection");
  31. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot7, "CHudWeaponSelection");
  32. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot8, "CHudWeaponSelection");
  33. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot9, "CHudWeaponSelection");
  34. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot0, "CHudWeaponSelection");
  35. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Slot10, "CHudWeaponSelection");
  36. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, Close, "CHudWeaponSelection");
  37. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, NextWeapon, "CHudWeaponSelection");
  38. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, PrevWeapon, "CHudWeaponSelection");
  39. DECLARE_HUD_COMMAND_NAME(CBaseHudWeaponSelection, LastWeapon, "CHudWeaponSelection");
  40. HOOK_COMMAND( slot1, Slot1 );
  41. HOOK_COMMAND( slot2, Slot2 );
  42. HOOK_COMMAND( slot3, Slot3 );
  43. HOOK_COMMAND( slot4, Slot4 );
  44. HOOK_COMMAND( slot5, Slot5 );
  45. HOOK_COMMAND( slot6, Slot6 );
  46. HOOK_COMMAND( slot7, Slot7 );
  47. HOOK_COMMAND( slot8, Slot8 );
  48. HOOK_COMMAND( slot9, Slot9 );
  49. HOOK_COMMAND( slot0, Slot0 );
  50. HOOK_COMMAND( slot10, Slot10 );
  51. HOOK_COMMAND( cancelselect, Close );
  52. HOOK_COMMAND( invnext, NextWeapon );
  53. HOOK_COMMAND( invprev, PrevWeapon );
  54. HOOK_COMMAND( lastinv, LastWeapon );
  55. // instance info
  56. CBaseHudWeaponSelection *CBaseHudWeaponSelection::s_pInstance = NULL;
  57. CBaseHudWeaponSelection *CBaseHudWeaponSelection::GetInstance()
  58. {
  59. return s_pInstance;
  60. }
  61. CBaseHudWeaponSelection *GetHudWeaponSelection()
  62. {
  63. return CBaseHudWeaponSelection::GetInstance();
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Purpose: Constructor
  67. //-----------------------------------------------------------------------------
  68. CBaseHudWeaponSelection::CBaseHudWeaponSelection( const char *pElementName ) : CHudElement( pElementName )
  69. {
  70. s_pInstance = this;
  71. SetHiddenBits( HIDEHUD_WEAPONSELECTION | HIDEHUD_NEEDSUIT | HIDEHUD_PLAYERDEAD | HIDEHUD_INVEHICLE );
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Purpose:
  75. //-----------------------------------------------------------------------------
  76. void CBaseHudWeaponSelection::Init(void)
  77. {
  78. Reset();
  79. // Initialise the weapons resource
  80. gWR.Init();
  81. m_flSelectionTime = gpGlobals->curtime;
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose:
  85. //-----------------------------------------------------------------------------
  86. void CBaseHudWeaponSelection::Reset(void)
  87. {
  88. gWR.Reset();
  89. // Start hidden
  90. m_bSelectionVisible = false;
  91. m_flSelectionTime = gpGlobals->curtime;
  92. gHUD.UnlockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) );
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Purpose:
  96. //-----------------------------------------------------------------------------
  97. void CBaseHudWeaponSelection::UpdateSelectionTime( void )
  98. {
  99. m_flSelectionTime = gpGlobals->curtime;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Purpose:
  103. //-----------------------------------------------------------------------------
  104. void CBaseHudWeaponSelection::VidInit(void)
  105. {
  106. // If we've already loaded weapons, let's get new sprites
  107. gWR.LoadAllWeaponSprites();
  108. // set spacing of pickup history
  109. CHudHistoryResource *pHudHR = GET_HUDELEMENT( CHudHistoryResource );
  110. if( pHudHR )
  111. {
  112. pHudHR->SetHistoryGap( 21 );
  113. }
  114. Reset();
  115. }
  116. //-----------------------------------------------------------------------------
  117. // Purpose:
  118. //-----------------------------------------------------------------------------
  119. void CBaseHudWeaponSelection::OnThink( void )
  120. {
  121. // Don't allow weapon selection if we're frozen in place
  122. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  123. if ( pPlayer->GetFlags() & FL_FROZEN || pPlayer->IsPlayerDead() )
  124. {
  125. if ( IsInSelectionMode() )
  126. {
  127. CancelWeaponSelection();
  128. }
  129. }
  130. }
  131. //-----------------------------------------------------------------------------
  132. // Purpose: Think used for selection of weapon menu item.
  133. //-----------------------------------------------------------------------------
  134. void CBaseHudWeaponSelection::ProcessInput()
  135. {
  136. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  137. if ( !pPlayer )
  138. return;
  139. int nFastswitchMode = hud_fastswitch.GetInt();
  140. if ( ::input->IsSteamControllerActive() )
  141. {
  142. nFastswitchMode = HUDTYPE_FASTSWITCH;
  143. }
  144. // Check to see if the player is in VGUI mode...
  145. if ( pPlayer->IsInVGuiInputMode() && !pPlayer->IsInViewModelVGuiInputMode() )
  146. {
  147. // If so, close weapon selection when they press fire
  148. if ( gHUD.m_iKeyBits & IN_ATTACK )
  149. {
  150. if ( HUDTYPE_PLUS != nFastswitchMode )
  151. {
  152. // Swallow the button
  153. gHUD.m_iKeyBits &= ~IN_ATTACK;
  154. input->ClearInputButton( IN_ATTACK );
  155. }
  156. engine->ClientCmd( "cancelselect\n" );
  157. }
  158. return;
  159. }
  160. // Has the player selected a weapon?
  161. if ( gHUD.m_iKeyBits & (IN_ATTACK | IN_ATTACK2) )
  162. {
  163. if ( IsWeaponSelectable() )
  164. {
  165. #ifndef TF_CLIENT_DLL
  166. if ( HUDTYPE_PLUS != nFastswitchMode )
  167. #endif
  168. {
  169. // Swallow the button
  170. gHUD.m_iKeyBits &= ~(IN_ATTACK | IN_ATTACK2);
  171. input->ClearInputButton( IN_ATTACK );
  172. input->ClearInputButton( IN_ATTACK2 );
  173. }
  174. // select weapon
  175. SelectWeapon();
  176. }
  177. }
  178. }
  179. //-----------------------------------------------------------------------------
  180. // Purpose:
  181. //-----------------------------------------------------------------------------
  182. bool CBaseHudWeaponSelection::IsInSelectionMode()
  183. {
  184. return m_bSelectionVisible;
  185. }
  186. //-----------------------------------------------------------------------------
  187. // Purpose:
  188. //-----------------------------------------------------------------------------
  189. void CBaseHudWeaponSelection::OpenSelection( void )
  190. {
  191. m_bSelectionVisible = true;
  192. gHUD.LockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) );
  193. }
  194. //-----------------------------------------------------------------------------
  195. // Purpose:
  196. //-----------------------------------------------------------------------------
  197. void CBaseHudWeaponSelection::HideSelection( void )
  198. {
  199. m_bSelectionVisible = false;
  200. gHUD.UnlockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) );
  201. }
  202. //-----------------------------------------------------------------------------
  203. // Purpose: Returns whether a weapon can be selected in the HUD, based on hud type
  204. //-----------------------------------------------------------------------------
  205. bool CBaseHudWeaponSelection::CanBeSelectedInHUD( C_BaseCombatWeapon *pWeapon )
  206. {
  207. int nFastswitchMode = hud_fastswitch.GetInt();
  208. if ( ::input->IsSteamControllerActive() )
  209. {
  210. nFastswitchMode = HUDTYPE_FASTSWITCH;
  211. }
  212. // Xbox: In plus type, weapons without ammo can still be selected in the HUD
  213. if( HUDTYPE_PLUS == nFastswitchMode )
  214. {
  215. return pWeapon->VisibleInWeaponSelection();
  216. }
  217. if ( !pWeapon->VisibleInWeaponSelection() )
  218. {
  219. return false;
  220. }
  221. // All other current hud types
  222. return pWeapon->CanBeSelected();
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Purpose: handles keyboard input
  226. //-----------------------------------------------------------------------------
  227. int CBaseHudWeaponSelection::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
  228. {
  229. if (IsInSelectionMode() && pszCurrentBinding && !stricmp(pszCurrentBinding, "cancelselect"))
  230. {
  231. HideSelection();
  232. // returning 0 indicates, we've handled it, no more action needs to be taken
  233. return 0;
  234. }
  235. if ( down >= 1 && keynum >= KEY_1 && keynum <= KEY_9 )
  236. {
  237. if ( HandleHudMenuInput( keynum - KEY_0 ) )
  238. return 0;
  239. }
  240. // let someone else handle it
  241. return 1;
  242. }
  243. //-----------------------------------------------------------------------------
  244. // Purpose: called when a weapon has been picked up
  245. //-----------------------------------------------------------------------------
  246. void CBaseHudWeaponSelection::OnWeaponPickup( C_BaseCombatWeapon *pWeapon )
  247. {
  248. // add to pickup history
  249. CHudHistoryResource *pHudHR = GET_HUDELEMENT( CHudHistoryResource );
  250. if ( pHudHR )
  251. {
  252. pHudHR->AddToHistory( pWeapon );
  253. }
  254. }
  255. //------------------------------------------------------------------------
  256. // Command Handlers
  257. //------------------------------------------------------------------------
  258. void CBaseHudWeaponSelection::UserCmd_Slot1(void)
  259. {
  260. int nFastswitchMode = hud_fastswitch.GetInt();
  261. if ( ::input->IsSteamControllerActive() )
  262. {
  263. nFastswitchMode = HUDTYPE_FASTSWITCH;
  264. }
  265. if( HUDTYPE_CAROUSEL == nFastswitchMode )
  266. {
  267. UserCmd_LastWeapon();
  268. }
  269. else
  270. {
  271. SelectSlot( 1 );
  272. }
  273. }
  274. void CBaseHudWeaponSelection::UserCmd_Slot2(void)
  275. {
  276. int nFastswitchMode = hud_fastswitch.GetInt();
  277. if ( ::input->IsSteamControllerActive() )
  278. {
  279. nFastswitchMode = HUDTYPE_FASTSWITCH;
  280. }
  281. if( HUDTYPE_CAROUSEL == nFastswitchMode )
  282. {
  283. UserCmd_NextWeapon();
  284. }
  285. else
  286. {
  287. SelectSlot( 2 );
  288. }
  289. }
  290. void CBaseHudWeaponSelection::UserCmd_Slot3(void)
  291. {
  292. int nFastswitchMode = hud_fastswitch.GetInt();
  293. if ( ::input->IsSteamControllerActive() )
  294. {
  295. nFastswitchMode = HUDTYPE_FASTSWITCH;
  296. }
  297. if( HUDTYPE_CAROUSEL == nFastswitchMode )
  298. {
  299. engine->ClientCmd( "phys_swap" );
  300. }
  301. else
  302. {
  303. SelectSlot( 3 );
  304. }
  305. }
  306. void CBaseHudWeaponSelection::UserCmd_Slot4(void)
  307. {
  308. int nFastswitchMode = hud_fastswitch.GetInt();
  309. if ( ::input->IsSteamControllerActive() )
  310. {
  311. nFastswitchMode = HUDTYPE_FASTSWITCH;
  312. }
  313. if( HUDTYPE_CAROUSEL == nFastswitchMode )
  314. {
  315. UserCmd_PrevWeapon();
  316. }
  317. else
  318. {
  319. SelectSlot( 4 );
  320. }
  321. }
  322. void CBaseHudWeaponSelection::UserCmd_Slot5(void)
  323. {
  324. SelectSlot( 5 );
  325. }
  326. void CBaseHudWeaponSelection::UserCmd_Slot6(void)
  327. {
  328. SelectSlot( 6 );
  329. }
  330. void CBaseHudWeaponSelection::UserCmd_Slot7(void)
  331. {
  332. SelectSlot( 7 );
  333. }
  334. void CBaseHudWeaponSelection::UserCmd_Slot8(void)
  335. {
  336. SelectSlot( 8 );
  337. }
  338. void CBaseHudWeaponSelection::UserCmd_Slot9(void)
  339. {
  340. SelectSlot( 9 );
  341. }
  342. void CBaseHudWeaponSelection::UserCmd_Slot0(void)
  343. {
  344. SelectSlot( 0 );
  345. }
  346. void CBaseHudWeaponSelection::UserCmd_Slot10(void)
  347. {
  348. SelectSlot( 10 );
  349. }
  350. //-----------------------------------------------------------------------------
  351. // Purpose: returns true if the CHudMenu should take slot1, etc commands
  352. //-----------------------------------------------------------------------------
  353. bool CBaseHudWeaponSelection::IsHudMenuTakingInput()
  354. {
  355. CHudMenu *pHudMenu = GET_HUDELEMENT( CHudMenu );
  356. return ( pHudMenu && pHudMenu->IsMenuOpen() );
  357. }
  358. //-----------------------------------------------------------------------------
  359. // Purpose: returns true if the CHudMenu handles the slot command
  360. //-----------------------------------------------------------------------------
  361. bool CBaseHudWeaponSelection::HandleHudMenuInput( int iSlot )
  362. {
  363. CHudMenu *pHudMenu = GET_HUDELEMENT( CHudMenu );
  364. if ( !pHudMenu || !pHudMenu->IsMenuOpen() )
  365. return false;
  366. pHudMenu->SelectMenuItem( iSlot );
  367. return true;
  368. }
  369. //-----------------------------------------------------------------------------
  370. // Purpose: returns true if the weapon selection hud should be hidden because
  371. // the CHudMenu is open
  372. //-----------------------------------------------------------------------------
  373. bool CBaseHudWeaponSelection::IsHudMenuPreventingWeaponSelection()
  374. {
  375. // Don't allow weapon selection if we're frozen in place
  376. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  377. if ( pPlayer->GetFlags() & FL_FROZEN || pPlayer->IsPlayerDead() )
  378. return true;
  379. return IsHudMenuTakingInput();
  380. }
  381. //-----------------------------------------------------------------------------
  382. // Purpose: Menu Selection Code
  383. //-----------------------------------------------------------------------------
  384. void CBaseHudWeaponSelection::SelectSlot( int iSlot )
  385. {
  386. // A menu may be overriding weapon selection commands
  387. if ( HandleHudMenuInput( iSlot ) )
  388. {
  389. return;
  390. }
  391. // If we're not allowed to draw, ignore weapon selections
  392. if ( !BaseClass::ShouldDraw() )
  393. {
  394. return;
  395. }
  396. UpdateSelectionTime();
  397. SelectWeaponSlot( iSlot );
  398. }
  399. //-----------------------------------------------------------------------------
  400. // Purpose: Close the weapon selection
  401. //-----------------------------------------------------------------------------
  402. void CBaseHudWeaponSelection::UserCmd_Close(void)
  403. {
  404. CancelWeaponSelection();
  405. }
  406. //-----------------------------------------------------------------------------
  407. // Purpose: Selects the next item in the weapon menu
  408. //-----------------------------------------------------------------------------
  409. void CBaseHudWeaponSelection::UserCmd_NextWeapon(void)
  410. {
  411. // If we're not allowed to draw, ignore weapon selections
  412. if ( !BaseClass::ShouldDraw() )
  413. return;
  414. int nFastswitchMode = hud_fastswitch.GetInt();
  415. if ( ::input->IsSteamControllerActive() )
  416. {
  417. nFastswitchMode = HUDTYPE_FASTSWITCH;
  418. }
  419. CycleToNextWeapon();
  420. if( nFastswitchMode > 0 )
  421. {
  422. SelectWeapon();
  423. }
  424. UpdateSelectionTime();
  425. }
  426. //-----------------------------------------------------------------------------
  427. // Purpose: Selects the previous item in the menu
  428. //-----------------------------------------------------------------------------
  429. void CBaseHudWeaponSelection::UserCmd_PrevWeapon(void)
  430. {
  431. // If we're not allowed to draw, ignore weapon selections
  432. if ( !BaseClass::ShouldDraw() )
  433. return;
  434. int nFastswitchMode = hud_fastswitch.GetInt();
  435. if ( ::input->IsSteamControllerActive() )
  436. {
  437. nFastswitchMode = HUDTYPE_FASTSWITCH;
  438. }
  439. CycleToPrevWeapon();
  440. if( nFastswitchMode > 0 )
  441. {
  442. SelectWeapon();
  443. }
  444. UpdateSelectionTime();
  445. }
  446. //-----------------------------------------------------------------------------
  447. // Purpose: Switches the last weapon the player was using
  448. //-----------------------------------------------------------------------------
  449. void CBaseHudWeaponSelection::UserCmd_LastWeapon(void)
  450. {
  451. // If we're not allowed to draw, ignore weapon selections
  452. if ( !BaseClass::ShouldDraw() )
  453. return;
  454. /*
  455. if ( IsHudMenuPreventingWeaponSelection() )
  456. {
  457. return;
  458. }
  459. */
  460. SwitchToLastWeapon();
  461. }
  462. //-----------------------------------------------------------------------------
  463. // Purpose: Switches the last weapon the player was using
  464. //-----------------------------------------------------------------------------
  465. void CBaseHudWeaponSelection::SwitchToLastWeapon( void )
  466. {
  467. // Get the player's last weapon
  468. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  469. if ( !player )
  470. return;
  471. input->MakeWeaponSelection( player->GetLastWeapon() );
  472. }
  473. //-----------------------------------------------------------------------------
  474. // Purpose:
  475. //-----------------------------------------------------------------------------
  476. void CBaseHudWeaponSelection::SetWeaponSelected( void )
  477. {
  478. Assert( GetSelectedWeapon() );
  479. // Mark selection so that it's placed into next CUserCmd created
  480. input->MakeWeaponSelection( GetSelectedWeapon() );
  481. }
  482. //-----------------------------------------------------------------------------
  483. // Purpose: Player has chosen to draw the currently selected weapon
  484. //-----------------------------------------------------------------------------
  485. void CBaseHudWeaponSelection::SelectWeapon( void )
  486. {
  487. if ( !GetSelectedWeapon() )
  488. {
  489. engine->ClientCmd( "cancelselect\n" );
  490. return;
  491. }
  492. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  493. if ( !player )
  494. return;
  495. // Don't allow selections of weapons that can't be selected (out of ammo, etc)
  496. if ( !GetSelectedWeapon()->CanBeSelected() )
  497. {
  498. player->EmitSound( "Player.DenyWeaponSelection" );
  499. }
  500. else
  501. {
  502. SetWeaponSelected();
  503. m_hSelectedWeapon = NULL;
  504. engine->ClientCmd( "cancelselect\n" );
  505. // Play the "weapon selected" sound
  506. player->EmitSound( "Player.WeaponSelected" );
  507. }
  508. }
  509. //-----------------------------------------------------------------------------
  510. // Purpose: Abort selecting a weapon
  511. //-----------------------------------------------------------------------------
  512. void CBaseHudWeaponSelection::CancelWeaponSelection( void )
  513. {
  514. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  515. if ( !player )
  516. return;
  517. // Fastswitches happen in a single frame, so the Weapon Selection HUD Element isn't visible
  518. // yet, but it's going to be next frame. We need to ask it if it thinks it's going to draw,
  519. // instead of checking it's IsActive flag.
  520. if ( ShouldDraw() )
  521. {
  522. HideSelection();
  523. m_hSelectedWeapon = NULL;
  524. // Play the "close weapon selection" sound
  525. player->EmitSound( "Player.WeaponSelectionClose" );
  526. }
  527. else
  528. {
  529. engine->ClientCmd("escape");
  530. }
  531. }
  532. //-----------------------------------------------------------------------------
  533. // Purpose: Returns the first weapon for a given slot.
  534. //-----------------------------------------------------------------------------
  535. C_BaseCombatWeapon *CBaseHudWeaponSelection::GetFirstPos( int iSlot )
  536. {
  537. int iLowestPosition = MAX_WEAPON_POSITIONS;
  538. C_BaseCombatWeapon *pFirstWeapon = NULL;
  539. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  540. if ( !player )
  541. return NULL;
  542. for ( int i = 0; i < MAX_WEAPONS; i++ )
  543. {
  544. C_BaseCombatWeapon *pWeapon = player->GetWeapon( i );
  545. if ( !pWeapon )
  546. continue;
  547. if ( ( pWeapon->GetSlot() == iSlot ) && (pWeapon->VisibleInWeaponSelection()) )
  548. {
  549. // If this weapon is lower in the slot than the current lowest, it's our new winner
  550. if ( pWeapon->GetPosition() <= iLowestPosition )
  551. {
  552. iLowestPosition = pWeapon->GetPosition();
  553. pFirstWeapon = pWeapon;
  554. }
  555. }
  556. }
  557. return pFirstWeapon;
  558. }
  559. //-----------------------------------------------------------------------------
  560. // Purpose:
  561. //-----------------------------------------------------------------------------
  562. C_BaseCombatWeapon *CBaseHudWeaponSelection::GetNextActivePos( int iSlot, int iSlotPos )
  563. {
  564. if ( iSlotPos >= MAX_WEAPON_POSITIONS || iSlot >= MAX_WEAPON_SLOTS )
  565. return NULL;
  566. int iLowestPosition = MAX_WEAPON_POSITIONS;
  567. C_BaseCombatWeapon *pNextWeapon = NULL;
  568. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  569. if ( !player )
  570. return NULL;
  571. for ( int i = 0; i < MAX_WEAPONS; i++ )
  572. {
  573. C_BaseCombatWeapon *pWeapon = player->GetWeapon( i );
  574. if ( !pWeapon )
  575. continue;
  576. if ( CanBeSelectedInHUD( pWeapon ) && pWeapon->GetSlot() == iSlot )
  577. {
  578. // If this weapon is lower in the slot than the current lowest, and above our desired position, it's our new winner
  579. if ( pWeapon->GetPosition() <= iLowestPosition && pWeapon->GetPosition() >= iSlotPos )
  580. {
  581. iLowestPosition = pWeapon->GetPosition();
  582. pNextWeapon = pWeapon;
  583. }
  584. }
  585. }
  586. return pNextWeapon;
  587. }