BedItem* Tile::getBedItem() const { if(!hasFlag(TILESTATE_BED)) return NULL; if(ground && ground->getBed()) return ground->getBed(); if(const TileItemVector* items = getItemList()) { for(ItemVector::const_reverse_iterator it = items->rbegin(); it != items->rend(); ++it) { if((*it)->getBed()) return (*it)->getBed(); } } return NULL; }
Item* Tile::getUseItem() const { const TileItemVector* items = getItemList(); if (!items || items->size() == 0) { return ground; } for (Item* item : boost::adaptors::reverse(*items)) { if (Item::items[item->getID()].forceUse) { return item; } } Item* item = items->getTopDownItem(); if (!item) { item = items->getTopTopItem(); } return item; }
MagicField* Tile::getFieldItem() const { if (!hasFlag(TILESTATE_MAGICFIELD)) { return nullptr; } if (ground && ground->getMagicField()) { return ground->getMagicField(); } if (const TileItemVector* items = getItemList()) { for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) { if ((*it)->getMagicField()) { return (*it)->getMagicField(); } } } return nullptr; }
TrashHolder* Tile::getTrashHolder() const { if (!hasFlag(TILESTATE_TRASHHOLDER)) { return nullptr; } if (ground && ground->getTrashHolder()) { return ground->getTrashHolder(); } if (const TileItemVector* items = getItemList()) { for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) { if ((*it)->getTrashHolder()) { return (*it)->getTrashHolder(); } } } return nullptr; }
Item* Tile::getItemByTopOrder(uint32_t topOrder) { //topOrder: //1: borders //2: ladders, signs, splashes //3: doors etc //4: creatures if(TileItemVector* items = getItemList()){ ItemVector::reverse_iterator itEnd = ItemVector::reverse_iterator(items->getBeginTopItem()); for(ItemVector::reverse_iterator it = ItemVector::reverse_iterator(items->getEndTopItem()); it != itEnd; ++it){ if(Item::items[(*it)->getID()].alwaysOnTopOrder == (int32_t)topOrder){ return (*it); } } } return NULL; }
Mailbox* Tile::getMailbox() const { if (!hasFlag(TILESTATE_MAILBOX)) { return NULL; } if (ground && ground->getMailbox()) { return ground->getMailbox(); } if (const TileItemVector* items = getItemList()) { for (ItemVector::const_reverse_iterator it = items->rbegin(); it != items->rend(); ++it) { if ((*it)->getMailbox()) { return (*it)->getMailbox(); } } } return NULL; }
bool Tile::hasProperty(enum ITEMPROPERTY prop, bool checkSolidForItems /* =false */) const { if (ground && ground->hasProperty(prop)) { return true; } if (const TileItemVector* items = getItemList()) { for (ItemVector::const_iterator it = items->begin(); it != items->end(); ++it) { if ((*it)->hasProperty(prop) || (prop == BLOCKSOLID && checkSolidForItems && (*it)->isSolidForItems())) { return true; } } } return false; }
bool Tile::hasProperty(Item* exclude, enum ITEMPROPERTY prop) const { assert(exclude); if (ground && exclude != ground && ground->hasProperty(prop)) { return true; } if (const TileItemVector* items = getItemList()) { for (ItemVector::const_iterator it = items->begin(); it != items->end(); ++it) { Item* item = *it; if (item != exclude && item->hasProperty(prop)) { return true; } } } return false; }
Teleport* Tile::getTeleportItem() const { if (!hasFlag(TILESTATE_TELEPORT)) { return NULL; } if (const TileItemVector* items = getItemList()) { for (ItemVector::const_reverse_iterator it = items->rbegin(); it != items->rend(); ++it) { if ((*it)->getTeleport()) { return (*it)->getTeleport(); } } } return NULL; }
uint32_t Tile::__getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/) const { uint32_t count = 0; if (ground && ground->getID() == itemId) { count += Item::countByType(ground, subType); } const TileItemVector* items = getItemList(); if (items) { for (ItemVector::const_iterator it = items->begin(), end = items->end(); it != end; ++it) { Item* item = (*it); if (item->getID() == itemId) { count += Item::countByType(item, subType); } } } return count; }
// define an incompatibility between parameters (if one is set, any of the others can be set) bool ParameterManager::defineIncompatibility(const char *strParameters, bool bOneRequired) { Incompatibility incompatibility; // get the list of incompatible parameters incompatibility.vParameters = getItemList(strParameters); if ((incompatibility.vParameters == NULL) || (incompatibility.vParameters->size() < 2)) { return false; } // make sure all the parameters exist for(VString::iterator it = incompatibility.vParameters->begin() ; it != incompatibility.vParameters->end() ; ++it) { if (m_mParameter.find(*it) == m_mParameter.end()) { return false; } } incompatibility.bOneRequired = bOneRequired; m_vIncompatibility.push_back(incompatibility); return true; }
Thing* Tile::__getThing(uint32_t index) const { if (ground) { if (index == 0) { return ground; } --index; } const TileItemVector* items = getItemList(); if (items) { uint32_t topItemSize = items->getTopItemCount(); if (index < topItemSize) { return items->at(items->downItemCount + index); } index -= topItemSize; } if (const CreatureVector* creatures = getCreatures()) { if (index < (uint32_t)creatures->size()) { return creatures->at(index); } index -= (uint32_t)creatures->size(); } if (items) { if (index < items->getDownItemCount()) { return items->at(index); } } return NULL; }
int32_t Tile::getNewCreatureStackpos(const Player* player) { int32_t n = -1; if (ground) { ++n; } const TileItemVector* items = getItemList(); if (items) { n += items->getTopItemCount(); } if (const CreatureVector* creatures = getCreatures()) { for (CreatureVector::const_reverse_iterator cit = creatures->rbegin(); cit != creatures->rend(); ++cit) { if (!(*cit)->isInGhostMode() || player->isAccessPlayer()) { ++n; } } } return n + 1; }
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 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); } }
BTSpecialOperation *BTEditor::editSpecialOperation(BTDisplay &d, BTSpecialOperation *special) { BTDisplay::selectItem cmds[BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS]; for (int i = 0; i < BT_CONDITIONALCOMMANDS; ++i) { cmds[i].name = std::string("if ") + conditionalCommands[i]; cmds[i].value = i; } for (int i = 0; i < BT_SPECIALCOMMANDS; ++i) { cmds[i + BT_CONDITIONALCOMMANDS].name = specialCommands[i]; cmds[i + BT_CONDITIONALCOMMANDS].value = i + BT_CONDITIONALCOMMANDS; } std::sort(cmds, cmds + BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS); int start(0); int current(0); { BTSpecialConditional *specialCond = dynamic_cast<BTSpecialConditional*>(special); if (NULL != specialCond) { for (int i = 0; i < BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS; i++) { if (cmds[i].value == specialCond->getType()) { current = i; break; } } } BTSpecialCommand *specialCom = dynamic_cast<BTSpecialCommand*>(special); if (NULL != specialCom) { for (int i = 0; i < BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS; i++) { if (cmds[i].value == specialCom->getType() + BT_CONDITIONALCOMMANDS) { current = i; break; } } } } int original = current; d.addSelection(cmds, BT_SPECIALCOMMANDS + BT_CONDITIONALCOMMANDS, start, current); int key = d.process(); d.clearText(); if (key == 27) return NULL; std::string text; int number[3] = {0, 0, 0}; int count = 0; const char *cmd = NULL; if (cmds[current].value < BT_CONDITIONALCOMMANDS) { cmd = conditionalCommands[cmds[current].value]; if (original == current) { BTSpecialConditional *specialCond = dynamic_cast<BTSpecialConditional*>(special); if (NULL != specialCond) { for (int i = 0; i < specialCond->getArgumentCount(); i++) { number[i] = specialCond->getNumber(i); } text = specialCond->getText(); } } } else { cmd = specialCommands[cmds[current].value - BT_CONDITIONALCOMMANDS]; if (original == current) { BTSpecialCommand *specialCom = dynamic_cast<BTSpecialCommand*>(special); if (NULL != specialCom) { for (int i = 0; i < 3; i++) { number[i] = specialCom->getNumber(i); } text = specialCom->getText(); } } } const char *dollarSign; std::string newMap; int facingDir = -1; while (dollarSign = strchr(cmd, '$')) { switch (dollarSign[1]) { case 'S': { int len = levelMap->getNumOfSpecials(); BTDisplay::selectItem list[len]; for (int i = 0; i < len; ++i) { list[i].name = levelMap->getSpecial(i)->getName(); } int specialStart(0); d.addSelection(list, len, specialStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case 'I': { BTFactory<BTItem> &itemList = getItemList(); BTDisplay::selectItem items[itemList.size()]; for (size_t i = 0; i < itemList.size(); ++i) items[i].name = itemList[i].getName(); int itemStart(0); d.addSelection(items, itemList.size(), itemStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case 'A': case 'M': { BTFactory<BTMonster> &monsterList = getMonsterList(); BTDisplay::selectItem monsters[monsterList.size()]; for (size_t i = 0; i < monsterList.size(); ++i) monsters[i].name = monsterList[i].getName(); int monsterStart(0); d.addSelection(monsters, monsterList.size(), monsterStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case 'X': { BTFactory<BTSpell, BTSpell1> &spellList = getSpellList(); BTDisplay::selectItem spells[spellList.size()]; for (size_t i = 0; i < spellList.size(); ++i) spells[i].name = spellList[i].getName(); int spellStart(0); d.addSelection(spells, spellList.size(), spellStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case 'L': { if ((newMap.empty()) || (0 != PHYSFS_exists(newMap.c_str()))) { int origX = xPos; int origY = yPos; int origFacing = facing; bool toggle = false; if ((!newMap.empty()) && (newMap != levelMap->getFilename())) { toggleMap(); loadMap(newMap.c_str()); toggle = true; } BTDisplayConfig *oldConfig = d.getConfig(); BTDisplayConfig config; XMLSerializer parser; config.serialize(&parser); parser.parse(BTDisplay::applyDisplayDir("data/mapedit.xml").c_str(), true); d.setConfig(&config); xPos = number[count] % levelMap->getXSize(); yPos = levelMap->getYSize() - 1 - (number[count + 1] % levelMap->getYSize()); facing = number[count + 2]; p3dConfig = d.setWallGraphics(levelMap->getType()); unsigned char key = ' '; while (key != '\r') { if (levelMap->getSquare(yPos, xPos).getSpecial() > -1) d.drawLabel("main", levelMap->getSpecial(levelMap->getSquare(yPos, xPos).getSpecial())->getName()); else d.drawLabel("main", ""); d.drawView(); key = d.readChar(); switch (key) { case BTKEY_UP: if (yPos > 0) yPos--; else yPos = getYSize() - 1; break; case BTKEY_LEFT: if (xPos > 0) xPos--; else xPos = getXSize() - 1; break; case BTKEY_DOWN: if (yPos < getYSize() - 1) yPos++; else yPos = 0; break; case BTKEY_RIGHT: if (xPos < getXSize() - 1) xPos++; else xPos = 0; break; case BTKEY_PGDN: if (facing < 3) facing++; else facing = 0; break; case BTKEY_END: if (facing > 0) facing--; else facing = 3; break; default: break; } } number[count++] = xPos; number[count++] = levelMap->getYSize() - 1 - yPos; facingDir = facing; d.clearText(); d.setConfig(oldConfig); if (toggle) { toggleMap(); p3dConfig = d.setWallGraphics(levelMap->getType()); } xPos = origX; yPos = origY; facing = origFacing; break; } // Fall through to $O processing if map file does not exist. } case 'O': { std::string val; if (number[count] != 0) { char convert[30]; sprintf(convert, "%d", number[count]); val = convert; } d.addReadString("X>", 100, val); key = d.process(); d.clearText(); if (27 == key) return NULL; number[count++] = atol(val.c_str()); val = ""; if (number[count] != 0) { char convert[30]; sprintf(convert, "%d", number[count]); val = convert; } d.addReadString("Y>", 100, val); key = d.process(); d.clearText(); if (27 == key) return NULL; number[count++] = atol(val.c_str()); break; } case 'T': { BTDisplay::selectItem damage[BT_MONSTEREXTRADAMAGE]; for (int i = 0; i < BT_MONSTEREXTRADAMAGE; ++i) damage[i].name = extraDamage[i]; int damageStart(0); d.addSelection(damage, BT_MONSTEREXTRADAMAGE, damageStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case 'C': { BTJobList &jobList = getJobList(); BTDisplay::selectItem jobs[jobList.size()]; for (size_t i = 0; i < jobList.size(); ++i) jobs[i].name = jobList[i]->name; int jobStart(0); d.addSelection(jobs, jobList.size(), jobStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case 'R': { BTRaceList &raceList = getRaceList(); BTDisplay::selectItem races[raceList.size()]; for (size_t i = 0; i < raceList.size(); ++i) races[i].name = raceList[i]->name; int raceStart(0); d.addSelection(races, raceList.size(), raceStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case 'D': { if (facingDir != -1) { number[count++] = facingDir; } else { BTDisplay::selectItem dir[BT_DIRECTIONS]; for (int i = 0; i < BT_DIRECTIONS; ++i) dir[i].name = directions[i]; int dirStart(0); d.addSelection(dir, BT_DIRECTIONS, dirStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; } break; } case '#': case 'G': case 'F': case '!': case 'J': { std::string val; if (number[count] != 0) { char convert[30]; sprintf(convert, "%d", number[count]); val = convert; } d.addReadString("Number>", 100, val); key = d.process(); d.clearText(); if (27 == key) return NULL; number[count++] = atol(val.c_str()); break; } case 'P': { BTDisplayConfig *oldConfig = d.getConfig(); BTDisplayConfig config; XMLSerializer parser; config.serialize(&parser); parser.parse(BTDisplay::applyDisplayDir("data/pictureselect.xml").c_str(), true); d.setConfig(&config); d.clearText(); d.addText("Select Image"); int val(number[count]); d.addSelectImage(val); key = d.process(); d.clearText(); d.clearImage(); d.setConfig(oldConfig); if (27 == key) return NULL; number[count++] = val; break; } case 'E': { BTDisplay::selectItem effects[BT_SPELLTYPES_FULL]; for (int i = 0; i < BT_SPELLTYPES_FULL; ++i) effects[i].name = spellTypes[i]; int effectStart(0); d.addSelection(effects, BT_SPELLTYPES_FULL, effectStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case 'N': { char **files = PHYSFS_enumerateFiles(""); char **i; int count(1); for (i = files; *i != NULL; i++) { if (checkSkipFiles(*i)) continue; int len = strlen(*i); if ((len > 4) && (strcmp(".MAP", (*i) + (len - 4)) == 0)) { char tmp[len + 1]; strcpy(tmp, (*i)); strcpy(tmp + len - 3, "xml"); if (0 == PHYSFS_exists(tmp)) { count++; } } else if ((len > 4) && (strcmp(".xml", (*i) + (len - 4)) == 0)) { count++; } } BTDisplay::selectItem *list = new BTDisplay::selectItem[count]; int current = 0; for (i = files; *i != NULL; i++) { if (checkSkipFiles(*i)) continue; int len = strlen(*i); if ((len > 4) && (strcmp(".MAP", (*i) + (len - 4)) == 0)) { char tmp[len + 1]; strcpy(tmp, (*i)); strcpy(tmp + len - 3, "xml"); if (0 == PHYSFS_exists(tmp)) { list[current].name = *i; current++; } } else if ((len > 4) && (strcmp(".xml", (*i) + (len - 4)) == 0)) { list[current].name = *i; current++; } } list[current].name = "<New Map>"; PHYSFS_freeList(files); int start(0); int select(0); d.clearElements(); d.addSelection(list, count, start, select); unsigned int key = d.process(); d.clearText(); if (27 == key) return NULL; else if (count - 1 != select) text = list[select].name; else { d.addReadString(">", 100, text); key = d.process(); d.clearText(); if (27 == key) return NULL; } newMap = text; break; } case 'K': { BTSkillList &skillList = getSkillList(); BTDisplay::selectItem items[skillList.size()]; for (size_t i = 0; i < skillList.size(); ++i) items[i].name = skillList[i]->name; int itemStart(0); d.addSelection(items, skillList.size(), itemStart, number[count]); int key = d.process(); d.clearText(); if (key == 27) return NULL; count++; break; } case '$': default: d.addReadString(">", 100, text); key = d.process(); d.clearText(); if (27 == key) return NULL; break; } cmd = dollarSign + 2; } if (cmds[current].value < BT_CONDITIONALCOMMANDS) { BTSpecialConditional *opNew = new BTSpecialConditional(cmds[current].value, text.c_str()); for (int i = 0; i < count; ++i) opNew->addNumber(number[i]); BTSpecialConditional *opOld = dynamic_cast<BTSpecialConditional*>(special); if (opOld) { opNew->getThenClause()->moveFrom(opOld->getThenClause()); opNew->getElseClause()->moveFrom(opOld->getElseClause()); } return opNew; } else { BTSpecialCommand *opNew = new BTSpecialCommand(cmds[current].value - BT_CONDITIONALCOMMANDS); opNew->setText(text); for (int i = 0; i < count; ++i) opNew->setNumber(i, number[i]); return opNew; } }
void BTEditor::edit(BTDisplay &d) { char **files = PHYSFS_enumerateFiles(""); char **i; int count(4); d.setPsuedo3DConfig(&getPsuedo3DConfigList()); d.setWallGraphics(0); for (i = files; *i != NULL; i++) { if (checkSkipFiles(*i)) continue; int len = strlen(*i); if ((len > 4) && (strcmp(".MAP", (*i) + (len - 4)) == 0)) { char tmp[len + 1]; strcpy(tmp, (*i)); strcpy(tmp + len - 3, "xml"); if (0 == PHYSFS_exists(tmp)) { count++; } } else if ((len > 4) && (strcmp(".xml", (*i) + (len - 4)) == 0)) { count++; } } BTDisplay::selectItem *list = new BTDisplay::selectItem[count]; list[0].name = module->item; list[1].name = module->spell; list[2].name = module->monster; int current = 3; for (i = files; *i != NULL; i++) { if (checkSkipFiles(*i)) continue; int len = strlen(*i); if ((len > 4) && (strcmp(".MAP", (*i) + (len - 4)) == 0)) { char tmp[len + 1]; strcpy(tmp, (*i)); strcpy(tmp + len - 3, "xml"); if (0 == PHYSFS_exists(tmp)) { list[current].name = *i; current++; } } else if ((len > 4) && (strcmp(".xml", (*i) + (len - 4)) == 0)) { list[current].name = *i; current++; } } list[current].name = "<New Map>"; PHYSFS_freeList(files); int start(0); int select(0); d.clearElements(); d.addSelection(list, count, start, select); unsigned int key = d.process(); d.clearText(); if (key == 13) { if (list[select].name == module->monster) { BTFactory<BTMonster> &monsterList = getMonsterList(); BTMonsterListCompare compare; BTMonsterEditor monsterEditor; int monster = 0; while (-1 != (monster = monsterEditor.editFactoryList<BTMonster>(d, monsterList, compare, "<New Monster>"))) { ObjectSerializer serial; monsterList[monster].serialize(&serial); monsterEditor.edit(d, serial); } monsterList.save(module->monster); } else if (list[select].name == module->spell) { BTFactory<BTSpell, BTSpell1> &spellList = getSpellList(); BTSpellListCompare compare; int spell = 0; BTSpellEditor spellEditor; while (-1 != (spell = spellEditor.editFactoryList<BTSpell, BTSpell1>(d, spellList, compare, "<New Spell>"))) { ObjectSerializer serial; spellList[spell].serialize(&serial); spellEditor.edit(d, serial); } spellList.save(module->spell); } else if (list[select].name == module->item) { BTFactory<BTItem> &itemList = getItemList(); BTItemListCompare compare; int item = 0; BTItemEditor itemEditor; while (-1 != (item = itemEditor.editFactoryList<BTItem>(d, itemList, compare, "<New Item>"))) { ObjectSerializer serial; itemList[item].serialize(&serial); itemEditor.edit(d, serial); } itemList.save(module->item); } else if (count - 1 == select) { d.clearText(); d.drawText("Filename:"); std::string name = d.readString("", 60, ""); d.clearText(); editMap(d, name.c_str()); } else editMap(d, list[select].name.c_str()); } d.setPsuedo3DConfig(NULL); }
void LLNameListCtrl::mouseOverHighlightNthItem( S32 target_index ) { S32 cur_index = getHighlightedItemInx(); if (cur_index != target_index) { bool is_mouse_over_name_cell = false; S32 mouse_x, mouse_y; LLUI::getMousePositionLocal(this, &mouse_x, &mouse_y); S32 column_index = getColumnIndexFromOffset(mouse_x); LLScrollListItem* hit_item = hitItem(mouse_x, mouse_y); if (hit_item && column_index == mNameColumnIndex) { // Get the name cell which is currently under the mouse pointer. LLScrollListCell* hit_cell = hit_item->getColumn(column_index); if (hit_cell) { is_mouse_over_name_cell = getCellRect(cur_index, column_index).pointInRect(mouse_x, mouse_y); } } // If the tool tip is visible and the mouse is over the currently highlighted item's name cell, // we should not reset the highlighted item index i.e. set mHighlightedItem = -1 // and should not increase the width of the text inside the cell because it may // overlap the tool tip icon. if (LLToolTipMgr::getInstance()->toolTipVisible() && is_mouse_over_name_cell) return; if(0 <= cur_index && cur_index < (S32)getItemList().size()) { LLScrollListItem* item = getItemList()[cur_index]; if (item) { LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex)); if (cell) cell->setTextWidth(cell->getTextWidth() + info_icon_size); } else { llwarns << "highlighted name list item is NULL" << llendl; } } if(target_index != -1) { LLScrollListItem* item = getItemList()[target_index]; LLScrollListText* cell = dynamic_cast<LLScrollListText*>(item->getColumn(mNameColumnIndex)); if (item) { if (cell) cell->setTextWidth(cell->getTextWidth() - info_icon_size); } else { llwarns << "target name item is NULL" << llendl; } } } LLScrollListCtrl::mouseOverHighlightNthItem(target_index); }
++thingCount; return; } 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*/; 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) { const ItemType& oldType = Item::items[ground->getID()];
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*/; } }
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; }
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::__replaceThing(uint32_t index, Thing* thing) { int32_t pos = index; Item* item = thing->getItem(); if (item == NULL) { return /*RET_NOTPOSSIBLE*/; } Item* oldItem = NULL; 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 < (int32_t)creatures->size()) { return /*RET_NOTPOSSIBLE*/; } pos -= (uint32_t)creatures->size(); } if (items && !isInserted) { int32_t downItemSize = getDownItemCount(); if (pos < downItemSize) { ItemVector::iterator it = items->begin(); it += pos; pos = 0; oldItem = (*it); it = items->erase(it); items->insert(it, item); isInserted = true; } } if (isInserted) { item->setParent(this); updateTileFlags(oldItem, true); updateTileFlags(item, false); const ItemType& oldType = Item::items[oldItem->getID()]; const ItemType& newType = Item::items[item->getID()]; onUpdateTileItem(oldItem, oldType, item, newType); oldItem->setParent(NULL); return /*RET_NOERROR*/; } }
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); } }
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, 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; }
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); } } }
int main() { //Create two lists LinkedListP list1 = newList(); LinkedListP list2 = newList(); char name[10] = "Diana"; // Insert three items and print the list insertItemList( list1, "Alice" ); printf("\n\nCurrent item contains (Alice) %s\n", getItemList(list1)); insertItemList( list1, "Bob" ); printf("Current item contains (Bob) %s\n", getItemList(list1)); insertItemList( list1, "Carl" ); printf("Current item containsj (Carl) %s\n", getItemList(list1)); displayListForward(list1); displayListBackward(list1); printf("\n\nCurrent item contains (Carl) %s\n", getItemList(list1)); printf("Moving to NEXT item\n"); nextItemList( list1 ); printf("Current item contains (Bob) %s\n", getItemList( list1 )); //Try moving to previous - no change printf("moving to PREVIOUS item \n"); previousItemList( list1 ); printf("Current item contains (Carl) %s\n", getItemList( list1 )); //Add three more names into list1 printf("\n\nAdding three items Don, Eric, Diana\n"); addItemList( list1, "Don" ); addItemList( list1, "Eric" ); addItemList( list1, name ); //Use the utility function below to display list1 forward displayListForward(list1); //Change Diana's name //Notice that the node is NOT modified printf("\nSetting DIANA to DONNY\n"); strcpy(name, "Donny"); displayListForward(list1); //Insert two more people into list1 printf("\n\nInserting EARL and FRAN at front of list 10 :\n"); firstItemList(list1); insertItemList( list1, "Earl" ); insertItemList( list1, "Fran" ); displayListForward(list1); if(isEmptyList(list1)) printf("\n\nList 1 is empty\n"); else printf("\n\nList 1 is not empty\n"); if(isEmptyList(list2)) printf("List 2 is empty\n"); else printf("List 2 is not empty\n"); //Take three people from list1 and insert into list2 printf("\n\nRemove 3 from front of list 1 add to list 2\n"); firstItemList(list1); addItemList(list2, removeItemList(list1)); addItemList(list2, removeItemList(list1)); addItemList(list2, removeItemList(list1)); //Use the utility function below to display both lists forward printf("\nList 1 Forward\n"); displayListForward(list1); printf("List 1 Forward\n"); displayListBackward(list1); printf("\nList 2 Forward\n"); displayListForward(list2); printf("List 2 Backward\n"); displayListBackward(list2); //Free both lists list1 = freeList(list1); list2 = freeList(list2); if(list1 == NULL) printf("\n\nList 1 is NULL\n"); else printf("\n\nList 1 is not NULL\n"); if(list2 == NULL) printf("List 2 is NULL\n"); else printf("List 2 is not NULL\n"); return 0; }
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.map.clearSpectatorCache(); creatures->erase(it); } } return; } Item* item = thing->getItem(); if (!item) { return; } int32_t index = getThingIndex(item); if (index == -1) { return; } if (item == ground) { ground->setParent(nullptr); ground = nullptr; SpectatorVec list; g_game.map.getSpectators(list, getPosition(), true); onRemoveTileItem(list, std::vector<int32_t>(list.size(), 0), item); return; } TileItemVector* items = getItemList(); if (!items) { return; } const ItemType& itemType = Item::items[item->getID()]; if (itemType.alwaysOnTop) { auto it = std::find(items->getBeginTopItem(), items->getEndTopItem(), item); if (it == items->getEndTopItem()) { return; } std::vector<int32_t> oldStackPosVector; SpectatorVec list; g_game.map.getSpectators(list, getPosition(), true); for (Creature* spectator : list) { if (Player* tmpPlayer = spectator->getPlayer()) { oldStackPosVector.push_back(getStackposOfItem(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 (itemType.stackable && count != item->getItemCount()) { uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, static_cast<int32_t>(item->getItemCount() - count))); item->setItemCount(newCount); onUpdateTileItem(item, itemType, item, itemType); } else { std::vector<int32_t> oldStackPosVector; SpectatorVec list; g_game.map.getSpectators(list, getPosition(), true); for (Creature* spectator : list) { if (Player* tmpPlayer = spectator->getPlayer()) { oldStackPosVector.push_back(getStackposOfItem(tmpPlayer, item)); } } item->setParent(nullptr); items->erase(it); items->addDownItemCount(-1); onRemoveTileItem(list, oldStackPosVector, item); } } }
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; }