void CInventory::PostSerialize() { for( int i=0; i<IInventory::eInventorySlot_Last; ++i ) { const int itemIndex = FindItem( m_stats.slotsInfo[i].lastSelected ); // For whatever reason we don't have this last item in the inventory, // so find a suitable item in the same slot. if( itemIndex == -1 ) { const EntityId entityId = GetAnyEntityInSlot( i ); SetLastSelectedInSlot(entityId); } } // Benito - This is last minute workaround to solve a strange bug: // 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 // when the game is loaded, the item is not restored properly, because the entity does not get a serialize call. // 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 const bool ownerActorIsClientNotInVehicle = (m_pActor != NULL) && m_pActor->IsClient() && (m_pActor->GetLinkedVehicle() == NULL); if(ownerActorIsClientNotInVehicle) { IItem* pCurrentItem = gEnv->pGame->GetIGameFramework()->GetIItemSystem()->GetItem(m_stats.currentItemId); if((pCurrentItem != NULL) && (pCurrentItem->GetOwnerId() == 0)) { if(pCurrentItem->CanUse(m_pActor->GetEntityId())) { m_stats.currentItemId = 0; //Reset and use it again pCurrentItem->Use(m_pActor->GetEntityId()); } } } }
//------------------------------------------------------------------------ void CInventory::FullSerialize( TSerialize ser ) { MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_Other, 0, "Inventory serialization"); IEntityPoolManager* pMgr = gEnv->pEntitySystem->GetIEntityPoolManager(); if(pMgr && !gEnv->pSystem->IsSerializingFile()) { // Entities being activated from the pool shouldn't // serialize their inventories. The item ids in the bookmark // refer to the previous entities which no longer exist, instead the // actor will have been given a new equipment pack instead. // In that case just holster the default weapon. We will have to // select it after on the behavior or on the entity side if (ser.IsReading()) { EntityId currentItemId = 0; bool isUsing = false; ser.Value("using", isUsing); ser.Value("CurrentItem", currentItemId); if (currentItemId) { IItem *pItem = m_pGameFrameWork->GetIItemSystem()->GetItem(currentItemId); if(pItem && isUsing && !pItem->IsUsed()) { pItem->Use(GetEntityId()); return; } } HolsterItem(true); } else { bool isUsing = false; if (IItem *pItem = m_pGameFrameWork->GetIItemSystem()->GetItem(m_stats.currentItemId)) isUsing = pItem->IsUsed() && pItem->GetOwnerId() == GetEntityId(); ser.Value("using", isUsing); ser.Value("CurrentItem", m_stats.currentItemId); } return; } ser.BeginGroup("InventoryItems"); ser.Value("CurrentItem", m_stats.currentItemId); ser.Value("HolsterItem", m_stats.holsteredItemId); ser.Value("LastItem", m_stats.lastItemId); int s = m_stats.slots.size(); ser.Value("InventorySize", s); if(ser.IsReading()) m_stats.slots.resize(s); ser.Value("Slots", m_stats.slots ); ser.BeginGroup("accessorySlots"); int exSize = m_stats.accessorySlots.size(); ser.Value("Size", exSize); for(int i = 0; i < IInventory::eInventorySlot_Last; ++i) { ser.BeginGroup("SlotInfo"); ser.Value("slotInfoCount", m_stats.slotsInfo[i].count); ser.Value("slotInfoLastSelected", m_stats.slotsInfo[i].lastSelected); ser.EndGroup(); } if(ser.IsReading()) { m_stats.accessorySlots.resize(0); if(exSize>0) m_stats.accessorySlots.reserve(exSize); } for(int i = 0; i<exSize; ++i) { string accessoryName; if(ser.IsWriting()) accessoryName = m_stats.accessorySlots[i]->GetName(); ser.BeginGroup("Class"); ser.Value("AccessoryName", accessoryName); ser.EndGroup(); if(ser.IsReading()) { IEntityClass* pAccessoryClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(accessoryName); CRY_ASSERT(pAccessoryClass); if (pAccessoryClass != NULL) { m_stats.accessorySlots.push_back(pAccessoryClass); } } } ser.EndGroup();//"accessorySlots" ser.BeginGroup("Ammo"); if(ser.IsReading()) { m_stats.ammoInfo.clear(); } TAmmoInfoMap::iterator ammoInfoIt = m_stats.ammoInfo.begin(); int ammoAmount = m_stats.ammoInfo.size(); ser.Value("AmmoAmount", ammoAmount); for(int i = 0; i < ammoAmount; ++i) { string name; int amount = 0; int capacity = 0; if(ser.IsWriting()) { IEntityClass* pAmmoClass = ammoInfoIt->first; CRY_ASSERT(pAmmoClass); name = (pAmmoClass) ? pAmmoClass->GetName() : ""; const SAmmoInfo& ammoInfo = ammoInfoIt->second; amount = ammoInfo.GetCount(); //users = ammoInfo.GetUserCount(); capacity = ammoInfo.GetCapacity(); // Only use this iterator writing. If we're reading, we change the size // of the map and end up with an out of sync (and invalid) iterator. ++ammoInfoIt; } ser.BeginGroup("Ammo"); ser.Value("AmmoName", name); ser.Value("Bullets", amount); ser.Value("Capacity", capacity); ser.EndGroup(); if(ser.IsReading()) { IEntityClass* pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass(name); CRY_ASSERT(pClass); TAmmoInfoMap::iterator it = m_stats.ammoInfo.find(pClass); if (it == m_stats.ammoInfo.end()) { m_stats.ammoInfo[pClass] = SAmmoInfo(amount, capacity); } else { it->second.SetCount(amount); it->second.SetCapacity(capacity); } } } ser.EndGroup(); /* ser.BeginGroup("CategorySlots"); for (TSlotsInfo::iterator it = m_stats.slotsInfo.begin(); it != m_stats.slotsInfo.end(); ++it) { ser.Value("Count", it->second.count); } ser.EndGroup();*/ ser.EndGroup(); }