more work on xml stuff (prolly done for today)

This commit is contained in:
niczkx 2012-07-18 16:36:46 +02:00
parent 5015ced156
commit aef3a5b8db
13 changed files with 248 additions and 211 deletions

View File

@ -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

133
src/otclient/creatures.cpp Normal file
View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 <framework/xml/tinyxml.h>
#include <framework/core/resourcemanager.h>
#include <boost/filesystem.hpp>
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<int32>("type");
else
type = attrib->readType<int32>("typeex");
out.setId(type);
{
out.setHead(attrib->readType<int>(("head")));
out.setBody(attrib->readType<int>(("body")));
out.setLegs(attrib->readType<int>(("legs")));
out.setFeet(attrib->readType<int>(("feet")));
out.setAddons(attrib->readType<int>(("addons")));
out.setMount(attrib->readType<int>(("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;
}

View File

@ -27,11 +27,11 @@
#include <framework/luaengine/luaobject.h>
#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<MonsterTypePtr> m_monsters;
bool m_loaded;
std::vector<CreatureTypePtr> m_creatures;
Boolean<false> m_loaded;
};
#endif

View File

@ -48,7 +48,7 @@ class ThingTypeDat;
class ThingTypeOtb;
class House;
class Town;
class MonsterType;
class CreatureType;
typedef std::shared_ptr<MapView> MapViewPtr;
typedef std::shared_ptr<Tile> TilePtr;
@ -68,13 +68,14 @@ typedef std::shared_ptr<ThingTypeDat> ThingTypeDatPtr;
typedef std::shared_ptr<ThingTypeOtb> ThingTypeOtbPtr;
typedef std::shared_ptr<House> HousePtr;
typedef std::shared_ptr<Town> TownPtr;
typedef std::shared_ptr<MonsterType> MonsterTypePtr;
typedef std::shared_ptr<CreatureType> CreatureTypePtr;
typedef std::vector<ThingPtr> ThingList;
typedef std::vector<ThingTypeDatPtr> ThingTypeDatList;
typedef std::vector<ThingTypeOtbPtr> ThingTypeOtbList;
typedef std::vector<HousePtr> HouseList;
typedef std::vector<TownPtr> TownList;
typedef std::unordered_map<Position, TilePtr, PositionHasher> TileMap;
// net
class ProtocolLogin;

View File

@ -25,40 +25,30 @@
#include <framework/core/resourcemanager.h>
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<uint32>("rent");
m_size = elem->readType<uint32>("size");
uint32 townId = elem->readType<uint32>("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<uint32>("rent"));
setSize(elem->readType<uint32>("size"));
setTownId(elem->readType<uint32>("townid"));
m_isGuildHall = elem->readType<bool>("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)

View File

@ -27,32 +27,45 @@
#include "tile.h"
#include <framework/luaengine/luaobject.h>
#include <framework/util/attribstorage.h>
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<uint32>(HouseAttribId); }
std::string getName() { return m_attribs.get<std::string>(HouseAttribName); }
uint32 getRent() { return m_attribs.get<uint32>(HouseAttribRent); }
uint32 getSize() { return m_attribs.get<uint32>(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<uint16, Position> m_doors;
std::vector<TilePtr> m_tiles;
AttribStorage m_attribs;
TileMap m_tiles;
Boolean<false> m_isGuildHall;
friend class Houses;

View File

@ -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<House>("create", []{ return HousePtr(new House); });
g_lua.bindClassMemberFunction<House>("setId", &House::setId);
g_lua.bindClassMemberFunction<House>("setName", &House::setName);
g_lua.bindClassMemberFunction<House>("addDoor", &House::addDoor);
g_lua.bindClassMemberFunction<House>("addDoorPos", &House::addDoor); // alternative method
g_lua.bindClassMemberFunction<House>("setTile", &House::setTile);
g_lua.bindClassMemberFunction<House>("addTile", &House::addDoor); // alternative method
g_lua.bindClassMemberFunction<House>("addTile", &House::setTile); // alternative method
g_lua.bindClassMemberFunction<House>("setEntry", &House::setEntry);
g_lua.registerClass<Town>();
g_lua.bindClassStaticFunction<Town>("create", []{ return TownPtr(new Town); });
@ -296,14 +295,14 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassMemberFunction<Town>("getPos", &Town::getPos);
g_lua.bindClassMemberFunction<Town>("getTemplePos", &Town::getPos); // alternative method
g_lua.registerClass<MonsterType>();
g_lua.bindClassStaticFunction<MonsterType>("create", []{ return MonsterTypePtr(new MonsterType); });
g_lua.bindClassMemberFunction<MonsterType>("setPos", &MonsterType::setPos);
g_lua.bindClassMemberFunction<MonsterType>("setName", &MonsterType::setName);
g_lua.bindClassMemberFunction<MonsterType>("setOutfit", &MonsterType::setOutfit);
g_lua.bindClassMemberFunction<MonsterType>("getPos", &MonsterType::getPos);
g_lua.bindClassMemberFunction<MonsterType>("getName", &MonsterType::getName);
g_lua.bindClassMemberFunction<MonsterType>("getOutfit", &MonsterType::getOutfit);
g_lua.registerClass<CreatureType>();
g_lua.bindClassStaticFunction<CreatureType>("create", []{ return CreatureTypePtr(new CreatureType); });
g_lua.bindClassMemberFunction<CreatureType>("setPos", &CreatureType::setPos);
g_lua.bindClassMemberFunction<CreatureType>("setName", &CreatureType::setName);
g_lua.bindClassMemberFunction<CreatureType>("setOutfit", &CreatureType::setOutfit);
g_lua.bindClassMemberFunction<CreatureType>("getPos", &CreatureType::getPos);
g_lua.bindClassMemberFunction<CreatureType>("getName", &CreatureType::getName);
g_lua.bindClassMemberFunction<CreatureType>("getOutfit", &CreatureType::getOutfit);
g_lua.registerClass<Creature, Thing>();
g_lua.bindClassStaticFunction<Creature>("create", []{ return CreaturePtr(new Creature); });

View File

@ -205,13 +205,10 @@ void Map::loadOtbm(const std::string& fileName)
m_containers.push_back(mapContainer);
}
if(house) {
if(item->isMoveable()) {
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();
} else if(item->isDoor())
house->addDoor(item->getDoorId(), pos);
}
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<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
return ret;
}
MonsterTypePtr Map::getMonster(const std::string& name)
{
return m_monsters.getMonster(name);
}

View File

@ -26,7 +26,7 @@
#include "creature.h"
#include "houses.h"
#include "towns.h"
#include "monsters.h"
#include "creatures.h"
#include "animatedtext.h"
#include <framework/core/clock.h>
@ -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<std::vector<Otc::Direction>, Otc::PathFindResult> findPath(const Position& start, const Position& goal, int maxSteps);
private:
std::unordered_map<Position, TilePtr, PositionHasher> m_tiles;
TileMap m_tiles;
std::map<uint32, CreaturePtr> m_knownCreatures;
std::array<std::vector<MissilePtr>, Otc::MAX_Z+1> m_floorMissiles;
std::vector<AnimatedTextPtr> m_animatedTexts;
@ -189,7 +190,7 @@ private:
Houses m_houses;
Towns m_towns;
Monsters m_monsters;
Creatures m_creatures;
uint16 m_width, m_height;
};

View File

@ -1,105 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/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 <framework/xml/tinyxml.h>
#include <framework/core/resourcemanager.h>
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<int>("type");
else
type = attrib->readType<int>("typeex");
out.setId(type);
{
out.setHead(attrib->readType<int>(("head")));
out.setBody(attrib->readType<int>(("body")));
out.setLegs(attrib->readType<int>(("legs")));
out.setFeet(attrib->readType<int>(("feet")));
out.setAddons(attrib->readType<int>(("addons")));
out.setMount(attrib->readType<int>(("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;
}

View File

@ -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())

View File

@ -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;

View File

@ -27,6 +27,7 @@
#include <framework/core/declarations.h>
#include <framework/luaengine/luaobject.h>
#include <framework/xml/tinyxml.h>
#include <framework/util/attribstorage.h>
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<uint16>(OtbAttribServerId); }
uint16 getClientId() { return m_attribs.get<uint16>(OtbAttribClientId); }
OtbCategory getCategory() { return m_category; }
std::string getName() { return m_attribs.get<std::string>(OtbAttribName); }
std::string getDesc() { return m_attribs.get<std::string>(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<true> m_null;
AttribStorage m_attribs;
};
#endif