diff --git a/init.lua b/init.lua index 0bc3469e..deddc3b5 100644 --- a/init.lua +++ b/init.lua @@ -45,7 +45,7 @@ if g_resources.fileExists("/otclientrc.lua") then dofile("/otclientrc.lua") end ---g_things.loadOtb("/items.otb") ---g_map.loadOtbm("/forgotten.otbm") +g_things.loadOtb("/items.otb") +g_map.loadOtbm("/forgotten.otbm") diff --git a/modules/game/player.lua b/modules/game/player.lua index 715729a5..8043d336 100644 --- a/modules/game/player.lua +++ b/modules/game/player.lua @@ -31,3 +31,10 @@ function Player:isPartySharedExperienceActive() shield == ShieldBlueNoSharedExpBlink or shield == ShieldBlueNoSharedExp) end + +function Player:hasVip(creatureName) + for id, vip in pairs(g_game.getVips()) do + if (vip[1] == creatureName) then return true end + end + return false +end diff --git a/modules/game_console/console.lua b/modules/game_console/console.lua index f2cb0785..f4acfb75 100644 --- a/modules/game_console/console.lua +++ b/modules/game_console/console.lua @@ -403,7 +403,9 @@ function Console.popupMenu(mousePos, mouseButton, creatureName, text) if creatureName then if creatureName ~= g_game.getCharacterName() then menu:addOption(tr('Message to ' .. creatureName), function () g_game.openPrivateChannel(creatureName) end) - menu:addOption(tr('Add to VIP list'), function () g_game.addVip(creatureName) end) --TODO not show if creature already in vip + if (not Player:hasVip(creatureName)) then + menu:addOption(tr('Add to VIP list'), function () g_game.addVip(creatureName) end) + end -- TODO ignore creatureName menu:addSeparator() end diff --git a/modules/game_interface/gameinterface.lua b/modules/game_interface/gameinterface.lua index 13a1c402..92f2e28d 100644 --- a/modules/game_interface/gameinterface.lua +++ b/modules/game_interface/gameinterface.lua @@ -263,7 +263,9 @@ function GameInterface.createThingMenu(menuPosition, lookThing, useThing, creatu menu:addOption(tr('Invite to private chat'), function() g_game.inviteToOwnChannel(creatureName) end) menu:addOption(tr('Exclude from private chat'), function() g_game.excludeFromOwnChannel(creatureName) end) -- [TODO] must be removed after message's popup labels been implemented end - menu:addOption(tr('Add to VIP list'), function() g_game.addVip(creatureName) end) + if (not Player:hasVip(creatureName)) then + menu:addOption(tr('Add to VIP list'), function() g_game.addVip(creatureName) end) + end local localPlayerShield = localPlayer:asCreature():getShield() local creatureShield = creatureThing:getShield() diff --git a/src/framework/core/binarytree.cpp b/src/framework/core/binarytree.cpp index 3ebfa452..7a4ff7b5 100644 --- a/src/framework/core/binarytree.cpp +++ b/src/framework/core/binarytree.cpp @@ -60,7 +60,7 @@ void BinaryTree::seek(uint pos) uint8 BinaryTree::getU8() { - if(m_pos+1 > m_buffer.size()) + if (m_pos+1 > m_buffer.size()) stdext::throw_exception("BinaryTree: getU8 failed"); uint8 v = m_buffer[m_pos]; m_pos += 1; @@ -69,7 +69,7 @@ uint8 BinaryTree::getU8() uint16 BinaryTree::getU16() { - if(m_pos+2 > m_buffer.size()) + if (m_pos+2 > m_buffer.size()) stdext::throw_exception("BinaryTree: getU16 failed"); uint16 v = stdext::readLE16(&m_buffer[m_pos]); m_pos += 2; @@ -78,7 +78,7 @@ uint16 BinaryTree::getU16() uint32 BinaryTree::getU32() { - if(m_pos+4 > m_buffer.size()) + if (m_pos+4 > m_buffer.size()) stdext::throw_exception("BinaryTree: getU32 failed"); uint32 v = stdext::readLE32(&m_buffer[m_pos]); m_pos += 4; @@ -87,8 +87,8 @@ uint32 BinaryTree::getU32() uint64 BinaryTree::getU64() { - if(m_pos+8 > m_buffer.size()) - stdext::throw_exception("BinaryTree: getu64 failed"); + if (m_pos+8 > m_buffer.size()) + stdext::throw_exception("BinaryTree: getU64 failed"); uint64 v = stdext::readLE64(&m_buffer[m_pos]); m_pos += 8; return v; @@ -98,7 +98,10 @@ std::string BinaryTree::getString() { uint16 len = getU16(); if (len == 0 || len > 8192) - stdext::throw_exception("failed to get string from binary tree - invalid size read."); + stdext::throw_exception("BinaryTree: getString failed: invalid or too large string length"); + + if (m_pos+len > m_buffer.size()) + stdext::throw_exception("BinaryTree: getString failed: string length exceeded buffer size."); std::string ret((char *)&m_buffer[m_pos], len); m_pos += len; diff --git a/src/framework/pch.h b/src/framework/pch.h index e167b528..a27c02ee 100644 --- a/src/framework/pch.h +++ b/src/framework/pch.h @@ -63,4 +63,8 @@ // boost utilities #include +// tiny XML +#define TIXML_USE_STL +#include + #endif diff --git a/src/otclient/CMakeLists.txt b/src/otclient/CMakeLists.txt index 693778bf..dde44a03 100644 --- a/src/otclient/CMakeLists.txt +++ b/src/otclient/CMakeLists.txt @@ -74,6 +74,10 @@ SET(otclient_SOURCES ${otclient_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/core/thingtypeotb.h ${CMAKE_CURRENT_LIST_DIR}/core/tile.cpp ${CMAKE_CURRENT_LIST_DIR}/core/tile.h + ${CMAKE_CURRENT_LIST_DIR}/core/houses.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/houses.h + ${CMAKE_CURRENT_LIST_DIR}/core/towns.cpp + ${CMAKE_CURRENT_LIST_DIR}/core/towns.h # lua ${CMAKE_CURRENT_LIST_DIR}/luascript/luavaluecasts.cpp diff --git a/src/otclient/core/declarations.h b/src/otclient/core/declarations.h index 78dd4ccb..a03083de 100644 --- a/src/otclient/core/declarations.h +++ b/src/otclient/core/declarations.h @@ -43,6 +43,8 @@ class AnimatedText; class StaticText; class ThingTypeDat; class ThingTypeOtb; +class House; +class Town; typedef std::shared_ptr MapViewPtr; typedef std::shared_ptr TilePtr; @@ -60,9 +62,13 @@ typedef std::shared_ptr AnimatedTextPtr; typedef std::shared_ptr StaticTextPtr; typedef std::shared_ptr ThingTypeDatPtr; typedef std::shared_ptr ThingTypeOtbPtr; +typedef std::shared_ptr HousePtr; +typedef std::shared_ptr TownPtr; typedef std::vector ThingList; typedef std::vector ThingTypeDatList; typedef std::vector ThingTypeOtbList; +typedef std::vector HouseList; +typedef std::vector TownList; #endif diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index df5799fb..c9fbc41f 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -45,14 +45,14 @@ Item::Item() : ItemPtr Item::create(int id) { - ItemPtr item = ItemPtr(new Item); + ItemPtr item(new Item); item->setId(id); return item; } ItemPtr Item::createFromOtb(int id) { - ItemPtr item = ItemPtr(new Item); + ItemPtr item(new Item); item->setOtbId(id); return item; } @@ -204,70 +204,71 @@ bool Item::isValid() return g_things.isValidDatId(m_id, DatItemCategory); } -bool Item::unserializeAttr(const BinaryTreePtr &fin) +void Item::unserializeItem(const BinaryTreePtr &in) { - uint8 attrType; - while ((attrType = fin->getU8()) != 0) - readAttr((AttrTypes_t)attrType, fin); + // Yet another TODO. + while (in->canRead()) { + uint8 attrType = in->getU8(); + if (attrType == 0) + break; - return true; -} - -void Item::readAttr(AttrTypes_t attrType, const BinaryTreePtr &fin) -{ - switch (attrType) { - case ATTR_COUNT: - setSubType(fin->getU8()); - break; - case ATTR_ACTION_ID: - setActionId(fin->getU16()); - break; - case ATTR_UNIQUE_ID: - setUniqueId(fin->getU16()); - break; - case ATTR_NAME: - setName(fin->getString()); - break; - case ATTR_ARTICLE: - fin->getString(); - case ATTR_ATTACK: // \/ not needed. - case ATTR_EXTRAATTACK: - case ATTR_DEFENSE: - case ATTR_EXTRADEFENSE: - case ATTR_ARMOR: - case ATTR_ATTACKSPEED: - case ATTR_HPPITCHANCE: - case ATTR_DURATION: - fin->getU32(); - break; - case ATTR_SCRIPTPROTECTED: - case ATTR_DUALWIELD: - case ATTR_DECAYING_STATE: - case ATTR_HPPOUSEDOORID: - fin->getU8(); - break; - case ATTR_TEXT: - setText(fin->getString()); - break; - case ATTR_WRITTENDATE: - fin->getU32(); - break; - case ATTR_WRITTENBY: - fin->getString(); - break; - case ATTR_DESC: - setDescription(fin->getString()); - break; - case ATTR_RUNE_CHARGES: - fin->getU8(); - break; - case ATTR_TELE_DEST: // Teleport should read that. - case ATTR_SLEEPERGUID: // Bed should read that. - case ATTR_SLEEPSTART: - case ATTR_CONTAINER_ITEMS: - case ATTR_ATTRIBUTE_MAP: - default: - break; + switch ((AttrTypes_t)attrType) { + case ATTR_COUNT: + setSubType(in->getU8()); + break; + case ATTR_CHARGES: + setSubType(in->getU16()); + break; + case ATTR_ACTION_ID: + setActionId(in->getU16()); + break; + case ATTR_UNIQUE_ID: + setUniqueId(in->getU16()); + break; + case ATTR_NAME: + setName(in->getString()); + break; + case ATTR_ARTICLE: // ? + case ATTR_WRITTENBY: + case ATTR_DESC: + in->getString(); + break; + case ATTR_ATTACK: + case ATTR_EXTRAATTACK: + case ATTR_DEFENSE: + case ATTR_EXTRADEFENSE: + case ATTR_ARMOR: + case ATTR_ATTACKSPEED: + case ATTR_HITCHANCE: + case ATTR_DURATION: + case ATTR_WRITTENDATE: + case ATTR_SLEEPERGUID: + case ATTR_SLEEPSTART: + case ATTR_CONTAINER_ITEMS: + case ATTR_ATTRIBUTE_MAP: + in->skip(4); + break; + case ATTR_SCRIPTPROTECTED: + case ATTR_DUALWIELD: + case ATTR_DECAYING_STATE: + case ATTR_HOUSEDOORID: + case ATTR_RUNE_CHARGES: + in->skip(1); + break; + case ATTR_TEXT: + setText(in->getString()); + break; + case ATTR_DEPOT_ID: + in->skip(2); // trolol + break; + case ATTR_TELE_DEST: + { + Position pos(in->getU16(), in->getU16(), in->getU8()); + break; + } + default: + stdext::throw_exception(stdext::format("invalid item attribute %d", (int)attrType)); + } } } diff --git a/src/otclient/core/item.h b/src/otclient/core/item.h index a66997dd..6263f1db 100644 --- a/src/otclient/core/item.h +++ b/src/otclient/core/item.h @@ -29,8 +29,6 @@ enum AttrTypes_t { ATTR_END = 0, - //ATTR_DESCRIPTION = 1, - //ATTR_EXT_FILE = 2, ATTR_TILE_FLAGS = 3, ATTR_ACTION_ID = 4, ATTR_UNIQUE_ID = 5, @@ -39,10 +37,8 @@ enum AttrTypes_t { ATTR_TELE_DEST = 8, ATTR_ITEM = 9, ATTR_DEPOT_ID = 10, - //ATTR_EXT_SPAWN_FILE = 11, ATTR_RUNE_CHARGES = 12, - //ATTR_EXT_HPPOUSE_FILE = 13, - ATTR_HPPOUSEDOORID = 14, + ATTR_HOUSEDOORID = 14, ATTR_COUNT = 15, ATTR_DURATION = 16, ATTR_DECAYING_STATE = 17, @@ -60,7 +56,7 @@ enum AttrTypes_t { ATTR_EXTRADEFENSE = 36, ATTR_ARMOR = 37, ATTR_ATTACKSPEED = 38, - ATTR_HPPITCHANCE = 39, + ATTR_HITCHANCE = 39, ATTR_SHOOTRANGE = 40, ATTR_ARTICLE = 41, ATTR_SCRIPTPROTECTED = 42, @@ -100,10 +96,7 @@ public: ItemPtr asItem() { return std::static_pointer_cast(shared_from_this()); } bool isItem() { return true; } - // TODO: These should be abstract and declared in i.e containers, doors, etc. - bool unserializeAttr(const BinaryTreePtr &fin); - bool unserializeItemNode(const BinaryTreePtr &fin) { return unserializeAttr(fin); } - void readAttr(AttrTypes_t attrType, const BinaryTreePtr &fin); + void unserializeItem(const BinaryTreePtr &in); bool isMoveable(); private: diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index bcdb37ab..20c5b96f 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -27,12 +27,14 @@ #include "item.h" #include "missile.h" #include "statictext.h" +#include "houses.h" +#include "towns.h" #include #include "mapview.h" #include #include -#include +#include Map g_map; @@ -59,67 +61,61 @@ void Map::notificateTileUpdateToMapViews(const Position& pos) mapView->onTileUpdate(pos); } -bool Map::loadOtbm(const std::string& fileName) +void Map::loadOtbm(const std::string& fileName, bool /*display*/) { FileStreamPtr fin = g_resources.openFile(fileName); - if (!fin) { - g_logger.error(stdext::format("Unable to load map '%s'", fileName)); - return false; - } + if (!fin) + stdext::throw_exception(stdext::format("Unable to load map '%s'", fileName)); - if (!g_things.isOtbLoaded()/* || !g_things.isXmlLoaded()*/) { - g_logger.error("OTB and XML are not loaded yet to load a map."); - return false; - } + fin->cache(); + if (!g_things.isOtbLoaded()) + stdext::throw_exception("OTB isn't loaded yet to load a map."); + + if (fin->getU32()) + stdext::throw_exception("Unknown file version detected"); - assert(fin->getU32() == 0); BinaryTreePtr root = fin->getBinaryTree(); - root->skip(1); // Not sure, what exactly that is... perhaps node type? + if (root->getU8() != 0) + stdext::throw_exception("could not read root property!"); + uint32 headerVersion = root->getU32(); - dump << headerVersion; - if (!headerVersion || headerVersion > 3) { - g_logger.error("Unknown OTBM version detected."); - return false; - } + if (!headerVersion || headerVersion > 3) + stdext::throw_exception(stdext::format("Unknown OTBM version detected: %u.", headerVersion)); + + uint16 w = root->getU16(), h = root->getU16(); + dump << "Map size: " << w << "x" << h; - root->skip(1); // ?? uint32 headerMajorItems = root->getU8(); - dump << headerMajorItems; - dump << "major: " << g_things.getOtbMajorVersion(); - if (headerMajorItems < 3) { - g_logger.error("This map needs to be upgraded."); - return false; - } + if (headerMajorItems < 3) + stdext::throw_exception(stdext::format("This map needs to be upgraded. read %d what it's supposed to be: %u", + headerMajorItems, g_things.getOtbMajorVersion())); - if (headerMajorItems > g_things.getOtbMajorVersion()) { - g_logger.error("This map was saved with different OTB version."); - return false; - } + if (headerMajorItems > g_things.getOtbMajorVersion()) + stdext::throw_exception(stdext::format("This map was saved with different OTB version. read %d what it's supposed to be: %d", + headerMajorItems, g_things.getOtbMajorVersion())); - root->skip(1); /// ?? - uint32 headerMinorItems = root->getU8(); - dump << headerMinorItems; - dump << "minor: " << g_things.getOtbMinorVersion(); + root->skip(3); + uint32 headerMinorItems = root->getU32(); if (headerMinorItems > g_things.getOtbMinorVersion()) - g_logger.warning("This map needs an updated OTB."); + g_logger.warning(stdext::format("This map needs an updated OTB. read %d what it's supposed to be: %d", + headerMinorItems, g_things.getOtbMinorVersion())); BinaryTreePtr node = root->getChildren()[0]; - if (node->getU8() != OTBM_MAP_DATA) { - g_logger.error("Could not read data node."); - return false; - } + if (node->getU8() != OTBM_MAP_DATA) + stdext::throw_exception("Could not read root data node"); - std::string tmp; - uint8 attribute; + Boolean first; while (node->canRead()) { - attribute = node->getU8(); - tmp = node->getString(); + uint8 attribute = node->getU8(); + std::string tmp = node->getString(); switch (attribute) { case OTBM_ATTR_DESCRIPTION: - if (!m_description.empty()) - m_description += "\n" + tmp; - else + if (first) { + first = false; m_description = tmp; + } else { + m_description += "\n" + tmp; + } break; case OTBM_ATTR_SPAWN_FILE: m_spawnFile = fileName.substr(0, fileName.rfind('/') + 1) + tmp; @@ -128,151 +124,130 @@ bool Map::loadOtbm(const std::string& fileName) m_houseFile = fileName.substr(0, fileName.rfind('/') + 1) + tmp; break; default: - g_logger.error(stdext::format("Invalid attribute '%c'", attribute)); - break; + stdext::throw_exception(stdext::format("Invalid attribute '%c'", attribute)); } } - dump << m_description; - dump << m_houseFile; - dump << m_spawnFile; - for (const BinaryTreePtr &nodeMapData : node->getChildren()) { uint8 mapDataType = nodeMapData->getU8(); - dump << "mapData: " << (int)mapDataType; if (mapDataType == OTBM_TILE_AREA) { - dump << "Tile: reading pos..."; uint16 baseX = nodeMapData->getU16(), baseY = nodeMapData->getU16(); uint8 pz = nodeMapData->getU8(); for (const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) { uint8 type = nodeTile->getU8(); if (type == OTBM_TILE || type == OTBM_HOUSETILE) { - TilePtr tile = 0; - ItemPtr ground = 0; + TilePtr tile = nullptr; + ItemPtr ground = nullptr; + HousePtr house = nullptr; uint32 flags = 0; - uint16 px = baseX + nodeTile->getU16(), py = baseY + nodeTile->getU16(); + uint16 px = baseX + nodeTile->getU8(), py = baseY + nodeTile->getU8(); Position pos(px, py, pz); - // TODO: Houses. if (type == OTBM_HOUSETILE) { uint32 hId = nodeTile->getU32(); - tile = createTile(pos); - // TODO: add it to house. + if (!(house = g_houses.getHouse(hId))) + house = HousePtr(new House(hId)); + house->setTile(tile); } - uint8 tileAttr; while (nodeTile->canRead()) { - tileAttr = nodeTile->getU8(); + uint8 tileAttr = nodeTile->getU8(); switch (tileAttr) { - case OTBM_ATTR_TILE_FLAGS: { - uint32 _flags = nodeTile->getU32(); + case OTBM_ATTR_TILE_FLAGS: { + uint32 _flags = nodeTile->getU32(); + if ((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) + flags |= TILESTATE_PROTECTIONZONE; + else if ((_flags & TILESTATE_OPTIONALZONE) == TILESTATE_OPTIONALZONE) + flags |= TILESTATE_OPTIONALZONE; + else if ((_flags & TILESTATE_HARDCOREZONE) == TILESTATE_HARDCOREZONE) + flags |= TILESTATE_HARDCOREZONE; - if ((_flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) - flags |= TILESTATE_PROTECTIONZONE; - else if ((_flags & TILESTATE_OPTIONALZONE) == TILESTATE_OPTIONALZONE) - flags |= TILESTATE_OPTIONALZONE; - else if ((_flags & TILESTATE_HPPARDCOREZONE) == TILESTATE_HPPARDCOREZONE) - flags |= TILESTATE_HPPARDCOREZONE; + if ((_flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT) + flags |= TILESTATE_NOLOGOUT; - if ((_flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT) - flags |= TILESTATE_NOLOGOUT; + if ((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH) + flags |= TILESTATE_REFRESH; - if ((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH) - flags |= TILESTATE_REFRESH; - break; - } case OTBM_ATTR_ITEM: { - ItemPtr item = Item::createFromOtb(nodeTile->getU16()); - if (!item) { - g_logger.error(stdext::format("failed to create new item at tile pos %d, %d, %d", px, py, pz)); - return false; + break; } - - if (tile) { - tile->addThing(item); - } else if (item->isGround()) { - ground = item; - } else { - tile = createTile(pos); - tile->addThing(ground); - tile->addThing(item); + case OTBM_ATTR_ITEM: { + ItemPtr item = Item::createFromOtb(nodeTile->getU16()); + if (tile) + tile->addThing(item); + else if (item->isGround()) + ground = item; + else { + tile = createTile(pos, ground); + tile->addThing(item); + } + break; } - } default: { - g_logger.error(stdext::format("invalid tile attribute at pos %d, %d, %d", px, py, pz)); - return false; - } + default: + stdext::throw_exception(stdext::format("invalid tile attribute %d at pos %d, %d, %d", + (int)tileAttr, px, py, pz)); } } for (const BinaryTreePtr &nodeItem : nodeTile->getChildren()) { if (nodeItem->getU8() == OTBM_ITEM) { ItemPtr item = Item::createFromOtb(nodeItem->getU16()); - if (!item) { - g_logger.error(stdext::format("failed to create new item at pos %d, %d, %d", px, py, pz)); - return false; - } - - if (item->unserializeItemNode(nodeItem)) { - if (/* house && */item->isMoveable()) { - g_logger.warning(stdext::format("Moveable item found in house: %d at pos %d %d %d", item->getId(), - px, py, pz)); - item = nullptr; - } else if (tile) { - tile->addThing(item); - } else if (item->isGround()) { - ground = item; - } else { - tile = createTile(pos); - tile->addThing(ground); - tile->addThing(item); - } + item->unserializeItem(nodeItem); + if (house && item->isMoveable()) { + g_logger.warning(stdext::format("Moveable item found in house: %d at pos %d %d %d", item->getId(), + px, py, pz)); + item = nullptr; + } else if (tile) { + tile->addThing(item); + } else if (item->isGround()) { + ground = item; } else { - g_logger.error(stdext::format("failed to unserialize item with %d at pos %d %d %d", item->getId(), - px, py, pz)); - return false; + tile = createTile(pos, ground); + tile->addThing(item); } - } else { - g_logger.error(stdext::format("Unknown item node type %d", type)); - return false; - } + } else + stdext::throw_exception("Unknown item node"); } - if (!tile) { - tile = createTile(pos); - tile->addThing(ground); - } + if (!tile) + tile = createTile(pos, ground); tile->setFlags((tileflags_t)flags); - } else { - g_logger.error(stdext::format("Unknown tile node type %d", type)); - return false; - } + } else + stdext::throw_exception(stdext::format("Unknown tile node type %d", type)); } } else if (mapDataType == OTBM_TOWNS) { + TownPtr town = nullptr; for (const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) { if (nodeTown->getU8() == OTBM_TOWN) { uint32 townId = nodeTown->getU32(); std::string townName = nodeTown->getString(); - Position townCoords(nodeTown->getU16(), nodeTown->getU16(), nodeTown->getU8()); + if (!(town = g_towns.getTown(townId))) + town = TownPtr(new Town(townId, townName, townCoords)); } else - return false; + stdext::throw_exception("invalid town node"); } } else if (mapDataType == OTBM_WAYPOINTS && headerVersion > 1) { for (const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) { if (nodeWaypoint->getU8() == OTBM_WAYPOINT) { std::string name = nodeWaypoint->getString(); Position waypointPos(nodeWaypoint->getU16(), nodeWaypoint->getU16(), nodeWaypoint->getU8()); - } + if (waypointPos.isValid() && !name.empty()) + m_waypoints.insert(std::make_pair(waypointPos, name)); + + } else + stdext::throw_exception("invalid waypoint node"); } } else - return false; + stdext::throw_exception("Unknown map data node"); } - // TODO: Load house & spawns. - return true; + g_logger.debug("OTBM read successfully."); + fin->close(); + /// TODO read XML Stuff (houses & spawns). } bool Map::loadOtcm(const std::string& fileName) @@ -300,7 +275,7 @@ bool Map::loadOtcm(const std::string& fileName) fin->getString(); // world name if(datSignature != g_things.getDatSignature()) - g_logger.warning("otcm map loaded is was created with a different dat signature"); + g_logger.warning("otcm map loaded was created with a different dat signature"); break; } @@ -417,6 +392,7 @@ void Map::clean() { cleanDynamicThings(); m_tiles.clear(); + m_waypoints.clear(); } void Map::cleanDynamicThings() @@ -538,9 +514,12 @@ bool Map::removeThingByPos(const Position& pos, int stackPos) return false; } -TilePtr Map::createTile(const Position& pos) +TilePtr Map::createTile(const Position& pos, const ItemPtr &g) { TilePtr tile = TilePtr(new Tile(pos)); + if (g) + tile->addThing(g); + m_tiles[pos] = tile; return tile; } diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index 029d6fe6..4b79ff91 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -42,7 +42,7 @@ enum OTBM_AttrTypes_t OTBM_ATTR_SPAWN_FILE = 11, OTBM_ATTR_RUNE_CHARGES = 12, OTBM_ATTR_HOUSE_FILE = 13, - OTBM_ATTR_HPPOUSEDOORID = 14, + OTBM_ATTR_HOUSEDOORID = 14, OTBM_ATTR_COUNT = 15, OTBM_ATTR_DURATION = 16, OTBM_ATTR_DECAYING_STATE = 17, @@ -77,7 +77,7 @@ enum OTBM_NodeTypes_t enum { OTCM_SIGNATURE = 0x4D43544F, - OTCM_VERSION = 1, + OTCM_VERSION = 1 }; //@bindsingleton g_map @@ -93,7 +93,7 @@ public: bool loadOtcm(const std::string& fileName); void saveOtcm(const std::string& fileName); - bool loadOtbm(const std::string& fileName); + void loadOtbm(const std::string& fileName, bool display = false/* temporary*/); //void saveOtbm(const std::string& fileName); void clean(); @@ -106,7 +106,7 @@ public: bool removeThingByPos(const Position& pos, int stackPos); // tile related - TilePtr createTile(const Position& pos); + TilePtr createTile(const Position& pos, const ItemPtr &g = nullptr); const TilePtr& getTile(const Position& pos); TilePtr getOrCreateTile(const Position& pos); void cleanTile(const Position& pos); @@ -146,6 +146,7 @@ private: std::vector m_animatedTexts; std::vector m_staticTexts; std::vector m_mapViews; + std::unordered_map m_waypoints; Light m_light; Position m_centralPosition; diff --git a/src/otclient/core/thingtypemanager.cpp b/src/otclient/core/thingtypemanager.cpp index 1ea9ad8f..6782076f 100644 --- a/src/otclient/core/thingtypemanager.cpp +++ b/src/otclient/core/thingtypemanager.cpp @@ -30,9 +30,6 @@ #include #include -#define TIXML_USE_STL // use STL strings instead. -#include - ThingTypeManager g_things; void ThingTypeManager::init() @@ -112,9 +109,11 @@ bool ThingTypeManager::loadOtb(const std::string& file) root->getU32(); // build number root->skip(128); // description + m_otbTypes.resize(root->getChildren().size(), m_nullOtbType); for(const BinaryTreePtr& node : root->getChildren()) { ThingTypeOtbPtr otbType(new ThingTypeOtb); otbType->unserialize(node); + addOtbType(otbType); } m_otbLoaded = true; diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index 586502d2..013f7e9e 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -33,7 +33,7 @@ enum tileflags_t TILESTATE_TRASHED = 1 << 1, TILESTATE_OPTIONALZONE = 1 << 2, TILESTATE_NOLOGOUT = 1 << 3, - TILESTATE_HPPARDCOREZONE = 1 << 4, + TILESTATE_HARDCOREZONE = 1 << 4, TILESTATE_REFRESH = 1 << 5, // internal usage