示例#1
0
// ****************************************************************************
uint32 CInventoryBase::deleteStackItem(uint32 slot, uint32 quantity, TInventoryOpResult * res)
{
	nlassert(slot < _Items.size());
	
	uint32 nbDeletedItem = 0;

	CGameItemPtr item = getItem(slot);
	if(item->getStackSize() > quantity)
	{
		nbDeletedItem = quantity;
		item->setStackSize( item->getStackSize() - quantity );
//		log_Item_UpdateQuantity(item->getItemId(), item->getStackSize(), item->getStackSize() - quantity);
		if( res != NULL )
			*res = ior_ok;
	}
	else
	{
		nbDeletedItem = item->getStackSize();
		deleteItem(slot);
		if( res != NULL )
		{
			if( quantity == nbDeletedItem )
				*res = ior_ok;
			else
				*res = ior_stack_undersize;
		}
	}
	return nbDeletedItem;
}
示例#2
0
//-----------------------------------------------
// createInGameItem
//-----------------------------------------------
CGameItemPtr CGameItemManager::createInGameItem( uint16 quality, uint32 quantity, const NLMISC::CSheetId &sheet, const CEntityId &creatorId , const std::string * phraseId)
{
	H_AUTO(GIM_createInGameItem);

	static const CSheetId preorderSheetId("pre_order.sitem");
	
	if ( quantity == 0 || quality ==0 )
		return NULL;

//	static const CSheetId idSheetStack("stack.sitem");
	const CStaticItem* form = CSheets::getForm( sheet );
	if (!form)
	{
		nlwarning("<CCharacter::createInGameItem> Cannot find form of item %s", sheet.toString().c_str());
		return NULL;
	}

	CGameItemPtr item;
	CGameItemPtr sellingItem;
	// if item can be sold, get it in the sold items list
	if (	form->Family != ITEMFAMILY::RAW_MATERIAL 
		&&	form->Family != ITEMFAMILY::HARVEST_TOOL
		&&	form->Family != ITEMFAMILY::CRAFTING_TOOL
		&&	form->Family != ITEMFAMILY::CRYSTALLIZED_SPELL
		&&	form->Family != ITEMFAMILY::ITEM_SAP_RECHARGE
		&&	form->Family != ITEMFAMILY::FOOD
		)
	{
		vector< CGameItemPtr >::const_iterator it;
		const vector< CGameItemPtr >::const_iterator itEnd = CStaticItems::getStaticItems().end();
		for( it = CStaticItems::getStaticItems().begin(); it != itEnd; ++it )
		{
			if( (*it)->getSheetId() == sheet )
			{
				sellingItem = *it;
				break;
			}
		}
	}

	switch( form->Family )
	{
		case ITEMFAMILY::CRAFTING_TOOL:
		case ITEMFAMILY::HARVEST_TOOL:
		case ITEMFAMILY::RAW_MATERIAL:
		case ITEMFAMILY::TELEPORT:
		case ITEMFAMILY::CRYSTALLIZED_SPELL:
		case ITEMFAMILY::ITEM_SAP_RECHARGE:
		case ITEMFAMILY::MISSION_ITEM:
		case ITEMFAMILY::PET_ANIMAL_TICKET:
		case ITEMFAMILY::HANDLED_ITEM:
		case ITEMFAMILY::CONSUMABLE:
		case ITEMFAMILY::XP_CATALYSER:
		case ITEMFAMILY::SCROLL:
		case ITEMFAMILY::FOOD:
		case ITEMFAMILY::SCROLL_R2:
		case ITEMFAMILY::GENERIC_ITEM:
		{
			item = GameItemManager.createItem( const_cast< CSheetId& > ( sheet ), quality, true, true, creatorId);
		}
		break;
	default:
		{
			if( sellingItem != NULL )
			{
				item = sellingItem->getItemCopy();
				item->quality( quality );
				if ( phraseId )
					item->setPhraseId(*phraseId);
			}
			else if (sheet == preorderSheetId)
			{
				item = GameItemManager.createItem(sheet, quality, true, form->DropOrSell, creatorId);
			}
		}
		if( item == NULL)
		{
			nlwarning("<CCharacter::createInGameItem> Error while creating item : NULL pointer");
			return NULL;
		}
	}
	quantity = min(quantity, item->getMaxStackSize());
	item->setStackSize(quantity);
	return item;
} // createInGameItem //
示例#3
0
/// Remove the nth item from this inventory
// ****************************************************************************
CGameItemPtr CInventoryBase::removeItem(uint32 slot, uint32 quantity, TInventoryOpResult * res)
{
	nlassert(slot < _Items.size());

	CGameItemPtr ret = _Items[slot];

	if (quantity == 0)
	{
		if (res != NULL)
			*res = ior_ok;
		return NULL;
	}

	if (_Items[slot] != NULL)
	{
		if (quantity > _Items[slot]->getStackSize())
			quantity = _Items[slot]->getStackSize();

		// if we try to remove more items than available do not remove anything
		if (quantity > _Items[slot]->getNonLockedStackSize())
		{
			if (res != NULL)
				*res = ior_item_locked;
			return NULL;
		}

		INVENTORIES::TInventoryChangeFlags flagInvChg(INVENTORIES::ic_total_bulk);
		flagInvChg.setEnumValue(INVENTORIES::ic_total_weight);
		flagInvChg.setEnumValue(INVENTORIES::ic_item_list);

		// If we want to remove the whole stack
		if (quantity == _Items[slot]->getStackSize())
		{
			// callback all the views : 2 messages : 
			// * item removed
			// * inventory change bulk, weight and list
			INVENTORIES::TItemChangeFlags flagItemChg(INVENTORIES::itc_removed);
			TViewCont::iterator first(_InventoryViews.begin()), last(_InventoryViews.end());
			for (; first != last; ++first)
			{
				CInventoryViewPtr view = *first;
				
				view->onInventoryChanged(flagInvChg);
				view->onItemChanged(slot, flagItemChg);
			}

			// unlink from ref inventory
			if (_Items[slot]->getRefInventory() != NULL)
			{
				_Items[slot]->getRefInventory()->removeItem(_Items[slot]->getRefInventorySlot());
			}
			// unlink the item
			_Items[slot]->setInventory(CInventoryPtr(NULL), INVENTORIES::INVALID_INVENTORY_SLOT);
			_Items[slot] = NULL;
			++_FreeSlotCount;
			updateWeightAndBulk(ret, -sint32(ret->getStackSize()));
		}
		else // we want to remove a part of a stack
		{
			// create a new item
			ret = _Items[slot]->getItemCopy();
			ret->setStackSize(quantity);
			_Items[slot]->setStackSize(_Items[slot]->getStackSize()-quantity);

			// Done at the end because the item is not completly removed
			// callback all the views : 1 message :
			// * inventory change bulk, weight and list
			TViewCont::iterator first(_InventoryViews.begin()), last(_InventoryViews.end());
			for (; first != last; ++first)
			{
				CInventoryViewPtr view = *first;
				
				view->onInventoryChanged(flagInvChg);
			}
			
			// update ref inventory if some
			if (_Items[slot]->getRefInventory() != NULL)
			{
				_Items[slot]->getRefInventory()->onInventoryChanged(flagInvChg);
			}
		}
	}

	if (res != NULL)
		*res = ior_ok;

	// may be null
	return ret;
}
示例#4
0
// ****************************************************************************
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;
}