Example #1
0
Cylinder* Tile::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
	uint32_t& flags)
{
	Tile* destTile = NULL;
	*destItem = NULL;

	if(floorChangeDown()){
		int dx = getTilePosition().x;
		int dy = getTilePosition().y;
		int dz = getTilePosition().z + 1;
		Tile* downTile = g_game.getTile(dx, dy, dz);

		if(downTile){
			if(downTile->floorChange(NORTH))
				dy += 1;
			if(downTile->floorChange(SOUTH))
				dy -= 1;
			if(downTile->floorChange(EAST))
				dx -= 1;
			if(downTile->floorChange(WEST))
				dx += 1;
			destTile = g_game.getTile(dx, dy, dz);
		}
	}
	else if(floorChange()){
		int dx = getTilePosition().x;
		int dy = getTilePosition().y;
		int dz = getTilePosition().z - 1;

		if(floorChange(NORTH))
			dy -= 1;
		if(floorChange(SOUTH))
			dy += 1;
		if(floorChange(EAST))
			dx += 1;
		if(floorChange(WEST))
			dx -= 1;
		destTile = g_game.getTile(dx, dy, dz);
	}


	if(destTile == NULL){
		destTile = this;
	}
	else{
		flags |= FLAG_NOLIMIT; //Will ignore that there is blocking items/creatures
	}

	if(destTile){
		Thing* destThing = destTile->getTopDownItem();
		if(destThing)
			*destItem = destThing->getItem();
	}

	return destTile;
}
Example #2
0
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;
}
Example #3
0
Tile* Tile::queryDestination(int32_t&, const Thing&, Item** destItem, uint32_t& flags)
{
	Tile* destTile = nullptr;
	*destItem = nullptr;

	if (floorChangeDown()) {
		uint16_t dx = tilePos.x;
		uint16_t dy = tilePos.y;
		uint8_t dz = tilePos.z + 1;

		Tile* southDownTile = g_game.map.getTile(dx, dy - 1, dz);
		if (southDownTile && southDownTile->floorChange(DIRECTION_SOUTH_ALT)) {
			dy -= 2;
			destTile = g_game.map.getTile(dx, dy, dz);
		} else {
			Tile* eastDownTile = g_game.map.getTile(dx - 1, dy, dz);
			if (eastDownTile && eastDownTile->floorChange(DIRECTION_EAST_ALT)) {
				dx -= 2;
				destTile = g_game.map.getTile(dx, dy, dz);
			} else {
				Tile* downTile = g_game.map.getTile(dx, dy, dz);
				if (downTile) {
					if (downTile->floorChange(DIRECTION_NORTH)) {
						++dy;
					}

					if (downTile->floorChange(DIRECTION_SOUTH)) {
						--dy;
					}

					if (downTile->floorChange(DIRECTION_SOUTH_ALT)) {
						dy -= 2;
					}

					if (downTile->floorChange(DIRECTION_EAST)) {
						--dx;
					}

					if (downTile->floorChange(DIRECTION_EAST_ALT)) {
						dx -= 2;
					}

					if (downTile->floorChange(DIRECTION_WEST)) {
						++dx;
					}

					destTile = g_game.map.getTile(dx, dy, dz);
				}
			}
		}
	} else if (floorChange()) {
		uint16_t dx = tilePos.x;
		uint16_t dy = tilePos.y;
		uint8_t dz = tilePos.z - 1;

		if (floorChange(DIRECTION_NORTH)) {
			--dy;
		}

		if (floorChange(DIRECTION_SOUTH)) {
			++dy;
		}

		if (floorChange(DIRECTION_EAST)) {
			++dx;
		}

		if (floorChange(DIRECTION_WEST)) {
			--dx;
		}

		if (floorChange(DIRECTION_SOUTH_ALT)) {
			dy += 2;
		}

		if (floorChange(DIRECTION_EAST_ALT)) {
			dx += 2;
		}

		destTile = g_game.map.getTile(dx, dy, dz);
	}

	if (destTile == nullptr) {
		destTile = this;
	} else {
		flags |= FLAG_NOLIMIT;    //Will ignore that there is blocking items/creatures
	}

	if (destTile) {
		Thing* destThing = destTile->getTopDownItem();
		if (destThing) {
			*destItem = destThing->getItem();
		}
	}

	return destTile;
}
Example #4
0
ReturnValue Tile::queryAdd(int32_t, const Thing& thing, uint32_t, uint32_t flags, Creature*) const
{
	if (const Creature* creature = thing.getCreature()) {
		if (hasBitSet(FLAG_NOLIMIT, flags)) {
			return RETURNVALUE_NOERROR;
		}

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

		if (ground == nullptr) {
			return RETURNVALUE_NOTPOSSIBLE;
		}

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

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

			const CreatureVector* creatures = getCreatures();
			if (monster->canPushCreatures() && !monster->isSummon()) {
				if (creatures) {
					for (Creature* tileCreature : *creatures) {
						if (tileCreature->getPlayer() && tileCreature->getPlayer()->isInGhostMode()) {
							continue;
						}

						const Monster* creatureMonster = tileCreature->getMonster();
						if (!creatureMonster || !tileCreature->isPushable() ||
						        (creatureMonster->isSummon() && creatureMonster->getMaster()->getPlayer())) {
							return RETURNVALUE_NOTPOSSIBLE;
						}
					}
				}
			} else if (creatures && !creatures->empty()) {
				for (const Creature* tileCreature : *creatures) {
					if (!tileCreature->isInGhostMode()) {
						return RETURNVALUE_NOTENOUGHROOM;
					}
				}
			}

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

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

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

			MagicField* field = getFieldItem();
			if (field && !field->isBlocking()) {
				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)) {
						if (!(monster->canPushItems() || monster->hasCondition(Combat::DamageToConditionType(combatType)))) {
							return RETURNVALUE_NOTPOSSIBLE;
						}
					} else {
						return RETURNVALUE_NOTPOSSIBLE;
					}
				}
			}

			return RETURNVALUE_NOERROR;
		}

		const CreatureVector* creatures = getCreatures();
		if (const Player* player = creature->getPlayer()) {
			if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags) && !player->isAccessPlayer()) {
				for (const Creature* tileCreature : *creatures) {
					if (!player->canWalkthrough(tileCreature)) {
						return RETURNVALUE_NOTPOSSIBLE;
					}
				}
			}

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

			const Tile* playerTile = player->getTile();
			if (playerTile && player->isPzLocked()) {
				if (!playerTile->hasFlag(TILESTATE_PVPZONE)) {
					//player is trying to enter a pvp zone while being pz-locked
					if (hasFlag(TILESTATE_PVPZONE)) {
						return RETURNVALUE_PLAYERISPZLOCKEDENTERPVPZONE;
					}
				} else if (!hasFlag(TILESTATE_PVPZONE)) {
					// player is trying to leave a pvp zone while being pz-locked
					return RETURNVALUE_PLAYERISPZLOCKEDLEAVEPVPZONE;
				}

				if ((!playerTile->hasFlag(TILESTATE_NOPVPZONE) && hasFlag(TILESTATE_NOPVPZONE)) ||
					(!playerTile->hasFlag(TILESTATE_PROTECTIONZONE) && hasFlag(TILESTATE_PROTECTIONZONE))) {
					// player is trying to enter a non-pvp/protection zone while being pz-locked
					return RETURNVALUE_PLAYERISPZLOCKED;
				}
			}
		} else if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags)) {
			for (const Creature* tileCreature : *creatures) {
				if (!tileCreature->isInGhostMode()) {
					return RETURNVALUE_NOTENOUGHROOM;
				}
			}
		}

		const TileItemVector* items = getItemList();
		if (items) {
			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 RETURNVALUE_NOTENOUGHROOM;
				}
			} else {
				//FLAG_IGNOREBLOCKITEM is set
				if (ground) {
					const ItemType& iiType = Item::items[ground->getID()];
					if (iiType.blockSolid && (!iiType.moveable || ground->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID))) {
						return RETURNVALUE_NOTPOSSIBLE;
					}
				}

				for (const Item* item : *items) {
					const ItemType& iiType = Item::items[item->getID()];
					if (iiType.blockSolid && (!iiType.moveable || item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID))) {
						return RETURNVALUE_NOTPOSSIBLE;
					}
				}
			}
		}
	} else if (const Item* item = thing.getItem()) {
		const TileItemVector* items = getItemList();
		if (items && items->size() >= 0xFFFF) {
			return RETURNVALUE_NOTPOSSIBLE;
		}

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

		bool itemIsHangable = item->isHangable();
		if (ground == nullptr && !itemIsHangable) {
			return RETURNVALUE_NOTPOSSIBLE;
		}

		const CreatureVector* creatures = getCreatures();
		if (creatures && !creatures->empty() && item->isBlocking() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags)) {
			for (const Creature* tileCreature : *creatures) {
				if (!tileCreature->isInGhostMode()) {
					return RETURNVALUE_NOTENOUGHROOM;
				}
			}
		}

		if (itemIsHangable && hasFlag(TILESTATE_SUPPORTS_HANGABLE)) {
			if (items) {
				for (const Item* tileItem : *items) {
					if (tileItem->isHangable()) {
						return RETURNVALUE_NEEDEXCHANGE;
					}
				}
			}
		} else {
			if (ground) {
				const ItemType& iiType = Item::items[ground->getID()];
				if (iiType.blockSolid) {
					if (!iiType.allowPickupable || item->isMagicField() || item->isBlocking()) {
						if (!item->isPickupable()) {
							return RETURNVALUE_NOTENOUGHROOM;
						}

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

			if (items) {
				for (const Item* tileItem : *items) {
					const ItemType& iiType = Item::items[tileItem->getID()];
					if (!iiType.blockSolid) {
						continue;
					}

					if (iiType.allowPickupable && !item->isMagicField() && !item->isBlocking()) {
						continue;
					}

					if (!item->isPickupable()) {
						return RETURNVALUE_NOTENOUGHROOM;
					}

					if (!iiType.hasHeight || iiType.pickupable || iiType.isBed()) {
						return RETURNVALUE_NOTENOUGHROOM;
					}
				}
			}
		}
	}
	return RETURNVALUE_NOERROR;
}
Example #5
0
ReturnValue Tile::isBlocking(int objectstate, bool ignoreCreature /* = false*/, bool ignoreMoveableBlocking /*=false*/) const
{
	if(isPz() && ((objectstate & BLOCK_PZ) == BLOCK_PZ)) {
		return RET_PROTECTIONZONE;
	}

	if(((objectstate & BLOCK_PATHFIND) == BLOCK_PATHFIND) && (floorChange() || getTeleportItem())) {
		return RET_THEREISNOWAY;
	}
		
	if(ground) {
		const ItemType& groundType = Item::items[ground->getID()];

		if(((objectstate & BLOCK_PROJECTILE) == BLOCK_PROJECTILE) &&
			groundType.blockProjectile)
			return RET_CANNOTTHROW;

		/*
		if((groundType.blockPathFind || groundType.blockSolid) && ((objectstate & BLOCK_PATHFIND) == BLOCK_PATHFIND))
			return RET_THEREISNOWAY;
		*/

		if(((objectstate & BLOCK_PICKUPABLE) == BLOCK_PICKUPABLE)) {			
			if(groundType.blockSolid && (!groundType.hasHeight || groundType.pickupable))
				return RET_NOTENOUGHROOM;
		}

		if(((objectstate & BLOCK_SOLID) == BLOCK_SOLID) && groundType.blockSolid)
			return RET_NOTENOUGHROOM;
	}
	else if( !((objectstate & BLOCK_PROJECTILE) == BLOCK_PROJECTILE)) {
		return RET_NOTILE;
	}

	if(!ignoreCreature && !creatures.empty() && ((objectstate & BLOCK_SOLID) == BLOCK_SOLID))
		return RET_CREATUREBLOCK;

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

		if(((objectstate & BLOCK_PROJECTILE) == BLOCK_PROJECTILE)) {
			if(iiType.blockProjectile)
				return RET_CANNOTTHROW;
			/*else
				continue;*/
		}

		/*
		if((iiType.blockPathFind || iiType.blockSolid) && ((objectstate & BLOCK_PATHFIND) == BLOCK_PATHFIND) &&
			!(ignoreMoveableBlocking && iiType.moveable))
			return RET_THEREISNOWAY;
			*/

		if(((objectstate & BLOCK_PICKUPABLE) == BLOCK_PICKUPABLE)) {			
			if(iiType.blockSolid && (!iiType.hasHeight || iiType.pickupable))
				return RET_NOTENOUGHROOM;
		}

		if(((objectstate & BLOCK_SOLID) == BLOCK_SOLID) && iiType.blockSolid &&
			!(ignoreMoveableBlocking && iiType.moveable))
			return RET_NOTENOUGHROOM;
	}
	
	for (iit = downItems.begin(); iit != downItems.end(); ++iit) {
		const ItemType& iiType = Item::items[(*iit)->getID()];

		if(((objectstate & BLOCK_PROJECTILE) == BLOCK_PROJECTILE)) {
			if(iiType.blockProjectile)
				return RET_CANNOTTHROW;
			/*else
				continue;*/
		}

		/*
		if((iiType.blockPathFind || iiType.blockSolid) && ((objectstate & BLOCK_PATHFIND) == BLOCK_PATHFIND) &&
			!(ignoreMoveableBlocking && iiType.moveable))
			return RET_THEREISNOWAY;
		*/

		if(((objectstate & BLOCK_PICKUPABLE) == BLOCK_PICKUPABLE)) {
			if(iiType.blockSolid && (!iiType.hasHeight || iiType.pickupable))
				return RET_NOTENOUGHROOM;
		}

		if(((objectstate & BLOCK_SOLID) == BLOCK_SOLID) && iiType.blockSolid &&
			!(ignoreMoveableBlocking && iiType.moveable))
			return RET_NOTENOUGHROOM;
	}

	//return false;
	return RET_NOERROR;
}
Example #6
0
ReturnValue Tile::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
                             uint32_t flags, Creature* actor/* = NULL*/) 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 == NULL) {
			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 (creature->getPlayer() && creature->getPlayer()->isInGhostMode()) {
							continue;
						}

						const Monster* creatureMonster = creature->getMonster();

						if (!creatureMonster || !creature->isPushable() ||
						        (creatureMonster->isSummon() && creatureMonster->getMaster()->getPlayer())) {
							return RET_NOTPOSSIBLE;
						}
					}
				}
			} else if (creatures && !creatures->empty()) {
				for (CreatureVector::const_iterator cit = creatures->begin(); cit != creatures->end(); ++cit) {
					if (!(*cit)->isInGhostMode()) {
						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()) {
				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)) {
						if (!(monster->canPushItems() || monster->hasCondition(Combat::DamageToConditionType(combatType)))) {
							return RET_NOTPOSSIBLE;
						}
					} else {
						return RET_NOTPOSSIBLE;
					}
				}
			}

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

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

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

			}

			if ((hasFlag(TILESTATE_NOPVPZONE) || 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 (!(*cit)->isInGhostMode()) {
					return RET_NOTENOUGHROOM;
				}
			}
		}

		if (items) {
			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 (iiType.blockSolid && (!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 (iiType.blockSolid && (!iiType.moveable || iitem->getUniqueId() != 0)) {
							return RET_NOTPOSSIBLE;
						}
					}
				}
			}
		}
	} else if (const Item* item = thing->getItem()) {
		if (items && items->size() >= 0xFFFF) {
			return RET_NOTPOSSIBLE;
		}

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

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

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

		if (itemIsHangable && hasFlag(TILESTATE_SUPPORTS_HANGABLE)) {
			if (items) {
				for (ItemVector::const_iterator it = items->begin(), end = items->end(); it != end; ++it) {
					if ((*it)->isHangable()) {
						return RET_NEEDEXCHANGE;
					}
				}
			}
		} else {
			if (ground) {
				const ItemType& iiType = Item::items[ground->getID()];
				if (iiType.blockSolid) {
					if (!iiType.allowPickupable || item->isMagicField() || item->isBlocking()) {
						if (!item->isPickupable()) {
							return RET_NOTENOUGHROOM;
						}

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

			if (items) {
				for (ItemVector::const_iterator it = items->begin(), end = items->end(); it != end; ++it) {
					const ItemType& iiType = Item::items[(*it)->getID()];
					if (!iiType.blockSolid) {
						continue;
					}

					if (iiType.allowPickupable && !item->isMagicField() && !item->isBlocking()) {
						continue;
					}

					if (!item->isPickupable()) {
						return RET_NOTENOUGHROOM;
					}

					if (!iiType.hasHeight || iiType.pickupable || iiType.isBed()) {
						return RET_NOTENOUGHROOM;
					}
				}
			}
		}
	}
	return RET_NOERROR;
}
Example #7
0
Cylinder* Tile::__queryDestination(int32_t& index, const Thing* thing, Item** destItem,
	uint32_t& flags)
{
	Tile* destTile = NULL;
	*destItem = NULL;

	Position _pos = pos;
	if(floorChange(CHANGE_DOWN))
	{
		_pos.z++;
		
		if(Creature* creature = (Creature*) thing->getCreature()){
		 CreatureEventList moveEvents = creature->getCreatureEvents(CREATURE_EVENT_MOVE);
		 for(CreatureEventList::iterator it = moveEvents.begin(); it != moveEvents.end(); ++it)
			(*it)->executeMove(creature, creature->getPosition(), _pos);
		}
		
		for(int32_t i = CHANGE_FIRST_EX; i < CHANGE_LAST; ++i)
		{
			Position __pos = _pos;
			Tile* tmpTile = NULL;
			switch(i)
			{
				case CHANGE_NORTH_EX:
					__pos.y++;
					if((tmpTile = g_game.getTile(__pos)))
						__pos.y++;

					break;
				case CHANGE_SOUTH_EX:
					__pos.y--;
					if((tmpTile = g_game.getTile(__pos)))
						__pos.y--;

					break;
				case CHANGE_EAST_EX:
					__pos.x--;
					if((tmpTile = g_game.getTile(__pos)))
						__pos.x--;

					break;
				case CHANGE_WEST_EX:
					__pos.x++;
					if((tmpTile = g_game.getTile(__pos)))
						__pos.x++;

					break;
				default:
					break;
			}

			if(!tmpTile || !tmpTile->floorChange((FloorChange_t)i))
				continue;

			destTile = g_game.getTile(__pos);
			break;
		}

		if(!destTile)
		{
			if(Tile* downTile = g_game.getTile(_pos))
			{
				if(downTile->floorChange(CHANGE_NORTH) || downTile->floorChange(CHANGE_NORTH_EX))
					_pos.y++;

				if(downTile->floorChange(CHANGE_SOUTH) || downTile->floorChange(CHANGE_SOUTH_EX))
					_pos.y--;

				if(downTile->floorChange(CHANGE_EAST) || downTile->floorChange(CHANGE_EAST_EX))
					_pos.x--;

				if(downTile->floorChange(CHANGE_WEST) || downTile->floorChange(CHANGE_WEST_EX))
					_pos.x++;

				destTile = g_game.getTile(_pos);
			}
		}
	}
	else if(floorChange())
	{
		_pos.z--;
		if(floorChange(CHANGE_NORTH))
			_pos.y--;

		if(floorChange(CHANGE_SOUTH))
			_pos.y++;

		if(floorChange(CHANGE_EAST))
			_pos.x++;

		if(floorChange(CHANGE_WEST))
			_pos.x--;

		if(floorChange(CHANGE_NORTH_EX))
			_pos.y -= 2;

		if(floorChange(CHANGE_SOUTH_EX))
			_pos.y += 2;

		if(floorChange(CHANGE_EAST_EX))
			_pos.x += 2;

		if(floorChange(CHANGE_WEST_EX))
			_pos.x -= 2;

		destTile = g_game.getTile(_pos);
		if(Creature* creature = (Creature*) thing->getCreature()){
		 CreatureEventList moveEvents = creature->getCreatureEvents(CREATURE_EVENT_MOVE);
		 for(CreatureEventList::iterator it = moveEvents.begin(); it != moveEvents.end(); ++it)
			(*it)->executeMove(creature, creature->getPosition(), _pos);
		}
	}

	if(!destTile)
		destTile = this;
	else
		flags |= FLAG_NOLIMIT; //will ignore that there is blocking items/creatures

	if(destTile)
	{
		Thing* destThing = destTile->getTopDownItem();
		if(destThing && !destThing->isRemoved())
			*destItem = destThing->getItem();
	}

	return destTile;
}
Example #8
0
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;
}
Example #9
0
Cylinder* Tile::__queryDestination(int32_t& index, const Thing* thing, Item** destItem)
{
	Tile* destTile = NULL;
	*destItem = NULL;

	if(floorChange()){
		if(floorChange(NORTH) && floorChange(EAST)){
			destTile = g_game.getTile(getTilePosition().x + 1, getTilePosition().y - 1, getTilePosition().z - 1);
		}
		else if(floorChange(NORTH) && floorChange(WEST)){
			destTile = g_game.getTile(getTilePosition().x - 1, getTilePosition().y - 1, getTilePosition().z - 1);
		}
		else if(floorChange(SOUTH) && floorChange(EAST)){
			destTile = g_game.getTile(getTilePosition().x + 1, getTilePosition().y + 1, getTilePosition().z - 1);
		}
		else if(floorChange(SOUTH) && floorChange(WEST)){
			destTile = g_game.getTile(getTilePosition().x - 1, getTilePosition().y + 1, getTilePosition().z - 1);
		}
		else if(floorChange(NORTH)){
			destTile = g_game.getTile(getTilePosition().x, getTilePosition().y - 1, getTilePosition().z - 1);
		}
		else if(floorChange(SOUTH)){
			destTile = g_game.getTile(getTilePosition().x, getTilePosition().y + 1, getTilePosition().z - 1);
		}
		else if(floorChange(EAST)){
			destTile = g_game.getTile(getTilePosition().x + 1, getTilePosition().y, getTilePosition().z - 1);
		}
		else if(floorChange(WEST)){
			destTile = g_game.getTile(getTilePosition().x - 1, getTilePosition().y, getTilePosition().z - 1);
		}
	}

	if(destTile == NULL){
		destTile = this;
	}

	if(destTile->floorChangeDown()){
		destTile = g_game.getTile(getTilePosition().x, getTilePosition().y, getTilePosition().z + 1);

		if(destTile == NULL){
			return this;
		}
		else if(destTile->floorChange(NORTH) && destTile->floorChange(EAST)){
			destTile = g_game.getTile(getTilePosition().x - 1, getTilePosition().y + 1, getTilePosition().z + 1);
		}
		else if(destTile->floorChange(NORTH) && destTile->floorChange(WEST)){
			destTile = g_game.getTile(getTilePosition().x + 1, getTilePosition().y + 1, getTilePosition().z + 1);
		}
		else if(destTile->floorChange(SOUTH) && destTile->floorChange(EAST)){
			destTile = g_game.getTile(getTilePosition().x - 1, getTilePosition().y - 1, getTilePosition().z + 1);
		}
		else if(destTile->floorChange(SOUTH) && destTile->floorChange(WEST)){
			destTile = g_game.getTile(getTilePosition().x + 1, getTilePosition().y - 1, getTilePosition().z + 1);
		}
		else if(destTile->floorChange(NORTH)){
			destTile = g_game.getTile(getTilePosition().x, getTilePosition().y + 1, getTilePosition().z + 1);
		}
		else if(destTile->floorChange(SOUTH)){
			destTile = g_game.getTile(getTilePosition().x, getTilePosition().y - 1, getTilePosition().z + 1);
		}
		else if(destTile->floorChange(EAST)){
			destTile = g_game.getTile(getTilePosition().x - 1, getTilePosition().y, getTilePosition().z + 1);
		}
		else if(destTile->floorChange(WEST)){
			destTile = g_game.getTile(getTilePosition().x + 1, getTilePosition().y, getTilePosition().z + 1);
		}
	}

	Thing* destThing = destTile->getTopDownItem();
	if(destThing)
		*destItem = destThing->getItem();

	return destTile;
}
Example #10
0
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;
}
Example #11
0
Cylinder* Tile::__queryDestination(int32_t&, const Thing*, Item** destItem,
	uint32_t& flags)
{
	Tile* destTile = NULL;
	Position destPosition = pos;

	*destItem = NULL;
	if(floorChange(CHANGE_DOWN))
	{
		destPosition.z++;
		for(int32_t i = CHANGE_FIRST_EX; i < CHANGE_LAST; ++i)
		{
			Position tmpPosition = destPosition;
			Tile* tmpTile = NULL;
			switch(i)
			{
				case CHANGE_NORTH_EX:
					tmpPosition.y++;
					if((tmpTile = g_game.getTile(tmpPosition)))
						tmpPosition.y++;

					break;
				case CHANGE_SOUTH_EX:
					tmpPosition.y--;
					if((tmpTile = g_game.getTile(tmpPosition)))
						tmpPosition.y--;

					break;
				case CHANGE_EAST_EX:
					tmpPosition.x--;
					if((tmpTile = g_game.getTile(tmpPosition)))
						tmpPosition.x--;

					break;
				case CHANGE_WEST_EX:
					tmpPosition.x++;
					if((tmpTile = g_game.getTile(tmpPosition)))
						tmpPosition.x++;

					break;
				default:
					break;
			}

			if(!tmpTile || !tmpTile->floorChange((FloorChange_t)i))
				continue;

			destTile = g_game.getTile(tmpPosition);
			break;
		}

		if(!destTile)
		{
			if(Tile* downTile = g_game.getTile(destPosition))
			{
				if(downTile->floorChange(CHANGE_NORTH) || downTile->floorChange(CHANGE_NORTH_EX))
					destPosition.y++;

				if(downTile->floorChange(CHANGE_SOUTH) || downTile->floorChange(CHANGE_SOUTH_EX))
					destPosition.y--;

				if(downTile->floorChange(CHANGE_EAST) || downTile->floorChange(CHANGE_EAST_EX))
					destPosition.x--;

				if(downTile->floorChange(CHANGE_WEST) || downTile->floorChange(CHANGE_WEST_EX))
					destPosition.x++;

				destTile = g_game.getTile(destPosition);
			}
		}
	}
	else if(floorChange())
	{
		destPosition.z--;
		Position tmpPosition = destPosition;
		if(floorChange(CHANGE_NORTH_EX))
		{
			tmpPosition.y--;
			if((destTile = g_game.getTile(tmpPosition)))
				tmpPosition.y--;
		}
		else if(floorChange(CHANGE_SOUTH_EX))
		{
			tmpPosition.y++;
			if((destTile = g_game.getTile(tmpPosition)))
				tmpPosition.y++;
		}
		else if(floorChange(CHANGE_EAST_EX))
		{
			tmpPosition.x++;
			if((destTile = g_game.getTile(tmpPosition)))
				tmpPosition.x++;
		}
		else if(floorChange(CHANGE_WEST_EX))
		{
			tmpPosition.x--;
			if((destTile = g_game.getTile(tmpPosition)))
				tmpPosition.x--;
		}

		if(!destTile)
		{
			if(floorChange(CHANGE_NORTH))
				destPosition.y--;

			if(floorChange(CHANGE_SOUTH))
				destPosition.y++;

			if(floorChange(CHANGE_EAST))
				destPosition.x++;

			if(floorChange(CHANGE_WEST))
				destPosition.x--;

			destTile = g_game.getTile(destPosition);
		}
		else if(destTile->floorChange(CHANGE_DOWN))
		{
			if(Tile* tmpTile = g_game.getTile(tmpPosition))
				destTile = tmpTile;
		}
	}

	if(!destTile)
		destTile = this;
	else
		flags |= FLAG_NOLIMIT; //will ignore that there is blocking items/creatures

	if(destTile)
	{
		if(Item* item = destTile->getTopDownItem())
			*destItem = item;
	}

	return destTile;
}