diff --git a/src/otclient/CMakeLists.txt b/src/otclient/CMakeLists.txt index acf526c9..1f71e119 100644 --- a/src/otclient/CMakeLists.txt +++ b/src/otclient/CMakeLists.txt @@ -79,8 +79,8 @@ set(otclient_SOURCES ${otclient_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/houses.h ${CMAKE_CURRENT_LIST_DIR}/towns.cpp ${CMAKE_CURRENT_LIST_DIR}/towns.h - ${CMAKE_CURRENT_LIST_DIR}/monsters.cpp - ${CMAKE_CURRENT_LIST_DIR}/monsters.h + ${CMAKE_CURRENT_LIST_DIR}/creatures.cpp + ${CMAKE_CURRENT_LIST_DIR}/creatures.h # lua ${CMAKE_CURRENT_LIST_DIR}/luavaluecasts.cpp diff --git a/src/otclient/creatures.cpp b/src/otclient/creatures.cpp new file mode 100644 index 00000000..1eb92cf5 --- /dev/null +++ b/src/otclient/creatures.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "creatures.h" + +#include +#include +#include + +void Creatures::loadMonsters(const std::string& file) +{ + TiXmlDocument doc; + doc.Parse(g_resources.loadFile(file).c_str()); + if(doc.Error()) + stdext::throw_exception(stdext::format("cannot open monsters file '%s': '%s'", file, doc.ErrorDesc())); + + TiXmlElement* root = doc.FirstChildElement(); + if(!root || root->ValueStr() != "monsters") + stdext::throw_exception("malformed monsters xml file"); + + for(TiXmlElement* monster = root->FirstChildElement(); monster; monster = monster->NextSiblingElement()) { + std::string fname = file.substr(0, file.find_last_of('/')) + '/' + monster->Attribute("file"); + if(fname.substr(fname.length() - 4) != ".xml") + fname += ".xml"; + + loadSingleCreature(fname); + } + + doc.Clear(); + m_loaded = true; +} + +void Creatures::loadSingleCreature(const std::string& file) +{ + return loadCreatureBuffer(g_resources.loadFile(file)); +} + +void Creatures::loadNpcs(const std::string &folder) +{ + boost::filesystem::path npcPath(folder); + if(!boost::filesystem::exists(npcPath)) + stdext::throw_exception(stdext::format("NPCs folder '%s' was not found.", folder)); + + for(boost::filesystem::directory_iterator it(npcPath), end; it != end; ++it) { + std::string f = it->path().string(); + if(boost::filesystem::is_directory(it->status()) && ((f.size() > 4 ? f.substr(f.size() - 4) : "") != ".xml")) + continue; + + loadCreatureBuffer(g_resources.loadFile(f)); + } +} + +void Creatures::loadCreatureBuffer(const std::string &buffer) +{ + TiXmlDocument doc; + doc.Parse(buffer.c_str()); + if(doc.Error()) + stdext::throw_exception(stdext::format("cannot load creature buffer: %s", doc.ErrorDesc())); + + TiXmlElement* root = doc.FirstChildElement(); + if(!root || root->ValueStr() != "npc") + stdext::throw_exception(("invalid root tag name")); + + for(TiXmlElement* attrib = root->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) { + if(attrib->ValueStr() != "npc" && attrib->ValueStr() != "monster") + stdext::throw_exception(stdext::format("invalid attribute '%s'", attrib->ValueStr())); + + CreatureTypePtr newType(nullptr); + m_loadCreatureBuffer(attrib, newType); + } +} + +bool Creatures::m_loadCreatureBuffer(TiXmlElement* attrib, CreatureTypePtr& m) +{ + if(m || std::find(m_creatures.begin(), m_creatures.end(), m) != m_creatures.end()) + return true; + + m = CreatureTypePtr(new CreatureType(stdext::trim(stdext::tolower(attrib->Attribute("name"))))); + Outfit out; + + int32 type; + if(!attrib->Attribute("type").empty()) + type = attrib->readType("type"); + else + type = attrib->readType("typeex"); + + out.setId(type); + { + out.setHead(attrib->readType(("head"))); + out.setBody(attrib->readType(("body"))); + out.setLegs(attrib->readType(("legs"))); + out.setFeet(attrib->readType(("feet"))); + out.setAddons(attrib->readType(("addons"))); + out.setMount(attrib->readType(("mount"))); + } + m->setOutfit(out); + m_creatures.push_back(m); + + return type >= 0; +} + +CreatureTypePtr Creatures::getCreature(const std::string& name) +{ + auto it = std::find_if(m_creatures.begin(), m_creatures.end(), + [=] (const CreatureTypePtr& m) -> bool { return m->getName() == stdext::trim(stdext::tolower(name)); }); + return it != m_creatures.end() ? *it : nullptr; +} + +CreatureTypePtr Creatures::getCreature(const Position& pos) +{ + auto it = std::find_if(m_creatures.begin(), m_creatures.end(), + [=] (const CreatureTypePtr& m) -> bool { return m->getPos() == pos; }); + return it != m_creatures.end() ? *it : nullptr; +} diff --git a/src/otclient/monsters.h b/src/otclient/creatures.h similarity index 76% rename from src/otclient/monsters.h rename to src/otclient/creatures.h index 2f27beba..c33f3d75 100644 --- a/src/otclient/monsters.h +++ b/src/otclient/creatures.h @@ -27,11 +27,11 @@ #include #include "outfit.h" -class MonsterType : public LuaObject +class CreatureType : public LuaObject { public: - MonsterType() { } - MonsterType(const std::string& name) + CreatureType() { } + CreatureType(const std::string& name) : m_name(name) { } void setPos(const Position& pos) { m_pos = pos; } @@ -50,21 +50,27 @@ private: int m_spawnTime; }; -class Monsters +class Creatures { public: - void clear() { m_monsters.clear(); } + void clear() { m_creatures.clear(); } void loadMonsters(const std::string& file); - void loadSingleMonster(const std::string& file, const MonsterTypePtr& m = nullptr); + void loadSingleCreature(const std::string& file); + void loadNpcs(const std::string& folder); + void loadCreatureBuffer(const std::string& buffer); - MonsterTypePtr getMonster(const std::string& name); - MonsterTypePtr getMonsterByPos(const Position& pos); + CreatureTypePtr getCreature(const std::string& name); + CreatureTypePtr getCreature(const Position& pos); bool isLoaded() const { return m_loaded; } + +protected: + bool m_loadCreatureBuffer(TiXmlElement* elem, CreatureTypePtr& m); + private: - std::vector m_monsters; - bool m_loaded; + std::vector m_creatures; + Boolean m_loaded; }; #endif diff --git a/src/otclient/declarations.h b/src/otclient/declarations.h index 6f46e890..61674132 100644 --- a/src/otclient/declarations.h +++ b/src/otclient/declarations.h @@ -48,7 +48,7 @@ class ThingTypeDat; class ThingTypeOtb; class House; class Town; -class MonsterType; +class CreatureType; typedef std::shared_ptr MapViewPtr; typedef std::shared_ptr TilePtr; @@ -68,13 +68,14 @@ typedef std::shared_ptr ThingTypeDatPtr; typedef std::shared_ptr ThingTypeOtbPtr; typedef std::shared_ptr HousePtr; typedef std::shared_ptr TownPtr; -typedef std::shared_ptr MonsterTypePtr; +typedef std::shared_ptr CreatureTypePtr; typedef std::vector ThingList; typedef std::vector ThingTypeDatList; typedef std::vector ThingTypeOtbList; typedef std::vector HouseList; typedef std::vector TownList; +typedef std::unordered_map TileMap; // net class ProtocolLogin; diff --git a/src/otclient/houses.cpp b/src/otclient/houses.cpp index 6bc181c9..8d2096e3 100644 --- a/src/otclient/houses.cpp +++ b/src/otclient/houses.cpp @@ -25,40 +25,30 @@ #include House::House(uint32 hId, const std::string &name, const Position &pos) - : m_id(hId), m_name(name) { + setId(hId); + setName(name); if(pos.isValid()) - m_doors.insert(std::make_pair(0, pos)); // first door -} - -void House::addDoor(uint16 doorId, const Position& pos) -{ - if(m_doors.find(doorId) == m_doors.end()) - m_doors.insert(std::make_pair(doorId, pos)); + setEntry(pos); } void House::setTile(const TilePtr& tile) { tile->setFlags(TILESTATE_HOUSE); - if(std::find(m_tiles.begin(), m_tiles.end(), tile) == m_tiles.end()) - m_tiles.push_back(tile); + m_tiles.insert(std::make_pair(tile->getPosition(), tile)); } void House::load(const TiXmlElement *elem) { std::string name = elem->Attribute("name"); if(name.empty()) - name = stdext::format("UnNamed house #%u", getId()); - - m_rent = elem->readType("rent"); - m_size = elem->readType("size"); - - uint32 townId = elem->readType("townid"); - if(!g_map.getTown(townId)) - stdext::throw_exception(stdext::format("invalid town id for house %d", townId)); + name = stdext::format("Unnamed house #%lu", getId()); + setRent(elem->readType("rent")); + setSize(elem->readType("size")); + setTownId(elem->readType("townid")); m_isGuildHall = elem->readType("rent"); - addDoor(0, elem->readPos()); + setEntry(elem->readPos("entry")); } void Houses::addHouse(const HousePtr& house) @@ -77,10 +67,7 @@ void Houses::removeHouse(uint32 houseId) HousePtr Houses::getHouse(uint32 houseId) { auto it = findHouse(houseId); - if(it != m_houses.end()) - return *it; - - return nullptr; + return it != m_houses.end() ? *it : nullptr; } void Houses::load(const std::string& fileName) @@ -94,7 +81,7 @@ void Houses::load(const std::string& fileName) if(!root || root->ValueTStr() != "houses") stdext::throw_exception("invalid root tag name"); - for (TiXmlElement *elem = root->FirstChildElement(); elem; elem = elem->NextSiblingElement()) { + for(TiXmlElement *elem = root->FirstChildElement(); elem; elem = elem->NextSiblingElement()) { if(elem->ValueTStr() != "house") stdext::throw_exception("invalid house tag."); @@ -106,7 +93,7 @@ void Houses::load(const std::string& fileName) house->load(elem); } - stdext::throw_exception("This has not been fully implemented yet."); + g_logger.debug("Loaded houses.xml successfully."); } HouseList::iterator Houses::findHouse(uint32 houseId) diff --git a/src/otclient/houses.h b/src/otclient/houses.h index a7bed897..12185d23 100644 --- a/src/otclient/houses.h +++ b/src/otclient/houses.h @@ -27,32 +27,45 @@ #include "tile.h" #include +#include + +enum HouseAttributes +{ + HouseAttribId, + HouseAttribName, + HouseAttribTown, + HouseAttribEntry, + HouseAttribSize, + HouseAttribRent +}; class House : public LuaObject { public: House() { } House(uint32 hId, const std::string& name = "", const Position& pos=Position()); - ~House() { m_tiles.clear(); m_doors.clear(); } + ~House() { m_tiles.clear(); } - void setId(uint32 hId) { m_id = hId; } - void setName(const std::string& name) { m_name = name; } - void addDoor(uint16 doorId, const Position& pos); void setTile(const TilePtr& tile); + void setId(uint32 hId) { m_attribs.set(HouseAttribId, hId); } + void setName(const std::string& name) { m_attribs.set(HouseAttribName, name); } + void setTownId(uint32 tid) { m_attribs.set(HouseAttribTown, tid); } + void setSize(uint32 s) { m_attribs.set(HouseAttribSize, s); } + void setRent(uint32 r) { m_attribs.set(HouseAttribRent, r); } + void setEntry(const Position& p) { m_attribs.set(HouseAttribEntry, p); } - uint32 getId() const { return m_id; } - std::string getName() const { return m_name; } + uint32 getId() { return m_attribs.get(HouseAttribId); } + std::string getName() { return m_attribs.get(HouseAttribName); } + uint32 getRent() { return m_attribs.get(HouseAttribRent); } + uint32 getSize() { return m_attribs.get(HouseAttribSize); } protected: void load(const TiXmlElement* elem); void save(TiXmlElement &elem) { } // TODO private: - uint32 m_id, m_size, m_rent; - std::string m_name; - - std::map m_doors; - std::vector m_tiles; + AttribStorage m_attribs; + TileMap m_tiles; Boolean m_isGuildHall; friend class Houses; diff --git a/src/otclient/luafunctions.cpp b/src/otclient/luafunctions.cpp index 496b5b31..11814789 100644 --- a/src/otclient/luafunctions.cpp +++ b/src/otclient/luafunctions.cpp @@ -97,10 +97,10 @@ void OTClient::registerLuaFunctions() g_lua.bindSingletonFunction("g_map", "loadOtcm", &Map::loadOtcm, &g_map); g_lua.bindSingletonFunction("g_map", "saveOtcm", &Map::saveOtcm, &g_map); g_lua.bindSingletonFunction("g_map", "loadMonsters", &Map::loadMonsters, &g_map); - g_lua.bindSingletonFunction("g_map", "loadSingleMonster", &Map::loadSingleMonster, &g_map); + g_lua.bindSingletonFunction("g_map", "loadSingleCreature", &Map::loadSingleCreature, &g_map); g_lua.bindSingletonFunction("g_map", "getTown", &Map::getTown, &g_map); g_lua.bindSingletonFunction("g_map", "getHouse", &Map::getHouse, &g_map); - g_lua.bindSingletonFunction("g_map", "getMonster", &Map::getMonster, &g_map); + g_lua.bindSingletonFunction("g_map", "getCreature", &Map::getCreature, &g_map); g_lua.registerSingletonClass("g_game"); g_lua.bindSingletonFunction("g_game", "loginWorld", &Game::loginWorld, &g_game); @@ -280,10 +280,9 @@ void OTClient::registerLuaFunctions() g_lua.bindClassStaticFunction("create", []{ return HousePtr(new House); }); g_lua.bindClassMemberFunction("setId", &House::setId); g_lua.bindClassMemberFunction("setName", &House::setName); - g_lua.bindClassMemberFunction("addDoor", &House::addDoor); - g_lua.bindClassMemberFunction("addDoorPos", &House::addDoor); // alternative method g_lua.bindClassMemberFunction("setTile", &House::setTile); - g_lua.bindClassMemberFunction("addTile", &House::addDoor); // alternative method + g_lua.bindClassMemberFunction("addTile", &House::setTile); // alternative method + g_lua.bindClassMemberFunction("setEntry", &House::setEntry); g_lua.registerClass(); g_lua.bindClassStaticFunction("create", []{ return TownPtr(new Town); }); @@ -296,14 +295,14 @@ void OTClient::registerLuaFunctions() g_lua.bindClassMemberFunction("getPos", &Town::getPos); g_lua.bindClassMemberFunction("getTemplePos", &Town::getPos); // alternative method - g_lua.registerClass(); - g_lua.bindClassStaticFunction("create", []{ return MonsterTypePtr(new MonsterType); }); - g_lua.bindClassMemberFunction("setPos", &MonsterType::setPos); - g_lua.bindClassMemberFunction("setName", &MonsterType::setName); - g_lua.bindClassMemberFunction("setOutfit", &MonsterType::setOutfit); - g_lua.bindClassMemberFunction("getPos", &MonsterType::getPos); - g_lua.bindClassMemberFunction("getName", &MonsterType::getName); - g_lua.bindClassMemberFunction("getOutfit", &MonsterType::getOutfit); + g_lua.registerClass(); + g_lua.bindClassStaticFunction("create", []{ return CreatureTypePtr(new CreatureType); }); + g_lua.bindClassMemberFunction("setPos", &CreatureType::setPos); + g_lua.bindClassMemberFunction("setName", &CreatureType::setName); + g_lua.bindClassMemberFunction("setOutfit", &CreatureType::setOutfit); + g_lua.bindClassMemberFunction("getPos", &CreatureType::getPos); + g_lua.bindClassMemberFunction("getName", &CreatureType::getName); + g_lua.bindClassMemberFunction("getOutfit", &CreatureType::getOutfit); g_lua.registerClass(); g_lua.bindClassStaticFunction("create", []{ return CreaturePtr(new Creature); }); diff --git a/src/otclient/map.cpp b/src/otclient/map.cpp index e235a0fa..52078cbf 100644 --- a/src/otclient/map.cpp +++ b/src/otclient/map.cpp @@ -205,13 +205,10 @@ void Map::loadOtbm(const std::string& fileName) m_containers.push_back(mapContainer); } - if(house) { - if(item->isMoveable()) { - g_logger.warning(stdext::format("Movable item found in house: %d at pos %d %d %d - escaping...", item->getId(), - px, py, pz)); - item.reset(); - } else if(item->isDoor()) - house->addDoor(item->getDoorId(), pos); + if(house && item->isMoveable()) { + g_logger.warning(stdext::format("Movable item found in house: %d at pos %d %d %d - escaping...", item->getId(), + px, py, pz)); + item.reset(); } addThing(item, pos); @@ -232,7 +229,8 @@ void Map::loadOtbm(const std::string& fileName) if(!(town = m_towns.getTown(townId))) { town = TownPtr(new Town(townId, townName, townCoords)); m_towns.addTown(town); - } // a map editor cannot be that dumb and write duplicate towns + } + g_logger.debug(stdext::format("new town %ld %s", townId, townName)); } } else if(mapDataType == OTBM_WAYPOINTS && headerVersion > 1) { for(const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) { @@ -373,8 +371,8 @@ void Map::saveOtbm(const std::string &fileName) void Map::loadSpawns(const std::string &fileName) { - if(!m_monsters.isLoaded()) - stdext::throw_exception("cannot load spawns; monsters aren't loaded."); + if(!m_creatures.isLoaded()) + stdext::throw_exception("cannot load spawns; monsters/nps aren't loaded."); TiXmlDocument doc; doc.Parse(g_resources.loadFile(fileName).c_str()); @@ -394,10 +392,8 @@ void Map::loadSpawns(const std::string &fileName) if(mType->ValueStr() != "monster" && mType->ValueStr() != "npc") stdext::throw_exception(stdext::format("invalid spawn-subnode %s", mType->ValueStr())); - if(mType->ValueStr() == "npc") // escape npc's for now... - continue; std::string mName = mType->Attribute("name"); - MonsterTypePtr m = getMonster(mName); + CreatureTypePtr m = getCreature(mName); if (!m) stdext::throw_exception(stdext::format("unkown monster '%s'", stdext::trim(stdext::tolower(mName)))); @@ -560,7 +556,7 @@ void Map::clean() // This is a fix to a segfault on exit. m_towns.clear(); m_houses.clear(); - m_monsters.clear(); + m_creatures.clear(); } void Map::cleanDynamicThings() @@ -1030,8 +1026,3 @@ std::tuple, Otc::PathFindResult> Map::findPath(const return ret; } - -MonsterTypePtr Map::getMonster(const std::string& name) -{ - return m_monsters.getMonster(name); -} diff --git a/src/otclient/map.h b/src/otclient/map.h index 8b0d125a..7bb1231b 100644 --- a/src/otclient/map.h +++ b/src/otclient/map.h @@ -26,7 +26,7 @@ #include "creature.h" #include "houses.h" #include "towns.h" -#include "monsters.h" +#include "creatures.h" #include "animatedtext.h" #include @@ -119,8 +119,9 @@ public: void loadSpawns(const std::string& fileName); void saveSpawns(const std::string&) { } - void loadMonsters(const std::string& fileName) { m_monsters.loadMonsters(fileName); } - void loadSingleMonster(const std::string& file) { m_monsters.loadSingleMonster(file); } + void loadMonsters(const std::string& fileName) { m_creatures.loadMonsters(fileName); } + void loadSingleCreature(const std::string& file) { m_creatures.loadSingleCreature(file); } + void loadNpcs(const std::string& folder) { m_creatures.loadNpcs(folder); } void clean(); void cleanDynamicThings(); @@ -151,7 +152,7 @@ public: // town/house/monster related TownPtr getTown(uint32 tid) { return m_towns.getTown(tid); } HousePtr getHouse(uint32 hid) { return m_houses.getHouse(hid); } - MonsterTypePtr getMonster(const std::string &name); + CreatureTypePtr getCreature(const std::string &name) { return m_creatures.getCreature(name); } void setLight(const Light& light) { m_light = light; } void setCentralPosition(const Position& centralPosition); @@ -173,7 +174,7 @@ public: std::tuple, Otc::PathFindResult> findPath(const Position& start, const Position& goal, int maxSteps); private: - std::unordered_map m_tiles; + TileMap m_tiles; std::map m_knownCreatures; std::array, Otc::MAX_Z+1> m_floorMissiles; std::vector m_animatedTexts; @@ -189,7 +190,7 @@ private: Houses m_houses; Towns m_towns; - Monsters m_monsters; + Creatures m_creatures; uint16 m_width, m_height; }; diff --git a/src/otclient/monsters.cpp b/src/otclient/monsters.cpp deleted file mode 100644 index a5daec64..00000000 --- a/src/otclient/monsters.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2010-2012 OTClient - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "monsters.h" -#include "creature.h" - -#include -#include - -void Monsters::loadMonsters(const std::string& file) -{ - TiXmlDocument doc; - doc.Parse(g_resources.loadFile(file).c_str()); - if(doc.Error()) - stdext::throw_exception(stdext::format("cannot open monsters file '%s': '%s'", file, doc.ErrorDesc())); - - TiXmlElement* root = doc.FirstChildElement(); - if(!root || root->ValueStr() != "monsters") - stdext::throw_exception("malformed monsters xml file"); - - for(TiXmlElement* monster = root->FirstChildElement(); monster; monster = monster->NextSiblingElement()) { - MonsterTypePtr newMonster(new MonsterType(stdext::trim(stdext::tolower(monster->Attribute("name"))))); - std::string fname = file.substr(0, file.find_last_of('/')) + '/' + monster->Attribute("file"); - - if(fname.substr(fname.length() - 4) != ".xml") - fname += ".xml"; - - loadSingleMonster(fname, newMonster); - } - - doc.Clear(); - m_loaded = true; -} - -void Monsters::loadSingleMonster(const std::string& file, const MonsterTypePtr& m) -{ - if (!m || std::find(m_monsters.begin(), m_monsters.end(), m) != m_monsters.end()) - stdext::throw_exception("reloading monsters is not supported yet."); - - TiXmlDocument doc; - doc.Parse(g_resources.loadFile(file).c_str()); - if(doc.Error()) - stdext::throw_exception(stdext::format("cannot load single monster file '%s': '%s'", file, doc.ErrorDesc())); - - TiXmlElement* root = doc.FirstChildElement(); - if(!root || root->ValueStr() != "monster") - stdext::throw_exception(stdext::format("malformed monster xml file: %s", file)); - - for(TiXmlElement* attrib = root->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) { - if(attrib->ValueStr() == "look") { - Outfit out; - - int type = 0; - if(!attrib->Attribute("type").empty()) - type = attrib->readType("type"); - else - type = attrib->readType("typeex"); - out.setId(type); - { - out.setHead(attrib->readType(("head"))); - out.setBody(attrib->readType(("body"))); - out.setLegs(attrib->readType(("legs"))); - out.setFeet(attrib->readType(("feet"))); - out.setAddons(attrib->readType(("addons"))); - out.setMount(attrib->readType(("mount"))); - } - m->setOutfit(out); - } - } - - m_monsters.push_back(m); -} - -MonsterTypePtr Monsters::getMonster(const std::string& name) -{ - auto it = std::find_if(m_monsters.begin(), m_monsters.end(), - [=] (const MonsterTypePtr& m) -> bool { return m->getName() == stdext::trim(stdext::tolower(name)); }); - return it != m_monsters.end() ? *it : nullptr; -} - -MonsterTypePtr Monsters::getMonsterByPos(const Position& pos) -{ - auto it = std::find_if(m_monsters.begin(), m_monsters.end(), - [=] (const MonsterTypePtr& m) -> bool { return m->getPos() == pos; }); - return it != m_monsters.end() ? *it : nullptr; -} diff --git a/src/otclient/thingtypemanager.cpp b/src/otclient/thingtypemanager.cpp index 1b85ab55..36135ccf 100644 --- a/src/otclient/thingtypemanager.cpp +++ b/src/otclient/thingtypemanager.cpp @@ -124,6 +124,7 @@ void ThingTypeManager::loadOtb(const std::string& file) void ThingTypeManager::loadXml(const std::string& file) { + /// Read XML TiXmlDocument doc; doc.Parse(g_resources.loadFile(file).c_str()); if(doc.Error()) diff --git a/src/otclient/thingtypeotb.cpp b/src/otclient/thingtypeotb.cpp index 977d7b61..2f49b1ea 100644 --- a/src/otclient/thingtypeotb.cpp +++ b/src/otclient/thingtypeotb.cpp @@ -30,8 +30,6 @@ ThingTypeOtb::ThingTypeOtb() { m_category = OtbInvalidCateogry; - m_serverId = 0; - m_clientId = 0; } void ThingTypeOtb::unserialize(const BinaryTreePtr& node) @@ -51,23 +49,33 @@ void ThingTypeOtb::unserialize(const BinaryTreePtr& node) uint16 len = node->getU16(); switch(attr) { case OtbAttribServerId: { - m_serverId = node->getU16(); - if(m_serverId > 20000 && m_serverId < 20100) { - m_serverId -= 20000; - } else if(lastId > 99 && lastId != m_serverId - 1) { + uint16 serverId = node->getU16(); + if(serverId > 20000 && serverId < 20100) { + serverId -= 20000; + } else if(lastId > 99 && lastId != serverId - 1) { static ThingTypeOtbPtr dummyType(g_things.getNullOtbType()); - while(lastId != m_serverId - 1) { + while(lastId != serverId - 1) { dummyType->setServerId(++lastId); g_things.addOtbType(dummyType); } } assert(len == 2); + setServerId(serverId); break; } - case OtbAttribClientId: - m_clientId = node->getU16(); + case OtbAttribClientId: { + setClientId(node->getU16()); assert(len == 2); break; + } + case OtbAttribName: { + setName(node->getString()); + break; + } + case OtbAttribDesc: { + setDesc(node->getString()); + break; + } default: node->skip(len); // skip attribute break; diff --git a/src/otclient/thingtypeotb.h b/src/otclient/thingtypeotb.h index 6e78c111..31020cd4 100644 --- a/src/otclient/thingtypeotb.h +++ b/src/otclient/thingtypeotb.h @@ -27,6 +27,7 @@ #include #include #include +#include enum OtbCategory { @@ -88,23 +89,24 @@ public: void unserialize(const BinaryTreePtr& node); - uint16 getServerId() { return m_serverId; } - uint16 getClientId() { return m_clientId; } + uint16 getServerId() { return m_attribs.get(OtbAttribServerId); } + uint16 getClientId() { return m_attribs.get(OtbAttribClientId); } OtbCategory getCategory() { return m_category; } + std::string getName() { return m_attribs.get(OtbAttribName); } + std::string getDesc() { return m_attribs.get(OtbAttribDesc); } bool isNull() { return m_null; } - void setServerId(uint16 serverId) { m_serverId = serverId; } - void setName(const std::string& name) { m_name = name; } - void setDesc(const std::string& desc) { m_desc = desc; } + void setClientId(uint16 clientId) { m_attribs.set(OtbAttribClientId, clientId); } + void setServerId(uint16 serverId) { m_attribs.set(OtbAttribServerId, serverId); } + void setName(const std::string& name) { m_attribs.set(OtbAttribName, name); } + void setDesc(const std::string& desc) { m_attribs.set(OtbAttribDesc, desc); } private: - uint16 m_serverId; - uint16 m_clientId; - - std::string m_name, m_desc; OtbCategory m_category; Boolean m_null; + + AttribStorage m_attribs; }; #endif