void Container::__removeThing(Thing* thing, uint32_t count) { Item* item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } int32_t index = __getIndexOfThing(thing); if (index == -1) { return /*RETURNVALUE_NOTPOSSIBLE*/; } if (item->isStackable() && count != item->getItemCount()) { uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, item->getItemCount() - count)); const int32_t oldWeight = item->getWeight(); item->setItemCount(newCount); updateItemWeight(-oldWeight + item->getWeight()); //send change to client if (getParent()) { onUpdateContainerItem(index, item, item); } } else { updateItemWeight(-static_cast<int32_t>(item->getWeight())); //send change to client if (getParent()) { onRemoveContainerItem(index, item); } item->setParent(nullptr); itemlist.erase(itemlist.begin() + index); } }
void Tile::__updateThing(Thing* thing, uint16_t itemId, uint32_t count) { int32_t index = __getIndexOfThing(thing); if(index == -1) { #ifdef __DEBUG_MOVESYS__ std::clog << "[Failure - Tile::__updateThing] index == -1" << std::endl; #endif return/* RET_NOTPOSSIBLE*/; } Item* item = thing->getItem(); if(!item) { #ifdef __DEBUG_MOVESYS__ std::clog << "[Failure - Tile::__updateThing] item == NULL" << std::endl; #endif return/* RET_NOTPOSSIBLE*/; } //Need to update it here too since the old and new item is the same uint16_t oldId = item->getID(); updateTileFlags(item, true); item->setID(itemId); item->setSubType(count); updateTileFlags(item, false); onUpdateTileItem(item, Item::items[oldId], item, Item::items[itemId]); }
void Container::__updateThing(Thing* thing, uint16_t itemId, uint32_t count) { int32_t index = __getIndexOfThing(thing); if (index == -1) { return /*RET_NOTPOSSIBLE*/; } Item* item = thing->getItem(); if (item == NULL) { return /*RET_NOTPOSSIBLE*/; } const ItemType& oldType = Item::items[item->getID()]; const ItemType& newType = Item::items[itemId]; const double oldWeight = item->getWeight(); item->setID(itemId); item->setSubType(count); const double diffWeight = -oldWeight + item->getWeight(); totalWeight += diffWeight; if (Container* parentContainer = getParentContainer()) { parentContainer->updateItemWeight(diffWeight); } //send change to client if (getParent()) { onUpdateContainerItem(index, item, oldType, item, newType); } }
void Tile::__updateThing(Thing* thing, uint16_t itemId, uint32_t count) { int32_t index = __getIndexOfThing(thing); if (index == -1) { return /*RET_NOTPOSSIBLE*/; } Item* item = thing->getItem(); if (item == NULL) { return /*RET_NOTPOSSIBLE*/; } const ItemType& oldType = Item::items[item->getID()]; const ItemType& newType = Item::items[itemId]; updateTileFlags(item, true); item->setID(itemId); item->setSubType(count); updateTileFlags(item, false); onUpdateTileItem(item, oldType, item, newType); }
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) { 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; }
ReturnValue Tile::__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 || !count || (item->isStackable() && count > item->getItemCount()) || (!item->isMovable() && !hasBitSet(FLAG_IGNORENOTMOVABLE, flags))) return RET_NOTPOSSIBLE; return RET_NOERROR; }
void Tile::moveCreature(Creature* creature, Cylinder* toCylinder, bool teleport /* = false*/) { int32_t oldStackPos = __getIndexOfThing(creature); //remove the creature __removeThing(creature, 0); //add the creature toCylinder->__addThing(creature); Position fromPos = getPosition(); Position toPos = toCylinder->getPosition(); if(!teleport){ if(fromPos.y > toPos.y) creature->setDirection(NORTH); else if(fromPos.y < toPos.y) creature->setDirection(SOUTH); if(fromPos.x < toPos.x) creature->setDirection(EAST); else if(fromPos.x > toPos.x) creature->setDirection(WEST); } SpectatorVec list; SpectatorVec::iterator it; g_game.getSpectators(Range(fromPos, true), list); g_game.getSpectators(Range(toPos, true), list); //send to client Player* player = NULL; for(it = list.begin(); it != list.end(); ++it) { if(player = (*it)->getPlayer()){ player->sendCreatureMove(creature, fromPos, oldStackPos, teleport); } } g_game.isExecutingEvents = true; //event method for(it = list.begin(); it != list.end(); ++it) { (*it)->onCreatureMove(creature, fromPos, oldStackPos, teleport); } g_game.isExecutingEvents = false; toCylinder->postAddNotification(creature); postRemoveNotification(creature); }
void Container::__removeThing(Thing* thing, uint32_t count) { Item* item = thing->getItem(); if (item == NULL) { return /*RET_NOTPOSSIBLE*/; } int32_t index = __getIndexOfThing(thing); if (index == -1) { return /*RET_NOTPOSSIBLE*/; } if (item->isStackable() && count != item->getItemCount()) { uint8_t newCount = (uint8_t)std::max<int32_t>(0, item->getItemCount() - count); const double oldWeight = -item->getWeight(); item->setItemCount(newCount); const double diffWeight = oldWeight + item->getWeight(); totalWeight += diffWeight; //send change to client if (getParent()) { if (Container* parentContainer = getParentContainer()) { parentContainer->updateItemWeight(diffWeight); } const ItemType& it = Item::items[item->getID()]; onUpdateContainerItem(index, item, it, item, it); } } else { //send change to client if (getParent()) { if (Container* parentContainer = getParentContainer()) { parentContainer->updateItemWeight(-item->getWeight()); } onRemoveContainerItem(index, item); } totalWeight -= item->getWeight(); item->setParent(NULL); itemlist.erase(itemlist.begin() + index); } }
void Container::__updateThing(Thing* thing, uint16_t itemId, uint32_t count) { int32_t index = __getIndexOfThing(thing); if (index == -1) { return /*RETURNVALUE_NOTPOSSIBLE*/; } Item* item = thing->getItem(); if (item == nullptr) { return /*RETURNVALUE_NOTPOSSIBLE*/; } const int32_t oldWeight = item->getWeight(); item->setID(itemId); item->setSubType(count); updateItemWeight(-oldWeight + item->getWeight()); //send change to client if (getParent()) { onUpdateContainerItem(index, item, item); } }
void Tile::__updateThing(Thing* thing, uint32_t count) { int32_t index = __getIndexOfThing(thing); if(index == -1){ #ifdef __DEBUG__MOVESYS__ std::cout << "Failure: [Tile::__updateThing] index == -1" << std::endl; int *a = NULL; *a = 1; #endif return /*RET_NOTPOSSIBLE*/; } Item* item = thing->getItem(); if(item == NULL){ #ifdef __DEBUG__MOVESYS__ std::cout << "Failure: [Tile::__updateThing] item == NULL" << std::endl; int *a = NULL; *a = 1; #endif return /*RET_NOTPOSSIBLE*/; } item->setItemCountOrSubtype(count); onUpdateTileItem(index, item, item); }
ReturnValue Tile::__queryRemove(const Thing* thing, uint32_t count) const { uint32_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->isNotMoveable()){ return RET_NOTMOVEABLE; } return RET_NOERROR; }
void Container::__updateThing(Thing* thing, uint16_t itemId, uint32_t count) { int32_t index = __getIndexOfThing(thing); if(index == -1) { #ifdef __DEBUG_MOVESYS__ std::clog << "Failure: [Container::__updateThing] index == -1" << std::endl; #endif return /*RET_NOTPOSSIBLE*/; } Item* item = thing->getItem(); if(!item) { #ifdef __DEBUG_MOVESYS__ std::clog << "Failure: [Container::__updateThing] item == NULL" << std::endl; #endif return /*RET_NOTPOSSIBLE*/; } const ItemType& oldType = Item::items[item->getID()]; const ItemType& newType = Item::items[itemId]; const double oldWeight = item->getWeight(); item->setID(itemId); item->setSubType(count); const double diffWeight = -oldWeight + item->getWeight(); totalWeight += diffWeight; if(Container* parentContainer = getParentContainer()) parentContainer->updateItemWeight(diffWeight); //send change to client if(getParent()) onUpdateContainerItem(index, item, oldType, item, newType); }
void Tile::moveCreature(Creature* creature, Cylinder* toCylinder, bool teleport /* = false*/) { Tile* newTile = toCylinder->getTile(); int32_t oldStackPos = __getIndexOfThing(creature); Position oldPos = getPosition(); Position newPos = newTile->getPosition(); Player* tmpPlayer = NULL; SpectatorVec list; SpectatorVec::iterator it; g_game.getSpectators(list, oldPos, false, true); g_game.getSpectators(list, newPos, true, true); std::vector<uint32_t> oldStackPosVector; for (it = list.begin(); it != list.end(); ++it) { if ((tmpPlayer = (*it)->getPlayer())) { oldStackPosVector.push_back(getClientIndexOfThing(tmpPlayer, creature)); } } //remove the creature __removeThing(creature, 0); // Switch the node ownership if (qt_node != newTile->qt_node) { qt_node->removeCreature(creature); newTile->qt_node->addCreature(creature); } //add the creature newTile->__addThing(creature); int32_t newStackPos = newTile->__getIndexOfThing(creature); if (!teleport) { if (oldPos.y > newPos.y) { creature->setDirection(NORTH); } else if (oldPos.y < newPos.y) { creature->setDirection(SOUTH); } if (oldPos.x < newPos.x) { creature->setDirection(EAST); } else if (oldPos.x > newPos.x) { creature->setDirection(WEST); } } //send to client uint32_t i = 0; for (it = list.begin(); it != list.end(); ++it) { if ((tmpPlayer = (*it)->getPlayer())) { tmpPlayer->sendCreatureMove(creature, newTile, newPos, this, oldPos, oldStackPosVector[i], teleport); ++i; } } //event method for (it = list.begin(); it != list.end(); ++it) { (*it)->onCreatureMove(creature, newTile, newPos, this, oldPos, teleport); } postRemoveNotification(creature, toCylinder, oldStackPos, true); newTile->postAddNotification(creature, this, newStackPos); }
void Tile::__addThing(int32_t index, Thing* thing) { Creature* creature = thing->getCreature(); if(creature){ creature->setParent(this); creatures.insert(creatures.begin(), creature); } else{ Item* item = thing->getItem(); if(item == NULL){ #ifdef __DEBUG__MOVESYS__ std::cout << "Failure: [Tile::__addThing] item == NULL" << std::endl; int *a = NULL; *a = 1; #endif return /*RET_NOTPOSSIBLE*/; } item->setParent(this); if(item->isGroundTile()){ if(ground == NULL){ onAddTileItem(item); } else{ uint32_t index = __getIndexOfThing(ground); onUpdateTileItem(index, ground, item); ground->setParent(NULL); g_game.FreeThing(ground); ground = NULL; } ground = item; } else if(item->isAlwaysOnTop()){ if(item->isSplash()){ //remove old splash if exists ItemVector::iterator iit; for(iit = topItems.begin(); iit != topItems.end(); ++iit){ if((*iit)->isSplash()){ Item* oldSplash = *iit; __removeThing(oldSplash, 1); oldSplash->setParent(NULL); g_game.FreeThing(oldSplash); break; } } } bool isInserted = false; ItemVector::iterator iit; for(iit = topItems.begin(); iit != topItems.end(); ++iit){ //Note: this is different from internalAddThing if(Item::items[item->getID()].alwaysOnTopOrder <= Item::items[(*iit)->getID()].alwaysOnTopOrder){ topItems.insert(iit, item); isInserted = true; break; } } if(!isInserted){ topItems.push_back(item); } onAddTileItem(item); } else{ if(item->isMagicField()){ //remove old field item if exists ItemVector::iterator iit; for(iit = downItems.begin(); iit != downItems.end(); ++iit){ if((*iit)->isMagicField()){ Item* oldField = *iit; __removeThing(oldField, 1); oldField->setParent(NULL); g_game.FreeThing(oldField); break; } } } downItems.insert(downItems.begin(), item); onAddTileItem(item); } } }
void Tile::__addThing(int32_t index, Thing* thing) { Creature* creature = thing->getCreature(); if (creature) { g_game.clearSpectatorCache(); creature->setParent(this); CreatureVector* creatures = makeCreatures(); creatures->insert(creatures->begin(), creature); ++thingCount; } else { Item* item = thing->getItem(); if (!item) { #ifdef __DEBUG__MOVESYS__ std::cout << "Failure: [Tile::__addThing] item == NULL" << std::endl; DEBUG_REPORT #endif return /*RET_NOTPOSSIBLE*/; } TileItemVector* items = getItemList(); if (items && items->size() > 0xFFFF) { return /*RET_NOTPOSSIBLE*/; } item->setParent(this); if (item->isGroundTile()) { if (!ground) { ground = item; ++thingCount; onAddTileItem(item); } else { const ItemType& oldType = Item::items[ground->getID()]; const ItemType& newType = Item::items[item->getID()]; int32_t oldGroundIndex = __getIndexOfThing(ground); Item* oldGround = ground; ground->setParent(NULL); g_game.FreeThing(ground); ground = item; updateTileFlags(oldGround, true); updateTileFlags(item, false); onUpdateTileItem(oldGround, oldType, item, newType); postRemoveNotification(oldGround, NULL, oldGroundIndex, true); } } else if (item->isAlwaysOnTop()) { if (item->isSplash()) { //remove old splash if exists if (items) { for (ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it) { if ((*it)->isSplash()) { int32_t oldSplashIndex = __getIndexOfThing(*it); Item* oldSplash = *it; __removeThing(oldSplash, 1); oldSplash->setParent(NULL); g_game.FreeThing(oldSplash); postRemoveNotification(oldSplash, NULL, oldSplashIndex, true); break; } } } } bool isInserted = false; if (items) { for (ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it) { //Note: this is different from internalAddThing if (Item::items[item->getID()].alwaysOnTopOrder <= Item::items[(*it)->getID()].alwaysOnTopOrder) { items->insert(it, item); ++thingCount; isInserted = true; break; } } } else { items = makeItemList(); } if (!isInserted) { items->push_back(item); ++thingCount; } onAddTileItem(item); } else { if (item->isMagicField()) { //remove old field item if exists if (items) { MagicField* oldField = NULL; for (ItemVector::iterator it = items->getBeginDownItem(); it != items->getEndDownItem(); ++it) { if ((oldField = (*it)->getMagicField())) { if (oldField->isReplaceable()) { int32_t oldFieldIndex = __getIndexOfThing(*it); __removeThing(oldField, 1); oldField->setParent(NULL); g_game.FreeThing(oldField); postRemoveNotification(oldField, NULL, oldFieldIndex, true); break; } else { //This magic field cannot be replaced. item->setParent(NULL); g_game.FreeThing(item); return; } } } } } items = makeItemList(); items->insert(items->getBeginDownItem(), item); ++items->downItemCount; ++thingCount; onAddTileItem(item); } }
void Tile::__removeThing(Thing* thing, uint32_t count) { Creature* creature = thing->getCreature(); if(creature){ CreatureVector::iterator it = std::find(creatures.begin(), creatures.end(), thing); if(it == creatures.end()){ #ifdef __DEBUG__MOVESYS__ std::cout << "Failure: [Tile::__removeThing] creature not found" << std::endl; int *a = NULL; *a = 1; #endif return; //RET_NOTPOSSIBLE; } creatures.erase(it); return; } else{ Item* item = thing->getItem(); if(item == NULL){ #ifdef __DEBUG__MOVESYS__ std::cout << "Failure: [Tile::__removeThing] item == NULL" << std::endl; int *a = NULL; *a = 1; #endif return /*RET_NOTPOSSIBLE*/; } uint32_t index = __getIndexOfThing(item); if(index == -1){ #ifdef __DEBUG__MOVESYS__ std::cout << "Failure: [Tile::__removeThing] index == -1" << std::endl; int *a = NULL; *a = 1; #endif return /*RET_NOTPOSSIBLE*/; } if(item == ground){ onRemoveTileItem(index, item); ground->setParent(NULL); ground = NULL; return /*RET_NOERROR*/; } ItemVector::iterator iit; if(item->isAlwaysOnTop()){ for(iit = topItems.begin(); iit != topItems.end(); ++iit){ if(*iit == item){ onRemoveTileItem(index, item); (*iit)->setParent(NULL); topItems.erase(iit); return /*RET_NOERROR*/; } } } else{ for (iit = downItems.begin(); iit != downItems.end(); ++iit){ if(*iit == item){ if(item->isStackable() && count != item->getItemCount()){ int newCount = std::max(0, (int)(item->getItemCount() - count)); item->setItemCount(newCount); onUpdateTileItem(index, item, item); } else { onRemoveTileItem(index, item); (*iit)->setParent(NULL); downItems.erase(iit); } return /*RET_NOERROR*/; } } } } #ifdef __DEBUG__MOVESYS__ std::cout << "Failure: [Tile::__removeThing] thing not found" << std::endl; int *a = NULL; *a = 1; #endif }
void Tile::moveCreature(Creature* actor, Creature* creature, Cylinder* toCylinder, bool forceTeleport/* = false*/) { Tile* newTile = toCylinder->getTile(); SpectatorVec list; SpectatorVec::iterator it; g_game.getSpectators(list, pos, false, true); Position newPos = newTile->getPosition(); g_game.getSpectators(list, newPos, true, true); bool teleport = false; if(forceTeleport || !newTile->ground || !Position::areInRange<1,1,0>(pos, newPos)) teleport = true; std::vector<uint32_t> oldStackposVector; Player* tmpPlayer = NULL; for(it = list.begin(); it != list.end(); ++it) { if((tmpPlayer = (*it)->getPlayer())) oldStackposVector.push_back(getClientIndexOfThing(tmpPlayer, creature)); } int32_t oldStackpos = __getIndexOfThing(creature); //remove the creature __removeThing(creature, 0); //switch the node ownership if(qt_node != newTile->qt_node) { qt_node->removeCreature(creature); newTile->qt_node->addCreature(creature); } //add the creature newTile->__addThing(actor, creature); int32_t newStackpos = newTile->__getIndexOfThing(creature); if(!teleport) { if(pos.y > newPos.y) creature->setDirection(NORTH); else if(pos.y < newPos.y) creature->setDirection(SOUTH); if(pos.x < newPos.x) creature->setDirection(EAST); else if(pos.x > newPos.x) creature->setDirection(WEST); } //send to client int32_t i = 0; for(it = list.begin(); it != list.end(); ++it) { if((tmpPlayer = (*it)->getPlayer()) && tmpPlayer->canSeeCreature(creature)) tmpPlayer->sendCreatureMove(creature, newTile, newPos, this, pos, oldStackposVector[i++], teleport); } //event method for(it = list.begin(); it != list.end(); ++it) (*it)->onCreatureMove(creature, newTile, newPos, this, pos, teleport); postRemoveNotification(actor, creature, toCylinder, oldStackpos, true); newTile->postAddNotification(actor, creature, this, newStackpos); }
void Tile::moveCreature(Creature* creature, Cylinder* toCylinder, bool forceTeleport/* = false*/) { Tile* newTile = toCylinder->getTile(); int32_t oldStackPos = __getIndexOfThing(creature); Position oldPos = getPosition(); Position newPos = newTile->getPosition(); bool teleport = forceTeleport || !newTile->ground || !Position::areInRange<1, 1, 0>(oldPos, newPos); SpectatorVec list; g_game.getSpectators(list, oldPos, true); g_game.getSpectators(list, newPos, true); std::vector<int32_t> oldStackPosVector; for (Creature* spectator : list) { if (Player* tmpPlayer = spectator->getPlayer()) { if (tmpPlayer->canSeeCreature(creature)) { oldStackPosVector.push_back(getClientIndexOfCreature(tmpPlayer, creature)); } else { oldStackPosVector.push_back(-1); } } } //remove the creature __removeThing(creature, 0); // Switch the node ownership if (qt_node != newTile->qt_node) { qt_node->removeCreature(creature); newTile->qt_node->addCreature(creature); } //add the creature newTile->__addThing(creature); int32_t newStackPos = newTile->__getIndexOfThing(creature); if (!teleport) { if (oldPos.y > newPos.y) { creature->setDirection(NORTH); } else if (oldPos.y < newPos.y) { creature->setDirection(SOUTH); } if (oldPos.x < newPos.x) { creature->setDirection(EAST); } else if (oldPos.x > newPos.x) { creature->setDirection(WEST); } } //send to client size_t i = 0; for (Creature* spectator : list) { if (Player* tmpPlayer = spectator->getPlayer()) { //Use the correct stackpos int32_t stackpos = oldStackPosVector[i++]; if (stackpos != -1) { tmpPlayer->sendCreatureMove(creature, newPos, newTile->getStackposOfCreature(tmpPlayer, creature), oldPos, stackpos, teleport); } } } //event method for (Creature* spectator : list) { spectator->onCreatureMove(creature, newTile, newPos, this, oldPos, teleport); } postRemoveNotification(creature, toCylinder, oldStackPos, true); newTile->postAddNotification(creature, this, newStackPos); }
void Tile::__removeThing(Thing* thing, uint32_t count) { Creature* creature = thing->getCreature(); if (creature) { CreatureVector* creatures = getCreatures(); if (creatures) { CreatureVector::iterator it = std::find(creatures->begin(), creatures->end(), thing); if (it != creatures->end()) { g_game.clearSpectatorCache(); creatures->erase(it); } } return; } Item* item = thing->getItem(); if (!item) { return; } int32_t index = __getIndexOfThing(item); if (index == -1) { return; } if (item == ground) { ground->setParent(nullptr); ground = nullptr; const SpectatorVec& list = g_game.getSpectators(getPosition()); onRemoveTileItem(list, std::vector<int32_t>(list.size(), 0), item); return; } TileItemVector* items = getItemList(); if (!items) { return; } if (item->isAlwaysOnTop()) { auto it = std::find(items->getBeginTopItem(), items->getEndTopItem(), item); if (it == items->getEndTopItem()) { return; } std::vector<int32_t> oldStackPosVector; const SpectatorVec& list = g_game.getSpectators(getPosition()); for (Creature* spectator : list) { if (Player* tmpPlayer = spectator->getPlayer()) { oldStackPosVector.push_back(getStackposOfThing(tmpPlayer, item)); } } item->setParent(nullptr); items->erase(it); onRemoveTileItem(list, oldStackPosVector, item); } else { auto it = std::find(items->getBeginDownItem(), items->getEndDownItem(), item); if (it == items->getEndDownItem()) { return; } if (item->isStackable() && count != item->getItemCount()) { uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, static_cast<int32_t>(item->getItemCount() - count))); updateTileFlags(item, true); item->setItemCount(newCount); updateTileFlags(item, false); const ItemType& itemType = Item::items[item->getID()]; onUpdateTileItem(item, itemType, item, itemType); } else { std::vector<int32_t> oldStackPosVector; const SpectatorVec& list = g_game.getSpectators(getPosition()); for (Creature* spectator : list) { if (Player* tmpPlayer = spectator->getPlayer()) { oldStackPosVector.push_back(getStackposOfThing(tmpPlayer, item)); } } item->setParent(nullptr); items->erase(it); --items->downItemCount; onRemoveTileItem(list, oldStackPosVector, item); } } }
void Tile::__addThing(Creature* actor, int32_t, Thing* thing) { if(Creature* creature = thing->getCreature()) { g_game.clearSpectatorCache(); creature->setParent(this); CreatureVector* creatures = makeCreatures(); creatures->insert(creatures->begin(), creature); ++thingCount; return; } Item* item = thing->getItem(); if(!item) { #ifdef __DEBUG_MOVESYS__ std::clog << "[Failure - Tile::__addThing] item == NULL" << std::endl; #endif return/* RET_NOTPOSSIBLE*/; } TileItemVector* items = getItemList(); if(items && items->size() >= 0xFFFF) return/* RET_NOTPOSSIBLE*/; if(g_config.getBool(ConfigManager::STORE_TRASH) && !hasFlag(TILESTATE_TRASHED)) { g_game.addTrash(pos); setFlag(TILESTATE_TRASHED); } item->setParent(this); if(item->isGroundTile()) { if(ground) { int32_t oldGroundIndex = __getIndexOfThing(ground); Item* oldGround = ground; updateTileFlags(oldGround, true); updateTileFlags(item, false); ground = item; #ifdef __GROUND_CACHE__ std::map<Item*, int32_t>::iterator it = g_game.grounds.find(oldGround); bool erase = it == g_game.grounds.end(); if(!erase) { it->second--; erase = it->second < 1; if(erase) g_game.grounds.erase(it); } if(erase) { #endif oldGround->setParent(NULL); g_game.freeThing(oldGround); #ifdef __GROUND_CACHE__ } #endif postRemoveNotification(actor, oldGround, NULL, oldGroundIndex, true); onUpdateTile(); } else { ground = item; ++thingCount; onAddTileItem(item); } } else if(item->isAlwaysOnTop()) { if(item->isSplash()) { //remove old splash if exists if(items) { for(ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it) { if(!(*it)->isSplash()) continue; int32_t oldSplashIndex = __getIndexOfThing(*it); Item* oldSplash = *it; __removeThing(oldSplash, 1); oldSplash->setParent(NULL); g_game.freeThing(oldSplash); postRemoveNotification(actor, oldSplash, NULL, oldSplashIndex, true); break; } } } bool isInserted = false; if(items) { for(ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it) { //Note: this is different from internalAddThing if(Item::items[item->getID()].alwaysOnTopOrder > Item::items[(*it)->getID()].alwaysOnTopOrder) continue; items->insert(it, item); ++thingCount; isInserted = true; break; } } else items = makeItemList(); if(!isInserted) { items->push_back(item); ++thingCount; } onAddTileItem(item); } else { if(item->isMagicField()) { //remove old field item if exists if(items) { MagicField* oldField = NULL; for(ItemVector::iterator it = items->getBeginDownItem(); it != items->getEndDownItem(); ++it) { if(!(oldField = (*it)->getMagicField())) continue; if(oldField->isReplacable()) { int32_t oldFieldIndex = __getIndexOfThing(*it); __removeThing(oldField, 1); oldField->setParent(NULL); g_game.freeThing(oldField); postRemoveNotification(actor, oldField, NULL, oldFieldIndex, true); break; } //This magic field cannot be replaced. item->setParent(NULL); g_game.freeThing(item); return; } } } if(item->getID() == ITEM_WATERBALL_SPLASH && !hasFlag(TILESTATE_TRASHHOLDER)) item->setID(ITEM_WATERBALL); items = makeItemList(); items->insert(items->getBeginDownItem(), item); ++items->downItemCount; ++thingCount; onAddTileItem(item); } }
void Tile::__removeThing(Thing* thing, uint32_t count) { Creature* creature = thing->getCreature(); if (creature) { CreatureVector* creatures = getCreatures(); if (creatures) { CreatureVector::iterator it = std::find(creatures->begin(), creatures->end(), thing); if (it != creatures->end()) { g_game.clearSpectatorCache(); creatures->erase(it); } } return; } Item* item = thing->getItem(); if (item) { int32_t index = __getIndexOfThing(item); if (index == -1) { return; } if (item == ground) { const SpectatorVec& list = g_game.getSpectators(getPosition()); std::vector<uint32_t> oldStackPosVector; for (SpectatorVec::const_iterator it = list.begin(), end = list.end(); it != end; ++it) { if (Player* tmpPlayer = (*it)->getPlayer()) { oldStackPosVector.push_back(getClientIndexOfThing(tmpPlayer, ground)); } } ground->setParent(NULL); ground = NULL; onRemoveTileItem(list, oldStackPosVector, item); return; } if (item->isAlwaysOnTop()) { TileItemVector* items = getItemList(); if (items) { for (ItemVector::iterator it = items->getBeginTopItem(); it != items->getEndTopItem(); ++it) { if (*it == item) { const SpectatorVec& list = g_game.getSpectators(getPosition()); std::vector<uint32_t> oldStackPosVector; for (SpectatorVec::const_iterator iit = list.begin(), iend = list.end(); iit != iend; ++iit) { if (Player* tmpPlayer = (*iit)->getPlayer()) { oldStackPosVector.push_back(getClientIndexOfThing(tmpPlayer, *it)); } } (*it)->setParent(NULL); items->erase(it); onRemoveTileItem(list, oldStackPosVector, item); return; } } } } else { TileItemVector* items = getItemList(); if (items) { for (ItemVector::iterator it = items->getBeginDownItem(); it != items->getEndDownItem(); ++it) { if (*it == item) { if (item->isStackable() && count != item->getItemCount()) { uint8_t newCount = (uint8_t)std::max<int32_t>(0, (int32_t)(item->getItemCount() - count)); updateTileFlags(item, true); item->setItemCount(newCount); updateTileFlags(item, false); const ItemType& it = Item::items[item->getID()]; onUpdateTileItem(item, it, item, it); } else { const SpectatorVec& list = g_game.getSpectators(getPosition()); std::vector<uint32_t> oldStackPosVector; for (SpectatorVec::const_iterator iit = list.begin(), iend = list.end(); iit != iend; ++iit) { if (Player* tmpPlayer = (*iit)->getPlayer()) { oldStackPosVector.push_back(getClientIndexOfThing(tmpPlayer, *it)); } } (*it)->setParent(NULL); items->erase(it); --items->downItemCount; onRemoveTileItem(list, oldStackPosVector, item); } return; } } } } } }
void Tile::__removeThing(Thing* thing, uint32_t count) { Creature* creature = thing->getCreature(); if(creature) { if(CreatureVector* creatures = getCreatures()) { CreatureVector::iterator it = std::find(creatures->begin(), creatures->end(), thing); if(it == creatures->end()) { #ifdef __DEBUG_MOVESYS__ std::clog << "[Failure - Tile::__removeThing] creature not found" << std::endl; #endif return/* RET_NOTPOSSIBLE*/; } g_game.clearSpectatorCache(); creatures->erase(it); --thingCount; } #ifdef __DEBUG_MOVESYS__ else std::clog << "[Failure - Tile::__removeThing] creature not found" << std::endl; #endif return; } Item* item = thing->getItem(); if(!item) { #ifdef __DEBUG_MOVESYS__ std::clog << "[Failure - Tile::__removeThing] item == NULL" << std::endl; #endif return/* RET_NOTPOSSIBLE*/; } int32_t index = __getIndexOfThing(item); if(index == -1) { #ifdef __DEBUG_MOVESYS__ std::clog << "[Failure - Tile::__removeThing] index == -1" << std::endl; #endif return/* RET_NOTPOSSIBLE*/; } if(item == ground) { const SpectatorVec& list = g_game.getSpectators(pos); std::vector<int32_t> oldStackposVector; Player* tmpPlayer = NULL; for(SpectatorVec::const_iterator it = list.begin(); it != list.end(); ++it) { if((tmpPlayer = (*it)->getPlayer())) oldStackposVector.push_back(getClientIndexOfThing(tmpPlayer, ground)); } #ifdef __GROUND_CACHE__ std::map<Item*, int32_t>::iterator it = g_game.grounds.find(ground); bool erase = it == g_game.grounds.end(); if(!erase) { it->second--; erase = it->second < 1; if(erase) g_game.grounds.erase(it); } if(erase) { #endif ground->setParent(NULL); g_game.freeThing(ground); #ifdef __GROUND_CACHE__ } #endif ground = NULL; --thingCount; onRemoveTileItem(list, oldStackposVector, item); return/* RET_NOERROR*/; } TileItemVector* items = getItemList(); if(!items) return; if(item->isAlwaysOnTop()) { ItemVector::iterator it = std::find(items->getBeginTopItem(), items->getEndTopItem(), item); if(it != items->end()) { const SpectatorVec& list = g_game.getSpectators(pos); std::vector<int32_t> oldStackposVector; Player* tmpPlayer = NULL; for(SpectatorVec::const_iterator iit = list.begin(); iit != list.end(); ++iit) { if((tmpPlayer = (*iit)->getPlayer())) oldStackposVector.push_back(getClientIndexOfThing(tmpPlayer, item)); } item->setParent(NULL); items->erase(it); --thingCount; onRemoveTileItem(list, oldStackposVector, item); return/* RET_NOERROR*/; } } else { ItemVector::iterator it = std::find(items->getBeginDownItem(), items->getEndDownItem(), item); if(it != items->end()) { if(item->isStackable() && count != item->getItemCount()) { uint8_t newCount = (uint8_t)std::max((int32_t)0, (int32_t)(item->getItemCount() - count)); updateTileFlags(item, true); item->setItemCount(newCount); updateTileFlags(item, false); const ItemType& it = Item::items[item->getID()]; onUpdateTileItem(item, it, item, it); } else { const SpectatorVec& list = g_game.getSpectators(pos); std::vector<int32_t> oldStackposVector; Player* tmpPlayer = NULL; for(SpectatorVec::const_iterator iit = list.begin(); iit != list.end(); ++iit) { if((tmpPlayer = (*iit)->getPlayer())) oldStackposVector.push_back(getClientIndexOfThing(tmpPlayer, item)); } item->setParent(NULL); items->erase(it); --items->downItemCount; --thingCount; onRemoveTileItem(list, oldStackposVector, item); } return/* RET_NOERROR*/; } } #ifdef __DEBUG_MOVESYS__ std::clog << "[Failure - Tile::__removeThing] thing not found" << std::endl; #endif }
void Container::__removeThing(Thing* thing, uint32_t count) { Item* item = thing->getItem(); if(!item) { #ifdef __DEBUG_MOVESYS__ std::clog << "Failure: [Container::__removeThing] item == NULL" << std::endl; #endif return /*RET_NOTPOSSIBLE*/; } int32_t index = __getIndexOfThing(thing); if(index == -1) { #ifdef __DEBUG_MOVESYS__ std::clog << "Failure: [Container::__removeThing] index == -1" << std::endl; #endif return /*RET_NOTPOSSIBLE*/; } ItemList::iterator cit = std::find(itemlist.begin(), itemlist.end(), thing); if(cit == itemlist.end()) { #ifdef __DEBUG_MOVESYS__ std::clog << "Failure: [Container::__removeThing] item not found" << std::endl; #endif return /*RET_NOTPOSSIBLE*/; } if(item->isStackable() && count != item->getItemCount()) { const double oldWeight = -item->getWeight(); item->setItemCount(std::max(0, (int32_t)(item->getItemCount() - count))); const double diffWeight = oldWeight + item->getWeight(); totalWeight += diffWeight; //send change to client if(getParent()) { if(Container* parentContainer = getParentContainer()) parentContainer->updateItemWeight(diffWeight); const ItemType& it = Item::items[item->getID()]; onUpdateContainerItem(index, item, it, item, it); } } else { //send change to client if(getParent()) { if(Container* parentContainer = getParentContainer()) parentContainer->updateItemWeight(-item->getWeight()); onRemoveContainerItem(index, item); } totalWeight -= item->getWeight(); item->setParent(NULL); itemlist.erase(cit); } }
void Tile::moveCreature(Creature* creature, Cylinder* toCylinder, bool forceTeleport/* = false*/) { Tile* newTile = toCylinder->getTile(); int32_t oldStackPos = __getIndexOfThing(creature); Position oldPos = getPosition(); Position newPos = newTile->getPosition(); bool teleport = false; if (forceTeleport || !newTile->ground || !Position::areInRange<1, 1, 0>(oldPos, newPos)) { teleport = true; } SpectatorVec list; g_game.getSpectators(list, oldPos, true); g_game.getSpectators(list, newPos, true); SpectatorVec::const_iterator end = list.end(); std::vector<uint32_t> oldStackPosVector; for (SpectatorVec::const_iterator it = list.begin(); it != end; ++it) { if (Player* tmpPlayer = (*it)->getPlayer()) { oldStackPosVector.push_back(getClientIndexOfThing(tmpPlayer, creature)); } } //remove the creature __removeThing(creature, 0); // Switch the node ownership if (qt_node != newTile->qt_node) { qt_node->removeCreature(creature); newTile->qt_node->addCreature(creature); } //add the creature newTile->__addThing(creature); int32_t newStackPos = newTile->__getIndexOfThing(creature); if (!teleport) { if (oldPos.y > newPos.y) { creature->setDirection(NORTH); } else if (oldPos.y < newPos.y) { creature->setDirection(SOUTH); } if (oldPos.x < newPos.x) { creature->setDirection(EAST); } else if (oldPos.x > newPos.x) { creature->setDirection(WEST); } } //send to client uint32_t i = 0; for (SpectatorVec::const_iterator it = list.begin(); it != end; ++it) { if (Player* tmpPlayer = (*it)->getPlayer()) { //Use the correct stackpos if (!creature->isInGhostMode() || tmpPlayer->isAccessPlayer()) { tmpPlayer->sendCreatureMove(creature, newTile, newPos, this, oldPos, oldStackPosVector[i], teleport); } ++i; } } //event method for (SpectatorVec::const_iterator it = list.begin(); it != end; ++it) { (*it)->onCreatureMove(creature, newTile, newPos, this, oldPos, teleport); } postRemoveNotification(creature, toCylinder, oldStackPos, true); newTile->postAddNotification(creature, this, newStackPos); }