void Tile::onRemoveTileItem(const SpectatorVec& list, const std::vector<int32_t>& oldStackPosVector, Item* item) { if (item->hasProperty(CONST_PROP_MOVEABLE) || item->getContainer()) { auto it = g_game.browseFields.find(this); if (it != g_game.browseFields.end()) { it->second->removeThing(item, item->getItemCount()); } } resetTileFlags(item); const Position& cylinderMapPos = getPosition(); const ItemType& iType = Item::items[item->getID()]; //send to client size_t i = 0; for (Creature* spectator : list) { if (Player* tmpPlayer = spectator->getPlayer()) { tmpPlayer->sendRemoveTileThing(cylinderMapPos, oldStackPosVector[i++]); } } //event methods for (Creature* spectator : list) { spectator->onRemoveTileItem(this, cylinderMapPos, iType, item); } }
void Tile::updateThing(Thing* thing, uint16_t itemId, uint32_t count) { int32_t index = getThingIndex(thing); if (index == -1) { return /*RETURNVALUE_NOTPOSSIBLE*/; } Item* item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } const ItemType& oldType = Item::items[item->getID()]; const ItemType& newType = Item::items[itemId]; resetTileFlags(item); item->setID(itemId); item->setSubType(count); setTileFlags(item); onUpdateTileItem(item, oldType, item, newType); }
void Tile::onRemoveTileItem(const SpectatorVec& list, const std::vector<int32_t>& oldStackPosVector, Item* item) { resetTileFlags(item); const Position& cylinderMapPos = getPosition(); const ItemType& iType = Item::items[item->getID()]; //send to client size_t i = 0; for (Creature* spectator : list) { if (Player* tmpPlayer = spectator->getPlayer()) { tmpPlayer->sendRemoveTileThing(cylinderMapPos, oldStackPosVector[i++]); } } //event methods for (Creature* spectator : list) { spectator->onRemoveTileItem(this, cylinderMapPos, iType, item); } }
void Tile::replaceThing(uint32_t index, Thing* thing) { int32_t pos = index; Item* item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } Item* oldItem = nullptr; bool isInserted = false; if (ground) { if (pos == 0) { oldItem = ground; ground = item; isInserted = true; } --pos; } TileItemVector* items = getItemList(); if (items && !isInserted) { int32_t topItemSize = getTopItemCount(); if (pos < topItemSize) { ItemVector::iterator it = items->getBeginTopItem(); it += pos; oldItem = (*it); it = items->erase(it); items->insert(it, item); isInserted = true; } pos -= topItemSize; } CreatureVector* creatures = getCreatures(); if (creatures) { if (!isInserted && pos < static_cast<int32_t>(creatures->size())) { return /*RETURNVALUE_NOTPOSSIBLE*/; } pos -= static_cast<uint32_t>(creatures->size()); } if (items && !isInserted) { int32_t downItemSize = getDownItemCount(); if (pos < downItemSize) { ItemVector::iterator it = items->getBeginDownItem() + pos; oldItem = *it; it = items->erase(it); items->insert(it, item); isInserted = true; } } if (isInserted) { item->setParent(this); resetTileFlags(oldItem); setTileFlags(item); const ItemType& oldType = Item::items[oldItem->getID()]; const ItemType& newType = Item::items[item->getID()]; onUpdateTileItem(oldItem, oldType, item, newType); oldItem->setParent(nullptr); return /*RETURNVALUE_NOERROR*/; } }
void Tile::addThing(int32_t, Thing* thing) { Creature* creature = thing->getCreature(); if (creature) { g_game.map.clearSpectatorCache(); creature->setParent(this); CreatureVector* creatures = makeCreatures(); creatures->insert(creatures->begin(), creature); } else { Item* item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } TileItemVector* items = getItemList(); if (items && items->size() >= 0xFFFF) { return /*RETURNVALUE_NOTPOSSIBLE*/; } item->setParent(this); const ItemType& itemType = Item::items[item->getID()]; if (itemType.isGroundTile()) { if (ground == nullptr) { ground = item; onAddTileItem(item); } else { const ItemType& oldType = Item::items[ground->getID()]; Item* oldGround = ground; ground->setParent(nullptr); g_game.ReleaseItem(ground); ground = item; resetTileFlags(oldGround); setTileFlags(item); onUpdateTileItem(oldGround, oldType, item, itemType); postRemoveNotification(oldGround, nullptr, 0); } } else if (itemType.alwaysOnTop) { if (itemType.isSplash() && items) { //remove old splash if exists for (ItemVector::const_iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { Item* oldSplash = *it; if (!Item::items[oldSplash->getID()].isSplash()) { continue; } removeThing(oldSplash, 1); oldSplash->setParent(nullptr); g_game.ReleaseItem(oldSplash); postRemoveNotification(oldSplash, nullptr, 0); break; } } bool isInserted = false; if (items) { for (ItemVector::iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { //Note: this is different from internalAddThing if (itemType.alwaysOnTopOrder <= Item::items[(*it)->getID()].alwaysOnTopOrder) { items->insert(it, item); isInserted = true; break; } } } else { items = makeItemList(); } if (!isInserted) { items->push_back(item); } onAddTileItem(item); } else { if (itemType.isMagicField()) { //remove old field item if exists if (items) { for (ItemVector::const_iterator it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { MagicField* oldField = (*it)->getMagicField(); if (oldField) { if (oldField->isReplaceable()) { removeThing(oldField, 1); oldField->setParent(nullptr); g_game.ReleaseItem(oldField); postRemoveNotification(oldField, nullptr, 0); break; } else { //This magic field cannot be replaced. item->setParent(nullptr); g_game.ReleaseItem(item); return; } } } } } items = makeItemList(); items->insert(items->getBeginDownItem(), item); items->addDownItemCount(1); onAddTileItem(item); } } }