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.

1071 lines
31 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "cbase.h"
  7. #include "cs_hud_weaponselection.h"
  8. #include "iclientmode.h"
  9. #include "HUD/sfweaponselection.h"
  10. #include "iinput.h"
  11. #include "cs_gamerules.h"
  12. #include <keyvalues.h>
  13. #include <vgui/IScheme.h>
  14. #include <vgui/ISurface.h>
  15. #include <vgui/ISystem.h>
  16. #include <vgui_controls/AnimationController.h>
  17. #include "vgui/ILocalize.h"
  18. #include <string.h>
  19. // memdbgon must be the last include file in a .cpp file!!!
  20. #include "tier0/memdbgon.h"
  21. DECLARE_HUDELEMENT( CHudWeaponSelection );
  22. using namespace vgui;
  23. //-----------------------------------------------------------------------------
  24. // Purpose: Constructor
  25. //-----------------------------------------------------------------------------
  26. CHudWeaponSelection::CHudWeaponSelection( const char *pElementName ) : CBaseHudWeaponSelection(pElementName), BaseClass(NULL, "HudWeaponSelection")
  27. {
  28. vgui::Panel *pParent = GetClientMode()->GetViewport();
  29. SetParent( pParent );
  30. SetHiddenBits( HIDEHUD_WEAPONSELECTION | HIDEHUD_PLAYERDEAD );
  31. }
  32. //-----------------------------------------------------------------------------
  33. // Purpose: sets up display for showing weapon pickup
  34. //-----------------------------------------------------------------------------
  35. void CHudWeaponSelection::OnWeaponPickup( C_BaseCombatWeapon *pWeapon )
  36. {
  37. CWeaponCSBase* pCSWeapon = dynamic_cast<CWeaponCSBase*>( pWeapon );
  38. C_CSPlayer *pPlayer = GetHudPlayer();
  39. if ( pCSWeapon && !pCSWeapon->IsMarkedForDeletion() && pPlayer )
  40. {
  41. //const CCSWeaponInfo *pCSWeaponInfo = GetWeaponInfo( pCSWeapon->GetCSWeaponID() );
  42. if ( pPlayer->State_Get() == STATE_ACTIVE )
  43. {
  44. SFWeaponSelection *pHudWS = GET_HUDELEMENT( SFWeaponSelection );
  45. if ( pHudWS )
  46. {
  47. pHudWS->ShowAndUpdateSelection( WEPSELECT_PICKUP, pWeapon );
  48. }
  49. }
  50. }
  51. }
  52. //-----------------------------------------------------------------------------
  53. // Purpose: sets up display for showing weapon drop
  54. //-----------------------------------------------------------------------------
  55. void CHudWeaponSelection::OnWeaponDrop( C_BaseCombatWeapon *pWeapon )
  56. {
  57. CWeaponCSBase* pCSWeapon = dynamic_cast<CWeaponCSBase*>( pWeapon );
  58. C_CSPlayer *pPlayer = GetHudPlayer();
  59. if ( pCSWeapon && pPlayer )
  60. {
  61. if ( pPlayer->State_Get() == STATE_ACTIVE )
  62. {
  63. SFWeaponSelection *pHudWS = GET_HUDELEMENT( SFWeaponSelection );
  64. if ( pHudWS )
  65. {
  66. pHudWS->ShowAndUpdateSelection( WEPSELECT_DROP, pWeapon );
  67. }
  68. }
  69. }
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Purpose: sets up display for showing weapon pickup
  73. //-----------------------------------------------------------------------------
  74. void CHudWeaponSelection::OnWeaponSwitch( C_BaseCombatWeapon *pWeapon )
  75. {
  76. CWeaponCSBase* pCSWeapon = dynamic_cast<CWeaponCSBase*>( pWeapon );
  77. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  78. if ( pCSWeapon && pPlayer )
  79. {
  80. if ( pPlayer->State_Get() == STATE_ACTIVE )
  81. {
  82. SFWeaponSelection *pHudWS = GET_HUDELEMENT( SFWeaponSelection );
  83. if ( pHudWS )
  84. {
  85. pHudWS->ShowAndUpdateSelection( WEPSELECT_SWITCH, pWeapon );
  86. }
  87. }
  88. }
  89. }
  90. //-----------------------------------------------------------------------------
  91. // Purpose: updates animation status
  92. //-----------------------------------------------------------------------------
  93. void CHudWeaponSelection::OnThink()
  94. {
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose: returns true if the CHudMenu should take slot1, etc commands
  98. //-----------------------------------------------------------------------------
  99. bool CHudWeaponSelection::IsHudMenuTakingInput()
  100. {
  101. return CBaseHudWeaponSelection::IsHudMenuTakingInput();
  102. }
  103. //-----------------------------------------------------------------------------
  104. // Purpose: returns true if the weapon selection hud should be hidden because
  105. // the CHudMenu is open
  106. //-----------------------------------------------------------------------------
  107. bool CHudWeaponSelection::IsHudMenuPreventingWeaponSelection()
  108. {
  109. return false;
  110. }
  111. //-----------------------------------------------------------------------------
  112. // Purpose: returns true if the panel should draw
  113. //-----------------------------------------------------------------------------
  114. bool CHudWeaponSelection::ShouldDraw()
  115. {
  116. // [jason] Moving into Scaleform: sfhudhealthammopanel
  117. #if defined( CSTRIKE15 )
  118. if ( !IsPC() )
  119. {
  120. return false;
  121. }
  122. #endif
  123. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  124. if ( !pPlayer )
  125. {
  126. if ( IsInSelectionMode() )
  127. {
  128. HideSelection();
  129. }
  130. return false;
  131. }
  132. bool bret = CBaseHudWeaponSelection::ShouldDraw();
  133. if ( !bret )
  134. return false;
  135. return ( m_bSelectionVisible ) ? true : false;
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Purpose:
  139. //-----------------------------------------------------------------------------
  140. void CHudWeaponSelection::LevelInit()
  141. {
  142. CHudElement::LevelInit();
  143. m_iMaxSlots = clamp( m_iMaxSlots, 0, MAX_WEAPON_SLOTS );
  144. }
  145. //-------------------------------------------------------------------------
  146. // Purpose: draws the selection area
  147. //-------------------------------------------------------------------------
  148. void CHudWeaponSelection::Paint()
  149. {
  150. #if !defined( CSTRIKE15 )
  151. if (!ShouldDraw())
  152. return;
  153. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  154. if ( !pPlayer )
  155. return;
  156. // find and display our current selection
  157. C_BaseCombatWeapon *pSelectedWeapon = GetSelectedWeapon();
  158. if ( !pSelectedWeapon )
  159. return;
  160. int iActiveSlot = (pSelectedWeapon ? pSelectedWeapon->GetSlot() : -1);
  161. // interpolate the selected box size between the small box size and the large box size
  162. // interpolation has been removed since there is no weapon pickup animation anymore, so it's all at the largest size
  163. float percentageDone = 1.0f; //MIN(1.0f, (gpGlobals->curtime - m_flPickupStartTime) / m_flWeaponPickupGrowTime);
  164. int largeBoxWide = m_flSmallBoxSize + ((m_flLargeBoxWide - m_flSmallBoxSize) * percentageDone);
  165. int largeBoxTall = m_flSmallBoxSize + ((m_flLargeBoxTall - m_flSmallBoxSize) * percentageDone);
  166. Color selectedColor;
  167. {for (int i = 0; i < 4; i++)
  168. {
  169. selectedColor[i] = m_BoxColor[i] + ((m_SelectedBoxColor[i] - m_BoxColor[i]) * percentageDone);
  170. }}
  171. // calculate where to start drawing
  172. int width = (m_iMaxSlots - 1) * (m_flSmallBoxSize + m_flBoxGap) + largeBoxWide;
  173. int xpos = (GetWide() - width) / 2;
  174. int ypos = 0;
  175. // iterate over all the weapon slots
  176. for ( int i = 0; i < m_iMaxSlots; i++ )
  177. {
  178. if ( i == iActiveSlot )
  179. {
  180. bool bFirstItem = true;
  181. for (int slotpos = 0; slotpos < MAX_WEAPON_POSITIONS; slotpos++)
  182. {
  183. C_BaseCombatWeapon *pWeapon = GetWeaponInSlot(i, slotpos);
  184. if ( !pWeapon )
  185. continue;
  186. // draw selected weapon
  187. DrawBox(xpos, ypos, largeBoxWide, largeBoxTall, selectedColor, m_flSelectionAlphaOverride, bFirstItem ? i + 1 : -1);
  188. // draw icon
  189. Color col = GetFgColor();
  190. // icons use old system, drawing in screen space
  191. if ( pWeapon->GetSpriteActive() )
  192. {
  193. if (!pWeapon->CanBeSelected())
  194. {
  195. // unselectable weapon, display as such
  196. col = Color(255, 0, 0, col[3]);
  197. }
  198. else if (pWeapon == pSelectedWeapon)
  199. {
  200. // currently selected weapon, display brighter
  201. col[3] = m_flSelectionAlphaOverride;
  202. }
  203. pWeapon->GetSpriteActive()->DrawSelf( xpos + m_flIconXPos, ypos + m_flIconYPos, col );
  204. }
  205. // draw text
  206. col = m_TextColor;
  207. const FileWeaponInfo_t &weaponInfo = pWeapon->GetWpnData();
  208. if (pWeapon == pSelectedWeapon)
  209. {
  210. wchar_t text[128];
  211. wchar_t *tempString = g_pVGuiLocalize->Find(weaponInfo.szPrintName);
  212. // setup our localized string
  213. if ( tempString )
  214. {
  215. #ifdef WIN32
  216. _snwprintf(text, sizeof(text)/sizeof(wchar_t) - 1, L"%s", tempString);
  217. #else
  218. _snwprintf(text, sizeof(text)/sizeof(wchar_t) - 1, L"%S", tempString);
  219. #endif
  220. text[sizeof(text)/sizeof(wchar_t) - 1] = 0;
  221. }
  222. else
  223. {
  224. // string wasn't found by g_pVGuiLocalize->Find()
  225. g_pVGuiLocalize->ConvertANSIToUnicode(weaponInfo.szPrintName, text, sizeof(text));
  226. }
  227. surface()->DrawSetTextColor( col );
  228. surface()->DrawSetTextFont( m_hTextFont );
  229. // count the position
  230. int slen = 0, charCount = 0, maxslen = 0;
  231. {
  232. for (wchar_t *pch = text; *pch != 0; pch++)
  233. {
  234. if (*pch == '\n')
  235. {
  236. // newline character, drop to the next line
  237. if (slen > maxslen)
  238. {
  239. maxslen = slen;
  240. }
  241. slen = 0;
  242. }
  243. else if (*pch == '\r')
  244. {
  245. // do nothing
  246. }
  247. else
  248. {
  249. slen += surface()->GetCharacterWidth( m_hTextFont, *pch );
  250. charCount++;
  251. }
  252. }
  253. }
  254. if (slen > maxslen)
  255. {
  256. maxslen = slen;
  257. }
  258. int tx = xpos + ((largeBoxWide - maxslen) / 2);
  259. int ty = ypos + (int)m_flTextYPos;
  260. surface()->DrawSetTextPos( tx, ty );
  261. // adjust the charCount by the scan amount
  262. charCount *= m_flTextScan;
  263. for (wchar_t *pch = text; charCount > 0; pch++)
  264. {
  265. if (*pch == '\n')
  266. {
  267. // newline character, move to the next line
  268. surface()->DrawSetTextPos( xpos + ((largeBoxWide - slen) / 2), ty + (surface()->GetFontTall(m_hTextFont) * 1.1f));
  269. }
  270. else if (*pch == '\r')
  271. {
  272. // do nothing
  273. }
  274. else
  275. {
  276. surface()->DrawUnicodeChar(*pch);
  277. charCount--;
  278. }
  279. }
  280. }
  281. ypos += (largeBoxTall + m_flBoxGap);
  282. bFirstItem = false;
  283. }
  284. xpos += largeBoxWide;
  285. }
  286. else
  287. {
  288. // check to see if there is a weapons in this bucket
  289. if ( GetFirstPos( i ) )
  290. {
  291. // draw has weapon in slot
  292. DrawBox(xpos, ypos, m_flSmallBoxSize, m_flSmallBoxSize, m_BoxColor, m_flAlphaOverride, i + 1);
  293. }
  294. else
  295. {
  296. // draw empty slot
  297. DrawBox(xpos, ypos, m_flSmallBoxSize, m_flSmallBoxSize, m_EmptyBoxColor, m_flAlphaOverride, -1);
  298. }
  299. xpos += m_flSmallBoxSize;
  300. }
  301. // reset position
  302. ypos = 0;
  303. xpos += m_flBoxGap;
  304. }
  305. #endif // #if !defined( CSTRIKE15 )
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose: draws a selection box
  309. //-----------------------------------------------------------------------------
  310. void CHudWeaponSelection::DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, int number)
  311. {
  312. BaseClass::DrawBox( x, y, wide, tall, color, normalizedAlpha / 255.0f );
  313. // draw the number
  314. if (number >= 0)
  315. {
  316. Color numberColor = m_NumberColor;
  317. numberColor[3] *= normalizedAlpha / 255.0f;
  318. surface()->DrawSetTextColor(numberColor);
  319. surface()->DrawSetTextFont(m_hNumberFont);
  320. wchar_t wch = '0' + number;
  321. surface()->DrawSetTextPos(x + m_flSelectionNumberXPos, y + m_flSelectionNumberYPos);
  322. surface()->DrawUnicodeChar(wch);
  323. }
  324. }
  325. //-----------------------------------------------------------------------------
  326. // Purpose: hud scheme settings
  327. //-----------------------------------------------------------------------------
  328. void CHudWeaponSelection::ApplySchemeSettings(vgui::IScheme *pScheme)
  329. {
  330. BaseClass::ApplySchemeSettings(pScheme);
  331. SetPaintBackgroundEnabled(false);
  332. // set our size
  333. int screenWide, screenTall;
  334. int x, y;
  335. GetPos(x, y);
  336. GetHudSize(screenWide, screenTall);
  337. SetBounds(0, y, screenWide, screenTall - y);
  338. }
  339. //-----------------------------------------------------------------------------
  340. // Purpose: Opens weapon selection control
  341. //-----------------------------------------------------------------------------
  342. void CHudWeaponSelection::OpenSelection( void )
  343. {
  344. Assert(!IsInSelectionMode());
  345. CBaseHudWeaponSelection::OpenSelection();
  346. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("OpenWeaponSelectionMenu");
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Purpose: Closes weapon selection control
  350. //-----------------------------------------------------------------------------
  351. void CHudWeaponSelection::HideSelection( void )
  352. {
  353. CBaseHudWeaponSelection::HideSelection();
  354. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence("CloseWeaponSelectionMenu");
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose: Returns the next available weapon item in the weapon selection
  358. //-----------------------------------------------------------------------------
  359. C_BaseCombatWeapon *CHudWeaponSelection::FindNextWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition, WEAPON_SELECTION_MODE selectionMode /*WEAPON_SELECTION_NORMAL*/)
  360. {
  361. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  362. if ( !pPlayer )
  363. return NULL;
  364. C_BaseCombatWeapon *pNextWeapon = NULL;
  365. // search all the weapons looking for the closest next
  366. int iLowestNextSlot = MAX_WEAPON_SLOTS;
  367. int iLowestNextPosition = MAX_WEAPON_POSITIONS;
  368. for ( int i = 0; i < MAX_WEAPONS; i++ )
  369. {
  370. C_BaseCombatWeapon *pWeapon = pPlayer->GetWeapon(i);
  371. if ( !pWeapon )
  372. continue;
  373. if (selectionMode != WEAPON_SELECTION_NORMAL)
  374. {
  375. // skip over weapon types we arent including in this list
  376. CWeaponCSBase* pCSWeapon = dynamic_cast< CWeaponCSBase * >( pWeapon );
  377. if (!pCSWeapon)
  378. continue;
  379. bool isGrenade = pCSWeapon->IsKindOf( WEAPONTYPE_GRENADE );
  380. bool isBomb = pCSWeapon->IsKindOf( WEAPONTYPE_C4 );
  381. bool isStackable = pCSWeapon->IsKindOf( WEAPONTYPE_STACKABLEITEM );
  382. bool isMelee = pCSWeapon->IsKindOf( WEAPONTYPE_KNIFE );
  383. if ( ( selectionMode == WEAPON_SELECTION_GRENADE_AND_BOMB && !isGrenade && !isBomb ) ||
  384. ( selectionMode == WEAPON_SELECTION_GRENADE_AND_BOMB_AND_MELEE && !isGrenade && !isBomb && !isMelee ) ||
  385. ( selectionMode == WEAPON_SELECTION_NO_GRENADE_AND_BOMB && ( isGrenade || isBomb || isMelee ) ) ||
  386. ( selectionMode == WEAPON_SELECTION_GRENADE && !isGrenade ) ||
  387. ( selectionMode == WEAPON_SELECTION_MELEE && !isMelee ) ||
  388. ( selectionMode == WEAPON_SELECTION_ITEMSLOT && !isBomb && !isStackable ) )
  389. continue;
  390. }
  391. if ( pWeapon->CanBeSelected() )
  392. {
  393. int weaponSlot = pWeapon->GetSlot(), weaponPosition = pWeapon->GetPosition();
  394. // see if this weapon is further ahead in the selection list
  395. if ( weaponSlot > iCurrentSlot || (weaponSlot == iCurrentSlot && weaponPosition > iCurrentPosition) )
  396. {
  397. // see if this weapon is closer than the current lowest
  398. if ( weaponSlot < iLowestNextSlot || (weaponSlot == iLowestNextSlot && weaponPosition < iLowestNextPosition) )
  399. {
  400. iLowestNextSlot = weaponSlot;
  401. iLowestNextPosition = weaponPosition;
  402. pNextWeapon = pWeapon;
  403. }
  404. }
  405. }
  406. }
  407. return pNextWeapon;
  408. }
  409. //-----------------------------------------------------------------------------
  410. // Purpose: Returns the prior available weapon item in the weapon selection
  411. //-----------------------------------------------------------------------------
  412. C_BaseCombatWeapon *CHudWeaponSelection::FindPrevWeaponInWeaponSelection(int iCurrentSlot, int iCurrentPosition)
  413. {
  414. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  415. if ( !pPlayer )
  416. return NULL;
  417. C_BaseCombatWeapon *pPrevWeapon = NULL;
  418. // search all the weapons looking for the closest next
  419. int iLowestPrevSlot = -1;
  420. int iLowestPrevPosition = -1;
  421. for ( int i = 0; i < MAX_WEAPONS; i++ )
  422. {
  423. C_BaseCombatWeapon *pWeapon = pPlayer->GetWeapon(i);
  424. if ( !pWeapon )
  425. continue;
  426. if ( pWeapon->CanBeSelected() )
  427. {
  428. int weaponSlot = pWeapon->GetSlot(), weaponPosition = pWeapon->GetPosition();
  429. // see if this weapon is further ahead in the selection list
  430. if ( weaponSlot < iCurrentSlot || (weaponSlot == iCurrentSlot && weaponPosition < iCurrentPosition) )
  431. {
  432. // see if this weapon is closer than the current lowest
  433. if ( weaponSlot > iLowestPrevSlot || (weaponSlot == iLowestPrevSlot && weaponPosition > iLowestPrevPosition) )
  434. {
  435. iLowestPrevSlot = weaponSlot;
  436. iLowestPrevPosition = weaponPosition;
  437. pPrevWeapon = pWeapon;
  438. }
  439. }
  440. }
  441. }
  442. return pPrevWeapon;
  443. }
  444. //-----------------------------------------------------------------------------
  445. // Purpose: Moves the selection to the next item in the menu
  446. //-----------------------------------------------------------------------------
  447. void CHudWeaponSelection::CycleToNextWeapon( void )
  448. {
  449. CycleToNextWeapon(WEAPON_SELECTION_NORMAL);
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Purpose: Select the next grenade or bomb
  453. //-----------------------------------------------------------------------------
  454. void CHudWeaponSelection::CycleToNextGrenadeOrBomb( void )
  455. {
  456. CycleToNextWeapon(WEAPON_SELECTION_GRENADE_AND_BOMB);
  457. }
  458. //-----------------------------------------------------------------------------
  459. // Purpose: Select the next grenade or bomb
  460. //-----------------------------------------------------------------------------
  461. void CHudWeaponSelection::CycleToNextGrenadeBombOrMelee( void )
  462. {
  463. CycleToNextWeapon(WEAPON_SELECTION_GRENADE_AND_BOMB_AND_MELEE);
  464. }
  465. //-----------------------------------------------------------------------------
  466. // Purpose: Select the next pistol/gun/knife
  467. //-----------------------------------------------------------------------------
  468. void CHudWeaponSelection::CycleToNextNonGrenadeOrBomb( void )
  469. {
  470. CycleToNextWeapon(WEAPON_SELECTION_NO_GRENADE_AND_BOMB);
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Purpose: Select a weapon from nBucketID at the nSlotPos
  474. //-----------------------------------------------------------------------------
  475. void CHudWeaponSelection::SelectSpecificWeapon( CSWeaponID weaponID )
  476. {
  477. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  478. if ( !pPlayer )
  479. {
  480. return;
  481. }
  482. // Note[pfreese] This could probably just be replaced by a call to CBasePlayer::SelectItem().
  483. // It's interesting, and perhaps a bit worrying, that SelectItem() does additional
  484. // tests that the code in this file does not, such as verifying that the current
  485. // weapon can be holstered.
  486. //
  487. // Players who bind keys to the use command, e.g. "bind 6 use weapon_hegrenade" will
  488. // get weapons selected via the CBasePlayer::SelectItem() code path, which means they will
  489. // see slightly different behavior than players who switch weapons using the redirected
  490. // slotN commands above (the default configured through the Options UI.
  491. // get the weapon by ID if the player owns it
  492. CWeaponCSBase* pWeapon = pPlayer->GetCSWeapon(weaponID);
  493. if ( pWeapon != NULL )
  494. {
  495. // Make sure the player's allowed to switch weapons
  496. if ( pPlayer->IsAllowedToSwitchWeapons() == false )
  497. return;
  498. // Mark the change
  499. SetSelectedWeapon( pWeapon );
  500. SelectWeapon();
  501. if( m_bPlaySelectionSounds )
  502. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  503. }
  504. }
  505. void CHudWeaponSelection::SetSelectedWeapon( C_BaseCombatWeapon *pWeapon )
  506. {
  507. m_hSelectedWeapon = pWeapon;
  508. }
  509. // Switch to knife
  510. void CHudWeaponSelection::UserCmd_Slot3( void )
  511. {
  512. //SelectSpecificWeapon( WEAPON_KNIFE );
  513. CycleToNextWeapon( WEAPON_SELECTION_MELEE );
  514. }
  515. // Switch to breach charges
  516. void CHudWeaponSelection::UserCmd_Slot5( void )
  517. {
  518. CycleToNextWeapon( WEAPON_SELECTION_ITEMSLOT );
  519. }
  520. // Switch to hegrenade
  521. void CHudWeaponSelection::UserCmd_Slot6( void )
  522. {
  523. SelectSpecificWeapon( WEAPON_HEGRENADE );
  524. }
  525. // Switch to flashbang
  526. void CHudWeaponSelection::UserCmd_Slot7( void )
  527. {
  528. SelectSpecificWeapon( WEAPON_FLASHBANG );
  529. }
  530. // Switch to smoke grenade
  531. void CHudWeaponSelection::UserCmd_Slot8( void )
  532. {
  533. SelectSpecificWeapon( WEAPON_SMOKEGRENADE );
  534. }
  535. // Switch to decoy
  536. void CHudWeaponSelection::UserCmd_Slot9( void )
  537. {
  538. SelectSpecificWeapon( WEAPON_DECOY );
  539. }
  540. // Switch to molotov
  541. void CHudWeaponSelection::UserCmd_Slot10( void )
  542. {
  543. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  544. if ( !pPlayer )
  545. return;
  546. if ( pPlayer->HasWeaponOfType( WEAPON_MOLOTOV ) )
  547. SelectSpecificWeapon( WEAPON_MOLOTOV );
  548. else
  549. SelectSpecificWeapon( WEAPON_INCGRENADE );
  550. }
  551. // Switch to taser
  552. void CHudWeaponSelection::UserCmd_Slot11( void )
  553. {
  554. SelectSpecificWeapon( WEAPON_TASER );
  555. }
  556. // Cycle grenades
  557. void CHudWeaponSelection::UserCmd_Slot4( void )
  558. {
  559. CycleToNextWeapon( WEAPON_SELECTION_GRENADE );
  560. }
  561. void CHudWeaponSelection::UserCmd_GamePadSlot1( void )
  562. {
  563. SelectSpecificWeapon( WEAPON_TASER );
  564. }
  565. void CHudWeaponSelection::UserCmd_GamePadSlot2( void )
  566. {
  567. SelectSpecificWeapon( WEAPON_HEGRENADE );
  568. }
  569. void CHudWeaponSelection::UserCmd_GamePadSlot3( void )
  570. {
  571. SelectSpecificWeapon( WEAPON_FLASHBANG );
  572. }
  573. void CHudWeaponSelection::UserCmd_GamePadSlot4( void )
  574. {
  575. SelectSpecificWeapon( WEAPON_SMOKEGRENADE );
  576. }
  577. void CHudWeaponSelection::UserCmd_GamePadSlot5( void )
  578. {
  579. SelectSpecificWeapon( WEAPON_DECOY );
  580. }
  581. void CHudWeaponSelection::UserCmd_GamePadSlot6( void )
  582. {
  583. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  584. if ( !pPlayer )
  585. return;
  586. if ( pPlayer->HasWeaponOfType( WEAPON_MOLOTOV ) )
  587. SelectSpecificWeapon( WEAPON_MOLOTOV );
  588. else
  589. SelectSpecificWeapon( WEAPON_INCGRENADE );
  590. }
  591. //-----------------------------------------------------------------------------
  592. // Purpose: Moves the selection to the next item in the menu
  593. //-----------------------------------------------------------------------------
  594. void CHudWeaponSelection::CycleToNextWeapon(WEAPON_SELECTION_MODE selectionMode)
  595. {
  596. // Get the local player.
  597. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  598. if ( !pPlayer )
  599. return;
  600. C_BaseCombatWeapon *pNextWeapon = NULL;
  601. if ( IsInSelectionMode() )
  602. {
  603. // find the next selection spot
  604. C_BaseCombatWeapon *pWeapon = GetSelectedWeapon();
  605. if ( !pWeapon )
  606. return;
  607. pNextWeapon = FindNextWeaponInWeaponSelection( pWeapon->GetSlot(), pWeapon->GetPosition(), selectionMode );
  608. }
  609. else
  610. {
  611. // open selection at the current place
  612. pNextWeapon = pPlayer->GetActiveWeapon();
  613. if ( pNextWeapon )
  614. {
  615. pNextWeapon = FindNextWeaponInWeaponSelection( pNextWeapon->GetSlot(), pNextWeapon->GetPosition(), selectionMode );
  616. }
  617. }
  618. if ( !pNextWeapon )
  619. {
  620. // wrap around back to start
  621. pNextWeapon = FindNextWeaponInWeaponSelection(-1, -1, selectionMode);
  622. }
  623. if ( pNextWeapon )
  624. {
  625. SetSelectedWeapon( pNextWeapon );
  626. #if defined ( CSTRIKE15 )
  627. SelectWeapon();
  628. #else
  629. if( hud_fastswitch.GetInt() > 0 )
  630. {
  631. SelectWeapon();
  632. }
  633. else if ( !IsInSelectionMode() )
  634. {
  635. OpenSelection();
  636. }
  637. #endif
  638. // Play the "cycle to next weapon" sound
  639. if( m_bPlaySelectionSounds )
  640. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  641. }
  642. }
  643. //-----------------------------------------------------------------------------
  644. // Purpose: Moves the selection to the previous item in the menu
  645. //-----------------------------------------------------------------------------
  646. void CHudWeaponSelection::CycleToPrevWeapon( void )
  647. {
  648. // Get the local player.
  649. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  650. if ( !pPlayer )
  651. return;
  652. if ( pPlayer->IsPlayerDead() )
  653. return;
  654. C_BaseCombatWeapon *pNextWeapon = NULL;
  655. if ( IsInSelectionMode() )
  656. {
  657. // find the next selection spot
  658. C_BaseCombatWeapon *pWeapon = GetSelectedWeapon();
  659. if ( !pWeapon )
  660. return;
  661. pNextWeapon = FindPrevWeaponInWeaponSelection( pWeapon->GetSlot(), pWeapon->GetPosition() );
  662. }
  663. else
  664. {
  665. // open selection at the current place
  666. pNextWeapon = pPlayer->GetActiveWeapon();
  667. if ( pNextWeapon )
  668. {
  669. pNextWeapon = FindPrevWeaponInWeaponSelection( pNextWeapon->GetSlot(), pNextWeapon->GetPosition() );
  670. }
  671. }
  672. if ( !pNextWeapon )
  673. {
  674. // wrap around back to end of weapon list
  675. pNextWeapon = FindPrevWeaponInWeaponSelection(MAX_WEAPON_SLOTS, MAX_WEAPON_POSITIONS);
  676. }
  677. if ( pNextWeapon )
  678. {
  679. SetSelectedWeapon( pNextWeapon );
  680. #if defined ( CSTRIKE15 )
  681. SelectWeapon();
  682. #else
  683. if( hud_fastswitch.GetInt() > 0 )
  684. {
  685. SelectWeapon();
  686. }
  687. else if ( !IsInSelectionMode() )
  688. {
  689. OpenSelection();
  690. }
  691. #endif
  692. // Play the "cycle to next weapon" sound
  693. if( m_bPlaySelectionSounds )
  694. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  695. }
  696. }
  697. //-----------------------------------------------------------------------------
  698. // Purpose: Switches the last weapon the player was using
  699. //-----------------------------------------------------------------------------
  700. void CHudWeaponSelection::SwitchToLastWeapon( void )
  701. {
  702. // Get the player's last weapon
  703. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  704. if ( !player )
  705. return;
  706. if ( player->IsPlayerDead() )
  707. return;
  708. C_BaseCombatWeapon *lastWeapon = player->GetLastWeapon();
  709. C_BaseCombatWeapon *activeWeapon = player->GetActiveWeapon();
  710. if ( lastWeapon == activeWeapon )
  711. lastWeapon = NULL;
  712. // make sure our last weapon is still with us and valid (has ammo etc)
  713. if ( lastWeapon )
  714. {
  715. int i;
  716. for ( i = 0; i < MAX_WEAPONS; i++ )
  717. {
  718. C_BaseCombatWeapon *weapon = player->GetWeapon(i);
  719. if ( !weapon || !weapon->CanBeSelected() )
  720. continue;
  721. if (weapon == lastWeapon )
  722. break;
  723. }
  724. if ( i == MAX_WEAPONS )
  725. lastWeapon = NULL; // weapon not found/valid
  726. }
  727. // if we don't have a 'last weapon' choose best weapon
  728. if ( !lastWeapon )
  729. {
  730. lastWeapon = GameRules()->GetNextBestWeapon( player, activeWeapon );
  731. }
  732. ::input->MakeWeaponSelection( lastWeapon );
  733. }
  734. //-----------------------------------------------------------------------------
  735. // Purpose: returns the weapon in the specified slot
  736. //-----------------------------------------------------------------------------
  737. C_BaseCombatWeapon *CHudWeaponSelection::GetWeaponInSlot( int iSlot, int iSlotPos )
  738. {
  739. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  740. if ( !player )
  741. return NULL;
  742. if ( player->IsPlayerDead() )
  743. return NULL;
  744. for ( int i = 0; i < player->WeaponCount(); i++ )
  745. {
  746. C_BaseCombatWeapon *pWeapon = player->GetWeapon(i);
  747. if ( pWeapon == NULL )
  748. continue;
  749. if ( pWeapon->GetSlot() == iSlot && pWeapon->GetPosition() == iSlotPos )
  750. return pWeapon;
  751. }
  752. return NULL;
  753. }
  754. //-----------------------------------------------------------------------------
  755. // Purpose: returns the weapon in the specified slot
  756. //-----------------------------------------------------------------------------
  757. C_BaseCombatWeapon *CHudWeaponSelection::GetWeaponInSlotForTarget( C_BasePlayer *player, int iSlot, int iSlotPos )
  758. {
  759. C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
  760. if ( pLocalPlayer && pLocalPlayer == player )
  761. return GetWeaponInSlot( iSlot, iSlotPos );
  762. if ( !player )
  763. return NULL;
  764. if ( player->IsPlayerDead() )
  765. return NULL;
  766. for ( int i = 0; i < player->WeaponCount(); i++ )
  767. {
  768. C_BaseCombatWeapon *pWeapon = player->GetWeapon(i);
  769. if ( pWeapon == NULL )
  770. continue;
  771. if ( pWeapon->GetSlot() == iSlot && pWeapon->GetPosition() == iSlotPos )
  772. return pWeapon;
  773. }
  774. return NULL;
  775. }
  776. //-----------------------------------------------------------------------------
  777. // Purpose: Player has chosen to draw the currently selected weapon
  778. //-----------------------------------------------------------------------------
  779. void CHudWeaponSelection::SelectWeapon( void )
  780. {
  781. if ( !GetSelectedWeapon() )
  782. {
  783. engine->ClientCmd( "cancelselect\n" );
  784. return;
  785. }
  786. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  787. if ( !player )
  788. return;
  789. C_BaseCombatWeapon *activeWeapon = player->GetActiveWeapon();
  790. // Don't allow selections of weapons that can't be selected (out of ammo, etc)
  791. if ( !GetSelectedWeapon()->CanBeSelected() )
  792. {
  793. player->EmitSound( "Player.DenyWeaponSelection" );
  794. }
  795. else
  796. {
  797. // Only play the "weapon selected" sound if they are selecting
  798. // a weapon different than the one that is already active.
  799. if (GetSelectedWeapon() != activeWeapon)
  800. {
  801. if (player->GetTeamNumber() == TEAM_CT)
  802. {
  803. // Play the "weapon selected" sound
  804. player->EmitSound("Player.WeaponSelected_CT");
  805. }
  806. else
  807. {
  808. // Play the "weapon selected" sound
  809. player->EmitSound("Player.WeaponSelected_T");
  810. }
  811. }
  812. SetWeaponSelected();
  813. m_hSelectedWeapon = NULL;
  814. engine->ClientCmd( "cancelselect\n" );
  815. }
  816. }
  817. //-----------------------------------------------------------------------------
  818. // Purpose: Abort selecting a weapon
  819. //-----------------------------------------------------------------------------
  820. void CHudWeaponSelection::CancelWeaponSelection()
  821. {
  822. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  823. if ( !player )
  824. return;
  825. // Fastswitches happen in a single frame, so the Weapon Selection HUD Element isn't visible
  826. // yet, but it's going to be next frame. We need to ask it if it thinks it's going to draw,
  827. // instead of checking it's IsActive flag.
  828. if ( ShouldDraw() )
  829. {
  830. HideSelection();
  831. m_hSelectedWeapon = NULL;
  832. }
  833. else
  834. {
  835. // [pmf] The escape command causes the UI to be closed, which in turn causes an "unpause" command, which is blocked on multi-player games,
  836. // causing a warning. It seems like this escape command is only necessary when fast-switching is disabled. According to one of our designers,
  837. // we don't need non-fast-switching, so I'm removing this command injection to prevent the subsequent warning.
  838. // engine->ClientCmd("escape");
  839. }
  840. }
  841. //-----------------------------------------------------------------------------
  842. // Purpose: Moves selection to the specified slot
  843. //-----------------------------------------------------------------------------
  844. void CHudWeaponSelection::SelectWeaponSlot( int iSlot )
  845. {
  846. // iSlot is one higher than it should be, since it's the number key, not the 0-based index into the weapons
  847. --iSlot;
  848. // Get the local player.
  849. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  850. if ( !pPlayer )
  851. return;
  852. // Don't try and read past our possible number of slots
  853. if ( iSlot > MAX_WEAPON_SLOTS )
  854. return;
  855. // Make sure the player's allowed to switch weapons
  856. if ( pPlayer->IsAllowedToSwitchWeapons() == false )
  857. return;
  858. int slotPos = 0;
  859. C_BaseCombatWeapon *pActiveWeapon = GetSelectedWeapon();
  860. // start later in the list
  861. if ( IsInSelectionMode() && pActiveWeapon && pActiveWeapon->GetSlot() == iSlot )
  862. {
  863. slotPos = pActiveWeapon->GetPosition() + 1;
  864. }
  865. // find the weapon in this slot
  866. pActiveWeapon = GetNextActivePos( iSlot, slotPos );
  867. if ( !pActiveWeapon )
  868. {
  869. pActiveWeapon = GetNextActivePos( iSlot, 0 );
  870. }
  871. if ( pActiveWeapon != NULL )
  872. {
  873. // Mark the change
  874. SetSelectedWeapon( pActiveWeapon );
  875. bool bMultipleWeaponsInSlot = false;
  876. for( int i=0;i<MAX_WEAPON_POSITIONS;i++ )
  877. {
  878. C_BaseCombatWeapon *pSlotWpn = GetWeaponInSlot( pActiveWeapon->GetSlot(), i );
  879. if( pSlotWpn != NULL && pSlotWpn != pActiveWeapon )
  880. {
  881. bMultipleWeaponsInSlot = true;
  882. break;
  883. }
  884. }
  885. #if defined ( CSTRIKE15 )
  886. // only select if only one item in the bucket
  887. if( bMultipleWeaponsInSlot == false )
  888. {
  889. // only one active item in bucket, so change directly to weapon
  890. SelectWeapon();
  891. }
  892. #else
  893. // if fast weapon switch is on, then weapons can be selected in a single keypress
  894. // but only if there is only one item in the bucket
  895. if( hud_fastswitch.GetInt() > 0 && bMultipleWeaponsInSlot == false )
  896. {
  897. // only one active item in bucket, so change directly to weapon
  898. SelectWeapon();
  899. }
  900. else if ( !IsInSelectionMode() )
  901. {
  902. // open the weapon selection
  903. OpenSelection();
  904. }
  905. #endif
  906. }
  907. if( m_bPlaySelectionSounds )
  908. pPlayer->EmitSound( "Player.WeaponSelectionMoveSlot" );
  909. }