예제 #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
//---------------------------------------------------
// createItem :
//
//---------------------------------------------------
//CGameItemPtr CGameItemManager::createItem( CEntityId& id, CSheetId& sheetId, uint16 quality, sint16 slot, bool destroyable, bool dropable , const CEntityId &creatorId )
CGameItemPtr CGameItemManager::createItem( const CSheetId& sheetId, uint16 quality, bool destroyable, bool dropable , const CEntityId &creatorId )
{
	H_AUTO(GIM_createItem1);
	
	// test if the item already exists
//	map<CEntityId,CGameItemPtr>::iterator itIt = _Items.find( id );
//	if( itIt != _Items.end() )
//	{
//		nlwarning("<CGameItemManager::createItem> The item %s already exists",id.toString().c_str());
//		return NULL;
//	}

// MALKAV 22/01/03 :  get owner, if owner not found, returns before creating the item and display a simple warning
//	CGameItemPtr ownerItem = NULL;
//	if( owner != CEntityId::Unknown )
//	{
//		ownerItem = getItem( owner );
//		BOMB_IF(ownerItem == NULL ,"Bad owner found for item",return NULL);
//	}
//
	// create a new item
//	CGameItemPtr item = getNewItem( id, sheetId, quality, destroyable, dropable );
	CGameItemPtr item = getNewItem(sheetId, quality, destroyable, dropable );
	if( item != NULL )
	{
//		nldebug("<CGameItemManager::createItem> create item %s with owner %s",id.toString().c_str(), owner.toString().c_str());

//		(*item)->Owner = owner;
		(*item)->setCreator( creatorId );
		
		// insert the item in the map
//		_Items.insert( make_pair(id,item) );
//		_Items.insert( item );

		// insert the item in the children of the owner
// MALKAV 22/01/03 : test the owner existence sooner and use a warning instead of an nlerror to keep going
//		if( owner != CEntityId::Unknown )
//		{
//		 	CGameItemPtr ownerItem = getItem( owner );
//			if( ownerItem!=NULL )
//			{
//				(*ownerItem)->addChild( item, slot );
//			}
//			else
//			{				
//				nlerror("<CGameItemManager::createItem> Can't find the owner item %s",owner.toString().c_str());
//			}
//		}
	}
	else
	{
//		nlwarning("<CGameItemManager::createItem> Can't create the item %s with invalid sheet '%s'", id.toString().c_str(), sheetId.toString().c_str());
		nlwarning("<CGameItemManager::createItem> Can't create an item with invalid sheet '%s'", sheetId.toString().c_str());
	}

	log_Item_Create(item->getItemId(), item->getSheetId(), item->getStackSize(), item->quality());

	return item;

} // createItem //
예제 #3
0
// ****************************************************************************
CGameItemPtr CRefInventory::removeItem(uint32 slot, uint32 quantity, TInventoryOpResult * res)
{
	nlassert(slot < _Items.size());

	CGameItemPtr ret = _Items[slot];
	if (_Items[slot] != NULL)
	{
		// unlink the item
		_Items[slot]->setRefInventory(CInventoryPtr(NULL), INVENTORIES::INVALID_INVENTORY_SLOT);
		CGameItemPtr item = _Items[slot];
		_Items[slot] = NULL;
		++_FreeSlotCount;

		updateWeightAndBulk(ret, -sint32(ret->getStackSize()));

		// callbacks for derived class
		onItemChanged(slot, INVENTORIES::itc_removed);
		// callback views
		INVENTORIES::TInventoryChangeFlags flagInvChg(INVENTORIES::ic_total_bulk);
		flagInvChg.setEnumValue(INVENTORIES::ic_total_weight);
		flagInvChg.setEnumValue(INVENTORIES::ic_item_list);
		TViewCont::iterator first(_InventoryViews.begin()), last(_InventoryViews.end());
		for (; first != last; ++first)
		{
			CInventoryViewPtr view = *first;
			view->onInventoryChanged(flagInvChg);
			view->onItemChanged(slot, INVENTORIES::itc_removed);
		}
	}

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

	return ret;
}
예제 #4
0
/// test if we can stack an item on an existing one
// ****************************************************************************
CInventoryBase::TInventoryOpResult CInventoryBase::canStackItem(const CGameItemPtr &item, uint32 slotDst)
{
	if (item == NULL || slotDst >= getSlotCount())
		return ior_error;

	CGameItemPtr dstItem = getItem(slotDst);

	// ok if slot is empty
	if (dstItem == NULL)
		return ior_ok;

	// check item sheet and craft params
	if (!CGameItem::areStackable(item, dstItem))
		return ior_item_incompatible;

	const CStaticItem *srcForm = CSheets::getForm(item->getSheetId());

	if (dstItem->getStackSize() + item->getStackSize() > dstItem->getMaxStackSize())
		return ior_stack_oversize;

	return ior_ok;
}
예제 #5
0
// ****************************************************************************
void	CInventoryBase::onItemStackSizeChanged(uint32 slot, uint32 previousStackSize)
{
	CGameItemPtr item = getItem(slot);
	sint32 deltaSize = item->getStackSize() - previousStackSize;

	updateWeightAndBulk(item, deltaSize);

	// callback all the views
	TViewCont::iterator first(_InventoryViews.begin()), last(_InventoryViews.end());
	for (; first!= last; ++first)
	{
		CInventoryViewPtr view = *first;

		view->onItemStackSizeChanged(slot, previousStackSize);
	}
}
예제 #6
0
// ****************************************************************************
void CCharacterInvView::updateClientSlot(uint32 slot, const CGameItemPtr item)
{
	// do nothing if client is not ready
	if (!getCharacter()->getEnterFlag())
		return;

	if (item != NULL)
	{
		uint32 price;
		RM_FABER_STAT_TYPE::TRMStatType itemBestStat;

		getCharacter()->queryItemPrice( item, price );
		itemBestStat = item->getCraftParameters() == 0 ? RM_FABER_STAT_TYPE::Unknown : item->getCraftParameters()->getBestItemStat();

		BOTCHATTYPE::TBotChatResaleFlag resaleFlag = (item->durability() == item->maxDurability() ? BOTCHATTYPE::ResaleOk : BOTCHATTYPE::ResaleKOBroken);
		if (item->getLockedByOwner())
		{
			resaleFlag = BOTCHATTYPE::ResaleKOLockedByOwner;
		}

		INVENTORIES::CItemSlot itemSlot( slot );
		itemSlot.setItemProp( INVENTORIES::Sheet, item->getSheetId().asInt() );
		itemSlot.setItemProp( INVENTORIES::Quality, item->quality() );
		itemSlot.setItemProp( INVENTORIES::Quantity, item->getStackSize() );
		itemSlot.setItemProp( INVENTORIES::UserColor, item->color() );
		itemSlot.setItemProp( INVENTORIES::Locked, item->getLockCount() );
		itemSlot.setItemProp( INVENTORIES::Weight, item->weight() / 10 );
		itemSlot.setItemProp( INVENTORIES::NameId, item->sendNameId(getCharacter()) );
		itemSlot.setItemProp( INVENTORIES::Enchant, item->getClientEnchantValue() );
		itemSlot.setItemProp( INVENTORIES::Price, price );
		itemSlot.setItemProp( INVENTORIES::ResaleFlag, resaleFlag );
		itemSlot.setItemProp( INVENTORIES::ItemClass, item->getItemClass() );
		itemSlot.setItemProp( INVENTORIES::ItemBestStat, itemBestStat );
		itemSlot.setItemProp( INVENTORIES::PrerequisitValid, getCharacter()->checkPreRequired( item ) );
		itemSlot.setItemProp( INVENTORIES::Worned, (item->getItemWornState()==ITEM_WORN_STATE::Worned));
		getCharacter()->_InventoryUpdater.setItemProps( getInventory()->getInventoryId(), itemSlot );
	}
	else
	{
		// empty slot
		getCharacter()->_InventoryUpdater.resetItem( getInventory()->getInventoryId(), slot );
	}

	// send slot update to the client
	getCharacter()->_InventoryUpdater.incInfoVersion(getInventory()->getInventoryId(), slot);
}
예제 #7
0
// ****************************************************************************
CInventoryBase::TInventoryOpResult CRefInventory::doInsertItem(CGameItemPtr &item, uint32 slot, bool autoStack, bool ignoreWeightAndBulk)
{
	nlassert(item != NULL);
	nlassert(item->getRefInventory() == NULL);
	nlassert(slot < _Items.size() || slot == INVENTORIES::INVALID_INVENTORY_SLOT);

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

	// 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();

	// remove any item referenced here
	removeItem(slot);

	// insert and link the new item
	_Items[slot] = item;
	item->setRefInventory(CInventoryPtr(this), slot);
	updateWeightAndBulk(item, item->getStackSize());
	--_FreeSlotCount;

	// callbacks for derived class
	onItemChanged(slot, INVENTORIES::itc_inserted);
	// callback views
	/*TViewCont::iterator first(_InventoryViews.begin()), last(_InventoryViews.end());
	for (; first != last; ++first)
	{
		CInventoryViewPtr view = *first;
		view->onItemChanged(slot, itc_inserted);
	}*/

	return ior_ok;
}
예제 #8
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;
}
예제 #9
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;
}