uint32_t Tile::getHeight() const { uint32_t height = 0; Item* iiItem = NULL; for(uint32_t i = 0; i < getThingCount(); ++i){ iiItem = __getThing(i)->getItem(); if(iiItem && iiItem->hasProperty(HASHEIGHT)) ++height; } return height; }
Cylinder* Container::__queryDestination(int32_t& index, const Thing* thing, Item** destItem, uint32_t& flags) { if(index == 254 /*move up*/){ index = INDEX_WHEREEVER; *destItem = NULL; Container* parentContainer = dynamic_cast<Container*>(getParent()); if(parentContainer) return parentContainer; else return this; } else if(index == 255 /*add wherever*/){ index = INDEX_WHEREEVER; *destItem = NULL; return this; } else{ if(index >= (int32_t)capacity()){ /* if you have a container, maximize it to show all 20 slots then you open a bag that is inside the container you will have a bag with 8 slots and a "grey" area where the other 12 slots where from the container if you drop the item on that grey area the client calculates the slot position as if the bag has 20 slots */ index = INDEX_WHEREEVER; } if(index != INDEX_WHEREEVER){ Thing* destThing = __getThing(index); if(destThing) *destItem = destThing->getItem(); Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem); if(subCylinder){ index = INDEX_WHEREEVER; *destItem = NULL; return subCylinder; } } } return this; }
ReturnValue Container::__queryMaxCount(int32_t index, const Thing* thing, uint32_t count, uint32_t& maxQueryCount, uint32_t flags) const { const Item* item = thing->getItem(); if(item == NULL){ maxQueryCount = 0; return RET_NOTPOSSIBLE; } if( ((flags & FLAG_NOLIMIT) == FLAG_NOLIMIT) ){ maxQueryCount = std::max((uint32_t)1, count); return RET_NOERROR; } int32_t freeSlots = std::max((int32_t)(capacity() - size()), (int32_t)0); if(item->isStackable()){ uint32_t n = 0; if(index != INDEX_WHEREEVER){ const Thing* destThing = __getThing(index); const Item* destItem = NULL; if(destThing) destItem = destThing->getItem(); if(destItem && destItem->getID() == item->getID()){ n = 100 - destItem->getItemCount(); } } maxQueryCount = freeSlots * 100 + n; if(maxQueryCount < count){ return RET_CONTAINERNOTENOUGHROOM; } } else{ maxQueryCount = freeSlots; if(maxQueryCount == 0){ return RET_CONTAINERNOTENOUGHROOM; } } return RET_NOERROR; }
Cylinder* Container::__queryDestination(int32_t& index, const Thing* thing, Item** destItem, uint32_t& flags) { if(index == 254 /*move up*/) { index = INDEX_WHEREEVER; *destItem = NULL; Container* parentContainer = dynamic_cast<Container*>(getParent()); if(parentContainer) return parentContainer; return this; } if(index == 255 /*add wherever*/) { index = INDEX_WHEREEVER; *destItem = NULL; } else if(index >= (int32_t)capacity()) { /* if you have a container, maximize it to show all 20 slots then you open a bag that is inside the container you will have a bag with 8 slots and a "grey" area where the other 12 slots where from the container if you drop the item on that grey area the client calculates the slot position as if the bag has 20 slots */ index = INDEX_WHEREEVER; *destItem = NULL; } const Item* item = thing->getItem(); if(!item) return this; if(!((flags & FLAG_IGNOREAUTOSTACK) == FLAG_IGNOREAUTOSTACK) && item->isStackable() && item->getParent() != this) { //try to find a suitable item to stack with uint32_t n = itemlist.size(); for(ItemList::reverse_iterator cit = itemlist.rbegin(); cit != itemlist.rend(); ++cit, --n) { if((*cit)->getID() == item->getID() && (*cit)->getItemCount() < 100) { *destItem = (*cit); index = n; return this; } } } if(index != INDEX_WHEREEVER) { Thing* destThing = __getThing(index); if(destThing) *destItem = destThing->getItem(); if(Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem)) { index = INDEX_WHEREEVER; *destItem = NULL; return subCylinder; } } return this; }
ReturnValue Container::__queryMaxCount(int32_t index, const Thing* thing, uint32_t count, uint32_t& maxQueryCount, uint32_t flags) const { const Item* item = thing->getItem(); if(!item) { maxQueryCount = 0; return RET_NOTPOSSIBLE; } if(((flags & FLAG_NOLIMIT) == FLAG_NOLIMIT)) { maxQueryCount = std::max((uint32_t)1, count); return RET_NOERROR; } int32_t freeSlots = std::max((int32_t)(capacity() - size()), (int32_t)0); if(item->isStackable()) { uint32_t n = 0; if(index == INDEX_WHEREEVER) { //Iterate through every item and check how much free stackable slots there is. uint32_t slotIndex = 0; for(ItemList::const_iterator cit = itemlist.begin(); cit != itemlist.end(); ++cit, ++slotIndex) { if((*cit) != item && (*cit)->getID() == item->getID() && (*cit)->getItemCount() < 100) { uint32_t remainder = (100 - (*cit)->getItemCount()); if(__queryAdd(slotIndex, item, remainder, flags) == RET_NOERROR) n += remainder; } } } else { const Thing* destThing = __getThing(index-1); const Item* destItem = NULL; if(destThing) destItem = destThing->getItem(); if(destItem && destItem->getID() == item->getID() && destItem->getItemCount() < 100) { uint32_t remainder = 100 - destItem->getItemCount(); if(__queryAdd(index, item, remainder, flags) == RET_NOERROR) n = remainder; } } maxQueryCount = freeSlots * 100 + n; if(maxQueryCount < count) return RET_CONTAINERNOTENOUGHROOM; } else { maxQueryCount = freeSlots; if(maxQueryCount == 0) return RET_CONTAINERNOTENOUGHROOM; } return RET_NOERROR; }
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; }
Cylinder* Container::__queryDestination(int32_t& index, const Thing* thing, Item** destItem, uint32_t& flags) { if(index == 254 /*move up*/){ index = INDEX_WHEREEVER; *destItem = NULL; Container* parentContainer = dynamic_cast<Container*>(getParent()); if(parentContainer) return parentContainer; return this; } if(index == 255 /*add wherever*/){ index = INDEX_WHEREEVER; *destItem = NULL; } else if(index >= (int32_t)capacity()){ /* if you have a container, maximize it to show all 20 slots then you open a bag that is inside the container you will have a bag with 8 slots and a "grey" area where the other 12 slots where from the container if you drop the item on that grey area the client calculates the slot position as if the bag has 20 slots */ index = INDEX_WHEREEVER; *destItem = NULL; } const Item* item = thing->getItem(); if(item == NULL){ return this; } bool autoStack = g_config.getBoolean(ConfigManager::CONTAINER_ITEMS_AUTO_STACK); if(autoStack){ if(item->isStackable()){ if(item->getParent() != this){ //try find a suitable item to stack with uint32_t n = 0; for(ItemList::iterator cit = itemlist.begin(); cit != itemlist.end(); ++cit){ if((*cit) != item && (*cit)->getID() == item->getID() && (*cit)->getItemCount() < 100){ *destItem = (*cit); index = n; return this; } ++n; } } } } if(index != INDEX_WHEREEVER){ Thing* destThing = __getThing(index); if(destThing) *destItem = destThing->getItem(); Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem); if(subCylinder){ index = INDEX_WHEREEVER; *destItem = NULL; return subCylinder; } } return this; }
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; }
ReturnValue Tile::__queryAdd(int32_t index, const Thing* thing, uint32_t count, bool childIsOwner /*= false*/) const { Thing* iithing = NULL; if(const Creature* creature = thing->getCreature()){ if(!creatures.empty()) return RET_NOTPOSSIBLE; if(ground == NULL) return RET_NOTPOSSIBLE; if(const Monster* monster = creature->getMonster()){ if(hasFlag(TILESTATE_PROTECTIONZONE)) return RET_NOTPOSSIBLE; if(const MagicEffectItem* fieldItem = getFieldItem()){ const MagicEffectTargetCreatureCondition* magicTargetCondition = fieldItem->getCondition(); if(magicTargetCondition){ if((monster->getImmunities() & magicTargetCondition->attackType) != magicTargetCondition->attackType){ return RET_NOTPOSSIBLE; } } } if(floorChange() || getTeleportItem()){ return RET_NOTPOSSIBLE; } for(uint32_t i = 0; i < getThingCount(); ++i){ iithing = __getThing(i); if(const Item* iitem = iithing->getItem()){ const ItemType& iiType = Item::items[iitem->getID()]; if(iiType.blockSolid){ if(!monster->canPushItems() || !iiType.moveable){ return RET_NOTPOSSIBLE; } } } } return RET_NOERROR; } else if(const Player* player = creature->getPlayer()){ if(hasFlag(TILESTATE_PROTECTIONZONE) && player->pzLocked){ return RET_PLAYERISPZLOCKED; } } for(uint32_t i = 0; i < getThingCount(); ++i){ iithing = __getThing(i); if(const Item* iitem = iithing->getItem()){ const ItemType& iiType = Item::items[iitem->getID()]; if(iiType.blockSolid){ //check if this a creature that just is about to login/spawn //those can be placed here if the blocking item is moveable if(!creature->getParent()){ if(!iiType.moveable) return RET_NOTPOSSIBLE; } else return RET_NOTPOSSIBLE; } } } } else if(const Item* item = thing->getItem()){ //If its a new (summoned item) always accept it if(thing->getParent() == NULL){ return RET_NOERROR; } if(ground == NULL) return RET_NOTPOSSIBLE; if(!creatures.empty() && item->isBlocking()) return RET_NOTENOUGHROOM; for(uint32_t i = 0; i < getThingCount(); ++i){ iithing = __getThing(i); if(const Item* iitem = iithing->getItem()){ const ItemType& iiType = Item::items[iitem->getID()]; if(iiType.blockSolid){ if(item->isPickupable()){ //experimental //if((iiType.isVertical || iiType.isHorizontal) && item->isHangable()){ // ItemVector::const_iterator iit; // for(iit = downItems.begin(); iit != downItems.end(); ++iit){ // if((*iit)->isHangable()) // return RET_NOTENOUGHROOM; // } //} //else if(!iiType.hasHeight /*|| !iiType.moveable*/) return RET_NOTENOUGHROOM; else if(iiType.pickupable) return RET_NOTENOUGHROOM; } else return RET_NOTENOUGHROOM; } } } } return RET_NOERROR; }