Example #1
0
uint32_t MoveEvents::onCreatureMove(Creature* creature, const Tile* tile, const Position& fromPos, MoveEvent_t eventType)
{
	const Position& pos = tile->getPosition();

	uint32_t ret = 1;

	MoveEvent* moveEvent = getEvent(tile, eventType);
	if (moveEvent) {
		ret &= moveEvent->fireStepEvent(creature, nullptr, pos, fromPos);
	}

	for (size_t i = tile->getFirstIndex(), j = tile->getLastIndex(); i < j; ++i) {
		Thing* thing = tile->getThing(i);
		if (!thing) {
			continue;
		}

		Item* tileItem = thing->getItem();
		if (!tileItem) {
			continue;
		}

		moveEvent = getEvent(tileItem, eventType);
		if (moveEvent) {
			ret &= moveEvent->fireStepEvent(creature, tileItem, pos, fromPos);
		}
	}
	return ret;
}
Example #2
0
uint32_t MoveEvents::onCreatureMove(Creature* creature, const Tile* tile, bool isIn)
{
	MoveEvent_t eventType;

	if (isIn) {
		eventType = MOVE_EVENT_STEP_IN;
	} else {
		eventType = MOVE_EVENT_STEP_OUT;
	}

	Position pos = tile->getPosition();

	uint32_t ret = 1;

	MoveEvent* moveEvent = getEvent(tile, eventType);
	if (moveEvent) {
		ret = ret & moveEvent->fireStepEvent(creature, nullptr, pos);
	}

	for (int32_t i = tile->__getFirstIndex(), j = tile->__getLastIndex(); i < j; ++i) {
		Thing* thing = tile->__getThing(i);
		if (thing) {
			Item* tileItem = thing->getItem();
			if (tileItem) {
				moveEvent = getEvent(tileItem, eventType);
				if (moveEvent) {
					ret = ret & moveEvent->fireStepEvent(creature, tileItem, pos);
				}
			}
		}
	}

	return ret;
}
void Commands::removeThing(Player* player, const std::string& cmd, const std::string& param)
{
	Position pos = player->getPosition();
	pos = getNextPosition(player->direction, pos);
	Tile* removeTile = g_game.getMap()->getTile(pos);
	if (!removeTile) {
		player->sendTextMessage(MSG_STATUS_SMALL, "Tile not found.");
		g_game.addMagicEffect(pos, NM_ME_POFF);
		return;
	}

	Thing* thing = removeTile->getTopVisibleThing(player);
	if (!thing) {
		player->sendTextMessage(MSG_STATUS_SMALL, "Object not found.");
		g_game.addMagicEffect(pos, NM_ME_POFF);
		return;
	}

	if (Creature* creature = thing->getCreature()) {
		g_game.removeCreature(creature, true);
	} else {
		Item* item = thing->getItem();
		if (item) {
			if (item->isGroundTile()) {
				player->sendTextMessage(MSG_STATUS_SMALL, "You may not remove a ground tile.");
				g_game.addMagicEffect(pos, NM_ME_POFF);
				return;
			}

			g_game.internalRemoveItem(item, std::max<int32_t>(1, std::min<int32_t>(atoi(param.c_str()), item->getItemCount())));
			g_game.addMagicEffect(pos, NM_ME_MAGIC_BLOOD);
		}
	}
}
Example #4
0
uint32_t MoveEvents::onCreatureMove(Creature* creature, Tile* tile, bool isIn)
{
	MoveEvent_t eventType;
	if(isIn){
		eventType = MOVE_EVENT_STEP_IN;
	}
	else{
		eventType = MOVE_EVENT_STEP_OUT;
	}

	uint32_t ret = 1;
	MoveEvent* moveEvent = getEvent(tile, eventType);
	if(moveEvent){
		ret = ret & moveEvent->fireStepEvent(creature, NULL, tile->getPosition());
	}

	int32_t j = tile->__getLastIndex();
	Item* tileItem = NULL;
	for(int32_t i = tile->__getFirstIndex(); i < j; ++i){
		Thing* thing = tile->__getThing(i);
		if(thing && (tileItem = thing->getItem())){
			moveEvent = getEvent(tileItem, eventType);
			if(moveEvent){
				ret = ret & moveEvent->fireStepEvent(creature, tileItem, tile->getPosition());
			}
		}
	}
	return ret;
}
Example #5
0
ReturnValue DepotChest::queryAdd(int32_t index, const Thing& thing, uint32_t count,
		uint32_t flags, Creature* actor/* = nullptr*/) const
{
	const Item* item = thing.getItem();
	if (item == nullptr) {
		return RETURNVALUE_NOTPOSSIBLE;
	}

	bool skipLimit = hasBitSet(FLAG_NOLIMIT, flags);
	if (!skipLimit) {
		int32_t addCount = 0;

		if ((item->isStackable() && item->getItemCount() != count)) {
			addCount = 1;
		}

		if (item->getTopParent() != this) {
			if (const Container* container = item->getContainer()) {
				addCount = container->getItemHoldingCount() + 1;
			} else {
				addCount = 1;
			}
		}

		if (getItemHoldingCount() + addCount > maxDepotItems) {
			return RETURNVALUE_DEPOTISFULL;
		}
	}

	return Container::queryAdd(index, thing, count, flags, actor);
}
Example #6
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 #7
0
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 == nullptr) {
		maxQueryCount = 0;
		return RETURNVALUE_NOTPOSSIBLE;
	}

	if (hasBitSet(FLAG_NOLIMIT, flags)) {
		maxQueryCount = std::max<uint32_t>(1, count);
		return RETURNVALUE_NOERROR;
	}

	int32_t freeSlots = std::max<int32_t>(capacity() - size(), 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 (Item* containerItem : itemlist) {
				if (containerItem != item && containerItem->equals(item) && containerItem->getItemCount() < 100) {
					uint32_t remainder = (100 - containerItem->getItemCount());
					if (queryAdd(slotIndex++, *item, remainder, flags) == RETURNVALUE_NOERROR) {
						n += remainder;
					}
				}
			}
		} else {
			const Item* destItem = getItemByIndex(index);
			if (item->equals(destItem) && destItem->getItemCount() < 100) {
				uint32_t remainder = 100 - destItem->getItemCount();
				if (queryAdd(index, *item, remainder, flags) == RETURNVALUE_NOERROR) {
					n = remainder;
				}
			}
		}

		maxQueryCount = freeSlots * 100 + n;
		if (maxQueryCount < count) {
			return RETURNVALUE_CONTAINERNOTENOUGHROOM;
		}
	} else {
		maxQueryCount = freeSlots;
		if (maxQueryCount == 0) {
			return RETURNVALUE_CONTAINERNOTENOUGHROOM;
		}
	}
	return RETURNVALUE_NOERROR;
}
Example #8
0
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;
}
Example #9
0
ReturnValue Container::queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const
{
	int32_t index = getThingIndex(&thing);
	if (index == -1) {
		return RETURNVALUE_NOTPOSSIBLE;
	}

	const Item* item = thing.getItem();
	if (item == nullptr) {
		return RETURNVALUE_NOTPOSSIBLE;
	}

	if (count == 0 || (item->isStackable() && count > item->getItemCount())) {
		return RETURNVALUE_NOTPOSSIBLE;
	}

	if (!item->isMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)) {
		return RETURNVALUE_NOTMOVEABLE;
	}
	return RETURNVALUE_NOERROR;
}
Example #10
0
uint32_t MoveEvents::onItemMove(Item* item, Tile* tile, bool isAdd)
{
	MoveEvent_t eventType1, eventType2;
	if (isAdd) {
		eventType1 = MOVE_EVENT_ADD_ITEM;
		eventType2 = MOVE_EVENT_ADD_ITEM_ITEMTILE;
	} else {
		eventType1 = MOVE_EVENT_REMOVE_ITEM;
		eventType2 = MOVE_EVENT_REMOVE_ITEM_ITEMTILE;
	}

	uint32_t ret = 1;
	MoveEvent* moveEvent = getEvent(tile, eventType1);
	if (moveEvent) {
		ret &= moveEvent->fireAddRemItem(item, nullptr, tile->getPosition());
	}

	moveEvent = getEvent(item, eventType1);
	if (moveEvent) {
		ret &= moveEvent->fireAddRemItem(item, nullptr, tile->getPosition());
	}

	for (size_t i = tile->getFirstIndex(), j = tile->getLastIndex(); i < j; ++i) {
		Thing* thing = tile->getThing(i);
		if (!thing) {
			continue;
		}

		Item* tileItem = thing->getItem();
		if (!tileItem || tileItem == item) {
			continue;
		}

		moveEvent = getEvent(tileItem, eventType2);
		if (moveEvent) {
			ret &= moveEvent->fireAddRemItem(item, tileItem, tile->getPosition());
		}
	}
	return ret;
}
Example #11
0
ReturnValue Inbox::queryAdd(int32_t, const Thing& thing, uint32_t,
		uint32_t flags, Creature*) const
{
	if (!hasBitSet(FLAG_NOLIMIT, flags)) {
		return RETURNVALUE_CONTAINERNOTENOUGHROOM;
	}

	const Item* item = thing.getItem();
	if (!item) {
		return RETURNVALUE_NOTPOSSIBLE;
	}

	if (item == this) {
		return RETURNVALUE_THISISIMPOSSIBLE;
	}

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

	return RETURNVALUE_NOERROR;
}
Example #12
0
uint32_t MoveEvents::onItemMove(Item* item, Tile* tile, bool isAdd)
{
	MoveEvent_t eventType1;
	MoveEvent_t eventType2;
	if(isAdd){
		eventType1 = MOVE_EVENT_ADD_ITEM;
		eventType2 = MOVE_EVENT_ADD_ITEM_ITEMTILE;
	}
	else{
		eventType1 = MOVE_EVENT_REMOVE_ITEM;
		eventType2 = MOVE_EVENT_REMOVE_ITEM_ITEMTILE;
	}

	uint32_t ret = 1;

	MoveEvent* moveEvent = getEvent(tile, eventType1);
	if(moveEvent){
		ret = ret & moveEvent->fireAddRemItem(item, NULL, tile->getPosition());
	}

	moveEvent = getEvent(item, eventType1);
	if(moveEvent){
		ret = ret & moveEvent->fireAddRemItem(item, NULL, tile->getPosition());
	}

	int32_t j = tile->__getLastIndex();
	Item* tileItem = NULL;
	for(int32_t i = tile->__getFirstIndex(); i < j; ++i){
		Thing* thing = tile->__getThing(i);
		if(thing && (tileItem = thing->getItem()) && (tileItem != item)){
			moveEvent = getEvent(tileItem, eventType2);
			if(moveEvent){
				ret = ret & moveEvent->fireAddRemItem(item, tileItem, tile->getPosition());
			}
		}
	}

	return ret;
}
Example #13
0
ReturnValue Reward::queryAdd(int32_t, const Thing& thing, uint32_t,
	uint32_t, Creature* actor/* = nullptr*/) const
{
	if (actor) {
		return RETURNVALUE_NOTPOSSIBLE;
	}

	const Item* item = thing.getItem();
	if (!item) {
		return RETURNVALUE_NOTPOSSIBLE;		
	}
	
	if (item == this) {
		return RETURNVALUE_THISISIMPOSSIBLE;		
	}
	
	if (!item->isPickupable()) {
		return RETURNVALUE_CANNOTPICKUP;		
	}

	return RETURNVALUE_NOERROR;
}
Example #14
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 #15
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 #16
0
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;
}
Example #17
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 #18
0
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;
}
Example #19
0
ReturnValue Container::queryAdd(int32_t index, const Thing& thing, uint32_t count,
		uint32_t flags, Creature* actor/* = nullptr*/) const
{
	bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags);
	if (childIsOwner) {
		//a child container is querying, since we are the top container (not carried by a player)
		//just return with no error.
		return RETURNVALUE_NOERROR;
	}

	if (!unlocked) {
		return RETURNVALUE_NOTPOSSIBLE;
	}

	const Item* item = thing.getItem();
	if (item == nullptr) {
		return RETURNVALUE_NOTPOSSIBLE;
	}

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

	if (item == this) {
		return RETURNVALUE_THISISIMPOSSIBLE;
	}

	const Cylinder* cylinder = getParent();
	if (!hasBitSet(FLAG_NOLIMIT, flags)) {
		while (cylinder) {
			if (cylinder == &thing) {
				return RETURNVALUE_THISISIMPOSSIBLE;
			}

			if (dynamic_cast<const Inbox*>(cylinder)) {
				return RETURNVALUE_CONTAINERNOTENOUGHROOM;
			}

			cylinder = cylinder->getParent();
		}

		if (index == INDEX_WHEREEVER && size() >= capacity()) {
			return RETURNVALUE_CONTAINERNOTENOUGHROOM;
		}
	} else {
		while (cylinder) {
			if (cylinder == &thing) {
				return RETURNVALUE_THISISIMPOSSIBLE;
			}

			cylinder = cylinder->getParent();
		}
	}

	const Cylinder* topParent = getTopParent();
	if (topParent != this) {
		return topParent->queryAdd(INDEX_WHEREEVER, *item, count, flags | FLAG_CHILDISOWNER, actor);
	} else {
		return RETURNVALUE_NOERROR;
	}
}
Example #20
0
Tile* Tile::queryDestination(int32_t&, const Thing&, Item** destItem, uint32_t& flags)
{
	Tile* destTile = nullptr;
	*destItem = nullptr;

	if (hasFlag(TILESTATE_FLOORCHANGE_DOWN)) {
		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->hasFlag(TILESTATE_FLOORCHANGE_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->hasFlag(TILESTATE_FLOORCHANGE_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->hasFlag(TILESTATE_FLOORCHANGE_NORTH)) {
						++dy;
					}

					if (downTile->hasFlag(TILESTATE_FLOORCHANGE_SOUTH)) {
						--dy;
					}

					if (downTile->hasFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT)) {
						dy -= 2;
					}

					if (downTile->hasFlag(TILESTATE_FLOORCHANGE_EAST)) {
						--dx;
					}

					if (downTile->hasFlag(TILESTATE_FLOORCHANGE_EAST_ALT)) {
						dx -= 2;
					}

					if (downTile->hasFlag(TILESTATE_FLOORCHANGE_WEST)) {
						++dx;
					}

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

		if (hasFlag(TILESTATE_FLOORCHANGE_NORTH)) {
			--dy;
		}

		if (hasFlag(TILESTATE_FLOORCHANGE_SOUTH)) {
			++dy;
		}

		if (hasFlag(TILESTATE_FLOORCHANGE_EAST)) {
			++dx;
		}

		if (hasFlag(TILESTATE_FLOORCHANGE_WEST)) {
			--dx;
		}

		if (hasFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT)) {
			dy += 2;
		}

		if (hasFlag(TILESTATE_FLOORCHANGE_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 #21
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) && hasFlag(TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT)) {
			return RETURNVALUE_NOTPOSSIBLE;
		}

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

		if (const Monster* monster = creature->getMonster()) {
			if (hasFlag(TILESTATE_PROTECTIONZONE | TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT)) {
				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;
				}
			}
		}

		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;
				}
			}

			if (const auto items = getItemList()) {
				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 #22
0
Cylinder* 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.getTile(dx, dy - 1, dz);
		if (southDownTile && southDownTile->floorChange(SOUTH_ALT)) {
			dy -= 2;
			destTile = g_game.getTile(dx, dy, dz);
		} else {
			Tile* eastDownTile = g_game.getTile(dx - 1, dy, dz);
			if (eastDownTile && eastDownTile->floorChange(EAST_ALT)) {
				dx -= 2;
				destTile = g_game.getTile(dx, dy, dz);
			} else {
				Tile* downTile = g_game.getTile(dx, dy, dz);
				if (downTile) {
					if (downTile->floorChange(NORTH)) {
						++dy;
					}

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

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

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

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

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

					destTile = g_game.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(NORTH)) {
			--dy;
		}

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

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

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

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

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

		destTile = g_game.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 #23
0
uint32_t MoveEvents::onCreatureMove(Creature* creature, const Tile* fromTile, const Tile* toTile, bool isIn)
{
	MoveEvent_t eventType;
	const Tile* tile = NULL;

	if (isIn)
	{
		tile = toTile;
		eventType = MOVE_EVENT_STEP_IN;
	}
	else
	{
		tile = fromTile;
		eventType = MOVE_EVENT_STEP_OUT;
	}

	Position fromPos(0, 0, 0);

	if (fromTile)
	{
		fromPos = fromTile->getPosition();
	}

	Position toPos(0, 0, 0);

	if (toTile)
	{
		toPos = toTile->getPosition();
	}

	uint32_t ret = 1;
	MoveEvent* moveEvent = getEvent(tile, eventType);

	if (moveEvent)
	{
		ret = ret & moveEvent->fireStepEvent(creature, NULL, fromPos, toPos);
	}

	Item* tileItem = NULL;

	if (m_lastCacheTile == tile)
	{
		if (m_lastCacheItemVector.empty())
		{
			return ret;
		}

		//We can not use iterators here since the scripts can invalidate the iterator
		for (uint32_t i = 0; i < m_lastCacheItemVector.size(); ++i)
		{
			tileItem = m_lastCacheItemVector[i];

			if (tileItem)
			{
				moveEvent = getEvent(tileItem, eventType);

				if (moveEvent)
				{
					ret = ret & moveEvent->fireStepEvent(creature, tileItem, fromPos, toPos);
				}
			}
		}

		return ret;
	}

	m_lastCacheTile = tile;
	m_lastCacheItemVector.clear();
	//We can not use iterators here since the scripts can invalidate the iterator
	int32_t j = tile->__getLastIndex();

	for (int32_t i = tile->__getFirstIndex(); i < j; ++i)
	{
		Thing* thing = tile->__getThing(i);

		if (thing && (tileItem = thing->getItem()))
		{
			moveEvent = getEvent(tileItem, eventType);

			if (moveEvent)
			{
				m_lastCacheItemVector.push_back(tileItem);
				ret = ret & moveEvent->fireStepEvent(creature, tileItem, fromPos, toPos);
			}
			else if (hasTileEvent(tileItem))
			{
				m_lastCacheItemVector.push_back(tileItem);
			}
		}
	}

	return ret;
}
Example #24
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 #25
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 #26
0
uint32_t MoveEvents::onItemMove(Item* item, Tile* tile, bool isAdd)
{
	MoveEvent_t eventType1;
	MoveEvent_t eventType2;

	if (isAdd)
	{
		eventType1 = MOVE_EVENT_ADD_ITEM;
		eventType2 = MOVE_EVENT_ADD_ITEM_ITEMTILE;
	}
	else
	{
		eventType1 = MOVE_EVENT_REMOVE_ITEM;
		eventType2 = MOVE_EVENT_REMOVE_ITEM_ITEMTILE;
	}

	uint32_t ret = 1;
	MoveEvent* moveEvent = getEvent(tile, eventType1);

	if (moveEvent)
	{
		ret &= moveEvent->fireAddRemItem(item, NULL, tile->getPosition());
	}

	moveEvent = getEvent(item, eventType1);

	if (moveEvent)
	{
		ret &= moveEvent->fireAddRemItem(item, NULL, tile->getPosition());
	}

	Item* tileItem = NULL;

	if (m_lastCacheTile == tile)
	{
		if (m_lastCacheItemVector.empty())
		{
			return false;
		}

		//We can not use iterators here since the scripts can invalidate the iterator
		for (uint32_t i = 0; i < m_lastCacheItemVector.size(); ++i)
		{
			tileItem = m_lastCacheItemVector[i];

			if (tileItem && tileItem != item)
			{
				moveEvent = getEvent(tileItem, eventType2);

				if (moveEvent)
				{
					ret &= moveEvent->fireAddRemItem(item, tileItem, tile->getPosition());
				}
			}
		}

		return ret;
	}

	m_lastCacheTile = tile;
	m_lastCacheItemVector.clear();
	//We can not use iterators here since the scripts can invalidate the iterator
	int32_t j = tile->__getLastIndex();

	for (int32_t i = tile->__getFirstIndex(); i < j; ++i)
	{
		Thing* thing = tile->__getThing(i);

		if (thing && (tileItem = thing->getItem()) && (tileItem != item))
		{
			moveEvent = getEvent(tileItem, eventType2);

			if (moveEvent)
			{
				m_lastCacheItemVector.push_back(tileItem);
				ret &= moveEvent->fireAddRemItem(item, tileItem, tile->getPosition());
			}
			else if (hasTileEvent(tileItem))
			{
				m_lastCacheItemVector.push_back(tileItem);
			}
		}
	}

	return ret;
}