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.

577 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "weapon_csbase.h"
  8. #include "cs_ammodef.h"
  9. #include <vgui/IVGui.h>
  10. #include <vgui/IScheme.h>
  11. #include <vgui/ISurface.h>
  12. #include <vgui_controls/Label.h>
  13. #include <vgui/ILocalize.h>
  14. #include "vgui_controls/BuildGroup.h"
  15. #include "vgui_controls/BitmapImagePanel.h"
  16. #include "vgui_controls/TextEntry.h"
  17. #include "vgui_controls/TextImage.h"
  18. #include "vgui_controls/RichText.h"
  19. #include "vgui_controls/QueryBox.h"
  20. #include "career_box.h"
  21. #include "buypreset_listbox.h"
  22. #include "buypreset_weaponsetlabel.h"
  23. #include "cstrike/bot/shared_util.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include "tier0/memdbgon.h"
  26. using namespace vgui;
  27. //--------------------------------------------------------------------------------------------------------------
  28. //--------------------------------------------------------------------------------------------------------------
  29. WeaponImageInfo::WeaponImageInfo()
  30. {
  31. m_needLayout = m_isCentered = false;
  32. m_left = m_top = m_wide = m_tall = 0;
  33. m_isPrimary = false;
  34. memset( &m_weapon, 0, sizeof(ImageInfo) );
  35. memset( &m_ammo, 0, sizeof(ImageInfo) );
  36. m_weaponScale = m_ammoScale = 0;
  37. m_pAmmoText = new TextImage( "" );
  38. }
  39. //--------------------------------------------------------------------------------------------------------------
  40. WeaponImageInfo::~WeaponImageInfo()
  41. {
  42. delete m_pAmmoText;
  43. }
  44. //--------------------------------------------------------------------------------------------------------------
  45. void WeaponImageInfo::ApplyTextSettings( vgui::IScheme *pScheme, bool isProportional )
  46. {
  47. Color color = pScheme->GetColor( "FgColor", Color( 0, 0, 0, 0 ) );
  48. m_pAmmoText->SetColor( color );
  49. m_pAmmoText->SetFont( pScheme->GetFont( "Default", isProportional ) );
  50. m_pAmmoText->SetWrap( false );
  51. }
  52. //--------------------------------------------------------------------------------------------------------------
  53. void WeaponImageInfo::SetBounds( int left, int top, int wide, int tall )
  54. {
  55. m_left = left;
  56. m_top = top;
  57. m_wide = wide;
  58. m_tall = tall;
  59. m_needLayout = true;
  60. }
  61. //--------------------------------------------------------------------------------------------------------------
  62. void WeaponImageInfo::SetCentered( bool isCentered )
  63. {
  64. m_isCentered = isCentered;
  65. m_needLayout = true;
  66. }
  67. //--------------------------------------------------------------------------------------------------------------
  68. void WeaponImageInfo::SetScaleAt1024( int weaponScale, int ammoScale )
  69. {
  70. m_weaponScale = weaponScale;
  71. m_ammoScale = ammoScale;
  72. m_needLayout = true;
  73. }
  74. //--------------------------------------------------------------------------------------------------------------
  75. void WeaponImageInfo::SetWeapon( const BuyPresetWeapon *pWeapon, bool isPrimary, bool useCurrentAmmoType )
  76. {
  77. m_pAmmoText->SetText( L"" );
  78. m_weapon.image = NULL;
  79. m_ammo.image = NULL;
  80. m_isPrimary = isPrimary;
  81. if ( !pWeapon )
  82. return;
  83. wchar_t *multiplierString = g_pVGuiLocalize->Find("#Cstrike_BuyMenuPresetMultiplier");
  84. if ( !multiplierString )
  85. multiplierString = L"";
  86. const int BufLen = 32;
  87. wchar_t buf[BufLen];
  88. if ( pWeapon->GetAmmoType() == AMMO_CLIPS )
  89. {
  90. CSWeaponID weaponID = pWeapon->GetWeaponID();
  91. const CCSWeaponInfo *info = GetWeaponInfo( weaponID );
  92. int numClips = pWeapon->GetAmmoAmount();
  93. if ( info )
  94. {
  95. int maxRounds = GetCSAmmoDef()->MaxCarry( info->iAmmoType );
  96. int buyClipSize = GetCSAmmoDef()->GetBuySize( info->iAmmoType );
  97. int maxClips = (buyClipSize > 0) ? ceil(maxRounds/(float)buyClipSize) : 0;
  98. numClips = MIN( numClips, maxClips );
  99. m_weapon.image = scheme()->GetImage( ImageFnameFromWeaponID( weaponID, m_isPrimary ), true );
  100. if ( numClips == 0 )
  101. {
  102. m_ammo.image = NULL;
  103. }
  104. else if ( info->m_WeaponType == WEAPONTYPE_SHOTGUN )
  105. {
  106. m_ammo.image = scheme()->GetImage( "gfx/vgui/shell", true );
  107. }
  108. else if ( isPrimary )
  109. {
  110. m_ammo.image = scheme()->GetImage( "gfx/vgui/bullet", true );
  111. }
  112. else
  113. {
  114. m_ammo.image = scheme()->GetImage( "gfx/vgui/cartridge", true );
  115. }
  116. if ( numClips > 1 )
  117. {
  118. g_pVGuiLocalize->ConstructString( buf, sizeof(buf), multiplierString, 1, NumAsWString( numClips ) );
  119. m_pAmmoText->SetText( buf );
  120. }
  121. else
  122. {
  123. m_pAmmoText->SetText( L"" );
  124. }
  125. }
  126. else if ( numClips > 0 || !useCurrentAmmoType )
  127. {
  128. if ( useCurrentAmmoType )
  129. {
  130. CSWeaponID currentID = GetClientWeaponID( isPrimary );
  131. m_weapon.image = scheme()->GetImage( ImageFnameFromWeaponID( currentID, m_isPrimary ), true );
  132. info = GetWeaponInfo( currentID );
  133. if ( !info )
  134. {
  135. m_weapon.image = NULL;
  136. numClips = 0;
  137. }
  138. else if ( info->m_WeaponType == WEAPONTYPE_SHOTGUN )
  139. {
  140. m_ammo.image = scheme()->GetImage( "gfx/vgui/shell", true );
  141. }
  142. else if ( isPrimary )
  143. {
  144. m_ammo.image = scheme()->GetImage( "gfx/vgui/bullet", true );
  145. }
  146. else
  147. {
  148. m_ammo.image = scheme()->GetImage( "gfx/vgui/cartridge", true );
  149. }
  150. }
  151. else
  152. {
  153. m_weapon.image = scheme()->GetImage( ImageFnameFromWeaponID( weaponID, m_isPrimary ), true );
  154. if ( numClips == 0 )
  155. {
  156. m_ammo.image = NULL;
  157. }
  158. else if ( isPrimary )
  159. {
  160. m_ammo.image = scheme()->GetImage( "gfx/vgui/bullet", true );
  161. }
  162. else
  163. {
  164. m_ammo.image = scheme()->GetImage( "gfx/vgui/cartridge", true );
  165. }
  166. }
  167. if ( numClips > 1 )
  168. {
  169. g_pVGuiLocalize->ConstructString( buf, sizeof(buf), multiplierString, 1, NumAsWString( numClips ) );
  170. m_pAmmoText->SetText( buf );
  171. }
  172. else
  173. {
  174. m_pAmmoText->SetText( L"" );
  175. }
  176. }
  177. }
  178. m_needLayout = true;
  179. }
  180. //--------------------------------------------------------------------------------------------------------------
  181. void WeaponImageInfo::Paint()
  182. {
  183. if ( m_needLayout )
  184. PerformLayout();
  185. m_weapon.Paint();
  186. m_ammo.Paint();
  187. }
  188. //--------------------------------------------------------------------------------------------------------------
  189. void WeaponImageInfo::PaintText()
  190. {
  191. if ( m_needLayout )
  192. PerformLayout();
  193. m_pAmmoText->Paint();
  194. }
  195. //--------------------------------------------------------------------------------------------------------------
  196. void WeaponImageInfo::PerformLayout()
  197. {
  198. m_needLayout = false;
  199. m_weapon.FitInBounds( m_left, m_top, m_wide*0.8, m_tall, m_isCentered, m_weaponScale );
  200. int ammoX = MIN( m_wide*5/6, m_weapon.w );
  201. int ammoSize = m_tall * 9 / 16;
  202. if ( !m_isPrimary )
  203. {
  204. ammoSize = ammoSize * 25 / 40;
  205. ammoX = MIN( m_wide*5/6, m_weapon.w*3/4 );
  206. }
  207. if ( ammoX + ammoSize > m_wide )
  208. {
  209. ammoX = m_wide - ammoSize;
  210. }
  211. m_ammo.FitInBounds( m_left + ammoX, m_top + m_tall - ammoSize, ammoSize, ammoSize, false, m_ammoScale );
  212. int w, h;
  213. m_pAmmoText->ResizeImageToContent();
  214. m_pAmmoText->GetSize( w, h );
  215. if ( m_isPrimary )
  216. {
  217. if ( m_ammoScale < 75 )
  218. {
  219. m_pAmmoText->SetPos( m_left + ammoX + ammoSize*1.25f - w, m_top + m_tall - h );
  220. }
  221. else
  222. {
  223. m_pAmmoText->SetPos( m_left + ammoX + ammoSize - w, m_top + m_tall - h );
  224. }
  225. }
  226. else
  227. {
  228. m_pAmmoText->SetPos( m_left + ammoX + ammoSize, m_top + m_tall - h );
  229. }
  230. }
  231. //--------------------------------------------------------------------------------------------------------------
  232. //--------------------------------------------------------------------------------------------------------------
  233. WeaponLabel::WeaponLabel(Panel *parent, const char *panelName) : BaseClass( parent, panelName )
  234. {
  235. SetSize( 10, 10 );
  236. SetMouseInputEnabled( false );
  237. }
  238. //--------------------------------------------------------------------------------------------------------------
  239. WeaponLabel::~WeaponLabel()
  240. {
  241. }
  242. //--------------------------------------------------------------------------------------------------------------
  243. void WeaponLabel::SetWeapon( const BuyPresetWeapon *pWeapon, bool isPrimary, bool showAmmo )
  244. {
  245. BuyPresetWeapon weapon(WEAPON_NONE);
  246. if ( pWeapon )
  247. weapon = *pWeapon;
  248. if ( !showAmmo )
  249. weapon.SetAmmoAmount( 0 );
  250. m_weapon.SetWeapon( &weapon, isPrimary, false );
  251. }
  252. //--------------------------------------------------------------------------------------------------------------
  253. void WeaponLabel::ApplySchemeSettings(IScheme *pScheme)
  254. {
  255. BaseClass::ApplySchemeSettings( pScheme );
  256. m_weapon.ApplyTextSettings( pScheme, IsProportional() );
  257. }
  258. //--------------------------------------------------------------------------------------------------------------
  259. void WeaponLabel::PerformLayout()
  260. {
  261. BaseClass::PerformLayout();
  262. int wide, tall;
  263. GetSize( wide, tall );
  264. m_weapon.SetBounds( 0, 0, wide, tall );
  265. }
  266. //--------------------------------------------------------------------------------------------------------------
  267. void WeaponLabel::Paint()
  268. {
  269. BaseClass::Paint();
  270. m_weapon.Paint();
  271. m_weapon.PaintText();
  272. }
  273. //--------------------------------------------------------------------------------------------------------------
  274. //--------------------------------------------------------------------------------------------------------------
  275. ItemImageInfo::ItemImageInfo()
  276. {
  277. m_needLayout = false;
  278. m_left = m_top = m_wide = m_tall = 0;
  279. m_count = 0;
  280. memset( &m_image, 0, sizeof(ImageInfo) );
  281. m_pText = new TextImage( "" );
  282. SetBounds( 0, 0, 100, 100 );
  283. }
  284. //--------------------------------------------------------------------------------------------------------------
  285. ItemImageInfo::~ItemImageInfo()
  286. {
  287. delete m_pText;
  288. }
  289. //--------------------------------------------------------------------------------------------------------------
  290. void ItemImageInfo::ApplyTextSettings( vgui::IScheme *pScheme, bool isProportional )
  291. {
  292. Color color = pScheme->GetColor( "Label.TextColor", Color( 0, 0, 0, 0 ) );
  293. m_pText->SetColor( color );
  294. m_pText->SetFont( pScheme->GetFont( "Default", isProportional ) );
  295. m_pText->SetWrap( false );
  296. }
  297. //--------------------------------------------------------------------------------------------------------------
  298. void ItemImageInfo::SetBounds( int left, int top, int wide, int tall )
  299. {
  300. m_left = left;
  301. m_top = top;
  302. m_wide = wide;
  303. m_tall = tall;
  304. m_needLayout = true;
  305. }
  306. //--------------------------------------------------------------------------------------------------------------
  307. void ItemImageInfo::SetItem( const char *imageFname, int count )
  308. {
  309. m_pText->SetText( L"" );
  310. m_count = count;
  311. if ( imageFname )
  312. m_image.image = scheme()->GetImage( imageFname, true );
  313. else
  314. m_image.image = NULL;
  315. if ( count > 1 )
  316. {
  317. wchar_t *multiplierString = g_pVGuiLocalize->Find("#Cstrike_BuyMenuPresetMultiplier");
  318. if ( !multiplierString )
  319. multiplierString = L"";
  320. const int BufLen = 32;
  321. wchar_t buf[BufLen];
  322. g_pVGuiLocalize->ConstructString( buf, sizeof(buf), multiplierString, 1, NumAsWString( count ) );
  323. m_pText->SetText( buf );
  324. }
  325. m_needLayout = true;
  326. }
  327. //--------------------------------------------------------------------------------------------------------------
  328. void ItemImageInfo::Paint()
  329. {
  330. if ( m_needLayout )
  331. PerformLayout();
  332. if ( m_count )
  333. m_image.Paint();
  334. }
  335. //--------------------------------------------------------------------------------------------------------------
  336. void ItemImageInfo::PaintText()
  337. {
  338. if ( m_needLayout )
  339. PerformLayout();
  340. m_pText->Paint();
  341. }
  342. //--------------------------------------------------------------------------------------------------------------
  343. void ItemImageInfo::PerformLayout()
  344. {
  345. m_needLayout = false;
  346. m_image.FitInBounds( m_left, m_top, m_wide, m_tall, false, 0 );
  347. int w, h;
  348. m_pText->ResizeImageToContent();
  349. m_pText->GetSize( w, h );
  350. m_pText->SetPos( m_left + m_image.w - w, m_top + m_tall - h );
  351. }
  352. //--------------------------------------------------------------------------------------------------------------
  353. //--------------------------------------------------------------------------------------------------------------
  354. EquipmentLabel::EquipmentLabel(Panel *parent, const char *panelName, const char *imageFname) : BaseClass( parent, panelName )
  355. {
  356. SetSize( 10, 10 );
  357. m_item.SetItem( imageFname, 0 );
  358. SetMouseInputEnabled( false );
  359. }
  360. //--------------------------------------------------------------------------------------------------------------
  361. EquipmentLabel::~EquipmentLabel()
  362. {
  363. }
  364. //--------------------------------------------------------------------------------------------------------------
  365. void EquipmentLabel::SetItem( const char *imageFname, int count )
  366. {
  367. m_item.SetItem( imageFname, count );
  368. }
  369. //--------------------------------------------------------------------------------------------------------------
  370. void EquipmentLabel::ApplySchemeSettings(IScheme *pScheme)
  371. {
  372. BaseClass::ApplySchemeSettings( pScheme );
  373. m_item.ApplyTextSettings( pScheme, IsProportional() );
  374. }
  375. //--------------------------------------------------------------------------------------------------------------
  376. void EquipmentLabel::PerformLayout()
  377. {
  378. BaseClass::PerformLayout();
  379. int wide, tall;
  380. GetSize( wide, tall );
  381. m_item.SetBounds( 0, 0, wide, tall );
  382. }
  383. //--------------------------------------------------------------------------------------------------------------
  384. void EquipmentLabel::Paint()
  385. {
  386. BaseClass::Paint();
  387. m_item.Paint();
  388. m_item.PaintText();
  389. }
  390. //--------------------------------------------------------------------------------------------------------------
  391. //--------------------------------------------------------------------------------------------------------------
  392. /// Helper function: draws a simple dashed line
  393. void DrawDashedLine(int x0, int y0, int x1, int y1, int dashLen, int gapLen)
  394. {
  395. // work out which way the line goes
  396. if ((x1 - x0) > (y1 - y0))
  397. {
  398. // x direction line
  399. while (1)
  400. {
  401. if (x0 + dashLen > x1)
  402. {
  403. // draw partial
  404. surface()->DrawFilledRect(x0, y0, x1, y1+1);
  405. }
  406. else
  407. {
  408. surface()->DrawFilledRect(x0, y0, x0 + dashLen, y1+1);
  409. }
  410. x0 += dashLen;
  411. if (x0 + gapLen > x1)
  412. break;
  413. x0 += gapLen;
  414. }
  415. }
  416. else
  417. {
  418. // y direction
  419. while (1)
  420. {
  421. if (y0 + dashLen > y1)
  422. {
  423. // draw partial
  424. surface()->DrawFilledRect(x0, y0, x1+1, y1);
  425. }
  426. else
  427. {
  428. surface()->DrawFilledRect(x0, y0, x1+1, y0 + dashLen);
  429. }
  430. y0 += dashLen;
  431. if (y0 + gapLen > y1)
  432. break;
  433. y0 += gapLen;
  434. }
  435. }
  436. }
  437. //--------------------------------------------------------------------------------------------------------------
  438. //--------------------------------------------------------------------------------------------------------------
  439. void ImageInfo::Paint()
  440. {
  441. if ( !image )
  442. return;
  443. image->SetSize( w, h );
  444. image->SetPos( x, y );
  445. image->Paint();
  446. image->SetSize( 0, 0 ); // restore image size to content size to not mess up other places that use the same image
  447. }
  448. //--------------------------------------------------------------------------------------------------------------
  449. void ImageInfo::FitInBounds( int baseX, int baseY, int width, int height, bool center, int scaleAt1024, bool halfHeight )
  450. {
  451. if ( !image )
  452. {
  453. x = y = w = h = 0;
  454. return;
  455. }
  456. image->GetContentSize(fullW, fullH);
  457. if ( scaleAt1024 )
  458. {
  459. int screenW, screenH;
  460. GetHudSize( screenW, screenH );
  461. w = fullW * screenW / 1024 * scaleAt1024 / 100;
  462. h = fullH * screenW / 1024 * scaleAt1024 / 100;
  463. if ( fullH > 64 && scaleAt1024 == 100 )
  464. {
  465. w = w * 64 / fullH;
  466. h = h * 64 / fullH;
  467. }
  468. if ( h > height * 1.2 )
  469. scaleAt1024 = 0;
  470. }
  471. if ( !scaleAt1024 )
  472. {
  473. w = fullW;
  474. h = fullH;
  475. if ( h != height )
  476. {
  477. w = (int) w * 1.0f * height / h;
  478. h = height;
  479. }
  480. if ( w > width )
  481. {
  482. h = (int) h * 1.0f * width / w;
  483. w = width;
  484. }
  485. }
  486. if ( center )
  487. {
  488. x = baseX + (width - w)/2;
  489. }
  490. else
  491. {
  492. x = baseX;
  493. }
  494. y = baseY + (height - h)/2;
  495. }
  496. //--------------------------------------------------------------------------------------------------------------