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