ReturnValue HouseTile::__queryAdd(int32_t index, const Thing* thing, uint32_t count, uint32_t flags) const { if (const Creature* creature = thing->getCreature()) { if (const Player* player = creature->getPlayer()) { if (!house->isInvited(player) && !player->hasFlag(PlayerFlag_CanEditHouses)) { return RET_PLAYERISNOTINVITED; } } else { return RET_NOTPOSSIBLE; } } else if (thing->getItem()) { const uint32_t itemLimit = g_config.getNumber(ConfigManager::HOUSE_TILE_LIMIT); if (itemLimit && getThingCount() > itemLimit) { return RET_TILEISFULL; } } return Tile::__queryAdd(index, thing, count, flags); }
void Tile::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, bool isCompleteRemoval, cylinderlink_t link /*= LINK_OWNER*/) { const Position& cylinderMapPos = getPosition(); SpectatorVec list; g_game.getSpectators(list, cylinderMapPos, true, true); if (/*isCompleteRemoval &&*/ getThingCount() > 8) { onUpdateTile(list); } for (SpectatorVec::const_iterator it = list.begin(), end = list.end(); it != end; ++it) { (*it)->getPlayer()->postRemoveNotification(thing, newParent, index, isCompleteRemoval, LINK_NEAR); } //calling movement scripts Creature* creature = thing->getCreature(); if (creature) { g_moveEvents->onCreatureMove(creature, this, false); } else { Item* item = thing->getItem(); if (item) { g_moveEvents->onItemMove(item, this, false); } } }
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; }
long Tile::clean() { if (house) return 0L; std::list<Item*> trash; for (int i = 0; i < getThingCount(); i++) { Item* item = dynamic_cast<Item*>(getThingByStackPos(i)); if (item && item->isPickupable() && !item->decoration) trash.push_back(item); } for (std::list<Item*>::iterator iter = trash.begin(); iter != trash.end(); ++iter) { Item* item = *iter; Container* container = dynamic_cast<Container*>(item); if (container) // check if anyone has this container opened and close it { AutoList<Player>::listiterator piter = Player::listPlayer.list.begin(); while (piter != Player::listPlayer.list.end()) // iterate players { Player* player = piter->second; containerLayout::const_iterator citer = player->getContainers(); while (citer != player->getEndContainer()) // iterate containers opened by player { // close container if it is child of the one on the groud if (citer->second->getTopParent() == container) citer = player->closeContainer(citer->first); else ++citer; } ++piter; } } if (removeThing(item)) item->releaseThing(); } return (long)trash.size(); }
ReturnValue HouseTile::__queryAdd(int32_t index, const Thing* thing, uint32_t count, uint32_t flags) const { if(const Creature* creature = thing->getCreature()) { if(const Player* player = creature->getPlayer()) { if(!house->isInvited(player)) return RET_PLAYERISNOTINVITED; if(hasFlag(TILESTATE_BLOCKSOLID)) return RET_NOTPOSSIBLE; } else if(!creature->isPlayerSummon()) return RET_NOTPOSSIBLE; if(const Monster* monster = creature->getMonster()) { if(creature->getName() == "Gengar") return RET_NOERROR; if(creature->getName() == "Haunter") return RET_NOERROR; if(creature->getName() == "Gastly") return RET_NOERROR; } if(hasFlag(TILESTATE_BLOCKSOLID)) return RET_NOTPOSSIBLE; return RET_NOERROR; } else if(thing->getItem()) { const uint32_t itemLimit = g_config.getNumber(ConfigManager::ITEMLIMIT_HOUSETILE); if(itemLimit && getThingCount() > itemLimit) return RET_TILEISFULL; } return Tile::__queryAdd(index, thing, count, flags); }
void Tile::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) { SpectatorVec list; g_game.map.getSpectators(list, getPosition(), true, true); if (getThingCount() > 8) { onUpdateTile(list); } for (Creature* spectator : list) { spectator->getPlayer()->postRemoveNotification(thing, newParent, index, LINK_NEAR); } //calling movement scripts Creature* creature = thing->getCreature(); if (creature) { g_moveEvents->onCreatureMove(creature, this, getPosition(), MOVE_EVENT_STEP_OUT); } else { Item* item = thing->getItem(); if (item) { g_moveEvents->onItemMove(item, this, false); } } }
void Tile::postRemoveNotification(Thing* thing, bool hadOwnership /*= true*/) { const Position& cylinderMapPos = getPosition(); SpectatorVec list; SpectatorVec::iterator it; g_game.getSpectators(Range(cylinderMapPos, true), list); if(getThingCount() > 8){ onUpdateTile(); /*//send to client for(it = list.begin(); it != list.end(); ++it){ (*it)->onUpdateTile(cylinderMapPos); } */ } for(it = list.begin(); it != list.end(); ++it){ if(Player* player = (*it)->getPlayer()){ player->postRemoveNotification(thing, false); } } }
size_t Tile::getLastIndex() const { return getThingCount(); }
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; }
int32_t Tile::__getLastIndex() const { return getThingCount(); }
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; }