Example #1
0
IconType Condition::getIcon() const
{
	IconType icons = ICON_NONE;

	for(IconType::iterator i = ICON_POISON; i != IconType::end(); ++i){
		if(hasBitSet((*i).value(), flags)){
			icons |= *i;
		}
	}

	switch(combatType.value()){
		case enums::COMBAT_ENERGYDAMAGE: icons |= ICON_ENERGY; break;
		case enums::COMBAT_EARTHDAMAGE: icons |= ICON_POISON; break;
		case enums::COMBAT_FIREDAMAGE: icons |= ICON_BURN; break;
		case enums::COMBAT_DROWNDAMAGE: icons |= ICON_DROWNING; break;
		case enums::COMBAT_ICEDAMAGE: icons |= ICON_FREEZING; break;
		case enums::COMBAT_HOLYDAMAGE: icons |= ICON_DAZZLED; break;
		case enums::COMBAT_DEATHDAMAGE: icons |= ICON_CURSED; break;

		default:
			break;
	}

	return icons;
}
Example #2
0
ReturnValue Depot::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
	uint32_t flags) const
{
	const Item* item = thing->getItem();
	if(item == NULL){
		return RET_NOTPOSSIBLE;
	}

	if(!hasBitSet(FLAG_IGNORECAPACITY, flags)){
		int 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 > maxDepotLimit){
			return RET_DEPOTISFULL;
		}
	}

	return Container::__queryAdd(index, thing, count, flags);
}
Example #3
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 #4
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 == NULL)
	{
		maxQueryCount = 0;
		return RET_NOTPOSSIBLE;
	}

	if(hasBitSet(FLAG_NOLIMIT, flags))
	{
		maxQueryCount = std::max<uint32_t>(1, count);
		return RET_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(ItemDeque::const_iterator cit = itemlist.begin(); cit != itemlist.end(); ++cit, ++slotIndex)
			{
				if((*cit) != item && (*cit)->getID() == item->getID() && (*cit)->getItemCount() < 100)
				{
					uint32_t remainder = (100 - (*cit)->getItemCount());
					if(__queryAdd(slotIndex, item, remainder, flags) == RET_NOERROR)
						n += remainder;
				}
			}
		}
		else
		{
			const Item* destItem = getItem(index);
			if(destItem && destItem->getID() == item->getID() && destItem->getItemCount() < 100)
			{
				uint32_t remainder = 100 - destItem->getItemCount();
				if(__queryAdd(index, item, remainder, flags) == RET_NOERROR)
					n = remainder;
			}
		}

		maxQueryCount = freeSlots * 100 + n;
		if(maxQueryCount < count)
			return RET_CONTAINERNOTENOUGHROOM;
	}
	else
	{
		maxQueryCount = freeSlots;
		if(maxQueryCount == 0)
			return RET_CONTAINERNOTENOUGHROOM;
	}
	return RET_NOERROR;
}
Example #5
0
File: inbox.cpp Project: CkyLua/tfs
ReturnValue Inbox::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
	uint32_t flags, Creature* actor/* = NULL*/) const
{
	bool skipLimit = hasBitSet(FLAG_NOLIMIT, flags);
	if(!skipLimit)
		return RET_CONTAINERNOTENOUGHROOM;

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

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

    if(!item->isPickupable())
        return RET_CANNOTPICKUP;

    if(item == this)
        return RET_THISISIMPOSSIBLE;

    bool isInbox = false;

    if(const Container* container = item->getContainer())
    {
        for(const Cylinder* cylinder = getParent(); cylinder; cylinder = cylinder->getParent())
        {
            if(cylinder == container)
                return RET_THISISIMPOSSIBLE;

            if(!hasBitSet(FLAG_NOLIMIT, flags) && !isInbox && dynamic_cast<const Inbox*>(cylinder))
                isInbox = true;
        }
    }

    if(isInbox || (index == INDEX_WHEREEVER && size() >= capacity() && !hasBitSet(FLAG_NOLIMIT, flags)))
        return RET_CONTAINERNOTENOUGHROOM;

    const Cylinder* topParent = getTopParent();
    if(topParent != this)
        return topParent->__queryAdd(INDEX_WHEREEVER, item, count, flags | FLAG_CHILDISOWNER, actor);

    return RET_NOERROR;
}
Example #7
0
ReturnValue Tile::__queryRemove(const Thing* thing, uint32_t count, uint32_t flags) const
{
	int32_t index = __getIndexOfThing(thing);
	if(index == -1)
		return RET_NOTPOSSIBLE;
	const Item* item = thing->getItem();
	if(!item || !count || (item->isStackable() && count > item->getItemCount())
		|| (item->isNotMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)))
		return RET_NOTPOSSIBLE;
        
	return RET_NOERROR;
}
Example #8
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 #9
0
ReturnValue Container::__queryRemove(const Thing* thing, uint32_t count, uint32_t flags, Creature*) const
{
    int32_t index = __getIndexOfThing(thing);
    if(index == -1)
        return RET_NOTPOSSIBLE;

    const Item* item = thing->getItem();
    if(item == NULL)
        return RET_NOTPOSSIBLE;

    if(count == 0 || (item->isStackable() && count > item->getItemCount()))
        return RET_NOTPOSSIBLE;

    if(!item->isMovable() && !hasBitSet(FLAG_IGNORENOTMOVABLE, flags))
        return RET_NOTMOVABLE;

    return RET_NOERROR;
}
Example #10
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 #11
0
ReturnValue Container::__queryRemove(const Thing* thing, uint32_t count, uint32_t flags) const
{
	int32_t index = __getIndexOfThing(thing);
	if (index == -1) {
		return RET_NOTPOSSIBLE;
	}

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

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

	if (item->isNotMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)) {
		return RET_NOTMOVEABLE;
	}
	return RET_NOERROR;
}
Example #12
0
ReturnValue Inbox::__queryAdd(int32_t index, const Thing* thing, uint32_t count,
                              uint32_t flags, Creature* actor/* = nullptr*/) const
{
    if (!hasBitSet(FLAG_NOLIMIT, flags)) {
        return RET_CONTAINERNOTENOUGHROOM;
    }

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

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

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

    return RET_NOERROR;
}
Example #13
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 #14
0
bool Creature::onKilledCreature(Creature* target, uint32_t& flags, DeathEntry& entry)
{
	bool ret = true;
	if(master)
		ret = master->onKilledCreature(target, flags, entry);

	CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);
	if(!hasBitSet((uint32_t)KILLFLAG_LASTHIT, flags))
	{
		for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
			(*it)->executeKill(this, target, false);

		return true;
	}

	for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
	{
		if(!(*it)->executeKill(this, target, true) && ret)
			ret = false;
	}

	return ret;
}
Example #15
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 #16
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 #17
0
bool Creature::isSuppress(ConditionType_t type) const
{
	return hasBitSet((uint32_t)type, getConditionSuppressions());
}
Example #18
0
bool Creature::isImmune(ConditionType_t type) const
{
	return hasBitSet((uint32_t)type, getConditionImmunities());
}
Example #19
0
bool Creature::isImmune(CombatType_t type) const
{
	return hasBitSet((uint32_t)type, getDamageImmunities());
}
Example #20
0
bool Creature::onDeath()
{
	DeathList deathList = getKillers();
	bool deny = false;

	CreatureEventList prepareDeathEvents = getCreatureEvents(CREATURE_EVENT_PREPAREDEATH);
	for(CreatureEventList::iterator it = prepareDeathEvents.begin(); it != prepareDeathEvents.end(); ++it)
	{
		if(!(*it)->executePrepareDeath(this, deathList) && !deny)
			deny = true;
	}

	if(deny)
		return false;

	int32_t i = 0, size = deathList.size(), limit = g_config.getNumber(ConfigManager::DEATH_ASSISTS) + 1;
	if(limit > 0 && size > limit)
		size = limit;

	Creature* tmp = NULL;
	CreatureVector justifyVec;
	for(DeathList::iterator it = deathList.begin(); it != deathList.end(); ++it, ++i)
	{
		if(it->isNameKill())
			continue;

		bool lastHit = it == deathList.begin();
		uint32_t flags = KILLFLAG_NONE;
		if(lastHit)
			flags |= (uint32_t)KILLFLAG_LASTHIT;

		if(i < size)
		{
			if(it->getKillerCreature()->getPlayer())
				tmp = it->getKillerCreature();
			else if(it->getKillerCreature()->getPlayerMaster())
				tmp = it->getKillerCreature()->getMaster();
		}

		if(tmp)
		{
			if(std::find(justifyVec.begin(), justifyVec.end(), tmp) == justifyVec.end())
			{
				flags |= (uint32_t)KILLFLAG_JUSTIFY;
				justifyVec.push_back(tmp);
			}

			tmp = NULL;
		}

		if(!it->getKillerCreature()->onKilledCreature(this, flags, (*it)) && lastHit)
			return false;

		if(hasBitSet((uint32_t)KILLFLAG_UNJUSTIFIED, flags))
			it->setUnjustified(true);
	}

	for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it)
	{
		if((tmp = g_game.getCreatureByID(it->first)))
			tmp->onAttackedCreatureKilled(this);
	}

	dropCorpse(deathList);
	if(master)
		master->removeSummon(this);

	return true;
}
Example #21
0
std::string Item::getDescription(const ItemType& it, int32_t lookDistance, const Item* item/* = NULL*/,
	int32_t subType/* = -1*/, bool addArticle/* = true*/)
{
	std::stringstream s;
	s << getNameDescription(it, item, subType, addArticle);
	if(item)
		subType = item->getSubType();

	bool dot = true;
	if(it.isRune())
	{
		if(!it.runeSpellName.empty())
			s << "(\"" << it.runeSpellName << "\")";

		if(it.runeLevel > 0 || it.runeMagLevel > 0 || (it.vocationString != "" && it.wieldInfo == 0))
		{
			s << "." << std::endl << "It can only be used";
			if(it.vocationString != "" && it.wieldInfo == 0)
				s << " by " << it.vocationString;

			bool begin = true;
			if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && it.runeLevel > 0)
			{
				begin = false;
				s << " with level " << it.runeLevel;
			}

			if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && it.runeMagLevel > 0)
			{
				begin = false;
				s << " " << (begin ? "with" : "and") << " magic level " << it.runeMagLevel;
			}

			if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && !begin)
				s << " or higher";
		}
	}
	else if(it.weaponType != WEAPON_NONE)
	{
		bool begin = true;
		if(it.weaponType == WEAPON_DIST && it.ammoType != AMMO_NONE)
		{
			begin = false;
			s << " (Range:" << int32_t(item ? item->getShootRange() : it.shootRange);
			if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack())))
			{
				s << ", Atk " << std::showpos << int32_t(item ? item->getAttack() : it.attack);
				if(it.extraAttack || (item && item->getExtraAttack()))
					s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos;
			}

			if(it.hitChance != -1 || (item && item->getHitChance() != -1))
				s << ", Hit% " << std::showpos << (item ? item->getHitChance() : it.hitChance) << std::noshowpos;

			if(it.attackSpeed || (item && item->getAttackSpeed()))
				s << ", AS: " << (item ? item->getAttackSpeed() : it.attackSpeed);
		}
		else if(it.weaponType != WEAPON_AMMO && it.weaponType != WEAPON_WAND)
		{
			if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack())))
			{
				begin = false;
				s << " (Atk:";
				if(it.hasAbilities() && it.abilities->elementType != COMBAT_NONE)
				{
					s << std::max((int32_t)0, int32_t((item ? item->getAttack() : it.attack) - it.abilities->elementDamage));
					if(it.extraAttack || (item && item->getExtraAttack()))
						s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos;

					s << " physical + " << it.abilities->elementDamage << " " << getCombatName(it.abilities->elementType);
				}
				else
				{
					s << int32_t(item ? item->getAttack() : it.attack);
					if(it.extraAttack || (item && item->getExtraAttack()))
						s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos;
				}
			}

			if(it.defense || it.extraDefense || (item && (item->getDefense() || item->getExtraDefense())))
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "Def:" << int32_t(item ? item->getDefense() : it.defense);
				if(it.extraDefense || (item && item->getExtraDefense()))
					s << " " << std::showpos << int32_t(item ? item->getExtraDefense() : it.extraDefense) << std::noshowpos;
			}
		}

		if(it.attackSpeed || (item && item->getAttackSpeed()))
		{
			if(begin)
			{
				begin = false;
				s << " (";
			}
			else
				s << ", ";

			s << "AS: " << (item ? item->getAttackSpeed() : it.attackSpeed);
		}

		if(it.hasAbilities())
		{
			for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; ++i)
			{
				if(!it.abilities->skills[i])
					continue;

				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << getSkillName(i) << " " << std::showpos << (int32_t)it.abilities->skills[i] << std::noshowpos;
			}

			if(it.abilities->stats[STAT_MAGICLEVEL])
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "magic level " << std::showpos << (int32_t)it.abilities->stats[STAT_MAGICLEVEL] << std::noshowpos;
			}

			int32_t show = it.abilities->absorb[COMBAT_ALL];
			if(!show)
			{
				bool tmp = true;
				for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
				{
					if(!it.abilities->absorb[i])
						continue;

					if(tmp)
					{
						tmp = false;
						if(begin)
						{
							begin = false;
							s << " (";
						}
						else
							s << ", ";

						s << "protection ";
					}
					else
						s << ", ";

					s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%";
				}
			}
			else
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "protection all " << std::showpos << show << std::noshowpos << "%";
			}

			show = it.abilities->fieldAbsorb[COMBAT_ALL];
			if(!show)
			{
				bool tmp = true;
				for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
				{
					if(!it.abilities->fieldAbsorb[i])
						continue;

					if(tmp)
					{
						tmp = false;
						if(begin)
						{
							begin = false;
							s << " (";
						}
						else
							s << ", ";

						s << "protection ";
					}
					else
						s << ", ";

					s << getCombatName((CombatType_t)i) << " field " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%";
				}
			}
			else
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "protection all fields " << std::showpos << show << std::noshowpos << "%";
			}

			show = it.abilities->reflect[REFLECT_CHANCE][COMBAT_ALL];
			if(!show)
			{
				bool tmp = true;
				for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
				{
					if(!it.abilities->reflect[REFLECT_CHANCE][i] || !it.abilities->reflect[REFLECT_PERCENT][i])
						continue;

					if(tmp)
					{
						tmp = false;
						if(begin)
						{
							begin = false;
							s << " (";
						}
						else
							s << ", ";

						s << "reflect: ";
					}
					else
						s << ", ";

					s << it.abilities->reflect[REFLECT_CHANCE][i] << "% for ";
					if(it.abilities->reflect[REFLECT_PERCENT][i] > 99)
						s << "whole";
					else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 75)
						s << "huge";
					else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 50)
						s << "medium";
					else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 25)
						s << "small";
					else
						s << "tiny";

					s << getCombatName((CombatType_t)i);
				}

				if(!tmp)
					s << " damage";
			}
			else
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				int32_t tmp = it.abilities->reflect[REFLECT_PERCENT][COMBAT_ALL];
				s << "reflect: " << show << "% for ";
				if(tmp)
				{
					if(tmp > 99)
						s << "whole";
					else if(tmp >= 75)
						s << "huge";
					else if(tmp >= 50)
						s << "medium";
					else if(tmp >= 25)
						s << "small";
					else
						s << "tiny";
				}
				else
					s << "mixed";

				s << " damage";
			}

			if(it.abilities->speed)
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos;
			}

			if(it.abilities->invisible)
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "invisibility";
			}

			if(it.abilities->regeneration)
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "faster regeneration";
			}

			if(it.abilities->manaShield)
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "mana shield";
			}

			if(hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions))
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "hard drinking";
			}
		}

		if(it.dualWield || (item && item->isDualWield()))
		{
			if(begin)
			{
				begin = false;
				s << " (";
			}
			else
				s << ", ";

			s << "dual wielding";
		}

		if(!begin)
			s << ")";
	}
	else if(it.armor || (item && item->getArmor()) || it.showAttributes)
	{
		int32_t tmp = it.armor;
		if(item)
			tmp = item->getArmor();

		bool begin = true;
		if(tmp)
		{
			s << " (Arm:" << tmp;
			begin = false;
		}

		if(it.hasAbilities())
		{
			for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; ++i)
			{
				if(!it.abilities->skills[i])
					continue;

				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << getSkillName(i) << " " << std::showpos << (int32_t)it.abilities->skills[i] << std::noshowpos;
			}

			if(it.abilities->stats[STAT_MAGICLEVEL])
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "magic level " << std::showpos << (int32_t)it.abilities->stats[STAT_MAGICLEVEL] << std::noshowpos;
			}

			int32_t show = it.abilities->absorb[COMBAT_ALL];
			if(!show)
			{
				bool tmp = true;
				for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
				{
					if(!it.abilities->absorb[i])
						continue;

					if(tmp)
					{
						tmp = false;
						if(begin)
						{
							begin = false;
							s << " (";
						}
						else
							s << ", ";

						s << "protection ";
					}
					else
						s << ", ";

					s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%";
				}
			}
			else
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "protection all " << std::showpos << show << std::noshowpos << "%";
			}

			show = it.abilities->reflect[REFLECT_CHANCE][COMBAT_ALL];
			if(!show)
			{
				bool tmp = true;
				for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1)
				{
					if(!it.abilities->reflect[REFLECT_CHANCE][i] || !it.abilities->reflect[REFLECT_PERCENT][i])
						continue;

					if(tmp)
					{
						tmp = false;
						if(begin)
						{
							begin = false;
							s << " (";
						}
						else
							s << ", ";

						s << "reflect: ";
					}
					else
						s << ", ";

					s << it.abilities->reflect[REFLECT_CHANCE][i] << "% for ";
					if(it.abilities->reflect[REFLECT_PERCENT][i] > 99)
						s << "whole";
					else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 75)
						s << "huge";
					else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 50)
						s << "medium";
					else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 25)
						s << "small";
					else
						s << "tiny";

					s << getCombatName((CombatType_t)i);
				}

				if(!tmp)
					s << " damage";
			}
			else
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				int32_t tmp = it.abilities->reflect[REFLECT_PERCENT][COMBAT_ALL];
				s << "reflect: " << show << "% for ";
				if(tmp)
				{
					if(tmp > 99)
						s << "whole";
					else if(tmp >= 75)
						s << "huge";
					else if(tmp >= 50)
						s << "medium";
					else if(tmp >= 25)
						s << "small";
					else
						s << "tiny";
				}
				else
					s << "mixed";

				s << " damage";
			}

			if(it.abilities->speed)
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos;
			}

			if(it.abilities->invisible)
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "invisibility";
			}

			if(it.abilities->regeneration)
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "faster regeneration";
			}

			if(it.abilities->manaShield)
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "mana shield";
			}

			if(hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions))
			{
				if(begin)
				{
					begin = false;
					s << " (";
				}
				else
					s << ", ";

				s << "hard drinking";
			}

			if(!begin)
				s << ")";
		}
	}
	else if(it.isContainer())
		s << " (Vol:" << (int32_t)it.maxItems << ")";
	else if(it.isKey())
		s << " (Key:" << (item ? (int32_t)item->getActionId() : 0) << ")";
	else if(it.isFluidContainer())
	{
		if(subType > 0)
			s << " of " << (items[subType].name.length() ? items[subType].name : "unknown");
		else
			s << ". It is empty";
	}
	else if(it.isSplash())
	{
		s << " of ";
		if(subType > 0 && items[subType].name.length())
			s << items[subType].name;
		else
			s << "unknown";
	}
	else if(it.allowDistRead)
	{
		s << "." << std::endl;
		if(item && !item->getText().empty())
		{
			if(lookDistance <= 4)
			{
				if(!item->getWriter().empty())
				{
					s << item->getWriter() << " wrote";
					time_t date = item->getDate();
					if(date > 0)
						s << " on " << formatDate(date);

					s << ": ";
				}
				else
					s << "You read: ";

				std::string text = item->getText();
				s << text;

				char end = *text.rbegin();
				if(end == '?' || end == '!' || end == '.')
					dot = false;
			}
			else
				s << "You are too far away to read it";
		}
		else
			s << "Nothing is written on it";
	}
	else if(it.levelDoor && item && item->getActionId() >= (int32_t)it.levelDoor && item->getActionId()
		<= ((int32_t)it.levelDoor + g_config.getNumber(ConfigManager::MAXIMUM_DOOR_LEVEL)))
		s << " for level " << item->getActionId() - it.levelDoor;

	if(it.showCharges)
		s << " that has " << subType << " charge" << (subType != 1 ? "s" : "") << " left";

	if(it.showDuration)
	{
		if(item && item->hasIntegerAttribute("duration"))
		{
			int32_t duration = item->getDuration() / 1000;
			s << " that will expire in ";
			if(duration >= 86400)
			{
				uint16_t days = duration / 86400;
				uint16_t hours = (duration % 86400) / 3600;
				s << days << " day" << (days > 1 ? "s" : "");
				if(hours > 0)
					s << " and " << hours << " hour" << (hours > 1 ? "s" : "");
			}
			else if(duration >= 3600)
			{
				uint16_t hours = duration / 3600;
				uint16_t minutes = (duration % 3600) / 60;
				s << hours << " hour" << (hours > 1 ? "s" : "");
				if(hours > 0)
					s << " and " << minutes << " minute" << (minutes > 1 ? "s" : "");
			}
			else if(duration >= 60)
			{
				uint16_t minutes = duration / 60;
				uint16_t seconds = duration % 60;
				s << minutes << " minute" << (minutes > 1 ? "s" : "");
				if(seconds > 0)
					s << " and " << seconds << " second" << (seconds > 1 ? "s" : "");
			}
			else
				s << duration << " second" << (duration > 1 ? "s" : "");
		}
		else
			s << " that is brand-new";
	}

	if(dot)
		s << ".";

	if(it.wieldInfo)
	{
		s << std::endl << "It can only be wielded properly by ";
		if(it.wieldInfo & WIELDINFO_PREMIUM)
			s << "premium ";

		if(it.wieldInfo & WIELDINFO_VOCREQ)
			s << it.vocationString;
		else
			s << "players";

		if(it.wieldInfo & WIELDINFO_LEVEL)
			s << " of level " << (int32_t)it.minReqLevel << " or higher";

		if(it.wieldInfo & WIELDINFO_MAGLV)
		{
			if(it.wieldInfo & WIELDINFO_LEVEL)
				s << " and";
			else
				s << " of";

			s << " magic level " << (int32_t)it.minReqMagicLevel << " or higher";
		}

		s << ".";
	}

	if(lookDistance <= 1 && it.pickupable)
	{
		std::string tmp;
		if(!item)
			tmp = getWeightDescription(it.weight, it.stackable && it.showCount, subType);
		else
			tmp = item->getWeightDescription();

		if(!tmp.empty())
			s << std::endl << tmp;
	}

	if(item && !item->getSpecialDescription().empty())
		s << std::endl << item->getSpecialDescription();
	else if(!it.description.empty() && lookDistance <= 1)
		s << std::endl << it.description;

	std::string str = s.str();
	if(str.find("|PLAYERNAME|") != std::string::npos)
	{
		std::string tmp = "You";
		if(item)
		{
			if(const Player* player = item->getHoldingPlayer())
				tmp = player->getName();
		}

		replaceString(str, "|PLAYERNAME|", tmp);
	}

	if(str.find("|TIME|") != std::string::npos || str.find("|DATE|") != std::string::npos || str.find(
		"|DAY|") != std::string::npos || str.find("|MONTH|") != std::string::npos || str.find(
		"|YEAR|") != std::string::npos || str.find("|HOUR|") != std::string::npos || str.find(
		"|MINUTES|") != std::string::npos || str.find("|SECONDS|") != std::string::npos ||
		str.find("|WEEKDAY|") != std::string::npos || str.find("|YEARDAY|") != std::string::npos)
	{
		time_t now = time(NULL);
		tm* ts = localtime(&now);

		std::stringstream ss;
		ss << ts->tm_sec;
		replaceString(str, "|SECONDS|", ss.str());

		ss.str("");
		ss << ts->tm_min;
		replaceString(str, "|MINUTES|", ss.str());

		ss.str("");
		ss << ts->tm_hour;
		replaceString(str, "|HOUR|", ss.str());

		ss.str("");
		ss << ts->tm_mday;
		replaceString(str, "|DAY|", ss.str());

		ss.str("");
		ss << (ts->tm_mon + 1);
		replaceString(str, "|MONTH|", ss.str());

		ss.str("");
		ss << (ts->tm_year + 1900);
		replaceString(str, "|YEAR|", ss.str());

		ss.str("");
		ss << ts->tm_wday;
		replaceString(str, "|WEEKDAY|", ss.str());

		ss.str("");
		ss << ts->tm_yday;
		replaceString(str, "|YEARDAY|", ss.str());

		ss.str("");
		ss << ts->tm_hour << ":" << ts->tm_min << ":" << ts->tm_sec;
		replaceString(str, "|TIME|", ss.str());

		ss.str("");
		replaceString(str, "|DATE|", formatDateEx(now));
	}

	return str;
}
Example #22
0
Cylinder* Container::queryDestination(int32_t& index, const Thing& thing, Item** destItem,
		uint32_t& flags)
{
	if (!unlocked) {
		*destItem = nullptr;
		return this;
	}

	if (index == 254 /*move up*/) {
		index = INDEX_WHEREEVER;
		*destItem = nullptr;

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

	if (index == 255 /*add wherever*/) {
		index = INDEX_WHEREEVER;
		*destItem = nullptr;
	} else if (index >= static_cast<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 = nullptr;
	}

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

	if (index != INDEX_WHEREEVER) {
		Item* itemFromIndex = getItemByIndex(index);
		if (itemFromIndex) {
			*destItem = itemFromIndex;
		}

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

	bool autoStack = !hasBitSet(FLAG_IGNOREAUTOSTACK, flags);
	if (autoStack && item->isStackable() && item->getParent() != this) {
		//try find a suitable item to stack with
		uint32_t n = 0;
		for (Item* listItem : itemlist) {
			if (listItem != item && listItem->equals(item) && listItem->getItemCount() < 100) {
				*destItem = listItem;
				index = n;
				return this;
			}
			++n;
		}
	}
	return this;
}
Example #23
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 = !hasBitSet(FLAG_IGNOREAUTOSTACK, flags);
	if(autoStack && item->isStackable() && item->getParent() != this)
	{
		//try find a suitable item to stack with
		uint32_t n = 0;
		for(ItemDeque::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)
	{
		Item* itemFromIndex = getItem(index);
		if(itemFromIndex)
			*destItem = itemFromIndex;

		Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem);
		if(subCylinder)
		{
			index = INDEX_WHEREEVER;
			*destItem = NULL;
			return subCylinder;
		}
	}
	return this;
}
Example #24
0
bool Creature::isImmune(CombatType_t type) const
{
	return hasBitSet(static_cast<uint32_t>(type), getDamageImmunities());
}
Example #25
0
std::string Item::getDescription(const ItemType& it, int32_t lookDistance,
                                 const Item* item /*= NULL*/, int32_t subType /*= -1*/, bool addArticle /*= true*/)
{
	std::ostringstream s;
	s << getNameDescription(it, item, subType, addArticle);

	if (item) {
		subType = item->getSubType();
	}

	if (it.isRune()) {
		if (!it.runeSpellName.empty()) {
			s << " (\"" << it.runeSpellName << "\")";
		}

		if (it.runeLevel > 0 || it.runeMagLevel > 0) {
			int32_t tmpSubType = subType;

			if (item) {
				tmpSubType = item->getSubType();
			}

			s << ". " << (it.stackable && tmpSubType > 1 ? "They" : "It") << " can only be used with";

			if (it.runeLevel > 0) {
				s << " level " << it.runeLevel;
			}

			if (it.runeMagLevel > 0) {
				if (it.runeLevel > 0) {
					s << " and";
				}

				s << " magic level " << it.runeMagLevel;
			}

			s << " or higher";
		}
	} else if (it.weaponType != WEAPON_NONE) {
		if (it.weaponType == WEAPON_DIST && it.ammoType != AMMO_NONE) {
			s << " (Range:" << it.shootRange;

			if (it.attack != 0) {
				s << ", Atk " << std::showpos << it.attack << std::noshowpos;
			}

			if (it.hitChance != 0) {
				s << ", Hit% " << std::showpos << it.hitChance << std::noshowpos;
			}

			s << ")";
		} else if (it.weaponType != WEAPON_AMMO) {
			bool begin = true;

			if (it.attack != 0) {
				begin = false;
				s << " (Atk:" << it.attack;

				if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) {
					s << " physical + " << it.abilities->elementDamage << " " << getCombatName(it.abilities->elementType);
				}
			}

			if (it.defense != 0 || it.extraDefense != 0) {
				if (begin) {
					begin = false;
					s << " (";
				} else {
					s << ", ";
				}

				s << "Def:" << it.defense;

				if (it.extraDefense != 0 || (item && item->getExtraDefense() != 0)) {
					s << " " << std::showpos << it.extraDefense << std::noshowpos;
				}
			}

			if (it.abilities) {
				for (uint16_t i = SKILL_FIRST; i <= SKILL_LAST; i++) {
					if (!it.abilities->skills[i]) {
						continue;
					}

					if (begin) {
						begin = false;
						s << " (";
					} else {
						s << ", ";
					}

					s << getSkillName(i) << " " << std::showpos << it.abilities->skills[i] << std::noshowpos;
				}

				if (it.abilities->stats[STAT_MAGICPOINTS]) {
					if (begin) {
						begin = false;
						s << " (";
					} else {
						s << ", ";
					}

					s << "magic level " << std::showpos << it.abilities->stats[STAT_MAGICPOINTS] << std::noshowpos;
				}

				int32_t show = it.abilities->absorbPercent[COMBAT_FIRST];

				for (uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_COUNT; ++i) {
					if (it.abilities->absorbPercent[i] == show) {
						continue;
					}

					show = 0;
					break;
				}

				if (!show) {
					bool tmp = true;

					for (uint32_t i = COMBAT_FIRST; i <= COMBAT_COUNT; i++) {
						if (!it.abilities->absorbPercent[i]) {
							continue;
						}

						if (tmp) {
							tmp = false;

							if (begin) {
								begin = false;
								s << " (";
							} else {
								s << ", ";
							}

							s << "protection ";
						} else {
							s << ", ";
						}

						s << getCombatName(indexToCombatType(i)) << " " << std::showpos << it.abilities->absorbPercent[i] << std::noshowpos << "%";
					}
				} else {
					if (begin) {
						begin = false;
						s << " (";
					} else {
						s << ", ";
					}

					s << "protection all " << std::showpos << show << std::noshowpos << "%";
				}

				if (it.abilities->speed) {
					if (begin) {
						begin = false;
						s << " (";
					} else {
						s << ", ";
					}

					s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos;
				}
			}

			if (!begin) {
				s << ")";
			}
		}
	} else if (it.armor || (item && item->getArmor()) || it.showAttributes) {
		int32_t tmp = it.armor;

		if (item) {
			tmp = item->getArmor();
		}

		bool begin = true;

		if (tmp != 0) {
			s << " (Arm:" << tmp;
			begin = false;
		}

		if (it.abilities) {
			for (uint16_t i = SKILL_FIRST; i <= SKILL_LAST; i++) {
				if (!it.abilities->skills[i]) {
					continue;
				}

				if (begin) {
					begin = false;
					s << " (";
				} else {
					s << ", ";
				}

				s << getSkillName(i) << " " << std::showpos << it.abilities->skills[i] << std::noshowpos;
			}

			if (it.abilities->stats[STAT_MAGICPOINTS]) {
				if (begin) {
					begin = false;
					s << " (";
				} else {
					s << ", ";
				}

				s << "magic level " << std::showpos << it.abilities->stats[STAT_MAGICPOINTS] << std::noshowpos;
			}

			int32_t show = it.abilities->absorbPercent[COMBAT_FIRST];

			for (uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_COUNT; ++i) {
				if (it.abilities->absorbPercent[i] == show) {
					continue;
				}

				show = 0;
				break;
			}

			if (!show) {
				bool protectionBegin = true;
				for (uint32_t i = COMBAT_FIRST; i <= COMBAT_COUNT; i++) {
					if (!it.abilities->absorbPercent[i]) {
						continue;
					}

					if (protectionBegin) {
						protectionBegin = false;

						if (begin) {
							begin = false;
							s << " (";
						} else {
							s << ", ";
						}

						s << "protection ";
					} else {
						s << ", ";
					}

					s << getCombatName(indexToCombatType(i)) << " " << std::showpos << it.abilities->absorbPercent[i] << std::noshowpos << "%";
				}
			} else {
				if (begin) {
					begin = false;
					s << " (";
				} else {
					s << ", ";
				}

				s << "protection all " << std::showpos << show << std::noshowpos << "%";
			}

			if (it.abilities->speed) {
				if (begin) {
					begin = false;
					s << " (";
				} else {
					s << ", ";
				}

				s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos;
			}
		}

		if (!begin) {
			s << ")";
		}
	} else if (it.isContainer()) {
		s << " (Vol:" << (int32_t)it.maxItems << ")";
	} else {
		bool found = true;

		if (it.abilities) {
			if (it.abilities->speed > 0) {
				s << " (speed " << std::showpos << (it.abilities->speed / 2) << std::noshowpos << ")";
			} else if (it.abilities && hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions)) {
				s << " (hard drinking)";
			} else if (it.abilities->invisible) {
				s << " (invisibility)";
			} else if (it.abilities->regeneration) {
				s << " (faster regeneration)";
			} else if (it.abilities->manaShield) {
				s << " (mana shield)";
			} else {
				found = false;
			}
		} else {
			found = false;
		}

		if (!found) {
			if (it.isKey()) {
				s << " (Key:" << (item ? (int32_t)item->getActionId() : 0) << ")";
			} else if (it.isFluidContainer()) {
				if (subType > 0) {
					const std::string& itemName = items[subType].name;
					s << " of " << (itemName.length() ? itemName : "unknown");
				} else {
					s << ". It is empty";
				}
			} else if (it.isSplash()) {
				s << " of ";

				if (subType > 0 && items[subType].name.length()) {
					s << items[subType].name;
				} else {
					s << "unknown";
				}
			} else if (it.allowDistRead && it.id != 7369 && it.id != 7370 && it.id != 7371) {
				s << "." << std::endl;

				if (lookDistance <= 4) {
					if (item && !item->getText().empty()) {
						if (item->getWriter().length()) {
							s << item->getWriter() << " wrote";
							time_t date = item->getDate();

							if (date > 0) {
								s << " on " << formatDateShort(date);
							}

							s << ": ";
						} else {
							s << "You read: ";
						}

						std::string outtext;

						if (utf8ToLatin1(item->getText().c_str(), outtext)) {
							s << outtext;
						} else {
							s << item->getText();
						}
					} else {
						s << "Nothing is written on it";
					}
				} else {
					s << "You are too far away to read it";
				}
			} else if (it.levelDoor && item && item->getActionId() >= (int32_t)it.levelDoor) {
				s << " for level " << item->getActionId() - it.levelDoor;
			}
		}
	}

	if (it.showCharges) {
		s << " that has " << subType << " charge" << (subType != 1 ? "s" : "") << " left";
	}

	if (it.showDuration) {
		if (item && item->hasAttribute(ATTR_ITEM_DURATION)) {
			int32_t duration = item->getDuration() / 1000;
			s << " that will expire in ";

			if (duration >= 86400) {
				uint16_t days = duration / 86400;
				uint16_t hours = (duration % 86400) / 3600;
				s << days << " day" << (days != 1 ? "s" : "");

				if (hours > 0) {
					s << " and " << hours << " hour" << (hours != 1 ? "s" : "");
				}
			} else if (duration >= 3600) {
				uint16_t hours = duration / 3600;
				uint16_t minutes = (duration % 3600) / 60;
				s << hours << " hour" << (hours != 1 ? "s" : "");

				if (minutes > 0) {
					s << " and " << minutes << " minute" << (minutes != 1 ? "s" : "");
				}
			} else if (duration >= 60) {
				uint16_t minutes = duration / 60;
				s << minutes << " minute" << (minutes != 1 ? "s" : "");
				uint16_t seconds = duration % 60;

				if (seconds > 0) {
					s << " and " << seconds << " second" << (seconds != 1 ? "s" : "");
				}
			} else {
				s << duration << " second" << (duration != 1 ? "s" : "");
			}
		} else {
			s << " that is brand-new";
		}
	}

	if (!it.allowDistRead || item->getText().empty() || (it.id >= 7369 && it.id <= 7371)) {
		s << ".";
	}

	if (it.wieldInfo != 0) {
		s << std::endl << "It can only be wielded properly by ";

		if (it.wieldInfo & WIELDINFO_PREMIUM) {
			s << "premium ";
		}

		if (it.wieldInfo & WIELDINFO_VOCREQ) {
			s << it.vocationString;
		} else {
			s << "players";
		}

		if (it.wieldInfo & WIELDINFO_LEVEL) {
			s << " of level " << (int32_t)it.minReqLevel << " or higher";
		}

		if (it.wieldInfo & WIELDINFO_MAGLV) {
			if (it.wieldInfo & WIELDINFO_LEVEL) {
				s << " and";
			} else {
				s << " of";
			}

			s << " magic level " << (int32_t)it.minReqMagicLevel << " or higher";
		}

		s << ".";
	}

	if (lookDistance <= 1) {
		double weight = (item == NULL ? it.weight : item->getWeight());

		if (weight > 0 && it.pickupable) {
			int32_t count = weight / it.weight;
			s << std::endl << getWeightDescription(it, weight, count);
		}
	}

	if (item && !item->getSpecialDescription().empty()) {
		s << std::endl << item->getSpecialDescription();
	} else if (it.description.length() && lookDistance <= 1) {
		s << std::endl << it.description;
	}

	if (it.allowDistRead && it.id >= 7369 && it.id <= 7371 && !item->getText().empty()) {
		s << std::endl << item->getText();
	}

	return s.str();
}
Example #26
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 #27
0
bool Creature::isImmune(ConditionType_t type) const
{
	return hasBitSet(static_cast<uint32_t>(type), getConditionImmunities());
}
Example #28
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 #29
0
FILELOADER_ERRORS Items::loadFromOtb(const std::string& file)
{
	FileLoader f;
	if (!f.openFile(file.c_str(), "OTBI")) {
		return f.getError();
	}

	uint32_t type;
	NODE node = f.getChildNode(NO_NODE, type);

	PropStream props;
	if (f.getProps(node, props)) {
		//4 byte flags
		//attributes
		//0x01 = version data
		uint32_t flags;
		if (!props.read<uint32_t>(flags)) {
			return ERROR_INVALID_FORMAT;
		}

		uint8_t attr;
		if (!props.read<uint8_t>(attr)) {
			return ERROR_INVALID_FORMAT;
		}

		if (attr == ROOT_ATTR_VERSION) {
			uint16_t datalen;
			if (!props.read<uint16_t>(datalen)) {
				return ERROR_INVALID_FORMAT;
			}

			if (datalen != sizeof(VERSIONINFO)) {
				return ERROR_INVALID_FORMAT;
			}

			VERSIONINFO vi;
			if (!props.read(vi)) {
				return ERROR_INVALID_FORMAT;
			}

			Items::dwMajorVersion = vi.dwMajorVersion; //items otb format file version
			Items::dwMinorVersion = vi.dwMinorVersion; //client version
			Items::dwBuildNumber = vi.dwBuildNumber; //revision
		}
	}

	if (Items::dwMajorVersion == 0xFFFFFFFF) {
		std::cout << "[Warning - Items::loadFromOtb] items.otb using generic client version." << std::endl;
	} else if (Items::dwMajorVersion != 2) {
		std::cout << "Old version detected, a newer version of items.otb is required." << std::endl;
		return ERROR_INVALID_FORMAT;
	} else if (Items::dwMinorVersion < CLIENT_VERSION_800) {
		std::cout << "A newer version of items.otb is required." << std::endl;
		return ERROR_INVALID_FORMAT;
	}

	node = f.getChildNode(node, type);
	while (node != NO_NODE) {
		PropStream stream;
		if (!f.getProps(node, stream)) {
			return f.getError();
		}

		uint32_t flags;
		if (!stream.read<uint32_t>(flags)) {
			return ERROR_INVALID_FORMAT;
		}

		uint16_t serverId = 0;
		uint16_t clientId = 0;
		uint16_t speed = 0;
		uint16_t wareId = 0;
		uint8_t lightLevel = 0;
		uint8_t lightColor = 0;
		uint8_t alwaysOnTopOrder = 0;

		uint8_t attrib;
		while (stream.read<uint8_t>(attrib)) {
			uint16_t datalen;
			if (!stream.read<uint16_t>(datalen)) {
				return ERROR_INVALID_FORMAT;
			}

			switch (attrib) {
				case ITEM_ATTR_SERVERID: {
					if (datalen != sizeof(uint16_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint16_t>(serverId)) {
						return ERROR_INVALID_FORMAT;
					}

					if (serverId > 30000 && serverId < 30100) {
						serverId -= 30000;
					}
					break;
				}

				case ITEM_ATTR_CLIENTID: {
					if (datalen != sizeof(uint16_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint16_t>(clientId)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}

				case ITEM_ATTR_SPEED: {
					if (datalen != sizeof(uint16_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint16_t>(speed)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}

				case ITEM_ATTR_LIGHT2: {
					if (datalen != sizeof(lightBlock2)) {
						return ERROR_INVALID_FORMAT;
					}

					lightBlock2 lb2;
					if (!stream.read(lb2)) {
						return ERROR_INVALID_FORMAT;
					}

					lightLevel = static_cast<uint8_t>(lb2.lightLevel);
					lightColor = static_cast<uint8_t>(lb2.lightColor);
					break;
				}

				case ITEM_ATTR_TOPORDER: {
					if (datalen != sizeof(uint8_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint8_t>(alwaysOnTopOrder)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}

				case ITEM_ATTR_WAREID: {
					if (datalen != sizeof(uint16_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint16_t>(wareId)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}

				default: {
					//skip unknown attributes
					if (!stream.skip(datalen)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}
			}
		}

		reverseItemMap.emplace(clientId, serverId);

		// store the found item
		if (serverId >= items.size()) {
			items.resize(serverId + 1);
		}
		ItemType& iType = items[serverId];

		iType.group = static_cast<itemgroup_t>(type);
		switch (type) {
			case ITEM_GROUP_CONTAINER:
				iType.type = ITEM_TYPE_CONTAINER;
				break;
			case ITEM_GROUP_DOOR:
				//not used
				iType.type = ITEM_TYPE_DOOR;
				break;
			case ITEM_GROUP_MAGICFIELD:
				//not used
				iType.type = ITEM_TYPE_MAGICFIELD;
				break;
			case ITEM_GROUP_TELEPORT:
				//not used
				iType.type = ITEM_TYPE_TELEPORT;
				break;
			case ITEM_GROUP_NONE:
			case ITEM_GROUP_GROUND:
			case ITEM_GROUP_SPLASH:
			case ITEM_GROUP_FLUID:
			case ITEM_GROUP_CHARGES:
			case ITEM_GROUP_DEPRECATED:
				break;
			default:
				return ERROR_INVALID_FORMAT;
		}

		iType.blockSolid = hasBitSet(FLAG_BLOCK_SOLID, flags);
		iType.blockProjectile = hasBitSet(FLAG_BLOCK_PROJECTILE, flags);
		iType.blockPathFind = hasBitSet(FLAG_BLOCK_PATHFIND, flags);
		iType.hasHeight = hasBitSet(FLAG_HAS_HEIGHT, flags);
		iType.useable = hasBitSet(FLAG_USEABLE, flags);
		iType.pickupable = hasBitSet(FLAG_PICKUPABLE, flags);
		iType.moveable = hasBitSet(FLAG_MOVEABLE, flags);
		iType.stackable = hasBitSet(FLAG_STACKABLE, flags);

		iType.alwaysOnTop = hasBitSet(FLAG_ALWAYSONTOP, flags);
		iType.isVertical = hasBitSet(FLAG_VERTICAL, flags);
		iType.isHorizontal = hasBitSet(FLAG_HORIZONTAL, flags);
		iType.isHangable = hasBitSet(FLAG_HANGABLE, flags);
		iType.allowDistRead = hasBitSet(FLAG_ALLOWDISTREAD, flags);
		iType.rotatable = hasBitSet(FLAG_ROTATABLE, flags);
		iType.canReadText = hasBitSet(FLAG_READABLE, flags);
		iType.lookThrough = hasBitSet(FLAG_LOOKTHROUGH, flags);
		// iType.walkStack = !hasBitSet(FLAG_FULLTILE, flags);
		iType.forceUse = hasBitSet(FLAG_FORCEUSE, flags);

		iType.id = serverId;
		iType.clientId = clientId;
		iType.speed = speed;
		iType.lightLevel = lightLevel;
		iType.lightColor = lightColor;
		iType.wareId = wareId;
		iType.alwaysOnTopOrder = alwaysOnTopOrder;

		node = f.getNextNode(node, type);
	}

	items.shrink_to_fit();
	return ERROR_NONE;
}
Example #30
0
bool Creature::isSuppress(ConditionType_t type) const
{
	return hasBitSet(static_cast<uint32_t>(type), getConditionSuppressions());
}