Exemple #1
0
//---------------------------------------------------
// destroyItem :
//
//---------------------------------------------------
void CGameItemManager::destroyItem( CGameItemPtr &ptr )
{
	H_AUTO(GIM_destroyItem);
	
	if (ptr == NULL)
		return;

	// used to know if we modified the content of a bag on the ground
	CGameItemPtr modifiedBag = NULL;

	// Remove the item from it's inventory (if any)
	if (ptr->getInventory() != NULL)
	{
		ptr->getInventory()->removeItem(ptr->getInventorySlot());
	}
	if (ptr->getRefInventory() != NULL)
	{
		ptr->getRefInventory()->removeItem(ptr->getRefInventorySlot());
	}

	ptr.deleteItem();

} // destroyItem //
// ****************************************************************************
CInventoryBase::TInventoryOpResult CInventoryBase::doInsertItem(CGameItemPtr &item, uint32 slot, bool autoStack, bool ignoreWeightAndBulk)
{
	H_AUTO(doInsertItem);
	
	nlassert(item != NULL);
	nlassert(item->getInventory() == NULL);
	nlassert(slot < _Items.size() || slot == INVENTORIES::INSERT_IN_FIRST_FREE_SLOT);

	if (!ignoreWeightAndBulk)
	{
		if (item->getStackWeight() + getInventoryWeight() > getMaxWeight())
			return ior_overweight;
		if (item->getStackBulk() + getInventoryBulk() > getMaxBulk())
			return ior_overbulk;
	}

	if (autoStack)
	{
		H_AUTO(AutoStack);
		// If slot provided check we can stack if we can't find an empty slot
		if (slot != INVENTORIES::INSERT_IN_FIRST_FREE_SLOT)
			if (canStackItem(item, slot) != ior_ok)
				slot = INVENTORIES::INSERT_IN_FIRST_FREE_SLOT;

		uint32 slotBegin = slot;
		uint32 slotSearch;
		uint32 itemStackSize = item->getStackSize();

		// get first compatible stack
		if (slot == INVENTORIES::INSERT_IN_FIRST_FREE_SLOT)
			slotBegin = 0;
		slotSearch = slotBegin;
		// Modification to do : (slot to put item, stack size to put)
		vector< pair<uint32,uint32> > Modifs;

		// If slot provided is NULL directly insert item in it
		if (_Items[slotBegin] == NULL)
		{
			Modifs.push_back(make_pair(slotBegin, itemStackSize));
		}
		else
		{
			// do the following until all items in the stack are transfered to stacks (and empty slot)
			while (1)
			{
				// Search for a compatible stack (not null slot, not full slot)
				bool bFound = false;
				do
				{
					if (   (_Items[slotSearch] != NULL)
						&& (_Items[slotSearch]->getStackSize() < _Items[slotSearch]->getMaxStackSize())
						&& (CGameItem::areStackable(item, _Items[slotSearch]))) // no check on stack size here
					{
						bFound = true;
						break;
					}

					slotSearch++;
					if (slotSearch == getSlotCount()) slotSearch = 0;
				}
				while (slotSearch != slotBegin);

				if (bFound)
				{
					// We found a slot with an existing stack that is compatible
					// Try to put as much as we can into this stack
					if (itemStackSize > _Items[slotSearch]->getMaxStackSize() - _Items[slotSearch]->getStackSize())
					{
						uint32 sizePut = _Items[slotSearch]->getMaxStackSize() - _Items[slotSearch]->getStackSize();
						itemStackSize -= sizePut;
						Modifs.push_back(make_pair(slotSearch, sizePut));
						slotSearch++;
						if (slotSearch == getSlotCount()) slotSearch = 0;
						if (slotSearch != slotBegin)
							continue; // if we have not finished the loop try the next slot
					}
					else
					{
						Modifs.push_back(make_pair(slotSearch, itemStackSize));
						break; // finished
					}
				}

				// Can't insert item in an already existing stack
				if (getFreeSlotCount() == 0)
					return ior_no_free_slot; // No more empty slot in this inventory !!!
				slotSearch = getFirstFreeSlot();
				Modifs.push_back(make_pair(slotSearch, itemStackSize));
				break; // finished
			}
		}
		
		// Apply all modifs to the inventory
		bool bInserted = false;
		for (uint32 i = 0; i < Modifs.size(); ++i)
		{
			uint32 slotModif = Modifs[i].first;
			uint32 sizeModif = Modifs[i].second;

			if (_Items[slotModif] == NULL)
			{
				// set stack size before we add the item to the inventory to avoid the callback onItemStackSizeChanged()
				// which update weight and bulk
				item->setStackSize(sizeModif);

				// update weight and bulk "manually"
				updateWeightAndBulk(item, sizeModif);

				// put the item in the inventory
				_Items[slotModif] = item;
				item->setInventory(CInventoryPtr(this), slotModif);
				--_FreeSlotCount;
				onItemChanged(slotModif, INVENTORIES::itc_inserted);
				bInserted = true;
			}
			else
			{
				// callbacks are called in setStackSize (inventory onItemStackSizeChanged)
				_Items[slotModif]->setStackSize(_Items[slotModif]->getStackSize()+sizeModif);
			}
		}
		INVENTORIES::TInventoryChangeFlags flagInvChg(INVENTORIES::ic_total_bulk);
		flagInvChg.setEnumValue(INVENTORIES::ic_total_weight);
		flagInvChg.setEnumValue(INVENTORIES::ic_item_list);
		onInventoryChanged(flagInvChg);
		// If the item is not inserted into the inventory it has no more reason to exist because
		// it was fully splitted into all the stacks of the inventory
		if (!bInserted)
		{
			item.deleteItem();
			item = NULL;
		}
	}
	else
	{
		H_AUTO(NoneStackableItem);
		// check that we still have a free slot
		if (getFreeSlotCount() == 0)
			return ior_no_free_slot;

		if (slot == INVENTORIES::INSERT_IN_FIRST_FREE_SLOT)
			slot = getFirstFreeSlot();
		
		// delete any item on this slot
		if (_Items[slot] != NULL)
		{
			deleteItem(slot);
		}
		
		_Items[slot] = item;
		item->setInventory(CInventoryPtr(this), slot);
		updateWeightAndBulk(item, item->getStackSize());
		--_FreeSlotCount;
		
		// callback all the views : 2 messages : 
		// * item inserted 
		// * inventory change bulk, weight and list
		INVENTORIES::TInventoryChangeFlags flagInvChg(INVENTORIES::ic_total_bulk);
		flagInvChg.setEnumValue(INVENTORIES::ic_total_weight);
		flagInvChg.setEnumValue(INVENTORIES::ic_item_list);
		INVENTORIES::TItemChangeFlags flagItemChg(INVENTORIES::itc_inserted);
		TViewCont::iterator first(_InventoryViews.begin()), last(_InventoryViews.end());
		for (; first!= last; ++first)
		{
			CInventoryViewPtr view = *first;
			
			view->onInventoryChanged(flagInvChg);
			view->onItemChanged(slot, flagItemChg);
		}
	}
	return ior_ok;
}