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.

770 lines
26 KiB

  1. //========= Copyright � 1996-2003, Valve LLC, All rights reserved. ============
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "cbase.h"
  7. #include "cs_item_inventory.h"
  8. #include "item_creation.h"
  9. #include "vgui/ILocalize.h"
  10. #include "tier3/tier3.h"
  11. #ifdef CLIENT_DLL
  12. // #include "item_pickup_panel.h"
  13. #else
  14. #include "cs_player.h"
  15. #endif
  16. // memdbgon must be the last include file in a .cpp file!!!
  17. #include "tier0/memdbgon.h"
  18. //-----------------------------------------------------------------------------
  19. CCSInventoryManager g_CSInventoryManager;
  20. CInventoryManager *InventoryManager( void )
  21. {
  22. return &g_CSInventoryManager;
  23. }
  24. CCSInventoryManager *CSInventoryManager( void )
  25. {
  26. return &g_CSInventoryManager;
  27. }
  28. //-----------------------------------------------------------------------------
  29. // Purpose:
  30. //-----------------------------------------------------------------------------
  31. CCSInventoryManager::CCSInventoryManager( void )
  32. {
  33. #ifdef CLIENT_DLL
  34. /*
  35. m_LocalBackpack.SetBag( BAG_BACKPACK );
  36. for ( int i = CS_FIRST_NORMAL_CLASS; i < CS_LAST_NORMAL_CLASS; i++ )
  37. {
  38. m_LoadoutInventories[i].SetBag( GetLoadoutBagForClass(i) );
  39. }
  40. */
  41. #endif
  42. }
  43. //-----------------------------------------------------------------------------
  44. // Purpose:
  45. //-----------------------------------------------------------------------------
  46. void CCSInventoryManager::PostInit( void )
  47. {
  48. BaseClass::PostInit();
  49. GenerateBaseItems();
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Purpose: Generate & store the base item details for each class & loadout slot
  53. //-----------------------------------------------------------------------------
  54. void CCSInventoryManager::GenerateBaseItems( void )
  55. {
  56. /*
  57. for ( int slot = 0; slot < LOADOUT_POSITION_COUNT; slot++ )
  58. {
  59. baseitemcriteria_t pCriteria;
  60. pCriteria.iClass = 0; // FIXME[pmf]: set up CS class identifiers?
  61. pCriteria.iSlot = slot;
  62. int iItemDef = ItemSystem()->GenerateBaseItem( &pCriteria );
  63. if ( iItemDef != INVALID_ITEM_INDEX )
  64. {
  65. / *
  66. IHasAttributes *pItemInterface = dynamic_cast<IHasAttributes *>(pItem);
  67. if ( pItemInterface )
  68. {
  69. CScriptCreatedItem *pScriptItem = pItemInterface->GetAttributeManager()->GetItem();
  70. Msg("============================================\n");
  71. Msg("Inventory: Generating base item for %s, slot %s...\n", g_aPlayerClassNames_NonLocalized[iClass], g_szLoadoutStrings[slot] );
  72. Msg("Generated: %s \"%s\"\n", g_szQualityStrings[pScriptItem->GetItemQuality()], pEnt->GetClassname() );
  73. char tempstr[1024];
  74. g_pVGuiLocalize->ConvertUnicodeToANSI( pScriptItem->GetAttributeDescription(), tempstr, sizeof(tempstr) );
  75. Msg("%s", tempstr );
  76. Msg("\n============================================\n");
  77. }
  78. * /
  79. m_pBaseLoadoutItems[slot].Init( iItemDef, AE_USE_SCRIPT_VALUE, AE_USE_SCRIPT_VALUE, false );
  80. }
  81. else
  82. {
  83. m_pBaseLoadoutItems[slot].Invalidate();
  84. }
  85. }
  86. */
  87. }
  88. #ifdef CLIENT_DLL
  89. //-----------------------------------------------------------------------------
  90. // Purpose:
  91. //-----------------------------------------------------------------------------
  92. void CCSInventoryManager::UpdateLocalInventory( void )
  93. {
  94. BaseClass::UpdateLocalInventory();
  95. if ( steamapicontext->SteamUser() )
  96. {
  97. CSteamID steamID = steamapicontext->SteamUser()->GetSteamID();
  98. /*
  99. CSInventoryManager()->SteamRequestInventory( &m_LocalBackpack, steamID );
  100. // Request our loadouts.
  101. for ( int i = CS_FIRST_NORMAL_CLASS; i < CS_LAST_NORMAL_CLASS; i++ )
  102. {
  103. CSInventoryManager()->SteamRequestInventory( &m_LoadoutInventories[i], steamID );
  104. }
  105. */
  106. }
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Purpose:
  110. //-----------------------------------------------------------------------------
  111. /*
  112. bool CCSInventoryManager::EquipItemInLoadout( int iClass, int iSlot, globalindex_t iGlobalIndex )
  113. {
  114. CSteamID localSteamID = steamapicontext->SteamUser()->GetSteamID();
  115. inventory_bags_t iLoadoutBag = GetLoadoutBagForClass( iClass );
  116. CCSPlayerInventory *pInv = GetBagForPlayer( localSteamID, iLoadoutBag );
  117. if ( pInv )
  118. {
  119. uint32 iPosition = GetBackendPositionFor(iLoadoutBag,iSlot);
  120. if ( !iGlobalIndex )
  121. {
  122. CCSPlayerInventoryLoadout *pLoadoutInv = assert_cast<CCSPlayerInventoryLoadout*>( pInv );
  123. return pLoadoutInv->ClearLoadoutSlot( iPosition );
  124. }
  125. return pInv->MoveItemToPosition( iGlobalIndex, iPosition );
  126. }
  127. return false;
  128. }
  129. */
  130. //-----------------------------------------------------------------------------
  131. // Purpose: Fills out pList with all inventory items that could fit into the specified loadout slot for a given class
  132. //-----------------------------------------------------------------------------
  133. int CCSInventoryManager::GetAllUsableItemsForSlot( int iClass, int iSlot, CUtlVector<CScriptCreatedItem*> *pList )
  134. {
  135. // Assert( iClass >= CS_FIRST_NORMAL_CLASS && iClass < CS_CLASS_COUNT );
  136. Assert( iSlot >= -1 && iSlot < LOADOUT_POSITION_COUNT );
  137. int iCount = m_LocalInventory.GetItemCount();
  138. for ( int i = 0; i < iCount; i++ )
  139. {
  140. CScriptCreatedItem *pItem = m_LocalInventory.GetItem(i);
  141. CPersistentItemDefinition *pItemData = pItem->GetStaticData();
  142. if ( !pItemData->CanBeUsedByClass(iClass) )
  143. continue;
  144. // Passing in iSlot of -1 finds all items usable by the class
  145. if ( iSlot >= 0 && pItem->GetLoadoutSlot(iClass) != iSlot )
  146. continue;
  147. pList->AddToTail( m_LocalInventory.GetItem(i) );
  148. }
  149. return pList->Count();
  150. }
  151. #endif // CLIENT_DLL
  152. //-----------------------------------------------------------------------------
  153. // Purpose:
  154. //-----------------------------------------------------------------------------
  155. /*
  156. CScriptCreatedItem *CCSInventoryManager::GetItemInLoadoutForClass( int iClass, int iSlot, CSteamID *pID )
  157. {
  158. #ifdef CLIENT_DLL
  159. if ( !steamapicontext || !steamapicontext->SteamUser() )
  160. return NULL;
  161. CSteamID localSteamID = steamapicontext->SteamUser()->GetSteamID();
  162. pID = &localSteamID;
  163. #endif
  164. inventory_bags_t iLoadoutBag = GetLoadoutBagForClass( iClass );
  165. CCSPlayerInventory *pInv = GetBagForPlayer( *pID, iLoadoutBag );
  166. if ( !pInv )
  167. return NULL;
  168. CCSPlayerInventoryLoadout *pLoadoutInv = assert_cast<CCSPlayerInventoryLoadout*>( pInv );
  169. return pLoadoutInv->GetItemInLoadout( iSlot );
  170. }
  171. */
  172. //-----------------------------------------------------------------------------
  173. // Purpose:
  174. //-----------------------------------------------------------------------------
  175. CCSPlayerInventory *CCSInventoryManager::GetBagForPlayer( CSteamID &playerID, inventory_bags_t iBag )
  176. {
  177. for ( int i = 0; i < m_pInventories.Count(); i++ )
  178. {
  179. if ( m_pInventories[i].pInventory->GetOwner() != playerID )
  180. continue;
  181. CCSPlayerInventory *pCSInv = assert_cast<CCSPlayerInventory*>( m_pInventories[i].pInventory );
  182. if ( pCSInv->GetBag() == iBag )
  183. return pCSInv;
  184. }
  185. return NULL;
  186. }
  187. #ifdef CLIENT_DLL
  188. //-----------------------------------------------------------------------------
  189. // Purpose:
  190. //-----------------------------------------------------------------------------
  191. bool CCSInventoryManager::ShowItemsPickedUp( void )
  192. {
  193. // Go through the root inventory and find any items that are in the "found" position
  194. CUtlVector<CScriptCreatedItem*> aItemsFound;
  195. int iCount = m_LocalInventory.GetItemCount();
  196. for ( int i = 0; i < iCount; i++ )
  197. {
  198. if ( m_LocalInventory.GetItem(i)->GetInventoryPosition() == BACKEND_POSITION_FOR_NEW_ITEM )
  199. {
  200. aItemsFound.AddToTail( m_LocalInventory.GetItem(i) );
  201. m_LocalInventory.MoveItemToBackpack( m_LocalInventory.GetItem(i)->GetGlobalIndex() );
  202. }
  203. }
  204. if ( !aItemsFound.Count() )
  205. return CheckForRoomAndForceDiscard();
  206. // We're not forcing the player to make room yet. Just show the pickup panel.
  207. /*
  208. CItemPickupPanel *pItemPanel = OpenItemPickupPanel();
  209. for ( int i = 0; i < aItemsFound.Count(); i++ )
  210. {
  211. pItemPanel->AddItem( aItemsFound[i] );
  212. }
  213. */
  214. aItemsFound.Purge();
  215. return true;
  216. }
  217. //-----------------------------------------------------------------------------
  218. // Purpose:
  219. //-----------------------------------------------------------------------------
  220. bool CCSInventoryManager::CheckForRoomAndForceDiscard( void )
  221. {
  222. // Do we have room for the new item?
  223. int iCount = m_LocalInventory.GetItemCount();
  224. if ( iCount <= MAX_BACKPACK_SLOTS )
  225. return false;
  226. CScriptCreatedItem *pItem = m_LocalInventory.GetItem(MAX_BACKPACK_SLOTS);
  227. if ( !pItem )
  228. return false;
  229. // We're forcing the player to make room for items he's found. Bring up that panel with the first item over the limit.
  230. /*
  231. CItemDiscardPanel *pDiscardPanel = OpenItemDiscardPanel();
  232. pDiscardPanel->SetItem( pItem );
  233. */
  234. return true;
  235. }
  236. #endif
  237. //-----------------------------------------------------------------------------
  238. // Purpose: Returns the item data for the base item in the loadout slot for a given class
  239. //-----------------------------------------------------------------------------
  240. CScriptCreatedItem *CCSInventoryManager::GetBaseItemForClass( int iSlot )
  241. {
  242. Assert( iSlot >= 0 && iSlot < LOADOUT_POSITION_COUNT );
  243. return &m_pBaseLoadoutItems[iSlot];
  244. }
  245. //=======================================================================================================================
  246. // CS PLAYER INVENTORY
  247. //=======================================================================================================================
  248. //-----------------------------------------------------------------------------
  249. // Purpose:
  250. //-----------------------------------------------------------------------------
  251. CCSPlayerInventory::CCSPlayerInventory()
  252. {
  253. m_iBag = BAG_ALL_ITEMS;
  254. }
  255. #ifdef CLIENT_DLL
  256. //-----------------------------------------------------------------------------
  257. // Purpose:
  258. //-----------------------------------------------------------------------------
  259. bool CCSPlayerInventory::MoveItemToPosition( globalindex_t iGlobalIndex, int iPosition )
  260. {
  261. CCSPlayerInventory *pRootInv = CSInventoryManager()->GetBagForPlayer( m_OwnerID, BAG_ALL_ITEMS );
  262. if ( !pRootInv )
  263. return false;
  264. // Find the item in our root inventory (we don't know where it's moving from)
  265. CScriptCreatedItem *pMovingItem = pRootInv->GetInventoryItemByGlobalIndex( iGlobalIndex );
  266. if ( !pMovingItem )
  267. return false;
  268. // Is the item allowed to be in the new position?
  269. if ( !IsItemAllowedInPosition( pMovingItem, iPosition ) )
  270. return false;
  271. // Get the current item in the position
  272. CScriptCreatedItem *pItemAlreadyInPosition = GetItemByPosition(iPosition);
  273. if ( pItemAlreadyInPosition )
  274. {
  275. // See if that item is allowed to be where our new item is
  276. int iSwapPosition = pMovingItem->GetInventoryPosition();
  277. if ( !IsItemAllowedInPosition( pItemAlreadyInPosition, iSwapPosition ) )
  278. {
  279. // Try to move the swapped item to the backpack, and abort if that fails
  280. if ( !MoveItemToBackpack( pItemAlreadyInPosition->GetGlobalIndex() ) )
  281. return false;
  282. }
  283. else
  284. {
  285. // Move the swapped item to our current position
  286. SteamUserItems()->UpdateInventoryPos( pItemAlreadyInPosition->GetGlobalIndex(), iSwapPosition );
  287. }
  288. }
  289. SteamUserItems()->UpdateInventoryPos( iGlobalIndex, iPosition );
  290. return true;
  291. }
  292. //-----------------------------------------------------------------------------
  293. // Purpose: Tries to move the specified item into the player's backpack. If this inventory isn't the
  294. // backpack, it'll find the matching player's backpack and move it.
  295. // FAILS if the backpack is full. Returns false in that case.
  296. //-----------------------------------------------------------------------------
  297. bool CCSPlayerInventory::MoveItemToBackpack( globalindex_t iGlobalIndex )
  298. {
  299. if ( m_iBag != BAG_BACKPACK )
  300. {
  301. // We're not the backpack inventory. Find it and tell it to move the item.
  302. CCSPlayerInventory *pBackpackInv = CSInventoryManager()->GetBagForPlayer( m_OwnerID, BAG_BACKPACK );
  303. if ( pBackpackInv )
  304. return pBackpackInv->MoveItemToBackpack( iGlobalIndex );
  305. }
  306. return false;
  307. }
  308. #endif // CLIENT_DLL
  309. //-----------------------------------------------------------------------------
  310. // Purpose:
  311. //-----------------------------------------------------------------------------
  312. void CCSPlayerInventory::InventoryReceived( EItemRequestResult eResult, int iItems )
  313. {
  314. BaseClass::InventoryReceived( eResult, iItems );
  315. #ifdef CLIENT_DLL
  316. if ( eResult == k_EItemRequestResultOK && m_iBag == BAG_ALL_ITEMS )
  317. {
  318. // The base bag checks for duplicate positions
  319. int iCount = m_aInventoryItems.Count();
  320. for ( int i = iCount-1; i >= 0; i-- )
  321. {
  322. uint32 iPosition = m_aInventoryItems[i].GetInventoryPosition();
  323. // Waiting to be acknowledged?
  324. if ( iPosition == BACKEND_POSITION_FOR_NEW_ITEM )
  325. continue;
  326. bool bInvalidSlot = false;
  327. // Inside the backpack?
  328. if ( i > 0 )
  329. {
  330. // We're not in an invalid slot yet. But if we're in the same position as another item, we should be moved too.
  331. if ( iPosition == m_aInventoryItems[i-1].GetInventoryPosition() )
  332. {
  333. Warning("WARNING: Found item in a duplicate position. Moving to the backpack.\n" );
  334. bInvalidSlot = true;
  335. }
  336. }
  337. if ( bInvalidSlot )
  338. {
  339. // The item is in an invalid slot. Move it back to the backpack.
  340. if ( !MoveItemToBackpack( m_aInventoryItems[i].GetGlobalIndex() ) )
  341. {
  342. // We failed to move it to the backpack, because the player has no room.
  343. // Force them to "refind" the item, which will make them throw something out.
  344. SteamUserItems()->UpdateInventoryPos( m_aInventoryItems[i].GetGlobalIndex(), BACKEND_POSITION_FOR_NEW_ITEM );
  345. }
  346. }
  347. }
  348. }
  349. #endif
  350. }
  351. //-----------------------------------------------------------------------------
  352. // Purpose:
  353. //-----------------------------------------------------------------------------
  354. void CCSPlayerInventory::DumpInventoryToConsole( bool bRoot )
  355. {
  356. if ( bRoot )
  357. {
  358. Msg("========================================\n");
  359. #ifdef CLIENT_DLL
  360. Msg("(CLIENT) Inventory:\n");
  361. #else
  362. Msg("(SERVER) Inventory for account (%d):\n", m_OwnerID.GetAccountID() );
  363. #endif
  364. }
  365. Msg("Bag ID : %d\n", m_iBag );
  366. int iCount = m_aInventoryItems.Count();
  367. Msg(" Num items: %d\n", iCount );
  368. for ( int i = 0; i < iCount; i++ )
  369. {
  370. char tempstr[1024];
  371. g_pVGuiLocalize->ConvertUnicodeToANSI( m_aInventoryItems[i].GetItemName(), tempstr, sizeof(tempstr) );
  372. Msg(" %s (ID %I64d) at slot %d\n", tempstr, m_aInventoryItems[i].GetGlobalIndex(), ExtractBagSlotFromBackendPosition(m_aInventoryItems[i].GetInventoryPosition()) );
  373. }
  374. }
  375. //-----------------------------------------------------------------------------
  376. // Purpose: Used to reject items on the backend for inclusion into this inventory.
  377. // Mostly used for division of bags into different in-game inventories.
  378. //-----------------------------------------------------------------------------
  379. bool CCSPlayerInventory::ItemShouldBeIncluded( int iItemPosition )
  380. {
  381. if ( m_iBag )
  382. {
  383. int iItemBagPosition = ExtractBagFromBackendPosition( iItemPosition );
  384. if ( iItemBagPosition != m_iBag )
  385. return false;
  386. }
  387. return BaseClass::ItemShouldBeIncluded( iItemPosition );
  388. }
  389. //=======================================================================================================================
  390. // CS PLAYER INVENTORY
  391. //=======================================================================================================================
  392. //-----------------------------------------------------------------------------
  393. // Purpose:
  394. //-----------------------------------------------------------------------------
  395. #if 0
  396. CCSPlayerInventoryLoadout::CCSPlayerInventoryLoadout( void )
  397. {
  398. memset( m_LoadoutItems, LOADOUT_SLOT_USE_BASE_ITEM, LOADOUT_POSITION_COUNT * sizeof(int) );
  399. }
  400. //-----------------------------------------------------------------------------
  401. // Purpose: Returns the item in the specified loadout slot for a given class
  402. //-----------------------------------------------------------------------------
  403. CScriptCreatedItem *CCSPlayerInventoryLoadout::GetItemInLoadout( int iSlot )
  404. {
  405. if ( iSlot < 0 || iSlot >= LOADOUT_POSITION_COUNT )
  406. return NULL;
  407. // If we don't have an item in the loadout at that slot, we return the base item
  408. if ( m_LoadoutItems[iSlot] != LOADOUT_SLOT_USE_BASE_ITEM )
  409. {
  410. CScriptCreatedItem *pItem = GetInventoryItemByGlobalIndex( m_LoadoutItems[iSlot] );
  411. #ifdef GAME_DLL
  412. // To protect against users lying to the backend about the position of their items,
  413. // we need to validate their position on the server when we retrieve them.
  414. if ( IsItemAllowedInPosition( pItem, GetBackendPositionFor(GetBag(),iSlot) ) )
  415. #endif
  416. return pItem;
  417. }
  418. return CSInventoryManager()->GetBaseItemForClass( iSlot );
  419. }
  420. #ifdef CLIENT_DLL
  421. //-----------------------------------------------------------------------------
  422. // Purpose:
  423. //-----------------------------------------------------------------------------
  424. bool CCSPlayerInventoryLoadout::MoveItemToPosition( globalindex_t iGlobalIndex, int iPosition )
  425. {
  426. if ( !BaseClass::MoveItemToPosition( iGlobalIndex, iPosition ) )
  427. return false;
  428. // TODO: Prediction
  429. // Item has been moved, so update our loadout.
  430. //int iSlot = ExtractBagSlotFromBackendPosition( iPosition );
  431. //m_LoadoutItems[iSlot] = iGlobalIndex;
  432. return true;
  433. }
  434. //-----------------------------------------------------------------------------
  435. // Purpose: Removes any item in a loadout slot. If the slot hase a base item,
  436. // the player essentially returns to using that item.
  437. //-----------------------------------------------------------------------------
  438. bool CCSPlayerInventoryLoadout::ClearLoadoutSlot( int iPosition )
  439. {
  440. CScriptCreatedItem *pItemInSlot = GetItemByPosition(iPosition);
  441. if ( !pItemInSlot )
  442. return false;
  443. if ( !MoveItemToBackpack( pItemInSlot->GetGlobalIndex() ) )
  444. return false;
  445. /*
  446. // TODO: Prediction
  447. // It's been moved to the backpack, so clear out loadout entry
  448. int iSlot = ExtractBagSlotFromBackendPosition( iPosition );
  449. if ( iSlot >= 0 && iSlot < LOADOUT_POSITION_COUNT )
  450. {
  451. m_LoadoutItems[iSlot] = LOADOUT_SLOT_USE_BASE_ITEM;
  452. }
  453. */
  454. return true;
  455. }
  456. #endif // CLIENT_DLL
  457. //-----------------------------------------------------------------------------
  458. // Purpose: Returns true if the specified item is allowed to be stored at the specified position
  459. // DOES NOT check to make sure the position is clear. It's just a class / slot validity check.
  460. //-----------------------------------------------------------------------------
  461. bool CCSPlayerInventoryLoadout::IsItemAllowedInPosition( CScriptCreatedItem *pItem, int iPosition )
  462. {
  463. int iSlot = ExtractBagSlotFromBackendPosition( iPosition );
  464. if ( pItem->GetStaticData()->m_vbClassUsability.IsBitSet( GetLoadoutClass() ) && pItem->GetLoadoutSlot() == iSlot )
  465. return true;
  466. return false;
  467. }
  468. //-----------------------------------------------------------------------------
  469. // Purpose:
  470. //-----------------------------------------------------------------------------
  471. void CCSPlayerInventoryLoadout::InventoryReceived( EItemRequestResult eResult, int iItems )
  472. {
  473. if ( eResult == k_EItemRequestResultOK )
  474. {
  475. memset( m_LoadoutItems, LOADOUT_SLOT_USE_BASE_ITEM, LOADOUT_POSITION_COUNT * sizeof(int) );
  476. }
  477. #ifdef CLIENT_DLL
  478. if ( eResult == k_EItemRequestResultOK )
  479. {
  480. // Now that we have all our items, validate our loadout positions.
  481. int iCount = m_aInventoryItems.Count();
  482. for ( int i = iCount-1; i >= 0; i-- )
  483. {
  484. uint32 iPosition = m_aInventoryItems[i].GetInventoryPosition();
  485. // Waiting to be acknowledged?
  486. if ( iPosition == BACKEND_POSITION_FOR_NEW_ITEM )
  487. continue;
  488. Assert( ExtractBagFromBackendPosition( iPosition ) == m_iBag );
  489. int iBagSlot = ExtractBagSlotFromBackendPosition( iPosition );
  490. // Ensure it's in a valid loadout slot
  491. bool bInvalidSlot = (iBagSlot >= LOADOUT_POSITION_COUNT);
  492. if ( !bInvalidSlot )
  493. {
  494. bInvalidSlot = !IsItemAllowedInPosition( &m_aInventoryItems[i], iBagSlot );
  495. }
  496. if ( bInvalidSlot )
  497. {
  498. Warning("WARNING: Found item in an invalid loadout position. Moving to the backpack.\n" );
  499. // The item is in an invalid slot. Move it back to the backpack.
  500. if ( !MoveItemToBackpack( m_aInventoryItems[i].GetGlobalIndex() ) )
  501. {
  502. // We failed to move it to the backpack, because the player has no room.
  503. // Force them to "refind" the item, which will make them throw something out.
  504. SteamUserItems()->UpdateInventoryPos( m_aInventoryItems[i].GetGlobalIndex(), BACKEND_POSITION_FOR_NEW_ITEM );
  505. }
  506. }
  507. }
  508. }
  509. #endif
  510. BaseClass::InventoryReceived( eResult, iItems );
  511. }
  512. //-----------------------------------------------------------------------------
  513. // Purpose:
  514. //-----------------------------------------------------------------------------
  515. void CCSPlayerInventoryLoadout::ItemHasBeenUpdated( CScriptCreatedItem *pItem )
  516. {
  517. // Now that we have all our items, set up out loadout pointers
  518. uint32 iPosition = pItem->GetInventoryPosition();
  519. int iSlot = ExtractBagSlotFromBackendPosition( iPosition );
  520. if ( iSlot >= 0 && iSlot < LOADOUT_POSITION_COUNT )
  521. {
  522. Assert( GetInventoryItemByGlobalIndex(pItem->GetGlobalIndex()) );
  523. // This may be an invalid slot for the item, but CCSPlayerInventory::InventoryReceived()
  524. // will have detected that and sent off a request already to move it. The response
  525. // to that will clear this loadout slot.
  526. m_LoadoutItems[iSlot] = pItem->GetGlobalIndex();
  527. }
  528. }
  529. //-----------------------------------------------------------------------------
  530. // Purpose:
  531. //-----------------------------------------------------------------------------
  532. void CCSPlayerInventoryLoadout::ItemIsBeingRemoved( CScriptCreatedItem *pItem )
  533. {
  534. // Now that we have all our items, set up out loadout pointers
  535. uint32 iPosition = pItem->GetInventoryPosition();
  536. int iSlot = ExtractBagSlotFromBackendPosition( iPosition );
  537. if ( iSlot >= 0 && iSlot < LOADOUT_POSITION_COUNT )
  538. {
  539. m_LoadoutItems[iSlot] = LOADOUT_SLOT_USE_BASE_ITEM;
  540. }
  541. }
  542. //-----------------------------------------------------------------------------
  543. // Purpose:
  544. //-----------------------------------------------------------------------------
  545. void CCSPlayerInventoryLoadout::DumpInventoryToConsole( bool bRoot )
  546. {
  547. if ( bRoot )
  548. {
  549. Msg("========================================\n");
  550. #ifdef CLIENT_DLL
  551. Msg("(CLIENT) Inventory:\n");
  552. #else
  553. Msg("(SERVER) Inventory for account (%d):\n", m_OwnerID.GetAccountID() );
  554. #endif
  555. }
  556. Msg("Loadout for Class: %s (%d)\n", g_aPlayerClassNames_NonLocalized[GetLoadoutClass()], GetLoadoutClass() );
  557. BaseClass::DumpInventoryToConsole( false );
  558. if ( GetItemCount() > 0 )
  559. {
  560. Msg(" LOADOUT:\n");
  561. for ( int i = 0; i < LOADOUT_POSITION_COUNT; i++ )
  562. {
  563. Msg(" Slot %d: ", i );
  564. if ( m_LoadoutItems[i] != LOADOUT_SLOT_USE_BASE_ITEM )
  565. {
  566. CScriptCreatedItem *pItem = GetInventoryItemByGlobalIndex( m_LoadoutItems[i] );
  567. char tempstr[1024];
  568. g_pVGuiLocalize->ConvertUnicodeToANSI( pItem->GetItemName(), tempstr, sizeof(tempstr) );
  569. Msg("%s (ID %I64d)\n", tempstr, pItem->GetGlobalIndex() );
  570. }
  571. else
  572. {
  573. Msg("\n");
  574. }
  575. }
  576. }
  577. }
  578. #endif
  579. #if 0
  580. //-----------------------------------------------------------------------------
  581. // Purpose:
  582. //-----------------------------------------------------------------------------
  583. CCSPlayerInventoryBackpack::CCSPlayerInventoryBackpack( void )
  584. {
  585. SetBag( BAG_BACKPACK );
  586. m_iPredictedEmptySlot = 1;
  587. }
  588. #ifdef CLIENT_DLL
  589. //-----------------------------------------------------------------------------
  590. // Purpose:
  591. //-----------------------------------------------------------------------------
  592. void CCSPlayerInventoryBackpack::ItemHasBeenUpdated( CScriptCreatedItem *pItem )
  593. {
  594. BaseClass::ItemHasBeenUpdated( pItem );
  595. // Now that we have all our items, set up out loadout pointers
  596. uint32 iPosition = pItem->GetInventoryPosition();
  597. int iSlot = ExtractBagSlotFromBackendPosition( iPosition );
  598. if ( iSlot == m_iPredictedEmptySlot )
  599. {
  600. CalculateNextEmptySlot();
  601. }
  602. }
  603. //-----------------------------------------------------------------------------
  604. // Purpose:
  605. //-----------------------------------------------------------------------------
  606. void CCSPlayerInventoryBackpack::CalculateNextEmptySlot( void )
  607. {
  608. // Move forward looking for the first slot that doesn't have an item in it.
  609. // We start from our current slot and only move forward, so we don't run into the problem of
  610. // choosing a slot that's probably got another item in the process of being moved into it.
  611. do
  612. {
  613. m_iPredictedEmptySlot++;
  614. if ( !GetItemByPosition( GetBackendPositionFor(BAG_BACKPACK, m_iPredictedEmptySlot)) )
  615. break;
  616. } while ( m_iPredictedEmptySlot < 1000 );
  617. }
  618. //-----------------------------------------------------------------------------
  619. // Purpose: Tries to move the specified item into the player's backpack.
  620. // FAILS if the backpack is full. Returns false in that case.
  621. //-----------------------------------------------------------------------------
  622. bool CCSPlayerInventoryBackpack::MoveItemToBackpack( globalindex_t iGlobalIndex )
  623. {
  624. Warning("Moved item %I64d to backpack slot: %d\n", iGlobalIndex, m_iPredictedEmptySlot );
  625. Assert( GetItemByPosition(GetBackendPositionFor(BAG_BACKPACK, m_iPredictedEmptySlot)) == NULL );
  626. // Move to our current predicted empty slot, and then try to find the next slot.
  627. SteamUserItems()->UpdateInventoryPos( iGlobalIndex, GetBackendPositionFor(BAG_BACKPACK, m_iPredictedEmptySlot) );
  628. CalculateNextEmptySlot();
  629. return true;
  630. }
  631. #endif
  632. #ifdef CLIENT_DLL
  633. // WTF: Declaring this inline caused a compiler bug.
  634. CCSPlayerInventory *CCSInventoryManager::GetLocalCSInventory( void )
  635. {
  636. return &m_LocalInventory;
  637. }
  638. #endif
  639. #ifdef _DEBUG
  640. #if defined(CLIENT_DLL)
  641. CON_COMMAND_F( item_dumpinv, "Dumps the contents of a specified client inventory. Format: item_dumpinv <bag index>", FCVAR_CHEAT )
  642. #else
  643. CON_COMMAND_F( item_dumpinv_sv, "Dumps the contents of a specified server inventory. Format: item_dumpinv_sv <bag index>", FCVAR_CHEAT )
  644. #endif
  645. {
  646. int iBag = ( args.ArgC() > 1 ) ? atoi(args[1]) : BAG_ALL_ITEMS;
  647. #if defined(CLIENT_DLL)
  648. CSteamID steamID = steamapicontext->SteamUser()->GetSteamID();
  649. #else
  650. CSteamID steamID;
  651. CCSPlayer *pPlayer = ToCSPlayer( UTIL_GetCommandClient() );
  652. pPlayer->GetSteamID( &steamID );
  653. #endif
  654. CPlayerInventory *pInventory = CSInventoryManager()->GetBagForPlayer( steamID, (inventory_bags_t)iBag );
  655. if ( !pInventory )
  656. {
  657. Msg("No inventory for bag %d\n", iBag);
  658. return;
  659. }
  660. pInventory->DumpInventoryToConsole( true );
  661. }
  662. #endif
  663. #endif