Beispiel #1
0
void Tile::__addThing(Creature* actor, int32_t, Thing* thing)
{
	if(Creature* creature = thing->getCreature())
	{
		g_game.clearSpectatorCache();
		creature->setParent(this);

		CreatureVector* creatures = makeCreatures();
		creatures->insert(creatures->begin(), creature);

		++thingCount;
		return;
	}

	Item* item = thing->getItem();
	if(!item)
	{
#ifdef __DEBUG_MOVESYS__
		std::clog << "[Failure - Tile::__addThing] item == NULL" << std::endl;
#endif
		return/* RET_NOTPOSSIBLE*/;
	}

	TileItemVector* items = getItemList();
	if(items && items->size() >= 0xFFFF)
		return/* RET_NOTPOSSIBLE*/;

	if(g_config.getBool(ConfigManager::STORE_TRASH) && !hasFlag(TILESTATE_TRASHED))
	{
		g_game.addTrash(pos);
		setFlag(TILESTATE_TRASHED);
	}

	item->setParent(this);
	if(item->isGroundTile())
	{
		if(ground)
		{
			int32_t oldGroundIndex = __getIndexOfThing(ground);
			Item* oldGround = ground;

			updateTileFlags(oldGround, true);
			updateTileFlags(item, false);
			ground = item;

#ifdef __GROUND_CACHE__
			std::map<Item*, int32_t>::iterator it = g_game.grounds.find(oldGround);
			bool erase = it == g_game.grounds.end();
			if(!erase)
			{
				it->second--;
				erase = it->second < 1;
				if(erase)
					g_game.grounds.erase(it);
			}

			if(erase)
			{
#endif
				oldGround->setParent(NULL);
				g_game.freeThing(oldGround);
#ifdef __GROUND_CACHE__
			}
#endif

			postRemoveNotification(actor, oldGround, NULL, oldGroundIndex, true);
			onUpdateTile();
		}
		else
		{
			ground = item;
			++thingCount;
			onAddTileItem(item);
		}
	}
	else if(item->isAlwaysOnTop())
	{
		if(item->isSplash())
		{
			//remove old splash if exists
			if(items)
			{
				for(ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it)
				{
					if(!(*it)->isSplash())
						continue;

					int32_t oldSplashIndex = __getIndexOfThing(*it);
					Item* oldSplash = *it;

					__removeThing(oldSplash, 1);
					oldSplash->setParent(NULL);
					g_game.freeThing(oldSplash);

					postRemoveNotification(actor, oldSplash, NULL, oldSplashIndex, true);
					break;
				}
			}
		}

		bool isInserted = false;
		if(items)
		{
			for(ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it)
			{
				//Note: this is different from internalAddThing
				if(Item::items[item->getID()].alwaysOnTopOrder > Item::items[(*it)->getID()].alwaysOnTopOrder)
					continue;

				items->insert(it, item);
				++thingCount;

				isInserted = true;
				break;
			}
		}
		else
			items = makeItemList();

		if(!isInserted)
		{
			items->push_back(item);
			++thingCount;
		}

		onAddTileItem(item);
	}
	else
	{
		if(item->isMagicField())
		{
			//remove old field item if exists
			if(items)
			{
				MagicField* oldField = NULL;
				for(ItemVector::iterator it = items->getBeginDownItem(); it != items->getEndDownItem(); ++it)
				{
					if(!(oldField = (*it)->getMagicField()))
						continue;

					if(oldField->isReplacable())
					{
						int32_t oldFieldIndex = __getIndexOfThing(*it);
						__removeThing(oldField, 1);

						oldField->setParent(NULL);
						g_game.freeThing(oldField);

						postRemoveNotification(actor, oldField, NULL, oldFieldIndex, true);
						break;
					}

					//This magic field cannot be replaced.
					item->setParent(NULL);
					g_game.freeThing(item);
					return;
				}
			}
		}

		if(item->getID() == ITEM_WATERBALL_SPLASH && !hasFlag(TILESTATE_TRASHHOLDER))
			item->setID(ITEM_WATERBALL);

		items = makeItemList();
		items->insert(items->getBeginDownItem(), item);

		++items->downItemCount;
		++thingCount;
		onAddTileItem(item);
	}
}