void HouseTile::updateHouse(Item* item) { if (item->getTile() == this) { Door* door = item->getDoor(); if (door && door->getDoorId() != 0) { house->addDoor(door); } //[ added for beds system if (!door) { BedItem* bed = item->getBed(); if (bed) { // next, add it to the house house->addBed(bed); } } //] } }
void HouseTile::updateHouse(Item* item) { if(item->getTile() != this) return; Door* door = item->getDoor(); if(door && door->getDoorId()) house->addDoor(door); else if(BedItem* bed = item->getBed()) house->addBed(bed); }
void HouseTile::updateHouse(Item* item) { if(item->getTile() == this) { Door* door = item->getDoor(); if(door && door->getDoorId() != 0) house->addDoor(door); if(!door) { BedItem* bed = item->getBed(); if(bed) house->addBed(bed); } } }
bool IOMapOTBM::loadMap(Map* map, const std::string& identifier) { int64_t start = OTSYS_TIME(); FileLoader f; if(!f.openFile(identifier.c_str(), false, true)){ std::stringstream ss; ss << "Could not open the file " << identifier << "."; setLastErrorString(ss.str()); return false; } unsigned long type; PropStream propStream; NODE root = f.getChildNode((NODE)NULL, type); if(!f.getProps(root, propStream)){ setLastErrorString("Could not read root property."); return false; } OTBM_root_header* root_header; if(!propStream.GET_STRUCT(root_header)){ setLastErrorString("Could not read header."); return false; } if(root_header->version > 2){ setLastErrorString("Unknown OTBM version detected, please update your server.");; return false; } if(root_header->majorVersionItems > (unsigned long)Items::dwMajorVersion){ setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required."); return false; } // Prevent load maps saved with items.otb previous to // version 800, because of the change to stackable of // itemid 3965 if(root_header->minorVersionItems < CLIENT_VERSION_760){ setLastErrorString("This map needs to be updated."); return false; } if(root_header->minorVersionItems > (unsigned long)Items::dwMinorVersion){ std::cout << "Warning: [OTBM loader] This map needs an updated items OTB file." <<std::endl; } std::cout << "Map size: " << root_header->width << "x" << root_header->height << std::endl; map->mapWidth = root_header->width; map->mapHeight = root_header->height; NODE nodeMap = f.getChildNode(root, type); if(type != OTBM_MAP_DATA){ setLastErrorString("Could not read data node."); return false; } if(!f.getProps(nodeMap, propStream)){ setLastErrorString("Could not read map data attributes."); return false; } unsigned char attribute; std::string mapDescription; std::string tmp; while(propStream.GET_UCHAR(attribute)){ switch(attribute){ case OTBM_ATTR_DESCRIPTION: if(!propStream.GET_STRING(mapDescription)){ setLastErrorString("Invalid description tag."); return false; } std::cout << "Map description: " << mapDescription << std::endl; break; case OTBM_ATTR_EXT_SPAWN_FILE: if(!propStream.GET_STRING(tmp)){ setLastErrorString("Invalid spawn tag."); return false; } map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1); map->spawnfile += tmp; break; case OTBM_ATTR_EXT_HOUSE_FILE: if(!propStream.GET_STRING(tmp)){ setLastErrorString("Invalid house tag."); return false; } map->housefile = identifier.substr(0, identifier.rfind('/') + 1); map->housefile += tmp; break; default: setLastErrorString("Unknown header node."); return false; break; } } Tile* tile = NULL; NODE nodeMapData = f.getChildNode(nodeMap, type); while(nodeMapData != NO_NODE){ if(f.getError() != ERROR_NONE){ setLastErrorString("Invalid map node."); return false; } if(type == OTBM_TILE_AREA){ if(!f.getProps(nodeMapData, propStream)){ setLastErrorString("Invalid map node."); return false; } OTBM_Tile_area_coords* area_coord; if(!propStream.GET_STRUCT(area_coord)){ setLastErrorString("Invalid map node."); return false; } int base_x, base_y, base_z; base_x = area_coord->_x; base_y = area_coord->_y; base_z = area_coord->_z; NODE nodeTile = f.getChildNode(nodeMapData, type); while(nodeTile != NO_NODE){ if(f.getError() != ERROR_NONE){ setLastErrorString("Could not read node data."); return false; } if(type == OTBM_TILE || type == OTBM_HOUSETILE){ if(!f.getProps(nodeTile, propStream)){ setLastErrorString("Could not read node data."); return false; } unsigned short px, py, pz; OTBM_Tile_coords* tile_coord; if(!propStream.GET_STRUCT(tile_coord)){ setLastErrorString("Could not read tile position."); return false; } px = base_x + tile_coord->_x; py = base_y + tile_coord->_y; pz = base_z; bool isHouseTile = false; House* house = NULL; if(type == OTBM_TILE){ tile = new Tile(px, py, pz); } else if(type == OTBM_HOUSETILE){ uint32_t _houseid; if(!propStream.GET_ULONG(_houseid)){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Could not read house id."; setLastErrorString(ss.str()); return false; } house = Houses::getInstance().getHouse(_houseid, true); if(!house){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Could not create house id: " << _houseid; setLastErrorString(ss.str()); return false; } tile = new HouseTile(px, py, pz, house); house->addTile(static_cast<HouseTile*>(tile)); isHouseTile = true; } //read tile attributes unsigned char attribute; while(propStream.GET_UCHAR(attribute)){ switch(attribute){ case OTBM_ATTR_TILE_FLAGS: { uint32_t flags; if(!propStream.GET_ULONG(flags)){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to read tile flags."; setLastErrorString(ss.str()); return false; } if((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE){ tile->setFlag(TILESTATE_PROTECTIONZONE); } else if((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE){ tile->setFlag(TILESTATE_NOPVPZONE); } else if((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE){ tile->setFlag(TILESTATE_PVPZONE); } if((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT){ tile->setFlag(TILESTATE_NOLOGOUT); } if((flags & TILESTATE_REFRESH) == TILESTATE_REFRESH){ if(house){ std::cout << "Warning [x:" << px << ", y:" << py << ", z:" << pz << "] " << " House tile flagged as refreshing!"; } tile->setFlag(TILESTATE_REFRESH); } break; } case OTBM_ATTR_ITEM: { Item* item = Item::CreateItem(propStream); if(!item){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to create item."; setLastErrorString(ss.str()); return false; } if(isHouseTile && !item->isNotMoveable()){ std::cout << "Warning: [OTBM loader] Moveable item in house id = " << house->getHouseId() << " Item type = " << item->getID() << std::endl; delete item; item = NULL; } else{ tile->__internalAddThing(item); item->__startDecaying(); } break; } default: std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Unknown tile attribute."; setLastErrorString(ss.str()); return false; break; } } NODE nodeItem = f.getChildNode(nodeTile, type); while(nodeItem){ if(type == OTBM_ITEM){ PropStream propStream; f.getProps(nodeItem, propStream); Item* item = Item::CreateItem(propStream); if(!item){ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to create item."; setLastErrorString(ss.str()); return false; } if(item->unserializeItemNode(f, nodeItem, propStream)){ if(isHouseTile && !item->isNotMoveable()){ std::cout << "Warning: [OTBM loader] Moveable item in house id = " << house->getHouseId() << " Item type = " << item->getID() << std::endl; delete item; } else{ tile->__internalAddThing(item); item->__startDecaying(); // TESTING if(isHouseTile){ Door* door = item->getDoor(); if(door && door->getDoorId() != 0){ house->addDoor(door); } } // } } else{ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Failed to load item " << item->getID() << "."; setLastErrorString(ss.str()); delete item; return false; } } else{ std::stringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] " << "Unknown node type."; setLastErrorString(ss.str()); } nodeItem = f.getNextNode(nodeItem, type); } map->setTile(px, py, pz, tile); } else{ setLastErrorString("Unknown tile node."); return false; } nodeTile = f.getNextNode(nodeTile, type); } } else if(type == OTBM_TOWNS){ NODE nodeTown = f.getChildNode(nodeMapData, type); while(nodeTown != NO_NODE){ if(type == OTBM_TOWN){ if(!f.getProps(nodeTown, propStream)){ setLastErrorString("Could not read town data."); return false; } uint32_t townid = 0; if(!propStream.GET_ULONG(townid)){ setLastErrorString("Could not read town id."); return false; } Town* town = Towns::getInstance().getTown(townid); if(!town){ town = new Town(townid); Towns::getInstance().addTown(townid, town); } std::string townName = ""; if(!propStream.GET_STRING(townName)){ setLastErrorString("Could not read town name."); return false; } town->setName(townName); OTBM_TownTemple_coords *town_coords; if(!propStream.GET_STRUCT(town_coords)){ setLastErrorString("Could not read town coordinates."); return false; } Position pos; pos.x = town_coords->_x; pos.y = town_coords->_y; pos.z = town_coords->_z; town->setTemplePos(pos); } else{ setLastErrorString("Unknown town node."); return false; } nodeTown = f.getNextNode(nodeTown, type); } } else if(type == OTBM_WAYPOINTS && root_header->version >= 2){ NODE nodeWaypoint = f.getChildNode(nodeMapData, type); while(nodeWaypoint != NO_NODE){ if(type == OTBM_WAYPOINT){ if(!f.getProps(nodeWaypoint, propStream)){ setLastErrorString("Could not read town data."); return false; } std::string name; Position pos; if(!propStream.GET_STRING(name)){ setLastErrorString("Could not read waypoint name."); return false; } OTBM_TownTemple_coords* wp_coords; if(!propStream.GET_STRUCT(wp_coords)){ setLastErrorString("Could not read waypoint coordinates."); return false; } pos.x = wp_coords->_x; pos.y = wp_coords->_y; pos.z = wp_coords->_z; Waypoint_ptr wp(new Waypoint(name, pos)); map->waypoints.addWaypoint(wp); } else{ setLastErrorString("Unknown waypoint node."); return false; } nodeWaypoint = f.getNextNode(nodeWaypoint, type); } } else{ setLastErrorString("Unknown map node."); return false; } nodeMapData = f.getNextNode(nodeMapData, type); } std::cout << "Notice: [OTBM Loader] Loading time : " << (OTSYS_TIME() - start)/(1000.) << " s" << std::endl; return true; }