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.

442 lines
13 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Item pickup history displayed onscreen when items are picked up.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "history_resource.h"
  9. #include "hud_macros.h"
  10. #include <vgui_controls/Controls.h>
  11. #include <vgui/ILocalize.h>
  12. #include <vgui/ISurface.h>
  13. #include "iclientmode.h"
  14. #include "vgui_controls/AnimationController.h"
  15. // memdbgon must be the last include file in a .cpp file!!!
  16. #include "tier0/memdbgon.h"
  17. using namespace vgui;
  18. extern ConVar hud_drawhistory_time;
  19. #if !defined ( INCLUDE_SCALEFORM )
  20. DECLARE_HUDELEMENT( CHudHistoryResource );
  21. #endif //INCLUDE_SCALEFORM
  22. DECLARE_HUD_MESSAGE( CHudHistoryResource, ItemPickup );
  23. DECLARE_HUD_MESSAGE( CHudHistoryResource, AmmoDenied );
  24. //-----------------------------------------------------------------------------
  25. // Purpose: Constructor
  26. //-----------------------------------------------------------------------------
  27. CHudHistoryResource::CHudHistoryResource( const char *pElementName ) :
  28. CHudElement( pElementName ), BaseClass( NULL, "HudHistoryResource" )
  29. {
  30. vgui::Panel *pParent = GetClientMode()->GetViewport();
  31. SetParent( pParent );
  32. m_bDoNotDraw = true;
  33. m_wcsAmmoFullMsg[0] = 0;
  34. m_bNeedsDraw = false;
  35. SetHiddenBits( HIDEHUD_MISCSTATUS );
  36. }
  37. //-----------------------------------------------------------------------------
  38. // Purpose:
  39. //-----------------------------------------------------------------------------
  40. void CHudHistoryResource::ApplySchemeSettings( IScheme *pScheme )
  41. {
  42. BaseClass::ApplySchemeSettings( pScheme );
  43. SetPaintBackgroundEnabled( false );
  44. // lookup text to display for ammo full message
  45. wchar_t *wcs = g_pVGuiLocalize->Find("#hl2_AmmoFull");
  46. if (wcs)
  47. {
  48. wcsncpy(m_wcsAmmoFullMsg, wcs, sizeof(m_wcsAmmoFullMsg) / sizeof(wchar_t));
  49. }
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Purpose:
  53. //-----------------------------------------------------------------------------
  54. void CHudHistoryResource::Init( void )
  55. {
  56. HOOK_HUD_MESSAGE( CHudHistoryResource, ItemPickup );
  57. HOOK_HUD_MESSAGE( CHudHistoryResource, AmmoDenied );
  58. Reset();
  59. }
  60. //-----------------------------------------------------------------------------
  61. // Purpose:
  62. //-----------------------------------------------------------------------------
  63. void CHudHistoryResource::Reset( void )
  64. {
  65. m_PickupHistory.RemoveAll();
  66. m_iCurrentHistorySlot = 0;
  67. m_bDoNotDraw = true;
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Purpose: these kept only for hl1-port compatibility
  71. //-----------------------------------------------------------------------------
  72. void CHudHistoryResource::SetHistoryGap( int iNewHistoryGap )
  73. {
  74. }
  75. //-----------------------------------------------------------------------------
  76. // Purpose: adds an element to the history
  77. //-----------------------------------------------------------------------------
  78. void CHudHistoryResource::AddToHistory( C_BaseCombatWeapon *weapon )
  79. {
  80. // don't draw exhaustable weapons (grenades) since they'll have an ammo pickup icon as well
  81. if ( weapon->GetWpnData().iFlags & ITEM_FLAG_EXHAUSTIBLE )
  82. return;
  83. int iId = weapon->entindex();
  84. // don't show the same weapon twice
  85. for ( int i = 0; i < m_PickupHistory.Count(); i++ )
  86. {
  87. if ( m_PickupHistory[i].iId == iId )
  88. {
  89. // it's already in list
  90. return;
  91. }
  92. }
  93. AddIconToHistory( HISTSLOT_WEAP, iId, weapon, 0, NULL );
  94. }
  95. //-----------------------------------------------------------------------------
  96. // Purpose: Add a new entry to the pickup history
  97. //-----------------------------------------------------------------------------
  98. void CHudHistoryResource::AddToHistory( int iType, int iId, int iCount )
  99. {
  100. // Ignore adds with no count
  101. if ( iType == HISTSLOT_AMMO )
  102. {
  103. if ( !iCount )
  104. return;
  105. // clear out any ammo pickup denied icons, since we can obviously pickup again
  106. for ( int i = 0; i < m_PickupHistory.Count(); i++ )
  107. {
  108. if ( m_PickupHistory[i].type == HISTSLOT_AMMODENIED && m_PickupHistory[i].iId == iId )
  109. {
  110. // kill the old entry
  111. m_PickupHistory[i].DisplayTime = 0.0f;
  112. // change the pickup to be in this entry
  113. m_iCurrentHistorySlot = i;
  114. break;
  115. }
  116. }
  117. }
  118. AddIconToHistory( iType, iId, NULL, iCount, NULL );
  119. }
  120. //-----------------------------------------------------------------------------
  121. // Purpose: Add a new entry to the pickup history
  122. //-----------------------------------------------------------------------------
  123. void CHudHistoryResource::AddToHistory( int iType, const char *szName, int iCount )
  124. {
  125. if ( iType != HISTSLOT_ITEM )
  126. return;
  127. // Get the item's icon
  128. CHudTexture *i = HudIcons().GetIcon( szName );
  129. if ( i == NULL )
  130. return;
  131. AddIconToHistory( iType, 1, NULL, iCount, i );
  132. }
  133. //-----------------------------------------------------------------------------
  134. // Purpose: adds a history icon
  135. //-----------------------------------------------------------------------------
  136. void CHudHistoryResource::AddIconToHistory( int iType, int iId, C_BaseCombatWeapon *weapon, int iCount, CHudTexture *icon )
  137. {
  138. m_bNeedsDraw = true;
  139. // Check to see if the pic would have to be drawn too high. If so, start again from the bottom
  140. if ( (m_flHistoryGap * (m_iCurrentHistorySlot+1)) > GetTall() )
  141. {
  142. m_iCurrentHistorySlot = 0;
  143. }
  144. // If the history resource is appearing, slide the hint message element down
  145. if ( m_iCurrentHistorySlot == 0 )
  146. {
  147. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence( "HintMessageLower" );
  148. }
  149. // ensure the size
  150. m_PickupHistory.EnsureCount(m_iCurrentHistorySlot + 1);
  151. // default to just writing to the first slot
  152. HIST_ITEM *freeslot = &m_PickupHistory[m_iCurrentHistorySlot++];
  153. if ( iType == HISTSLOT_AMMODENIED && freeslot->DisplayTime )
  154. {
  155. // don't override existing pickup icons with denied icons
  156. return;
  157. }
  158. freeslot->iId = iId;
  159. freeslot->icon = icon;
  160. freeslot->type = iType;
  161. freeslot->m_hWeapon = weapon;
  162. freeslot->iCount = iCount;
  163. if (iType == HISTSLOT_AMMODENIED)
  164. {
  165. freeslot->DisplayTime = gpGlobals->curtime + (hud_drawhistory_time.GetFloat() / 2.0f);
  166. }
  167. else
  168. {
  169. freeslot->DisplayTime = gpGlobals->curtime + hud_drawhistory_time.GetFloat();
  170. }
  171. }
  172. //-----------------------------------------------------------------------------
  173. // Purpose: Handle an item pickup event from the server
  174. //-----------------------------------------------------------------------------
  175. bool CHudHistoryResource::MsgFunc_ItemPickup( const CCSUsrMsg_ItemPickup &msg )
  176. {
  177. // Add the item to the history
  178. AddToHistory( HISTSLOT_ITEM, msg.item().c_str() );
  179. return true;
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Purpose: ammo denied message
  183. //-----------------------------------------------------------------------------
  184. bool CHudHistoryResource::MsgFunc_AmmoDenied( const CCSUsrMsg_AmmoDenied &msg )
  185. {
  186. int iAmmo = msg.ammoidx();
  187. // see if there are any existing ammo items of that type
  188. for ( int i = 0; i < m_PickupHistory.Count(); i++ )
  189. {
  190. if ( m_PickupHistory[i].type == HISTSLOT_AMMO && m_PickupHistory[i].iId == iAmmo )
  191. {
  192. // it's already in the list as a pickup, ignore
  193. return true;
  194. }
  195. }
  196. // see if there are any denied ammo icons, if so refresh their timer
  197. for ( int i = 0; i < m_PickupHistory.Count(); i++ )
  198. {
  199. if ( m_PickupHistory[i].type == HISTSLOT_AMMODENIED && m_PickupHistory[i].iId == iAmmo )
  200. {
  201. // it's already in the list, refresh
  202. m_PickupHistory[i].DisplayTime = gpGlobals->curtime + (hud_drawhistory_time.GetFloat() / 2.0f);
  203. m_bNeedsDraw = true;
  204. return true;
  205. }
  206. }
  207. // add into the list
  208. AddToHistory( HISTSLOT_AMMODENIED, iAmmo, 0 );
  209. return true;
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Purpose: If there aren't any items in the history, clear it out.
  213. //-----------------------------------------------------------------------------
  214. void CHudHistoryResource::CheckClearHistory( void )
  215. {
  216. for ( int i = 0; i < m_PickupHistory.Count(); i++ )
  217. {
  218. if ( m_PickupHistory[i].type )
  219. return;
  220. }
  221. m_iCurrentHistorySlot = 0;
  222. // Slide the hint message element back up
  223. GetClientMode()->GetViewportAnimationController()->StartAnimationSequence( "HintMessageRaise" );
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Purpose: Save CPU cycles by letting the HUD system early cull
  227. // costly traversal. Called per frame, return true if thinking and
  228. // painting need to occur.
  229. //-----------------------------------------------------------------------------
  230. bool CHudHistoryResource::ShouldDraw( void )
  231. {
  232. #ifdef TF_CLIENT_DLL
  233. return false;
  234. #else
  235. return ( ( m_iCurrentHistorySlot > 0 || m_bNeedsDraw ) && CHudElement::ShouldDraw() );
  236. #endif
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Purpose: Draw the pickup history
  240. //-----------------------------------------------------------------------------
  241. void CHudHistoryResource::Paint( void )
  242. {
  243. if ( m_bDoNotDraw )
  244. {
  245. // this is to not draw things until the first rendered
  246. m_bDoNotDraw = false;
  247. return;
  248. }
  249. // set when drawing should occur
  250. // will be set if valid drawing does occur
  251. m_bNeedsDraw = false;
  252. int wide, tall;
  253. GetSize( wide, tall );
  254. for ( int i = 0; i < m_PickupHistory.Count(); i++ )
  255. {
  256. if ( m_PickupHistory[i].type )
  257. {
  258. m_PickupHistory[i].DisplayTime = MIN( m_PickupHistory[i].DisplayTime, gpGlobals->curtime + hud_drawhistory_time.GetFloat() );
  259. if ( m_PickupHistory[i].DisplayTime <= gpGlobals->curtime )
  260. {
  261. // pic drawing time has expired
  262. memset( &m_PickupHistory[i], 0, sizeof(HIST_ITEM) );
  263. CheckClearHistory();
  264. continue;
  265. }
  266. float elapsed = m_PickupHistory[i].DisplayTime - gpGlobals->curtime;
  267. float scale = elapsed * 80;
  268. Color clr = GetHud().m_clrNormal;
  269. clr[3] = MIN( scale, 255 );
  270. bool bUseAmmoFullMsg = false;
  271. // get the icon and number to draw
  272. const CHudTexture *itemIcon = NULL;
  273. const CHudTexture *itemAmmoIcon = NULL;
  274. int iAmount = 0;
  275. bool bHalfHeight = true;
  276. switch ( m_PickupHistory[i].type )
  277. {
  278. case HISTSLOT_AMMO:
  279. {
  280. // Get the weapon we belong to
  281. const FileWeaponInfo_t *pWpnInfo = gWR.GetWeaponFromAmmo( m_PickupHistory[i].iId );
  282. if ( pWpnInfo && ( pWpnInfo->iMaxClip1 >= 0 || pWpnInfo->iMaxClip2 >= 0 ) )
  283. {
  284. // The weapon will be the main icon, and the ammo the smaller
  285. itemIcon = pWpnInfo->iconSmall;
  286. itemAmmoIcon = gWR.GetAmmoIconFromWeapon( m_PickupHistory[i].iId );
  287. }
  288. else
  289. {
  290. itemIcon = gWR.GetAmmoIconFromWeapon( m_PickupHistory[i].iId );
  291. itemAmmoIcon = NULL;
  292. }
  293. iAmount = m_PickupHistory[i].iCount;
  294. }
  295. break;
  296. case HISTSLOT_AMMODENIED:
  297. {
  298. itemIcon = gWR.GetAmmoIconFromWeapon( m_PickupHistory[i].iId );
  299. iAmount = 0;
  300. bUseAmmoFullMsg = true;
  301. // display as red
  302. clr = GetHud().m_clrCaution;
  303. clr[3] = MIN( scale, 255 );
  304. }
  305. break;
  306. case HISTSLOT_WEAP:
  307. {
  308. C_BaseCombatWeapon *pWeapon = m_PickupHistory[i].m_hWeapon;
  309. if ( !pWeapon )
  310. return;
  311. if ( !pWeapon->HasAmmo() )
  312. {
  313. // if the weapon doesn't have ammo, display it as red
  314. clr = GetHud().m_clrCaution;
  315. clr[3] = MIN( scale, 255 );
  316. }
  317. itemIcon = pWeapon->GetSpriteInactive();
  318. bHalfHeight = false;
  319. }
  320. break;
  321. case HISTSLOT_ITEM:
  322. {
  323. if ( !m_PickupHistory[i].iId )
  324. continue;
  325. itemIcon = m_PickupHistory[i].icon;
  326. bHalfHeight = false;
  327. }
  328. break;
  329. default:
  330. // unknown history type
  331. Assert( 0 );
  332. break;
  333. }
  334. if ( !itemIcon )
  335. continue;
  336. if ( clr[3] )
  337. {
  338. // valid drawing will occur
  339. m_bNeedsDraw = true;
  340. }
  341. int ypos = tall - (m_flHistoryGap * (i + 1));
  342. int xpos = wide - itemIcon->Width() - m_flIconInset;
  343. // Adjust for a half-height icon
  344. if ( bHalfHeight )
  345. {
  346. ypos += itemIcon->Height() / 2;
  347. }
  348. itemIcon->DrawSelf( xpos, ypos, clr );
  349. if ( itemAmmoIcon )
  350. {
  351. itemAmmoIcon->DrawSelf( xpos - ( itemAmmoIcon->Width() * 1.25f ), ypos, clr );
  352. }
  353. if ( iAmount )
  354. {
  355. wchar_t text[16];
  356. Q_snwprintf( text, sizeof( text ) / sizeof(wchar_t), L"%i", m_PickupHistory[i].iCount );
  357. // offset the number to sit properly next to the icon
  358. ypos -= ( surface()->GetFontTall( m_hNumberFont ) - itemIcon->Height() ) / 2;
  359. vgui::surface()->DrawSetTextFont( m_hNumberFont );
  360. vgui::surface()->DrawSetTextColor( clr );
  361. vgui::surface()->DrawSetTextPos( wide - m_flTextInset, ypos );
  362. vgui::surface()->DrawUnicodeString( text );
  363. }
  364. else if ( bUseAmmoFullMsg )
  365. {
  366. // offset the number to sit properly next to the icon
  367. ypos -= ( surface()->GetFontTall( m_hTextFont ) - itemIcon->Height() ) / 2;
  368. vgui::surface()->DrawSetTextFont( m_hTextFont );
  369. vgui::surface()->DrawSetTextColor( clr );
  370. vgui::surface()->DrawSetTextPos( wide - m_flTextInset, ypos );
  371. vgui::surface()->DrawUnicodeString( m_wcsAmmoFullMsg );
  372. }
  373. }
  374. }
  375. }