コード例 #1
0
ファイル: tile.cpp プロジェクト: divinity76/server
uint32_t Tile::getHeight() const
{
	uint32_t height = 0;
	Item* iiItem = NULL;
	for(uint32_t i = 0; i < getThingCount(); ++i){
		iiItem = __getThing(i)->getItem();

		if(iiItem && iiItem->hasProperty(HASHEIGHT))
			++height;
	}

	return height;
}
コード例 #2
0
ファイル: container.cpp プロジェクト: ChubNtuck/avesta74
Cylinder* Container::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
	uint32_t& flags)
{
	if(index == 254 /*move up*/){
		index = INDEX_WHEREEVER;
		*destItem = NULL;
		
		Container* parentContainer = dynamic_cast<Container*>(getParent());
		if(parentContainer)
			return parentContainer;
		else
			return this;
	}
	else if(index == 255 /*add wherever*/){
		index = INDEX_WHEREEVER;
		*destItem = NULL;
		return this;
	}
	else{
		if(index >= (int32_t)capacity()){
			/*
			if you have a container, maximize it to show all 20 slots
			then you open a bag that is inside the container you will have a bag with 8 slots
			and a "grey" area where the other 12 slots where from the container
			if you drop the item on that grey area
			the client calculates the slot position as if the bag has 20 slots
			*/

			index = INDEX_WHEREEVER;
		}

		if(index != INDEX_WHEREEVER){
			Thing* destThing = __getThing(index);
			if(destThing)
				*destItem = destThing->getItem();

			Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem);

			if(subCylinder){
				index = INDEX_WHEREEVER;
				*destItem = NULL;
				return subCylinder;
			}
		}
	}
	
	return this;
}
コード例 #3
0
ファイル: container.cpp プロジェクト: ChubNtuck/avesta74
ReturnValue Container::__queryMaxCount(int32_t index, const Thing* thing, uint32_t count,
	uint32_t& maxQueryCount, uint32_t flags) const
{
	const Item* item = thing->getItem();
	if(item == NULL){
		maxQueryCount = 0;
		return RET_NOTPOSSIBLE;
	}

	if( ((flags & FLAG_NOLIMIT) == FLAG_NOLIMIT) ){
		maxQueryCount = std::max((uint32_t)1, count);
		return RET_NOERROR;
	}

	int32_t freeSlots = std::max((int32_t)(capacity() - size()), (int32_t)0);

	if(item->isStackable()){
		uint32_t n = 0;
		
		if(index != INDEX_WHEREEVER){
			const Thing* destThing = __getThing(index);
			const Item* destItem = NULL;
			if(destThing)
				destItem = destThing->getItem();

			if(destItem && destItem->getID() == item->getID()){
				n = 100 - destItem->getItemCount();
			}
		}

		maxQueryCount = freeSlots * 100 + n;

		if(maxQueryCount < count){
			return RET_CONTAINERNOTENOUGHROOM;
		}
	}
	else{
		maxQueryCount = freeSlots;

		if(maxQueryCount == 0){
			return RET_CONTAINERNOTENOUGHROOM;
		}
	}

	return RET_NOERROR;
}
コード例 #4
0
ファイル: container.cpp プロジェクト: Klailex/otxserver
Cylinder* Container::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
                                        uint32_t& flags)
{
    if(index == 254 /*move up*/)
    {
        index = INDEX_WHEREEVER;
        *destItem = NULL;

        Container* parentContainer = dynamic_cast<Container*>(getParent());
        if(parentContainer)
            return parentContainer;

        return this;
    }

    if(index == 255 /*add wherever*/)
    {
        index = INDEX_WHEREEVER;
        *destItem = NULL;
    }
    else if(index >= (int32_t)capacity())
    {
        /*
        if you have a container, maximize it to show all 20 slots
        then you open a bag that is inside the container you will have a bag with 8 slots
        and a "grey" area where the other 12 slots where from the container
        if you drop the item on that grey area the client calculates the slot position
        as if the bag has 20 slots
        */

        index = INDEX_WHEREEVER;
        *destItem = NULL;
    }

    const Item* item = thing->getItem();
    if(!item)
        return this;

    if(!((flags & FLAG_IGNOREAUTOSTACK) == FLAG_IGNOREAUTOSTACK)
            && item->isStackable() && item->getParent() != this)
    {
        //try to find a suitable item to stack with
        uint32_t n = itemlist.size();
        for(ItemList::reverse_iterator cit = itemlist.rbegin(); cit != itemlist.rend(); ++cit, --n)
        {
            if((*cit)->getID() == item->getID() && (*cit)->getItemCount() < 100)
            {
                *destItem = (*cit);
                index = n;
                return this;
            }
        }
    }

    if(index != INDEX_WHEREEVER)
    {
        Thing* destThing = __getThing(index);
        if(destThing)
            *destItem = destThing->getItem();

        if(Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem))
        {
            index = INDEX_WHEREEVER;
            *destItem = NULL;
            return subCylinder;
        }
    }

    return this;
}
コード例 #5
0
ファイル: container.cpp プロジェクト: Klailex/otxserver
ReturnValue Container::__queryMaxCount(int32_t index, const Thing* thing, uint32_t count,
                                       uint32_t& maxQueryCount, uint32_t flags) const
{
    const Item* item = thing->getItem();
    if(!item)
    {
        maxQueryCount = 0;
        return RET_NOTPOSSIBLE;
    }

    if(((flags & FLAG_NOLIMIT) == FLAG_NOLIMIT))
    {
        maxQueryCount = std::max((uint32_t)1, count);
        return RET_NOERROR;
    }

    int32_t freeSlots = std::max((int32_t)(capacity() - size()), (int32_t)0);
    if(item->isStackable())
    {
        uint32_t n = 0;
        if(index == INDEX_WHEREEVER)
        {
            //Iterate through every item and check how much free stackable slots there is.
            uint32_t slotIndex = 0;
            for(ItemList::const_iterator cit = itemlist.begin(); cit != itemlist.end(); ++cit, ++slotIndex)
            {
                if((*cit) != item && (*cit)->getID() == item->getID() && (*cit)->getItemCount() < 100)
                {
                    uint32_t remainder = (100 - (*cit)->getItemCount());
                    if(__queryAdd(slotIndex, item, remainder, flags) == RET_NOERROR)
                        n += remainder;
                }
            }
        }
        else
        {
            const Thing* destThing = __getThing(index-1);
            const Item* destItem = NULL;
            if(destThing)
                destItem = destThing->getItem();

            if(destItem && destItem->getID() == item->getID() && destItem->getItemCount() < 100)
            {
                uint32_t remainder = 100 - destItem->getItemCount();
                if(__queryAdd(index, item, remainder, flags) == RET_NOERROR)
                    n = remainder;
            }
        }

        maxQueryCount = freeSlots * 100 + n;
        if(maxQueryCount < count)
            return RET_CONTAINERNOTENOUGHROOM;
    }
    else
    {
        maxQueryCount = freeSlots;
        if(maxQueryCount == 0)
            return RET_CONTAINERNOTENOUGHROOM;
    }

    return RET_NOERROR;
}
コード例 #6
0
ファイル: tile.cpp プロジェクト: edubart/otserv
ReturnValue Tile::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
                             uint32_t flags) const
{
	const CreatureVector* creatures = getCreatures();
	const TileItemVector* items = getItemList();

	if (const Creature* creature = thing->getCreature())
	{
		if (hasBitSet(FLAG_NOLIMIT, flags))
		{
			return RET_NOERROR;
		}

		if (hasBitSet(FLAG_PATHFINDING, flags))
		{
			if (floorChange() || positionChange())
			{
				return RET_NOTPOSSIBLE;
			}
		}

		if (!ground)
		{
			return RET_NOTPOSSIBLE;
		}

		if (const Monster* monster = creature->getMonster())
		{
			if (hasFlag(TILESTATE_PROTECTIONZONE))
			{
				return RET_NOTPOSSIBLE;
			}

			if (floorChange() || positionChange())
			{
				return RET_NOTPOSSIBLE;
			}

			if (monster->canPushCreatures() && !monster->isSummon())
			{
				if (creatures)
				{
					Creature* creature;

					for (uint32_t i = 0; i < creatures->size(); ++i)
					{
						creature = creatures->at(i);

						if (monster->canWalkthrough(creature))
						{
							continue;
						}

						if (!creature->getMonster() ||
						        !creature->isPushable() ||
						        (creature->getMonster()->isPlayerSummon()))
						{
							return RET_NOTPOSSIBLE;
						}
					}
				}
			}
			else if (creatures && !creatures->empty())
			{
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if (!monster->canWalkthrough(*cit))
					{
						return RET_NOTENOUGHROOM;
					}
				}
			}

			if (hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID))
			{
				return RET_NOTPOSSIBLE;
			}

			if (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH))
			{
				return RET_NOTPOSSIBLE;
			}

			if (hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH)))
			{
				if (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags)))
				{
					return RET_NOTPOSSIBLE;
				}
			}

			MagicField* field = getFieldItem();

			if (field && !field->isBlocking(monster))
			{
				CombatType_t combatType = field->getCombatType();

				//There are 3 options for a monster to enter a magic field
				//1) Monster is immune
				if (!monster->isImmune(combatType))
				{
					//2) Monster is "strong" enough to handle the damage and was attacked
					//3) Monster is already afflicated by this type of condition
					if (hasBitSet(FLAG_IGNOREFIELDDAMAGE, flags))
					{
						if (!monster->hasCondition(Combat::DamageToConditionType(combatType), false))
						{
							if (!monster->canPushItems() || !monster->hadRecentBattle())
							{
								return RET_NOTPOSSIBLE;
							}
						}
					}
					else
					{
						return RET_NOTPOSSIBLE;
					}
				}
			}
		}
		else if (const Player* player = creature->getPlayer())
		{
			if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
			{
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if (!player->canWalkthrough(*cit))
					{
						return RET_NOTENOUGHROOM; //RET_NOTPOSSIBLE
					}
				}
			}

			if (!player->getParent() && hasFlag(TILESTATE_NOLOGOUT))
			{
				//player is trying to login to a "no logout" tile
				return RET_NOTPOSSIBLE;
			}

			if (player->getTile())
			{
				if (player->isPzLocked() && !player->getTile()->hasFlag(TILESTATE_PVPZONE) && hasFlag(TILESTATE_PVPZONE))
				{
					//player is trying to enter a pvp zone while being pz-locked
					return RET_PLAYERISPZLOCKEDENTERPVPZONE;
				}

				if (player->isPzLocked() && player->getTile()->hasFlag(TILESTATE_PVPZONE) && !hasFlag(TILESTATE_PVPZONE))
				{
					//player is trying to leave a pvp zone while being pz-locked
					return RET_PLAYERISPZLOCKEDLEAVEPVPZONE;
				}
			}

			if (hasFlag(TILESTATE_NOPVPZONE) && player->isPzLocked())
			{
				return RET_PLAYERISPZLOCKED;
			}

			if (hasFlag(TILESTATE_PROTECTIONZONE) && player->isPzLocked())
			{
				return RET_PLAYERISPZLOCKED;
			}
		}
		else
		{
			if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
			{
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if (!creature->canWalkthrough(*cit))
					{
						return RET_NOTENOUGHROOM;
					}
				}
			}
		}

		if (items)
		{
			MagicField* field = getFieldItem();

			if (field && field->isBlocking(creature))
			{
				return RET_NOTPOSSIBLE;
			}

			if (!hasBitSet(FLAG_IGNOREBLOCKITEM, flags))
			{
				//If the FLAG_IGNOREBLOCKITEM bit isn't set we dont have to iterate every single item
				if (hasFlag(TILESTATE_BLOCKSOLID))
				{
					return RET_NOTENOUGHROOM;
				}
			}
			else
			{
				//FLAG_IGNOREBLOCKITEM is set
				if (ground)
				{
					const ItemType& iiType = Item::items[ground->getID()];

					if (ground->isBlocking(creature) && (!iiType.moveable || ground->getUniqueId() != 0))
					{
						return RET_NOTPOSSIBLE;
					}
				}

				if (const TileItemVector* items = getItemList())
				{
					Item* iitem;

					for (ItemVector::const_iterator it = items->begin(); it != items->end(); ++it)
					{
						iitem = (*it);
						const ItemType& iiType = Item::items[iitem->getID()];

						if (iitem->isBlocking(creature) && (!iiType.moveable || iitem->getUniqueId() != 0))
						{
							return RET_NOTPOSSIBLE;
						}
					}
				}
			}
		}
	}
	else if (const Item* item = thing->getItem())
	{
#ifdef __DEBUG__

		if (!thing->getParent() && !hasBitSet(FLAG_NOLIMIT, flags))
		{
			std::cout << "Notice: Tile::__queryAdd() - thing->getParent() == NULL" << std::endl;
		}

#endif

		if (items)
		{
			int64_t c = g_config.getNumber(ConfigManager::MAX_STACK_SIZE);
			//acceptable stack sizes should be higher than 100 and <= than 65535
			uint16_t max_stack_size = uint16_t(std::max(std::min(c, int64_t(0xFFFF)), int64_t(100)));

			if (items->size() >= max_stack_size)
			{
				return RET_NOTPOSSIBLE;
			}
		}

		if (hasBitSet(FLAG_NOLIMIT, flags))
		{
			return RET_NOERROR;
		}

		bool itemIsHangable = item->isHangable();

		if (!ground && !itemIsHangable)
		{
			return RET_NOTPOSSIBLE;
		}

		if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
		{
			for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
			{
				if ((!(*cit)->getPlayer() || !(*cit)->getPlayer()->hasSomeInvisibilityFlag()) && item->isBlocking(*cit))
				{
					return RET_NOTENOUGHROOM;
				}
			}
		}

		const uint32_t itemLimit = g_config.getNumber(hasFlag(TILESTATE_PROTECTIONZONE) ? ConfigManager::PROTECTION_TILE_LIMIT : ConfigManager::TILE_LIMIT);

		if (itemLimit && getThingCount() > itemLimit)
		{
			return RET_TILEISFULL;
		}

		bool hasHangable = false;
		bool supportHangable = false;

		if (items)
		{
			Thing* iithing = NULL;

			for (uint32_t i = 0; i < getThingCount(); ++i)
			{
				iithing = __getThing(i);

				if (const Item* iitem = iithing->getItem())
				{
					const ItemType& iiType = Item::items[iitem->getID()];

					if (iiType.isHangable)
					{
						hasHangable = true;
					}

					if (iiType.isHorizontal || iiType.isVertical)
					{
						supportHangable = true;
					}

					if (itemIsHangable && (iiType.isHorizontal || iiType.isVertical))
					{
						//
					}
					else if (iiType.blockSolid || iiType.isSolidForItems())
					{
						if (item->isPickupable())
						{
							if (iiType.allowPickupable)
							{
								continue;
							}

							if (!iiType.hasHeight || iiType.pickupable || iiType.isBed())
							{
								return RET_NOTENOUGHROOM;
							}
						}
						else
						{
							return RET_NOTENOUGHROOM;
						}
					}
				}
			}
		}

		if (itemIsHangable && hasHangable && supportHangable)
		{
			return RET_NEEDEXCHANGE;
		}
	}

	return RET_NOERROR;
}
コード例 #7
0
ファイル: container.cpp プロジェクト: TwistedScorpio/OTHire
Cylinder* Container::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
	uint32_t& flags)
{
	if(index == 254 /*move up*/){
		index = INDEX_WHEREEVER;
		*destItem = NULL;

		Container* parentContainer = dynamic_cast<Container*>(getParent());
		if(parentContainer)
			return parentContainer;

		return this;
	}

	if(index == 255 /*add wherever*/){
		index = INDEX_WHEREEVER;
		*destItem = NULL;
	}
	else if(index >= (int32_t)capacity()){
		/*
		if you have a container, maximize it to show all 20 slots
		then you open a bag that is inside the container you will have a bag with 8 slots
		and a "grey" area where the other 12 slots where from the container
		if you drop the item on that grey area
		the client calculates the slot position as if the bag has 20 slots
		*/

		index = INDEX_WHEREEVER;
		*destItem = NULL;
	}

	const Item* item = thing->getItem();
	if(item == NULL){
		return this;
	}

	bool autoStack = g_config.getBoolean(ConfigManager::CONTAINER_ITEMS_AUTO_STACK);
	if(autoStack){
		if(item->isStackable()){
			if(item->getParent() != this){
				//try find a suitable item to stack with
				uint32_t n = 0;
				for(ItemList::iterator cit = itemlist.begin(); cit != itemlist.end(); ++cit){
					if((*cit) != item && (*cit)->getID() == item->getID() && (*cit)->getItemCount() < 100){
						*destItem = (*cit);
						index = n;
						return this;
					}

					++n;
				}
			}
		}
	}

	if(index != INDEX_WHEREEVER){
		Thing* destThing = __getThing(index);
		if(destThing)
			*destItem = destThing->getItem();

		Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem);

		if(subCylinder){
			index = INDEX_WHEREEVER;
			*destItem = NULL;
			return subCylinder;
		}
	}

	return this;
}
コード例 #8
0
ファイル: tile.cpp プロジェクト: CaosJunior/DxP
ReturnValue Tile::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
	uint32_t flags) const
{
	const CreatureVector* creatures = getCreatures();
	const TileItemVector* items = getItemList();
	if(const Creature* creature = thing->getCreature())
	{
        if(ground)
	{
	 if(const Monster* monster = creature->getMonster())
				{
					const ItemType& iType = Item::items[ground->getID()];
					if(ground->getID() == 11756)
						return RET_NOTPOSSIBLE;
					if(ground->getID() == 4821)
						return RET_NOTPOSSIBLE;
                    if(ground->getID() == 4822)
						return RET_NOTPOSSIBLE;
                    if(ground->getID() == 4823)
						return RET_NOTPOSSIBLE;
                    if(ground->getID() == 4824)
						return RET_NOTPOSSIBLE;
                    if(ground->getID() == 4825)
						return RET_NOTPOSSIBLE;                	
				}
    }      
             
		if(hasBitSet(FLAG_NOLIMIT, flags))
			return RET_NOERROR;

		if(hasBitSet(FLAG_PATHFINDING, flags))
		{
			if(floorChange() || positionChange())
				return RET_NOTPOSSIBLE;
		}

		if(!ground)
			return RET_NOTPOSSIBLE;

		if(const Monster* monster = creature->getMonster())
		{
			if((hasFlag(TILESTATE_PROTECTIONZONE)) && monster->isSummon())
				return RET_NOERROR;

			if(floorChange() || positionChange())
				return RET_NOTPOSSIBLE;

			if(monster->canPushCreatures() && !monster->isSummon())
			{
				if(creatures)
				{
					Creature* tmp = NULL;
					for(uint32_t i = 0; i < creatures->size(); ++i)
					{
						tmp = creatures->at(i);
						if(creature->canWalkthrough(tmp))
							continue;

						if(!tmp->getMonster() || !tmp->isPushable() ||
							(tmp->getMonster()->isSummon() &&
							tmp->getMonster()->isPlayerSummon()))
							return RET_NOTPOSSIBLE;
					}
				}
			}
			else if(creatures && !creatures->empty())
			{
				for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if(!creature->canWalkthrough(*cit))
						return RET_NOTENOUGHROOM;
				}
			}

			if(hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID))
				return RET_NOTPOSSIBLE;

			if(hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH))
				return RET_NOTPOSSIBLE;

			if((hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH)))
				&& (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags))))
				return RET_NOTPOSSIBLE;

			MagicField* field = getFieldItem();
			if(field && !field->isBlocking(monster))
			{
				CombatType_t combatType = field->getCombatType();
				//There is 3 options for a monster to enter a magic field
				//1) Monster is immune
				if(!monster->isImmune(combatType))
				{
					//1) Monster is "strong" enough to handle the damage
					//2) Monster is already afflicated by this type of condition
					if(!hasBitSet(FLAG_IGNOREFIELDDAMAGE, flags))
						return RET_NOTPOSSIBLE;

					if(!monster->canPushItems() && !monster->hasCondition(
						Combat::DamageToConditionType(combatType), false))
						return RET_NOTPOSSIBLE;
				}
			}

			return RET_NOERROR;
		}
		else if(const Player* player = creature->getPlayer())
		{
			if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
			{
				for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
				{
					if(!creature->canWalkthrough(*cit))
						return RET_NOTENOUGHROOM; //RET_NOTPOSSIBLE
				}
			}

			if(!player->getParent() && hasFlag(TILESTATE_NOLOGOUT)) //player is trying to login to a "no logout" tile
				return RET_NOTPOSSIBLE;

			if(player->isPzLocked() && !player->getTile()->hasFlag(TILESTATE_PVPZONE) && hasFlag(TILESTATE_PVPZONE)) //player is trying to enter a pvp zone while being pz-locked
				return RET_PLAYERISPZLOCKEDENTERPVPZONE;

			if(player->isPzLocked() && player->getTile()->hasFlag(TILESTATE_PVPZONE) && !hasFlag(TILESTATE_PVPZONE)) //player is trying to leave a pvp zone while being pz-locked
				return RET_PLAYERISPZLOCKEDLEAVEPVPZONE;

			if(hasFlag(TILESTATE_NOPVPZONE) && player->isPzLocked())
				return RET_PLAYERISPZLOCKED;

			if(hasFlag(TILESTATE_PROTECTIONZONE) && player->isPzLocked())
				return RET_PLAYERISPZLOCKED;
		}
		else if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
		{
			for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
			{
				if(!creature->canWalkthrough(*cit))
					return RET_NOTENOUGHROOM;
			}
		}

		if(items)
		{
			MagicField* field = getFieldItem();
			if(field && field->isBlocking(creature))
				return RET_NOTPOSSIBLE;

			if(!hasBitSet(FLAG_IGNOREBLOCKITEM, flags))
			{
				//If the FLAG_IGNOREBLOCKITEM bit isn't set we dont have to iterate every single item
				if(hasFlag(TILESTATE_BLOCKSOLID))
					return RET_NOTENOUGHROOM;
			}
			else
			{
				//FLAG_IGNOREBLOCKITEM is set
				if(ground)
				{
					const ItemType& iType = Item::items[ground->getID()];
					if(ground->isBlocking(creature) && (!iType.moveable || (ground->isLoadedFromMap() &&
						(ground->getUniqueId() || (ground->getActionId()
						&& ground->getContainer())))))
						return RET_NOTPOSSIBLE;
				}

				if(const TileItemVector* items = getItemList())
				{
					Item* iItem = NULL;
					for(ItemVector::const_iterator it = items->begin(); it != items->end(); ++it)
					{
						iItem = (*it);
						const ItemType& iType = Item::items[iItem->getID()];
						if(iItem->isBlocking(creature) && (!iType.moveable || (iItem->isLoadedFromMap() &&
							(iItem->getUniqueId() || (iItem->getActionId()
							&& iItem->getContainer())))))
							return RET_NOTPOSSIBLE;
					}
				}
			}
		}
	}
	else if(const Item* item = thing->getItem())
	{
#ifdef __DEBUG__
		if(thing->getParent() == NULL && !hasBitSet(FLAG_NOLIMIT, flags))
			std::cout << "[Notice - Tile::__queryAdd] thing->getParent() == NULL" << std::endl;

#endif
		if(items && items->size() >= 0xFFFF)
			return RET_NOTPOSSIBLE;

		if(hasBitSet(FLAG_NOLIMIT, flags))
			return RET_NOERROR;

		bool itemIsHangable = item->isHangable();
		if(!ground && !itemIsHangable)
			return RET_NOTPOSSIBLE;

		if(creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags))
		{
			for(CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit)
			{
				if(!(*cit)->isGhost() && item->isBlocking(*cit))
					return RET_NOTENOUGHROOM;
			}
		}

		if(hasFlag(TILESTATE_PROTECTIONZONE))
		{
			const uint32_t itemLimit = g_config.getNumber(ConfigManager::ITEMLIMIT_PROTECTIONZONE);
			if(itemLimit && getThingCount() > itemLimit)
				return RET_TILEISFULL;
		}

		bool hasHangable = false, supportHangable = false;
		if(items)
		{
			Thing* iThing = NULL;
			for(uint32_t i = 0; i < getThingCount(); ++i)
			{
				iThing = __getThing(i);
				if(const Item* iItem = iThing->getItem())
				{
					const ItemType& iType = Item::items[iItem->getID()];
					if(iType.isHangable)
						hasHangable = true;

					if(iType.isHorizontal || iType.isVertical)
						supportHangable = true;

					if(itemIsHangable && (iType.isHorizontal || iType.isVertical))
						continue;
					else if(iType.blockSolid)
					{
						if(!item->isPickupable())
							return RET_NOTENOUGHROOM;

						if(iType.allowPickupable)
							continue;

						if(!iType.hasHeight || iType.pickupable || iType.isBed())
							return RET_NOTENOUGHROOM;
					}
				}
			}
		}

		if(itemIsHangable && hasHangable && supportHangable)
			return RET_NEEDEXCHANGE;
	}

	return RET_NOERROR;
}
コード例 #9
0
ファイル: tile.cpp プロジェクト: divinity76/server
ReturnValue Tile::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
	bool childIsOwner /*= false*/) const
{
	Thing* iithing = NULL;

	if(const Creature* creature = thing->getCreature()){
		if(!creatures.empty())
			return RET_NOTPOSSIBLE;

		if(ground == NULL)
			return RET_NOTPOSSIBLE;
		
		if(const Monster* monster = creature->getMonster()){
			if(hasFlag(TILESTATE_PROTECTIONZONE))
				return RET_NOTPOSSIBLE;

			if(const MagicEffectItem* fieldItem = getFieldItem()){
				const MagicEffectTargetCreatureCondition* magicTargetCondition = fieldItem->getCondition();

				if(magicTargetCondition){
					if((monster->getImmunities() & magicTargetCondition->attackType) != magicTargetCondition->attackType){
						return RET_NOTPOSSIBLE;
					}
				}
			}

			if(floorChange() || getTeleportItem()){
				return RET_NOTPOSSIBLE;
			}

			for(uint32_t i = 0; i < getThingCount(); ++i){
				iithing = __getThing(i);

				if(const Item* iitem = iithing->getItem()){
					const ItemType& iiType = Item::items[iitem->getID()];

					if(iiType.blockSolid){
						if(!monster->canPushItems() || !iiType.moveable){
							return RET_NOTPOSSIBLE;
						}
					}
				}
			}

			return RET_NOERROR;
		}
		else if(const Player* player = creature->getPlayer()){
			if(hasFlag(TILESTATE_PROTECTIONZONE) && player->pzLocked){
				return RET_PLAYERISPZLOCKED;
			}
		}

		for(uint32_t i = 0; i < getThingCount(); ++i){
			iithing = __getThing(i);

			if(const Item* iitem = iithing->getItem()){
				const ItemType& iiType = Item::items[iitem->getID()];

				if(iiType.blockSolid){
					//check if this a creature that just is about to login/spawn
					//those can be placed here if the blocking item is moveable
					if(!creature->getParent()){
						if(!iiType.moveable)
							return RET_NOTPOSSIBLE;
					}
					else
						return RET_NOTPOSSIBLE;
				}
			}
		}
	}
	else if(const Item* item = thing->getItem()){
		//If its a new (summoned item) always accept it
		if(thing->getParent() == NULL){
			return RET_NOERROR;
		}

		if(ground == NULL)
			return RET_NOTPOSSIBLE;

		if(!creatures.empty() && item->isBlocking())
			return RET_NOTENOUGHROOM;

		for(uint32_t i = 0; i < getThingCount(); ++i){
			iithing = __getThing(i);

			if(const Item* iitem = iithing->getItem()){
				const ItemType& iiType = Item::items[iitem->getID()];

				if(iiType.blockSolid){
					if(item->isPickupable()){
						//experimental
						//if((iiType.isVertical || iiType.isHorizontal) && item->isHangable()){
						//	ItemVector::const_iterator iit;
						//	for(iit = downItems.begin(); iit != downItems.end(); ++iit){
						//		if((*iit)->isHangable())
						//			return RET_NOTENOUGHROOM;
						//	}
						//}
						//else
						if(!iiType.hasHeight /*|| !iiType.moveable*/)
							return RET_NOTENOUGHROOM;
						else if(iiType.pickupable)
							return RET_NOTENOUGHROOM;
					}
					else
						return RET_NOTENOUGHROOM;
				}
			}
		}
	}

	return RET_NOERROR;
}