BVB Source Codes

CRYENGINE Show Inventory.cpp Source code

Return Download CRYENGINE: download Inventory.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /*************************************************************************
  4.    -------------------------------------------------------------------------
  5.    $Id$
  6.    $DateTime$
  7.  
  8.    -------------------------------------------------------------------------
  9.    History:
  10.    - 18:8:2005   17:27 : Created by M谩rcio Martins
  11.  
  12. *************************************************************************/
  13. #include "StdAfx.h"
  14. #include "Inventory.h"
  15. #include <CryEntitySystem/IEntitySystem.h>
  16. #include "IGameObject.h"
  17. #include "CryAction.h"
  18. #include "ScriptBind_Inventory.h"
  19. #include "IActorSystem.h"
  20.  
  21. //------------------------------------------------------------------------
  22. CInventory::CInventory()
  23.         : m_pGameFrameWork(nullptr)
  24.         , m_pActor(nullptr)
  25.         , m_bSerializeLTL(false)
  26.         , m_iteratingListeners(false)
  27.         , m_ignoreNextClear(false)
  28. {
  29.         m_stats.slots.reserve(gEnv->pConsole->GetCVar("i_inventory_capacity")->GetIVal());
  30. }
  31.  
  32. //------------------------------------------------------------------------
  33. CInventory::~CInventory()
  34. {
  35.         CCryAction* pCryAction = static_cast<CCryAction*>(gEnv->pGameFramework);
  36.         pCryAction->GetInventoryScriptBind()->DetachFrom(this);
  37. }
  38.  
  39. //------------------------------------------------------------------------
  40. bool CInventory::Init(IGameObject* pGameObject)
  41. {
  42.         SetGameObject(pGameObject);
  43.         // attach script bind
  44.         CCryAction* pCryAction = static_cast<CCryAction*>(gEnv->pGameFramework);
  45.         pCryAction->GetInventoryScriptBind()->AttachTo(this);
  46.  
  47.         m_pGameFrameWork = pCryAction;
  48.  
  49.         m_pActor = pCryAction->GetIActorSystem()->GetActor(pGameObject->GetEntityId());
  50.  
  51.         return true;
  52. }
  53.  
  54. //------------------------------------------------------------------------
  55. bool CInventory::ReloadExtension(IGameObject* pGameObject, const SEntitySpawnParams& params)
  56. {
  57.         ResetGameObject();
  58.  
  59.         Destroy();
  60.  
  61.         return true;
  62. }
  63.  
  64. //------------------------------------------------------------------------
  65. void CInventory::PostReloadExtension(IGameObject* pGameObject, const SEntitySpawnParams& params)
  66. {
  67.         // attach script bind
  68.         CCryAction* pCryAction = static_cast<CCryAction*>(gEnv->pGameFramework);
  69.         pCryAction->GetInventoryScriptBind()->AttachTo(this);
  70.  
  71.         m_pActor = pCryAction->GetIActorSystem()->GetActor(pGameObject->GetEntityId());
  72. }
  73.  
  74. //------------------------------------------------------------------------
  75. void CInventory::FullSerialize(TSerialize ser)
  76. {
  77.         MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Inventory serialization");
  78.  
  79.         ser.BeginGroup("InventoryItems");
  80.  
  81.         ser.Value("CurrentItem", m_stats.currentItemId);
  82.         ser.Value("HolsterItem", m_stats.holsteredItemId);
  83.         ser.Value("LastItem", m_stats.lastItemId);
  84.         int s = m_stats.slots.size();
  85.         ser.Value("InventorySize", s);
  86.         if (ser.IsReading())
  87.                 m_stats.slots.resize(s);
  88.  
  89.         ser.Value("Slots", m_stats.slots);
  90.  
  91.         ser.BeginGroup("accessorySlots");
  92.         int exSize = m_stats.accessorySlots.size();
  93.         ser.Value("Size", exSize);
  94.  
  95.         for (int i = 0; i < IInventory::eInventorySlot_Last; ++i)
  96.         {
  97.                 ser.BeginGroup("SlotInfo");
  98.                 ser.Value("slotInfoCount", m_stats.slotsInfo[i].count);
  99.                 ser.Value("slotInfoLastSelected", m_stats.slotsInfo[i].lastSelected);
  100.                 ser.EndGroup();
  101.         }
  102.  
  103.         if (ser.IsReading())
  104.         {
  105.                 m_stats.accessorySlots.resize(0);
  106.                 if (exSize > 0)
  107.                         m_stats.accessorySlots.reserve(exSize);
  108.         }
  109.         for (int i = 0; i < exSize; ++i)
  110.         {
  111.                 string accessoryName;
  112.                 if (ser.IsWriting())
  113.                         accessoryName = m_stats.accessorySlots[i]->GetName();
  114.  
  115.                 ser.BeginGroup("Class");
  116.                 ser.Value("AccessoryName", accessoryName);
  117.                 ser.EndGroup();
  118.  
  119.                 if (ser.IsReading())
  120.                 {
  121.                         IEntityClass* pAccessoryClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(accessoryName);
  122.                         CRY_ASSERT(pAccessoryClass);
  123.                         if (pAccessoryClass != NULL)
  124.                         {
  125.                                 m_stats.accessorySlots.push_back(pAccessoryClass);
  126.                         }
  127.                 }
  128.         }
  129.         ser.EndGroup();//"accessorySlots"
  130.  
  131.         ser.BeginGroup("Ammo");
  132.         if (ser.IsReading())
  133.         {
  134.                 m_stats.ammoInfo.clear();
  135.         }
  136.  
  137.         TAmmoInfoMap::iterator ammoInfoIt = m_stats.ammoInfo.begin();
  138.         int ammoAmount = m_stats.ammoInfo.size();
  139.         ser.Value("AmmoAmount", ammoAmount);
  140.         for (int i = 0; i < ammoAmount; ++i)
  141.         {
  142.                 string name;
  143.                 int amount = 0;
  144.                 int capacity = 0;
  145.                 if (ser.IsWriting())
  146.                 {
  147.                         IEntityClass* pAmmoClass = ammoInfoIt->first;
  148.                         CRY_ASSERT(pAmmoClass);
  149.                         name = (pAmmoClass) ? pAmmoClass->GetName() : "";
  150.  
  151.                         const SAmmoInfo& ammoInfo = ammoInfoIt->second;
  152.  
  153.                         amount = ammoInfo.GetCount();
  154.                         //users = ammoInfo.GetUserCount();
  155.                         capacity = ammoInfo.GetCapacity();
  156.                         // Only use this iterator writing. If we're reading, we change the size
  157.                         // of the map and end up with an out of sync (and invalid) iterator.
  158.                         ++ammoInfoIt;
  159.                 }
  160.                 ser.BeginGroup("Ammo");
  161.                 ser.Value("AmmoName", name);
  162.                 ser.Value("Bullets", amount);
  163.                 ser.Value("Capacity", capacity);
  164.                 ser.EndGroup();
  165.                 if (ser.IsReading())
  166.                 {
  167.                         IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(name);
  168.                         CRY_ASSERT(pClass);
  169.                         TAmmoInfoMap::iterator it = m_stats.ammoInfo.find(pClass);
  170.                         if (it == m_stats.ammoInfo.end())
  171.                         {
  172.                                 m_stats.ammoInfo[pClass] = SAmmoInfo(amount, capacity);
  173.                         }
  174.                         else
  175.                         {
  176.                                 it->second.SetCount(amount);
  177.                                 it->second.SetCapacity(capacity);
  178.                         }
  179.                 }
  180.         }
  181.         ser.EndGroup();
  182.  
  183.         /*
  184.            ser.BeginGroup("CategorySlots");
  185.  
  186.            for (TSlotsInfo::iterator it = m_stats.slotsInfo.begin(); it != m_stats.slotsInfo.end(); ++it)
  187.            {
  188.             ser.Value("Count", it->second.count);
  189.            }
  190.  
  191.            ser.EndGroup();*/
  192.  
  193.         ser.EndGroup();
  194. }
  195.  
  196. void CInventory::PostSerialize()
  197. {
  198.         for (int i = 0; i < IInventory::eInventorySlot_Last; ++i)
  199.         {
  200.                 const int itemIndex = FindItem(m_stats.slotsInfo[i].lastSelected);
  201.  
  202.                 // For whatever reason we don't have this last item in the inventory,
  203.                 // so find a suitable item in the same slot.
  204.                 if (itemIndex == -1)
  205.                 {
  206.                         const EntityId entityId = GetAnyEntityInSlot(i);
  207.  
  208.                         SetLastSelectedInSlot(entityId);
  209.                 }
  210.         }
  211.  
  212.         // Benito - This is last minute workaround to solve a strange bug:
  213.         // If the game is saved while you had equipped a 'heavy weapon' (dynamic one, not present in the level) but this ones is holstered at the moment of save
  214.         // when the game is loaded, the item is not restored properly, because the entity does not get a serialize call.
  215.         // This code ensures that weapon goes back to the hands of the player, adding as many checks here as possible before doing the final call
  216.         const bool ownerActorIsClientNotInVehicle = (m_pActor != NULL) && m_pActor->IsClient() && (m_pActor->GetLinkedVehicle() == NULL);
  217.         if (ownerActorIsClientNotInVehicle)
  218.         {
  219.                 IItem* pCurrentItem = gEnv->pGameFramework->GetIItemSystem()->GetItem(m_stats.currentItemId);
  220.                 if ((pCurrentItem != NULL) && (pCurrentItem->GetOwnerId() == 0))
  221.                 {
  222.                         if (pCurrentItem->CanUse(m_pActor->GetEntityId()))
  223.                         {
  224.                                 m_stats.currentItemId = 0; //Reset and use it again
  225.                                 pCurrentItem->Use(m_pActor->GetEntityId());
  226.                         }
  227.                 }
  228.         }
  229. }
  230.  
  231. //------------------------------------------------------------------------
  232. void CInventory::SerializeInventoryForLevelChange(TSerialize ser)
  233. {
  234.         IActor* pActor = GetActor();
  235.         if (!pActor)
  236.                 return;
  237.  
  238.         if (ser.IsReading())
  239.         {
  240.                 m_stats.ammoInfo.clear();
  241.         }
  242.  
  243.         m_bSerializeLTL = true;
  244.  
  245.         //Items by class (accessories)
  246.         ser.BeginGroup("accessorySlots");
  247.         int exSize = m_stats.accessorySlots.size();
  248.         ser.Value("Size", exSize);
  249.  
  250.         if (ser.IsReading())
  251.         {
  252.                 m_stats.accessorySlots.resize(0);
  253.                 if (exSize > 0)
  254.                         m_stats.accessorySlots.reserve(exSize);
  255.         }
  256.         for (int i = 0; i < exSize; ++i)
  257.         {
  258.                 string accessoryName;
  259.                 if (ser.IsWriting())
  260.                         accessoryName = m_stats.accessorySlots[i]->GetName();
  261.  
  262.                 ser.BeginGroup("Class");
  263.                 ser.Value("AccessoryName", accessoryName);
  264.                 ser.EndGroup();
  265.  
  266.                 if (ser.IsReading())
  267.                 {
  268.                         IEntityClass* pAccessoryClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(accessoryName);
  269.                         CRY_ASSERT(pAccessoryClass);
  270.                         if (pAccessoryClass)
  271.                         {
  272.                                 m_stats.accessorySlots.push_back(pAccessoryClass);
  273.                         }
  274.                 }
  275.         }
  276.         ser.EndGroup();//"accessorySlots"
  277.  
  278.         if (ser.IsReading())
  279.         {
  280.                 for (int r = 0; r < m_stats.slots.size(); ++r)
  281.                 {
  282.                         IItem* pItem = m_pGameFrameWork->GetIItemSystem()->GetItem(m_stats.slots[r]);
  283.                         if (pItem)
  284.                         {
  285.                                 pItem->Drop();
  286.                                 pItem->GetEntity()->SetFlags(pItem->GetEntity()->GetFlags() | ENTITY_FLAG_UPDATE_HIDDEN);
  287.                                 pItem->GetEntity()->Hide(true);
  288.                                 gEnv->pEntitySystem->RemoveEntity(m_stats.slots[r]);
  289.                         }
  290.                 }
  291.         }
  292.  
  293.         int numItems = 0;
  294.  
  295.         string currentItemNameOnReading;
  296.  
  297.         if (ser.IsReading())
  298.         {
  299.                 m_stats.slots.clear();
  300.                 m_stats.currentItemId = 0;
  301.                 m_stats.holsteredItemId = 0;
  302.                 m_stats.lastItemId = 0;
  303.  
  304.                 string itemName;
  305.                 ser.Value("numOfItems", numItems);
  306.                 for (int i = 0; i < numItems; ++i)
  307.                 {
  308.                         ser.BeginGroup("Items");
  309.                         bool nextItemExists = false;
  310.                         ser.Value("nextItemExists", nextItemExists);
  311.                         if (nextItemExists)
  312.                         {
  313.                                 ser.Value("ItemName", itemName);
  314.                                 EntityId id = m_pGameFrameWork->GetIItemSystem()->GiveItem(pActor, itemName.c_str(), false, false, false);
  315.                                 IItem* pItem = m_pGameFrameWork->GetIItemSystem()->GetItem(id);
  316.                                 if (pItem)
  317.                                 {
  318.                                         //actual serialization
  319.                                         pItem->SerializeLTL(ser);
  320.                                 }
  321.                                 else
  322.                                 {
  323.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Couldn't spawn inventory item %s, got id %u.", itemName.c_str(), id);
  324.                                 }
  325.                         }
  326.  
  327.                         ser.EndGroup();
  328.                 }
  329.                 ser.Value("CurrentItemName", itemName);
  330.                 if (stricmp(itemName.c_str(), "none"))
  331.                 {
  332.                         currentItemNameOnReading = itemName;
  333.                         IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(itemName.c_str());
  334.                         if (pClass)
  335.                         {
  336.                                 if (IItem* pItem = m_pGameFrameWork->GetIItemSystem()->GetItem(GetItemByClass(pClass)))
  337.                                 {
  338.                                         if (pActor->GetCurrentItem() && pActor->GetCurrentItem() != pItem)
  339.                                                 pActor->GetCurrentItem()->Select(false);
  340.                                         pItem->Select(true);
  341.                                         m_stats.currentItemId = pItem->GetEntityId();
  342.                                 }
  343.                                 else
  344.                                         m_stats.currentItemId = m_pGameFrameWork->GetIItemSystem()->GiveItem(pActor, itemName.c_str(), false, true, false);
  345.                         }
  346.                 }
  347.         }
  348.         else
  349.         {
  350.                 numItems = m_stats.slots.size();
  351.                 ser.Value("numOfItems", numItems);
  352.  
  353.                 for (int i = 0; i < numItems; ++i)
  354.                 {
  355.                         ser.BeginGroup("Items");
  356.                         IItem* pItem = m_pGameFrameWork->GetIItemSystem()->GetItem(m_stats.slots[i]);
  357.                         bool nextItem = true;
  358.                         if (pItem)
  359.                         {
  360.                                 ser.Value("nextItemExists", nextItem);
  361.                                 ser.Value("ItemName", pItem->GetEntity()->GetClass()->GetName());
  362.                                 pItem->SerializeLTL(ser);
  363.                         }
  364.                         else
  365.                         {
  366.                                 nextItem = false;
  367.                                 ser.Value("nextItemExists", nextItem);
  368.                         }
  369.                         ser.EndGroup();
  370.                 }
  371.                 bool currentItemIsInInventory = stl::find(m_stats.slots, m_stats.currentItemId);
  372.                 IItem* pCurrentItem = NULL;
  373.  
  374.                 if (currentItemIsInInventory)
  375.                 {
  376.                         pCurrentItem = m_pGameFrameWork->GetIItemSystem()->GetItem(m_stats.currentItemId);
  377.                 }
  378.                 else
  379.                 {
  380.                         pCurrentItem = m_pGameFrameWork->GetIItemSystem()->GetItem(GetHolsteredItem());
  381.                         //Fallback to last selected one...
  382.                         if (!pCurrentItem)
  383.                         {
  384.                                 pCurrentItem = m_pGameFrameWork->GetIItemSystem()->GetItem(GetLastItem());
  385.                                 // desperate fallback to any weapon...
  386.                                 // this fallback should never be needed. However, right now it happens if the player loads a savegame where a heavyweapon is being used, right before the end of the mission.
  387.                                 // that is a bug, but at this point is safer to just do this bruteforce fallback instead of fixing it
  388.                                 // TODO: to fix that and remove this fallback...
  389.                                 if (!pCurrentItem)
  390.                                 {
  391.                                         for (int i = 0; i < numItems; ++i)
  392.                                         {
  393.                                                 IItem* pItem = m_pGameFrameWork->GetIItemSystem()->GetItem(m_stats.slots[i]);
  394.                                                 if (pItem)
  395.                                                 {
  396.                                                         const char* pCategoryName = m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pItem->GetEntity()->GetClass()->GetName());
  397.                                                         if (pCategoryName)
  398.                                                         {
  399.                                                                 EInventorySlots slotType = GetSlotForItemCategory(pCategoryName);
  400.                                                                 if (slotType == eInventorySlot_Weapon)
  401.                                                                 {
  402.                                                                         pCurrentItem = pItem;
  403.                                                                         break;
  404.                                                                 }
  405.                                                         }
  406.                                                 }
  407.                                         }
  408.                                 }
  409.                         }
  410.                 }
  411.  
  412.                 if (pCurrentItem)
  413.                 {
  414.                         ser.Value("CurrentItemName", pCurrentItem->GetEntity()->GetClass()->GetName());
  415.                 }
  416.                 else
  417.                 {
  418.                         string name("none");
  419.                         ser.Value("CurrentItemName", name);
  420.                 }
  421.         }
  422.  
  423.         //**************************************AMMO
  424.  
  425.         ser.BeginGroup("Ammo");
  426.  
  427.         TAmmoInfoMap::iterator ammoInfoIt = m_stats.ammoInfo.begin();
  428.         int ammoAmount = m_stats.ammoInfo.size();
  429.         ser.Value("AmmoAmount", ammoAmount);
  430.         for (int i = 0; i < ammoAmount; ++i)
  431.         {
  432.                 string name;
  433.                 int amount = 0;
  434.                 int users = 0;
  435.                 int capacity = 0;
  436.                 if (ser.IsWriting())
  437.                 {
  438.                         IEntityClass* pAmmoClass = ammoInfoIt->first;
  439.                         CRY_ASSERT(pAmmoClass);
  440.                         name = (pAmmoClass) ? pAmmoClass->GetName() : "";
  441.                         const SAmmoInfo& ammoInfo = ammoInfoIt->second;
  442.                         ;
  443.                         amount = ammoInfo.GetCount();
  444.                         capacity = ammoInfo.GetCapacity();
  445.  
  446.                         ++ammoInfoIt;
  447.                 }
  448.                 ser.BeginGroup("Ammo");
  449.                 ser.Value("AmmoName", name);
  450.                 ser.Value("Bullets", amount);
  451.                 ser.Value("Capacity", capacity);
  452.                 ser.EndGroup();
  453.                 if (ser.IsReading())
  454.                 {
  455.                         IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(name);
  456.                         CRY_ASSERT(pClass);
  457.                         TAmmoInfoMap::iterator it = m_stats.ammoInfo.find(pClass);
  458.                         if (it == m_stats.ammoInfo.end())
  459.                         {
  460.                                 m_stats.ammoInfo[pClass] = SAmmoInfo(amount, capacity);
  461.                         }
  462.                         else
  463.                         {
  464.                                 it->second.SetCount(amount);
  465.                                 it->second.SetCapacity(capacity);
  466.                         }
  467.                 }
  468.         }
  469.  
  470.         ser.EndGroup();
  471.  
  472.         m_bSerializeLTL = false;
  473. }
  474.  
  475. //------------------------------------------------------------------------
  476. void CInventory::ProcessEvent(SEntityEvent& event)
  477. {
  478.         FUNCTION_PROFILER(gEnv->pSystem, PROFILE_ACTION);
  479.  
  480.         if (event.event == ENTITY_EVENT_RESET)
  481.         {
  482.                 if (gEnv->IsEditor())
  483.                 {
  484.                         if (event.nParam[0]) // entering game mode in editor
  485.                                 m_editorstats = m_stats;
  486.                         else
  487.                         {
  488.                                 // leaving game mode
  489.                                 if (m_stats.currentItemId != INVALID_ENTITYID)
  490.                                         m_pGameFrameWork->GetIItemSystem()->SetActorItem(m_pActor, INVALID_ENTITYID, false);
  491.                                 m_stats = m_editorstats;
  492.  
  493.                                 //Validate inventory, some things might have changed, like some FG removing items while in editor game
  494.                                 Validate();
  495.                         }
  496.                 }
  497.         }
  498. }
  499.  
  500. //------------------------------------------------------------------------
  501. bool CInventory::AddItem(EntityId id)
  502. {
  503.         if (FindItem(id) > -1)
  504.                 return true;
  505.  
  506.         if (m_stats.slots.size() >= gEnv->pConsole->GetCVar("i_inventory_capacity")->GetIVal())
  507.                 return false;
  508.  
  509.         AddItemToCategorySlot(id);
  510.  
  511.         m_stats.slots.push_back(id);
  512.         std::sort(m_stats.slots.begin(), m_stats.slots.end(), compare_slots());
  513.  
  514.         TListenerVec::iterator iter = m_listeners.begin();
  515.         m_iteratingListeners = true;
  516.         while (iter != m_listeners.end())
  517.         {
  518.                 (*iter)->OnAddItem(id);
  519.                 ++iter;
  520.         }
  521.         m_iteratingListeners = false;
  522.  
  523.         return true;
  524. }
  525.  
  526. //------------------------------------------------------------------------
  527. bool CInventory::RemoveItem(EntityId id)
  528. {
  529.         bool result = stl::find_and_erase(m_stats.slots, id);
  530.  
  531.         if (result)
  532.                 RemoveItemFromCategorySlot(id);
  533.  
  534.         return result;
  535. }
  536.  
  537. //------------------------------------------------------------------------
  538. void CInventory::RemoveAllItems(bool forceClear)
  539. {
  540.         this->Clear(forceClear);
  541. }
  542.  
  543. //------------------------------------------------------------------------
  544. int CInventory::Validate()
  545. {
  546.         TInventoryVector copyOfSlots;
  547.         copyOfSlots.reserve(m_stats.slots.size());
  548.         std::swap(copyOfSlots, m_stats.slots);
  549.  
  550.         int count = 0;
  551.         const int slotCount = copyOfSlots.size();
  552.  
  553.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  554.         for (int i = 0; i < slotCount; ++i)
  555.         {
  556.                 EntityId itemId = copyOfSlots[i];
  557.                 IEntity* pEntity = pEntitySystem->GetEntity(itemId);
  558.                 if (!pEntity)
  559.                 {
  560.                         ++count;
  561.                 }
  562.                 else
  563.                 {
  564.                         m_stats.slots.push_back(itemId);
  565.                 }
  566.         }
  567.  
  568.         return count;
  569. }
  570.  
  571. //------------------------------------------------------------------------
  572. void CInventory::Destroy()
  573. {
  574.         //
  575.         //CryLog("%s::CInventory::Destroy()",GetEntity()->GetName());
  576.         //
  577.         if (!GetISystem()->IsSerializingFile())
  578.         {
  579.                 IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  580.                 IItemSystem* pItemSystem = gEnv->pGameFramework->GetIItemSystem();
  581.  
  582.                 TInventoryVector deleteList = m_stats.slots;
  583.                 for (TInventoryIt it = deleteList.begin(); it != deleteList.end(); ++it)
  584.                 {
  585.                         EntityId entityId = *it;
  586.  
  587.                         IItem* pItem = pItemSystem->GetItem(entityId);
  588.                         if (pItem)
  589.                         {
  590.                                 RemoveItemFromCategorySlot(pItem->GetEntityId());
  591.                                 pItem->RemoveOwnerAttachedAccessories();
  592.                                 pItem->AttachToHand(false);
  593.                                 pItem->AttachToBack(false);
  594.                                 pItem->SetOwnerId(0);
  595.                         }
  596.  
  597.                         pEntitySystem->RemoveEntity(entityId);
  598.                 }
  599.         }
  600.  
  601.         Clear();
  602. }
  603.  
  604. //------------------------------------------------------------------------
  605. void CInventory::Clear(bool forceClear)
  606. {
  607.         if (m_ignoreNextClear && !forceClear)
  608.         {
  609.                 m_ignoreNextClear = false;
  610.                 return;
  611.         }
  612.  
  613.         if (!gEnv->bServer)
  614.         {
  615.                 IItemSystem* pItemSystem = gEnv->pGameFramework->GetIItemSystem();
  616.  
  617.                 TInventoryIt end = m_stats.slots.end();
  618.                 for (TInventoryIt it = m_stats.slots.begin(); it != end; ++it)
  619.                 {
  620.                         if (IItem* pItem = pItemSystem->GetItem(*it))
  621.                         {
  622.                                 pItem->RemoveOwnerAttachedAccessories();
  623.                                 pItem->AttachToHand(false);
  624.                                 pItem->AttachToBack(false);
  625.                                 pItem->SetOwnerId(0);
  626.                                 pItem->GetEntity()->Hide(true);
  627.                         }
  628.                 }
  629.         }
  630.  
  631.         m_stats.slots.clear();
  632.         m_stats.accessorySlots.clear();
  633.         ResetAmmoAndUsers();
  634.  
  635.         for (int i = 0; i < IInventory::eInventorySlot_Last; ++i)
  636.         {
  637.                 m_stats.slotsInfo[i].Reset();
  638.         }
  639.  
  640.         m_stats.currentItemId = 0;
  641.         m_stats.holsteredItemId = 0;
  642.         m_stats.lastItemId = 0;
  643.  
  644.         TListenerVec::iterator iter = m_listeners.begin();
  645.         m_iteratingListeners = true;
  646.         while (iter != m_listeners.end())
  647.         {
  648.                 (*iter)->OnClearInventory();
  649.                 ++iter;
  650.         }
  651.         m_iteratingListeners = false;
  652. }
  653.  
  654. //------------------------------------------------------------------------
  655. #if DEBUG_INVENTORY_ENABLED
  656.  
  657. void CInventory::Dump() const
  658. {
  659.         struct Dumper
  660.         {
  661.                 Dumper(EntityId entityId, const char* desc)
  662.                 {
  663.                         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  664.                         IEntity* pEntity = pEntitySystem->GetEntity(entityId);
  665.                         CryLogAlways(">> Id: %u [%s] $3%s $5%s", entityId, pEntity ? pEntity->GetName() : "<unknown>", pEntity ? pEntity->GetClass()->GetName() : "<unknown>", desc ? desc : "");
  666.                 }
  667.         };
  668.  
  669.         int count = GetCount();
  670.         CryLogAlways("-- $3%s$1's Inventory: %d Items --", GetEntity()->GetName(), count);
  671.  
  672.         if (count)
  673.         {
  674.                 for (TInventoryCIt it = m_stats.slots.begin(); it != m_stats.slots.end(); ++it)
  675.                         Dumper dump(*it, 0);
  676.         }
  677.  
  678.         CryLogAlways(">> --");
  679.  
  680.         Dumper current(m_stats.currentItemId, "Current");
  681.         Dumper last(m_stats.lastItemId, "Last");
  682.         Dumper holstered(m_stats.holsteredItemId, "Holstered");
  683.  
  684.         CryLogAlways("-- $3%s$1's Inventory: %" PRISIZE_T " Ammo Types --", GetEntity()->GetName(), m_stats.ammoInfo.size());
  685.  
  686.         if (!m_stats.ammoInfo.empty())
  687.         {
  688.                 for (TAmmoInfoMap::const_iterator ait = m_stats.ammoInfo.begin(); ait != m_stats.ammoInfo.end(); ++ait)
  689.                         CryLogAlways(">> [%s] $3%d$1/$3%d", ait->first->GetName(), ait->second.GetCount(), GetAmmoCapacity(ait->first));
  690.         }
  691. }
  692.  
  693. #endif //DEBUG_INVENTORY_ENABLED
  694.  
  695. //------------------------------------------------------------------------
  696. int CInventory::GetCapacity() const
  697. {
  698.         return gEnv->pConsole->GetCVar("i_inventory_capacity")->GetIVal();
  699. }
  700.  
  701. //------------------------------------------------------------------------
  702. int CInventory::GetCount() const
  703. {
  704.         return m_stats.slots.size();
  705. }
  706.  
  707. //------------------------------------------------------------------------
  708. int CInventory::GetCountOfClass(const char* className) const
  709. {
  710.         int count = 0;
  711.  
  712.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  713.  
  714.         IEntityClass* pClass = (className != NULL) ? pEntitySystem->GetClassRegistry()->FindClass(className) : NULL;
  715.         if (pClass)
  716.         {
  717.                 for (TInventoryCIt it = m_stats.slots.begin(); it != m_stats.slots.end(); ++it)
  718.                 {
  719.                         IEntity* pEntity = pEntitySystem->GetEntity(*it);
  720.                         if ((pEntity != NULL) && (pEntity->GetClass() == pClass))
  721.                         {
  722.                                 ++count;
  723.                         }
  724.                 }
  725.                 TInventoryVectorEx::const_iterator endEx = m_stats.accessorySlots.end();
  726.                 for (TInventoryVectorEx::const_iterator cit = m_stats.accessorySlots.begin(); cit != endEx; ++cit)
  727.                 {
  728.                         if (*cit == pClass)
  729.                         {
  730.                                 count++;
  731.                         }
  732.                 }
  733.         }
  734.  
  735.         return count;
  736. }
  737. //------------------------------------------------------------------------
  738. int CInventory::GetCountOfCategory(const char* categoryName) const
  739. {
  740.         IItemSystem* pItemSystem = gEnv->pGameFramework->GetIItemSystem();
  741.  
  742.         int count = 0;
  743.         TInventoryCIt end = m_stats.slots.end();
  744.         for (TInventoryCIt it = m_stats.slots.begin(); it != end; ++it)
  745.         {
  746.                 IItem* pItem = pItemSystem->GetItem(*it);
  747.                 if (pItem)
  748.                 {
  749.                         const char* cat = pItemSystem->GetItemCategory(pItem->GetEntity()->GetClass()->GetName());
  750.                         if (!strcmp(cat, categoryName))
  751.                                 count++;
  752.                 }
  753.  
  754.         }
  755.         TInventoryVectorEx::const_iterator endEx = m_stats.accessorySlots.end();
  756.         for (TInventoryVectorEx::const_iterator cit = m_stats.accessorySlots.begin(); cit != endEx; ++cit)
  757.         {
  758.                 const char* cat = pItemSystem->GetItemCategory((*cit)->GetName());
  759.                 if (!strcmp(cat, categoryName))
  760.                         count++;
  761.         }
  762.  
  763.         return count;
  764. }
  765.  
  766. //------------------------------------------------------------------------
  767. int CInventory::GetCountOfUniqueId(uint8 uniqueId) const
  768. {
  769.         //Skip uniqueId 0
  770.         if (!uniqueId)
  771.                 return 0;
  772.  
  773.         IItemSystem* pItemSystem = gEnv->pGameFramework->GetIItemSystem();
  774.  
  775.         int count = 0;
  776.         TInventoryCIt end = m_stats.slots.end();
  777.         for (TInventoryCIt it = m_stats.slots.begin(); it != end; ++it)
  778.         {
  779.                 IItem* pItem = pItemSystem->GetItem(*it);
  780.                 if (pItem)
  781.                 {
  782.                         uint8 id = pItemSystem->GetItemUniqueId(pItem->GetEntity()->GetClass()->GetName());
  783.                         if (id == uniqueId)
  784.                                 count++;
  785.                 }
  786.  
  787.         }
  788.  
  789.         TInventoryVectorEx::const_iterator endEx = m_stats.accessorySlots.end();
  790.         for (TInventoryVectorEx::const_iterator cit = m_stats.accessorySlots.begin(); cit != endEx; ++cit)
  791.         {
  792.                 uint8 id = pItemSystem->GetItemUniqueId((*cit)->GetName());
  793.                 if (id == uniqueId)
  794.                         count++;
  795.         }
  796.  
  797.         return count;
  798. }
  799.  
  800. //------------------------------------------------------------------------
  801. int CInventory::GetSlotCount(int slotId) const
  802. {
  803.         return m_stats.slotsInfo[slotId].count;
  804. }
  805.  
  806. //------------------------------------------------------------------------
  807. EntityId CInventory::GetItem(int slotId) const
  808. {
  809.         if (slotId < 0 || slotId >= m_stats.slots.size())
  810.                 return 0;
  811.         return m_stats.slots[slotId];
  812. }
  813.  
  814. //------------------------------------------------------------------------
  815. const char* CInventory::GetItemString(int slotId) const
  816. {
  817.         if (slotId < 0 || slotId >= m_stats.slots.size())
  818.                 return "";
  819.  
  820.         EntityId ItemId = GetItem(slotId);
  821.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(ItemId);
  822.         if (pEntity)
  823.                 return pEntity->GetClass()->GetName();
  824.         else
  825.                 return "";
  826. }
  827.  
  828. //------------------------------------------------------------------------
  829. EntityId CInventory::GetItemByClass(IEntityClass* pClass, IItem* pIgnoreItem) const
  830. {
  831.         if (!pClass)
  832.                 return 0;
  833.  
  834.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  835.  
  836.         TInventoryCIt end = m_stats.slots.end();
  837.         for (TInventoryCIt it = m_stats.slots.begin(); it != end; ++it)
  838.         {
  839.                 if (IEntity* pEntity = pEntitySystem->GetEntity(*it))
  840.                         if (pEntity->GetClass() == pClass)
  841.                                 if (!pIgnoreItem || pIgnoreItem->GetEntity() != pEntity)
  842.                                         return *it;
  843.         }
  844.  
  845.         return 0;
  846. }
  847.  
  848. //------------------------------------------------------------------------
  849. IItem* CInventory::GetItemByName(const char* name) const
  850. {
  851.         if (!name)
  852.                 return 0;
  853.  
  854.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  855.  
  856.         TInventoryCIt end = m_stats.slots.end();
  857.         for (TInventoryCIt it = m_stats.slots.begin(); it != end; ++it)
  858.         {
  859.                 if (IEntity* pEntity = pEntitySystem->GetEntity(*it))
  860.                         if (!strcmp(pEntity->GetName(), name))
  861.                                 return gEnv->pGameFramework->GetIItemSystem()->GetItem(pEntity->GetId());
  862.         }
  863.  
  864.         return 0;
  865. }
  866.  
  867. //------------------------------------------
  868. int CInventory::GetAccessoryCount() const
  869. {
  870.         return m_stats.accessorySlots.size();
  871. }
  872.  
  873. //----------------------------------------
  874. const char* CInventory::GetAccessory(int slotId) const
  875. {
  876.         if (slotId >= 0 && slotId < m_stats.accessorySlots.size())
  877.         {
  878.                 return m_stats.accessorySlots[slotId]->GetName();
  879.         }
  880.  
  881.         return NULL;
  882. }
  883.  
  884. //----------------------------------------
  885. const IEntityClass* CInventory::GetAccessoryClass(int slotId) const
  886. {
  887.         if (slotId >= 0 && slotId < m_stats.accessorySlots.size())
  888.         {
  889.                 return m_stats.accessorySlots[slotId];
  890.         }
  891.  
  892.         return NULL;
  893. }
  894.  
  895. //----------------------------------------
  896. bool CInventory::HasAccessory(IEntityClass* pClass) const
  897. {
  898.         int size = m_stats.accessorySlots.size();
  899.         for (int i = 0; i < size; i++)
  900.         {
  901.                 if (m_stats.accessorySlots[i] == pClass)
  902.                         return true;
  903.         }
  904.  
  905.         return false;
  906. }
  907.  
  908. //-------------------------------------------------------------------
  909. bool CInventory::AddAccessory(IEntityClass* accessoryClass)
  910. {
  911.         if (accessoryClass == NULL)
  912.                 return false;
  913.  
  914.         if (GetAccessorySlotIndex(accessoryClass) > -1)
  915.                 return true;
  916.  
  917.         m_stats.accessorySlots.push_back(accessoryClass);
  918.         std::sort(m_stats.accessorySlots.begin(), m_stats.accessorySlots.end(), compare_class_slots());
  919.  
  920.         TListenerVec::iterator iter = m_listeners.begin();
  921.         m_iteratingListeners = true;
  922.         while (iter != m_listeners.end())
  923.         {
  924.                 (*iter)->OnAddAccessory(accessoryClass);
  925.                 ++iter;
  926.         }
  927.         m_iteratingListeners = false;
  928.  
  929.         return true;
  930. }
  931.  
  932. //-------------------------------------------------------------------
  933. int CInventory::GetAccessorySlotIndex(IEntityClass* accessoryClass) const
  934. {
  935.         for (int i = 0; i < m_stats.accessorySlots.size(); i++)
  936.         {
  937.                 if (m_stats.accessorySlots[i] == accessoryClass)
  938.                         return i;
  939.         }
  940.         return -1;
  941. }
  942.  
  943. //------------------------------------------------------------------------
  944. int CInventory::FindItem(EntityId itemId) const
  945. {
  946.         for (int i = 0; i < m_stats.slots.size(); i++)
  947.         {
  948.                 if (m_stats.slots[i] == itemId)
  949.                         return i;
  950.         }
  951.         return -1;
  952. }
  953.  
  954. //------------------------------------------------------------------------
  955. int CInventory::FindNext(IEntityClass* pClass, const char* category, int firstSlot, bool wrap) const
  956. {
  957.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  958.         for (int i = (firstSlot > -1) ? firstSlot + 1 : 0; i < m_stats.slots.size(); i++)
  959.         {
  960.                 IEntity* pEntity = pEntitySystem->GetEntity(m_stats.slots[i]);
  961.                 bool ok = true;
  962.                 if (pEntity->GetClass() != pClass)
  963.                         ok = false;
  964.                 if (ok && category && category[0] && strcmp(m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pEntity->GetClass()->GetName()), category))
  965.                         ok = false;
  966.  
  967.                 if (ok)
  968.                         return i;
  969.         }
  970.  
  971.         if (wrap && firstSlot > 0)
  972.         {
  973.                 for (int i = 0; i < firstSlot; i++)
  974.                 {
  975.                         IEntity* pEntity = pEntitySystem->GetEntity(m_stats.slots[i]);
  976.                         bool ok = true;
  977.                         if (pEntity->GetClass() != pClass)
  978.                                 ok = false;
  979.                         if (ok && category && category[0] && strcmp(m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pEntity->GetClass()->GetName()), category))
  980.                                 ok = false;
  981.  
  982.                         if (ok)
  983.                                 return i;
  984.                 }
  985.         }
  986.  
  987.         return -1;
  988. }
  989.  
  990. //------------------------------------------------------------------------
  991. int CInventory::FindPrev(IEntityClass* pClass, const char* category, int firstSlot, bool wrap) const
  992. {
  993.         IEntitySystem* pEntitySystem = gEnv->pEntitySystem;
  994.         for (int i = (firstSlot > -1) ? firstSlot + 1 : 0; i < m_stats.slots.size(); i++)
  995.         {
  996.                 IEntity* pEntity = pEntitySystem->GetEntity(m_stats.slots[firstSlot - i]);
  997.                 bool ok = true;
  998.                 if (pEntity->GetClass() != pClass)
  999.                         ok = false;
  1000.                 if (ok && category && category[0] && strcmp(m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pEntity->GetClass()->GetName()), category))
  1001.                         ok = false;
  1002.  
  1003.                 if (ok)
  1004.                         return i;
  1005.         }
  1006.  
  1007.         if (wrap && firstSlot > 0)
  1008.         {
  1009.                 int count = GetCount();
  1010.                 for (int i = 0; i < firstSlot; i++)
  1011.                 {
  1012.                         IEntity* pEntity = pEntitySystem->GetEntity(m_stats.slots[count - i + firstSlot]);
  1013.                         bool ok = true;
  1014.                         if (pEntity->GetClass() != pClass)
  1015.                                 ok = false;
  1016.                         if (ok && category && category[0] && strcmp(m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pEntity->GetClass()->GetName()), category))
  1017.                                 ok = false;
  1018.  
  1019.                         if (ok)
  1020.                                 return i;
  1021.                 }
  1022.         }
  1023.  
  1024.         return -1;
  1025. }
  1026.  
  1027. //------------------------------------------------------------------------
  1028. EntityId CInventory::GetHolsteredItem() const
  1029. {
  1030.         return m_stats.holsteredItemId;
  1031. }
  1032.  
  1033. //------------------------------------------------------------------------
  1034. EntityId CInventory::GetCurrentItem() const
  1035. {
  1036.         return m_stats.currentItemId;
  1037. }
  1038.  
  1039. //------------------------------------------------------------------------
  1040. void CInventory::SetCurrentItem(EntityId itemId)
  1041. {
  1042.         m_stats.currentItemId = itemId;
  1043.  
  1044.         SetLastSelectedInSlot(itemId);
  1045. }
  1046.  
  1047. //------------------------------------------------------------------------
  1048. void CInventory::SetLastItem(EntityId itemId)
  1049. {
  1050.         m_stats.lastItemId = itemId;
  1051. }
  1052.  
  1053. //------------------------------------------------------------------------
  1054. EntityId CInventory::GetLastItem() const
  1055. {
  1056.         if (FindItem(m_stats.lastItemId) > -1)
  1057.                 return m_stats.lastItemId;
  1058.  
  1059.         return 0;
  1060. }
  1061.  
  1062. //------------------------------------------------------------------------
  1063. void CInventory::HolsterItem(bool holster)
  1064. {
  1065.         //CryLogAlways("%s::HolsterItem(%s)", GetEntity()->GetName(), holster?"true":"false");
  1066.  
  1067.         if (!holster)
  1068.         {
  1069.                 if (m_stats.holsteredItemId)
  1070.                 {
  1071.                         IItem* pItem = m_pGameFrameWork->GetIItemSystem()->GetItem(m_stats.holsteredItemId);
  1072.  
  1073.                         if (pItem && pItem->CanSelect())
  1074.                         {
  1075.                                 m_pGameFrameWork->GetIItemSystem()->SetActorItem(GetActor(), m_stats.holsteredItemId, false);
  1076.                         }
  1077.                         else
  1078.                         {
  1079.                                 m_pGameFrameWork->GetIItemSystem()->SetActorItem(GetActor(), GetLastItem(), false);
  1080.                         }
  1081.                 }
  1082.  
  1083.                 m_stats.holsteredItemId = 0;
  1084.         }
  1085.         else if (m_stats.currentItemId && (!m_stats.holsteredItemId || m_stats.holsteredItemId == m_stats.currentItemId))
  1086.         {
  1087.                 m_stats.holsteredItemId = m_stats.currentItemId;
  1088.                 m_pGameFrameWork->GetIItemSystem()->SetActorItem(GetActor(), (EntityId)0, false);
  1089.         }
  1090. }
  1091.  
  1092. //------------------------------------------------------------------------
  1093. int CInventory::GetAmmoTypesCount() const
  1094. {
  1095.         return m_stats.ammoInfo.size();
  1096. }
  1097.  
  1098. //------------------------------------------------------------------------
  1099. IEntityClass* CInventory::GetAmmoType(int idx) const
  1100. {
  1101.         CRY_ASSERT(idx < m_stats.ammoInfo.size());
  1102.         TAmmoInfoMap::const_iterator it = m_stats.ammoInfo.begin();
  1103.         std::advance(it, idx);
  1104.         return it->first;
  1105. }
  1106.  
  1107. //------------------------------------------------------------------------
  1108. void CInventory::SetAmmoCount(IEntityClass* pAmmoType, int count)
  1109. {
  1110.         int capacity = GetAmmoCapacity(pAmmoType);
  1111.         CRY_ASSERT(pAmmoType);
  1112.         if (pAmmoType)
  1113.         {
  1114.                 if (capacity > 0)
  1115.                         m_stats.ammoInfo[pAmmoType].SetCount(min(count, capacity));
  1116.                 else
  1117.                         m_stats.ammoInfo[pAmmoType].SetCount(count);
  1118.         }
  1119.  
  1120.         TListenerVec::iterator iter = m_listeners.begin();
  1121.         m_iteratingListeners = true;
  1122.         while (iter != m_listeners.end())
  1123.         {
  1124.                 (*iter)->OnSetAmmoCount(pAmmoType, count);
  1125.                 ++iter;
  1126.         }
  1127.         m_iteratingListeners = false;
  1128. }
  1129.  
  1130. //------------------------------------------------------------------------
  1131. int CInventory::GetAmmoCount(IEntityClass* pAmmoType) const
  1132. {
  1133.         TAmmoInfoMap::const_iterator it = m_stats.ammoInfo.find(pAmmoType);
  1134.         if (it != m_stats.ammoInfo.end())
  1135.                 return it->second.GetCount();
  1136.  
  1137.         return 0;
  1138. }
  1139.  
  1140. //------------------------------------------------------------------------
  1141. void CInventory::SetAmmoCapacity(IEntityClass* pAmmoType, int max)
  1142. {
  1143.         //
  1144.         //CryLog("%s::CInventory::SetAmmoCapacity(%s,%d)", GetEntity()->GetName(),pAmmoType->GetName(), max);
  1145.         //
  1146.         if (pAmmoType)
  1147.         {
  1148.                 m_stats.ammoInfo[pAmmoType].SetCapacity(max);
  1149.  
  1150.                 if (GetAmmoCount(pAmmoType) > max)
  1151.                 {
  1152.                         SetAmmoCount(pAmmoType, max);
  1153.                 }
  1154.         }
  1155. }
  1156.  
  1157. //------------------------------------------------------------------------
  1158. int CInventory::GetAmmoCapacity(IEntityClass* pAmmoType) const
  1159. {
  1160.         TAmmoInfoMap::const_iterator it = m_stats.ammoInfo.find(pAmmoType);
  1161.         if (it != m_stats.ammoInfo.end())
  1162.                 return it->second.GetCapacity();
  1163.  
  1164.         return 0;
  1165. }
  1166.  
  1167. //------------------------------------------------------------------------
  1168. void CInventory::ResetAmmo()
  1169. {
  1170.         TAmmoInfoMap::iterator ammoInfoEndIt = m_stats.ammoInfo.end();
  1171.         for (TAmmoInfoMap::iterator ammoInfoIt = m_stats.ammoInfo.begin(); ammoInfoIt != ammoInfoEndIt; ++ammoInfoIt)
  1172.         {
  1173.                 ammoInfoIt->second.ResetCount();
  1174.         }
  1175. }
  1176.  
  1177. //------------------------------------------------------------------------
  1178. void CInventory::SetInventorySlotCapacity(IInventory::EInventorySlots slotId, unsigned int capacity)
  1179. {
  1180.         CRY_ASSERT_MESSAGE(((slotId >= 0) && (slotId < IInventory::eInventorySlot_Last)), "Invalid inventory slot!");
  1181.  
  1182.         m_stats.slotsInfo[slotId].maxCapacity = capacity;
  1183. }
  1184.  
  1185. //------------------------------------------------------------------------
  1186. void CInventory::AssociateItemCategoryToSlot(const char* itemCategory, IInventory::EInventorySlots slotId)
  1187. {
  1188.         CRY_ASSERT_MESSAGE(((slotId >= 0) && (slotId < IInventory::eInventorySlot_Last)), "Invalid inventory slot!");
  1189.  
  1190.         m_stats.categoriesToSlot.insert(TCategoriesToSlot::value_type(itemCategory, slotId));
  1191. }
  1192.  
  1193. //------------------------------------------------------------------------
  1194. EntityId CInventory::GetLastSelectedInSlot(IInventory::EInventorySlots slotId) const
  1195. {
  1196.         CRY_ASSERT_MESSAGE(((slotId >= 0) && (slotId < IInventory::eInventorySlot_Last)), "Invalid inventory slot!");
  1197.  
  1198.         return m_stats.slotsInfo[slotId].lastSelected;
  1199. }
  1200.  
  1201. //------------------------------------------------------------------------
  1202. void CInventory::SetLastSelectedInSlot(EntityId entityId)
  1203. {
  1204.         EInventorySlots slot = GetSlotFromEntityID(entityId);
  1205.         if (slot < eInventorySlot_Last)
  1206.         {
  1207.                 m_stats.slotsInfo[slot].lastSelected = entityId;
  1208.         }
  1209. }
  1210.  
  1211. //------------------------------------------------------------------------
  1212. void CInventory::AddItemToCategorySlot(EntityId entityId)
  1213. {
  1214.         EInventorySlots slot = GetSlotFromEntityID(entityId);
  1215.         if (slot < eInventorySlot_Last)
  1216.         {
  1217.                 m_stats.slotsInfo[slot].count++;
  1218.  
  1219.                 if ((m_stats.slotsInfo[slot].lastSelected == 0) || (gEnv->pEntitySystem->GetEntity(m_stats.slotsInfo[slot].lastSelected) == NULL))
  1220.                 {
  1221.                         m_stats.slotsInfo[slot].lastSelected = entityId;
  1222.                 }
  1223.         }
  1224. }
  1225.  
  1226. //------------------------------------------------------------------------
  1227. void CInventory::RemoveItemFromCategorySlot(EntityId entityId)
  1228. {
  1229.         EInventorySlots slot = GetSlotFromEntityID(entityId);
  1230.         if (slot < eInventorySlot_Last)
  1231.         {
  1232.                 m_stats.slotsInfo[slot].count--;
  1233.                 if ((m_stats.slotsInfo[slot].count > 0) && (entityId == m_stats.slotsInfo[slot].lastSelected))
  1234.                 {
  1235.  
  1236.                         const EntityId entityID = GetAnyEntityInSlot(slot);
  1237.                         if (entityID != 0)
  1238.                         {
  1239.                                 m_stats.slotsInfo[slot].lastSelected = entityID;
  1240.                         }
  1241.                 }
  1242.                 else
  1243.                 {
  1244.                         m_stats.slotsInfo[slot].lastSelected = 0;
  1245.                 }
  1246.         }
  1247. }
  1248.  
  1249. //------------------------------------------------------------------------
  1250. bool CInventory::IsAvailableSlotForItemClass(const char* itemClass) const
  1251. {
  1252.         const char* category = m_pGameFrameWork->GetIItemSystem()->GetItemCategory(itemClass);
  1253.  
  1254.         //If not category info, assume there is space
  1255.         if (!category || category[0] == '\0')
  1256.                 return true;
  1257.  
  1258.         return IsAvailableSlotForItemCategory(category);
  1259. }
  1260.  
  1261. //------------------------------------------------------------------------
  1262. bool CInventory::IsAvailableSlotForItemCategory(const char* itemCategory) const
  1263. {
  1264.         TCategoriesToSlot::const_iterator catToSlotCit = m_stats.categoriesToSlot.find(CONST_TEMP_STRING(itemCategory));
  1265.         if (catToSlotCit == m_stats.categoriesToSlot.end())
  1266.                 return true;
  1267.  
  1268.         const SSlotInfo& slotInfo = m_stats.slotsInfo[catToSlotCit->second];
  1269.  
  1270.         return (slotInfo.maxCapacity > slotInfo.count);
  1271. }
  1272.  
  1273. //------------------------------------------------------------------------
  1274. bool CInventory::AreItemsInSameSlot(const char* itemClass1, const char* itemClass2) const
  1275. {
  1276.         const char* category1 = m_pGameFrameWork->GetIItemSystem()->GetItemCategory(itemClass1);
  1277.         if (!category1 || category1[0] == '\0')
  1278.                 return false;
  1279.  
  1280.         const char* category2 = m_pGameFrameWork->GetIItemSystem()->GetItemCategory(itemClass2);
  1281.         if (!category2 || category2[0] == '\0')
  1282.                 return false;
  1283.  
  1284.         TCategoriesToSlot::const_iterator cit1 = m_stats.categoriesToSlot.find(CONST_TEMP_STRING(category1));
  1285.         TCategoriesToSlot::const_iterator cit2 = m_stats.categoriesToSlot.find(CONST_TEMP_STRING(category2));
  1286.         TCategoriesToSlot::const_iterator end = m_stats.categoriesToSlot.end();
  1287.  
  1288.         return ((cit1 != end) && (cit2 != end) && (cit1->second == cit2->second));
  1289. }
  1290.  
  1291. //----------------------------------------------------------------------
  1292. IInventory::EInventorySlots CInventory::GetSlotForItemCategory(const char* itemCategory) const
  1293. {
  1294.         TCategoriesToSlot::const_iterator cit1 = m_stats.categoriesToSlot.find(CONST_TEMP_STRING(itemCategory));
  1295.  
  1296.         return (cit1 != m_stats.categoriesToSlot.end()) ? cit1->second : IInventory::eInventorySlot_Last;
  1297. }
  1298.  
  1299. //------------------------------------------------------------------------
  1300. // client side call for RemoveAllItems
  1301. void CInventory::RMIReqToServer_RemoveAllItems() const
  1302. {
  1303.         TRMIInventory_Dummy Info;
  1304.  
  1305.         GetGameObject()->InvokeRMI(SvReq_RemoveAllItems(), Info, eRMI_ToServer);
  1306. }
  1307.  
  1308. // RMI receiver in the server to remove all items from the inventory. changes are automatically propagated to the clients
  1309. IMPLEMENT_RMI(CInventory, SvReq_RemoveAllItems)
  1310. {
  1311.         IItemSystem* pItemSystem = CCryAction::GetCryAction()->GetIItemSystem();
  1312.  
  1313.         IItem* pItem = pItemSystem->GetItem(GetCurrentItem());
  1314.         if (pItem)
  1315.         {
  1316.                 pItem->Select(false);
  1317.                 pItemSystem->SetActorItem(GetActor(), (EntityId)0, false);
  1318.         }
  1319.  
  1320.         Destroy();
  1321.  
  1322.         if (gEnv->bMultiplayer)
  1323.         {
  1324.                 TRMIInventory_Dummy Info;
  1325.                 GetGameObject()->InvokeRMI(Cl_RemoveAllAmmo(), Info, eRMI_ToAllClients);
  1326.         }
  1327.         else
  1328.         {
  1329.                 ResetAmmo();
  1330.         }
  1331.  
  1332.         return true;
  1333. }
  1334.  
  1335. //------------------------------------------------------------------------
  1336. // client side call for AddItem
  1337. void CInventory::RMIReqToServer_AddItem(const char* _pszItemClass) const
  1338. {
  1339.         TRMIInventory_Item Info(_pszItemClass);
  1340.  
  1341.         GetGameObject()->InvokeRMI(SvReq_AddItem(), Info, eRMI_ToServer);
  1342. }
  1343.  
  1344. // RMI receiver in the server to add an item to the inventory. change is automatically propagated to the clients
  1345. IMPLEMENT_RMI(CInventory, SvReq_AddItem)
  1346. {
  1347.         TRMIInventory_Item Info(params);
  1348.  
  1349.         gEnv->pGameFramework->GetIItemSystem()->GiveItem(GetActor(), Info.m_ItemClass.c_str(), false, true, true);
  1350.  
  1351.         return true;
  1352. }
  1353.  
  1354. //------------------------------------------------------------------------
  1355. // client side call for RemoveItem
  1356. void CInventory::RMIReqToServer_RemoveItem(const char* _pszItemClass) const
  1357. {
  1358.         TRMIInventory_Item Info(_pszItemClass);
  1359.  
  1360.         GetGameObject()->InvokeRMI(SvReq_RemoveItem(), Info, eRMI_ToServer);
  1361. }
  1362.  
  1363. // RMI receiver in the server to remove an item from the inventory. change is automatically propagated to the clients
  1364. IMPLEMENT_RMI(CInventory, SvReq_RemoveItem)
  1365. {
  1366.         TRMIInventory_Item Info(params);
  1367.  
  1368.         IItemSystem* pItemSystem = CCryAction::GetCryAction()->GetIItemSystem();
  1369.  
  1370.         IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(Info.m_ItemClass.c_str());
  1371.         if (pClass)
  1372.         {
  1373.                 IItem* pItem = pItemSystem->GetItem(GetItemByClass(pClass));
  1374.                 if (pItem && pItem->GetEntityId() == GetCurrentItem())
  1375.                 {
  1376.                         pItem->Select(false);
  1377.                         pItemSystem->SetActorItem(GetActor(), (EntityId)0, false);
  1378.                 }
  1379.  
  1380.                 if (pItem)
  1381.                         gEnv->pEntitySystem->RemoveEntity(pItem->GetEntityId());
  1382.         }
  1383.         return true;
  1384. }
  1385.  
  1386. //------------------------------------------------------------------------
  1387. IMPLEMENT_RMI(CInventory, Cl_SetAmmoCapacity)
  1388. {
  1389.         IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(params.m_AmmoClass.c_str());
  1390.         CRY_ASSERT(pClass);
  1391.  
  1392.         SetAmmoCapacity(pClass, params.m_iAmount);
  1393.  
  1394.         return true;
  1395. }
  1396.  
  1397. //------------------------------------------------------------------------
  1398. // client side call for SetAmmoCount
  1399. void CInventory::RMIReqToServer_SetAmmoCount(const char* _pszAmmoClass, int _iAmount) const
  1400. {
  1401.         TRMIInventory_Ammo Info(_pszAmmoClass, _iAmount);
  1402.  
  1403.         GetGameObject()->InvokeRMI(SvReq_SetAmmoCount(), Info, eRMI_ToServer);
  1404. }
  1405.  
  1406. // RMI receiver in the server to set the ammo count for an ammo class in the inventory.
  1407. IMPLEMENT_RMI(CInventory, SvReq_SetAmmoCount)
  1408. {
  1409.         TRMIInventory_Ammo Info(params);
  1410.  
  1411.         GetGameObject()->InvokeRMI(Cl_SetAmmoCount(), Info, eRMI_ToAllClients);
  1412.         return true;
  1413. }
  1414.  
  1415. // RMI receiver in clients for SetAmmoCount. This is needed because ammo changes are not automatically propagated
  1416. IMPLEMENT_RMI(CInventory, Cl_SetAmmoCount)
  1417. {
  1418.         TRMIInventory_Ammo Info(params);
  1419.  
  1420.         IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(Info.m_AmmoClass.c_str());
  1421.         if (pClass)
  1422.                 SetAmmoCount(pClass, Info.m_iAmount);
  1423.         return true;
  1424. }
  1425.  
  1426. // RMI receiver in clients for RemoveAllAmmo. This is needed because ammo changes are not automatically propagated
  1427. IMPLEMENT_RMI(CInventory, Cl_RemoveAllAmmo)
  1428. {
  1429.         ResetAmmo();
  1430.         return true;
  1431. }
  1432.  
  1433. //------------------------------------------------------------------------
  1434. // client side call for AddEquipmentPack
  1435. void CInventory::RMIReqToServer_AddEquipmentPack(const char* _pszEquipmentPack, bool _bAdd, bool _bPrimary) const
  1436. {
  1437.         TRMIInventory_EquipmentPack Info(_pszEquipmentPack, _bAdd, _bPrimary);
  1438.  
  1439.         GetGameObject()->InvokeRMI(SvReq_AddEquipmentPack(), Info, eRMI_ToServer);
  1440. }
  1441.  
  1442. // RMI receiver in the server to add an equipment pack to the inventory. change is automatically propagated to the clients
  1443. IMPLEMENT_RMI(CInventory, SvReq_AddEquipmentPack)
  1444. {
  1445.         TRMIInventory_EquipmentPack Info(params);
  1446.  
  1447.         CCryAction::GetCryAction()->GetIItemSystem()->GetIEquipmentManager()->GiveEquipmentPack(GetActor(), Info.m_EquipmentPack.c_str(), Info.m_bAdd, Info.m_bPrimary);
  1448.  
  1449.         return true;
  1450. }
  1451.  
  1452. //////////////////////////////////////////////////////////////////////////
  1453. void CInventory::AddAmmoUser(IEntityClass* pAmmoType)
  1454. {
  1455.         CRY_ASSERT(pAmmoType);
  1456.  
  1457.         if (pAmmoType)
  1458.         {
  1459.                 m_stats.ammoInfo[pAmmoType].AddUser();
  1460.         }
  1461. }
  1462.  
  1463. //////////////////////////////////////////////////////////////////////////
  1464. void CInventory::RemoveAmmoUser(IEntityClass* pAmmoType)
  1465. {
  1466.         CRY_ASSERT(pAmmoType);
  1467.  
  1468.         TAmmoInfoMap::iterator ammoUserIt = m_stats.ammoInfo.find(pAmmoType);
  1469.  
  1470.         CRY_ASSERT_MESSAGE(ammoUserIt != m_stats.ammoInfo.end(), "Trying to remove user of an ammo which never was added.");
  1471.  
  1472.         if (ammoUserIt != m_stats.ammoInfo.end())
  1473.         {
  1474.                 ammoUserIt->second.RemoveUser();
  1475.         }
  1476. }
  1477.  
  1478. //////////////////////////////////////////////////////////////////////////
  1479. int CInventory::GetNumberOfUsersForAmmo(IEntityClass* pAmmoType) const
  1480. {
  1481.         TAmmoInfoMap::const_iterator ammoUserCit = m_stats.ammoInfo.find(pAmmoType);
  1482.         if (ammoUserCit != m_stats.ammoInfo.end())
  1483.         {
  1484.                 return ammoUserCit->second.GetUserCount();
  1485.         }
  1486.  
  1487.         return 0;
  1488. }
  1489.  
  1490. //////////////////////////////////////////////////////////////////////////
  1491. void CInventory::ResetAmmoAndUsers()
  1492. {
  1493.         m_stats.ammoInfo.clear();
  1494. }
  1495.  
  1496. void CInventory::AddListener(struct IInventoryListener* pListener)
  1497. {
  1498.         CRY_ASSERT_MESSAGE(m_iteratingListeners == false, "AddListener called during a listener broadcast.");
  1499.         stl::push_back_unique(m_listeners, pListener);
  1500. }
  1501.  
  1502. void CInventory::RemoveListener(struct IInventoryListener* pListener)
  1503. {
  1504.         CRY_ASSERT_MESSAGE(m_iteratingListeners == false, "RemoveListener called during a listener broadcast.");
  1505.         stl::find_and_erase(m_listeners, pListener);
  1506. }
  1507.  
  1508. //////////////////////////////////////////////////////////////////////////
  1509. void CInventory::SetHolsteredItem(EntityId itemId)
  1510. {
  1511.         m_stats.holsteredItemId = itemId;
  1512. }
  1513.  
  1514. //////////////////////////////////////////////////////////////////////////
  1515. void CInventory::IgnoreNextClear()
  1516. {
  1517.         m_ignoreNextClear = true;
  1518. }
  1519.  
  1520. //////////////////////////////////////////////////////////////////////////
  1521. CInventory::EInventorySlots CInventory::GetSlotFromEntityID(EntityId entityID) const
  1522. {
  1523.         IEntity* pEntity = gEnv->pEntitySystem->GetEntity(entityID);
  1524.  
  1525.         if (pEntity)
  1526.         {
  1527.                 const char* category = m_pGameFrameWork->GetIItemSystem()->GetItemCategory(pEntity->GetClass()->GetName());
  1528.  
  1529.                 if (!category || category[0] == '\0')
  1530.                         return eInventorySlot_Last;
  1531.  
  1532.                 TCategoriesToSlot::const_iterator catToSlotCit = m_stats.categoriesToSlot.find(CONST_TEMP_STRING(category));
  1533.                 if (catToSlotCit == m_stats.categoriesToSlot.end())
  1534.                         return eInventorySlot_Last;
  1535.  
  1536.                 return catToSlotCit->second;
  1537.         }
  1538.  
  1539.         return eInventorySlot_Last;
  1540. }
  1541.  
  1542. EntityId CInventory::GetAnyEntityInSlot(int slot) const
  1543. {
  1544.         TInventoryCIt it = m_stats.slots.begin();
  1545.         const TInventoryCIt iEnd = m_stats.slots.end();
  1546.         for (; it != iEnd; ++it)
  1547.         {
  1548.                 if (GetSlotFromEntityID(*it) == slot)
  1549.                 {
  1550.                         return *it;
  1551.                 }
  1552.         }
  1553.  
  1554.         return 0;
  1555. }
  1556.  
downloadInventory.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top