Fixed bug with adding Vip from console or map, who is already on viplist.

This commit is contained in:
Kamil 2012-07-09 08:59:16 +02:00 committed by niczkx
parent c8d9833444
commit 8f492f7e06
14 changed files with 226 additions and 225 deletions

View File

@ -45,7 +45,7 @@ if g_resources.fileExists("/otclientrc.lua") then
dofile("/otclientrc.lua") dofile("/otclientrc.lua")
end end
--g_things.loadOtb("/items.otb") g_things.loadOtb("/items.otb")
--g_map.loadOtbm("/forgotten.otbm") g_map.loadOtbm("/forgotten.otbm")

View File

@ -31,3 +31,10 @@ function Player:isPartySharedExperienceActive()
shield == ShieldBlueNoSharedExpBlink or shield == ShieldBlueNoSharedExpBlink or
shield == ShieldBlueNoSharedExp) shield == ShieldBlueNoSharedExp)
end 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

View File

@ -403,7 +403,9 @@ function Console.popupMenu(mousePos, mouseButton, creatureName, text)
if creatureName then if creatureName then
if creatureName ~= g_game.getCharacterName() then if creatureName ~= g_game.getCharacterName() then
menu:addOption(tr('Message to ' .. creatureName), function () g_game.openPrivateChannel(creatureName) end) 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 -- TODO ignore creatureName
menu:addSeparator() menu:addSeparator()
end end

View File

@ -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('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 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 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 localPlayerShield = localPlayer:asCreature():getShield()
local creatureShield = creatureThing:getShield() local creatureShield = creatureThing:getShield()

View File

@ -60,7 +60,7 @@ void BinaryTree::seek(uint pos)
uint8 BinaryTree::getU8() uint8 BinaryTree::getU8()
{ {
if(m_pos+1 > m_buffer.size()) if (m_pos+1 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU8 failed"); stdext::throw_exception("BinaryTree: getU8 failed");
uint8 v = m_buffer[m_pos]; uint8 v = m_buffer[m_pos];
m_pos += 1; m_pos += 1;
@ -69,7 +69,7 @@ uint8 BinaryTree::getU8()
uint16 BinaryTree::getU16() uint16 BinaryTree::getU16()
{ {
if(m_pos+2 > m_buffer.size()) if (m_pos+2 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU16 failed"); stdext::throw_exception("BinaryTree: getU16 failed");
uint16 v = stdext::readLE16(&m_buffer[m_pos]); uint16 v = stdext::readLE16(&m_buffer[m_pos]);
m_pos += 2; m_pos += 2;
@ -78,7 +78,7 @@ uint16 BinaryTree::getU16()
uint32 BinaryTree::getU32() uint32 BinaryTree::getU32()
{ {
if(m_pos+4 > m_buffer.size()) if (m_pos+4 > m_buffer.size())
stdext::throw_exception("BinaryTree: getU32 failed"); stdext::throw_exception("BinaryTree: getU32 failed");
uint32 v = stdext::readLE32(&m_buffer[m_pos]); uint32 v = stdext::readLE32(&m_buffer[m_pos]);
m_pos += 4; m_pos += 4;
@ -87,8 +87,8 @@ uint32 BinaryTree::getU32()
uint64 BinaryTree::getU64() uint64 BinaryTree::getU64()
{ {
if(m_pos+8 > m_buffer.size()) if (m_pos+8 > m_buffer.size())
stdext::throw_exception("BinaryTree: getu64 failed"); stdext::throw_exception("BinaryTree: getU64 failed");
uint64 v = stdext::readLE64(&m_buffer[m_pos]); uint64 v = stdext::readLE64(&m_buffer[m_pos]);
m_pos += 8; m_pos += 8;
return v; return v;
@ -98,7 +98,10 @@ std::string BinaryTree::getString()
{ {
uint16 len = getU16(); uint16 len = getU16();
if (len == 0 || len > 8192) 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); std::string ret((char *)&m_buffer[m_pos], len);
m_pos += len; m_pos += len;

View File

@ -63,4 +63,8 @@
// boost utilities // boost utilities
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
// tiny XML
#define TIXML_USE_STL
#include <framework/thirdparty/tinyxml.h>
#endif #endif

View File

@ -74,6 +74,10 @@ SET(otclient_SOURCES ${otclient_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/core/thingtypeotb.h ${CMAKE_CURRENT_LIST_DIR}/core/thingtypeotb.h
${CMAKE_CURRENT_LIST_DIR}/core/tile.cpp ${CMAKE_CURRENT_LIST_DIR}/core/tile.cpp
${CMAKE_CURRENT_LIST_DIR}/core/tile.h ${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 # lua
${CMAKE_CURRENT_LIST_DIR}/luascript/luavaluecasts.cpp ${CMAKE_CURRENT_LIST_DIR}/luascript/luavaluecasts.cpp

View File

@ -43,6 +43,8 @@ class AnimatedText;
class StaticText; class StaticText;
class ThingTypeDat; class ThingTypeDat;
class ThingTypeOtb; class ThingTypeOtb;
class House;
class Town;
typedef std::shared_ptr<MapView> MapViewPtr; typedef std::shared_ptr<MapView> MapViewPtr;
typedef std::shared_ptr<Tile> TilePtr; typedef std::shared_ptr<Tile> TilePtr;
@ -60,9 +62,13 @@ typedef std::shared_ptr<AnimatedText> AnimatedTextPtr;
typedef std::shared_ptr<StaticText> StaticTextPtr; typedef std::shared_ptr<StaticText> StaticTextPtr;
typedef std::shared_ptr<ThingTypeDat> ThingTypeDatPtr; typedef std::shared_ptr<ThingTypeDat> ThingTypeDatPtr;
typedef std::shared_ptr<ThingTypeOtb> ThingTypeOtbPtr; typedef std::shared_ptr<ThingTypeOtb> ThingTypeOtbPtr;
typedef std::shared_ptr<House> HousePtr;
typedef std::shared_ptr<Town> TownPtr;
typedef std::vector<ThingPtr> ThingList; typedef std::vector<ThingPtr> ThingList;
typedef std::vector<ThingTypeDatPtr> ThingTypeDatList; typedef std::vector<ThingTypeDatPtr> ThingTypeDatList;
typedef std::vector<ThingTypeOtbPtr> ThingTypeOtbList; typedef std::vector<ThingTypeOtbPtr> ThingTypeOtbList;
typedef std::vector<HousePtr> HouseList;
typedef std::vector<TownPtr> TownList;
#endif #endif

View File

@ -45,14 +45,14 @@ Item::Item() :
ItemPtr Item::create(int id) ItemPtr Item::create(int id)
{ {
ItemPtr item = ItemPtr(new Item); ItemPtr item(new Item);
item->setId(id); item->setId(id);
return item; return item;
} }
ItemPtr Item::createFromOtb(int id) ItemPtr Item::createFromOtb(int id)
{ {
ItemPtr item = ItemPtr(new Item); ItemPtr item(new Item);
item->setOtbId(id); item->setOtbId(id);
return item; return item;
} }
@ -204,70 +204,71 @@ bool Item::isValid()
return g_things.isValidDatId(m_id, DatItemCategory); return g_things.isValidDatId(m_id, DatItemCategory);
} }
bool Item::unserializeAttr(const BinaryTreePtr &fin) void Item::unserializeItem(const BinaryTreePtr &in)
{ {
uint8 attrType; // Yet another TODO.
while ((attrType = fin->getU8()) != 0) while (in->canRead()) {
readAttr((AttrTypes_t)attrType, fin); uint8 attrType = in->getU8();
if (attrType == 0)
break;
return true; switch ((AttrTypes_t)attrType) {
} case ATTR_COUNT:
setSubType(in->getU8());
void Item::readAttr(AttrTypes_t attrType, const BinaryTreePtr &fin) break;
{ case ATTR_CHARGES:
switch (attrType) { setSubType(in->getU16());
case ATTR_COUNT: break;
setSubType(fin->getU8()); case ATTR_ACTION_ID:
break; setActionId(in->getU16());
case ATTR_ACTION_ID: break;
setActionId(fin->getU16()); case ATTR_UNIQUE_ID:
break; setUniqueId(in->getU16());
case ATTR_UNIQUE_ID: break;
setUniqueId(fin->getU16()); case ATTR_NAME:
break; setName(in->getString());
case ATTR_NAME: break;
setName(fin->getString()); case ATTR_ARTICLE: // ?
break; case ATTR_WRITTENBY:
case ATTR_ARTICLE: case ATTR_DESC:
fin->getString(); in->getString();
case ATTR_ATTACK: // \/ not needed. break;
case ATTR_EXTRAATTACK: case ATTR_ATTACK:
case ATTR_DEFENSE: case ATTR_EXTRAATTACK:
case ATTR_EXTRADEFENSE: case ATTR_DEFENSE:
case ATTR_ARMOR: case ATTR_EXTRADEFENSE:
case ATTR_ATTACKSPEED: case ATTR_ARMOR:
case ATTR_HPPITCHANCE: case ATTR_ATTACKSPEED:
case ATTR_DURATION: case ATTR_HITCHANCE:
fin->getU32(); case ATTR_DURATION:
break; case ATTR_WRITTENDATE:
case ATTR_SCRIPTPROTECTED: case ATTR_SLEEPERGUID:
case ATTR_DUALWIELD: case ATTR_SLEEPSTART:
case ATTR_DECAYING_STATE: case ATTR_CONTAINER_ITEMS:
case ATTR_HPPOUSEDOORID: case ATTR_ATTRIBUTE_MAP:
fin->getU8(); in->skip(4);
break; break;
case ATTR_TEXT: case ATTR_SCRIPTPROTECTED:
setText(fin->getString()); case ATTR_DUALWIELD:
break; case ATTR_DECAYING_STATE:
case ATTR_WRITTENDATE: case ATTR_HOUSEDOORID:
fin->getU32(); case ATTR_RUNE_CHARGES:
break; in->skip(1);
case ATTR_WRITTENBY: break;
fin->getString(); case ATTR_TEXT:
break; setText(in->getString());
case ATTR_DESC: break;
setDescription(fin->getString()); case ATTR_DEPOT_ID:
break; in->skip(2); // trolol
case ATTR_RUNE_CHARGES: break;
fin->getU8(); case ATTR_TELE_DEST:
break; {
case ATTR_TELE_DEST: // Teleport should read that. Position pos(in->getU16(), in->getU16(), in->getU8());
case ATTR_SLEEPERGUID: // Bed should read that. break;
case ATTR_SLEEPSTART: }
case ATTR_CONTAINER_ITEMS: default:
case ATTR_ATTRIBUTE_MAP: stdext::throw_exception(stdext::format("invalid item attribute %d", (int)attrType));
default: }
break;
} }
} }

View File

@ -29,8 +29,6 @@
enum AttrTypes_t { enum AttrTypes_t {
ATTR_END = 0, ATTR_END = 0,
//ATTR_DESCRIPTION = 1,
//ATTR_EXT_FILE = 2,
ATTR_TILE_FLAGS = 3, ATTR_TILE_FLAGS = 3,
ATTR_ACTION_ID = 4, ATTR_ACTION_ID = 4,
ATTR_UNIQUE_ID = 5, ATTR_UNIQUE_ID = 5,
@ -39,10 +37,8 @@ enum AttrTypes_t {
ATTR_TELE_DEST = 8, ATTR_TELE_DEST = 8,
ATTR_ITEM = 9, ATTR_ITEM = 9,
ATTR_DEPOT_ID = 10, ATTR_DEPOT_ID = 10,
//ATTR_EXT_SPAWN_FILE = 11,
ATTR_RUNE_CHARGES = 12, ATTR_RUNE_CHARGES = 12,
//ATTR_EXT_HPPOUSE_FILE = 13, ATTR_HOUSEDOORID = 14,
ATTR_HPPOUSEDOORID = 14,
ATTR_COUNT = 15, ATTR_COUNT = 15,
ATTR_DURATION = 16, ATTR_DURATION = 16,
ATTR_DECAYING_STATE = 17, ATTR_DECAYING_STATE = 17,
@ -60,7 +56,7 @@ enum AttrTypes_t {
ATTR_EXTRADEFENSE = 36, ATTR_EXTRADEFENSE = 36,
ATTR_ARMOR = 37, ATTR_ARMOR = 37,
ATTR_ATTACKSPEED = 38, ATTR_ATTACKSPEED = 38,
ATTR_HPPITCHANCE = 39, ATTR_HITCHANCE = 39,
ATTR_SHOOTRANGE = 40, ATTR_SHOOTRANGE = 40,
ATTR_ARTICLE = 41, ATTR_ARTICLE = 41,
ATTR_SCRIPTPROTECTED = 42, ATTR_SCRIPTPROTECTED = 42,
@ -100,10 +96,7 @@ public:
ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); } ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); }
bool isItem() { return true; } bool isItem() { return true; }
// TODO: These should be abstract and declared in i.e containers, doors, etc. void unserializeItem(const BinaryTreePtr &in);
bool unserializeAttr(const BinaryTreePtr &fin);
bool unserializeItemNode(const BinaryTreePtr &fin) { return unserializeAttr(fin); }
void readAttr(AttrTypes_t attrType, const BinaryTreePtr &fin);
bool isMoveable(); bool isMoveable();
private: private:

View File

@ -27,12 +27,14 @@
#include "item.h" #include "item.h"
#include "missile.h" #include "missile.h"
#include "statictext.h" #include "statictext.h"
#include "houses.h"
#include "towns.h"
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
#include "mapview.h" #include "mapview.h"
#include <framework/core/resourcemanager.h> #include <framework/core/resourcemanager.h>
#include <framework/core/filestream.h> #include <framework/core/filestream.h>
#include <framework/core/binarytree.h> #include <framework/core/binarytree.h>
Map g_map; Map g_map;
@ -59,67 +61,61 @@ void Map::notificateTileUpdateToMapViews(const Position& pos)
mapView->onTileUpdate(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); FileStreamPtr fin = g_resources.openFile(fileName);
if (!fin) { if (!fin)
g_logger.error(stdext::format("Unable to load map '%s'", fileName)); stdext::throw_exception(stdext::format("Unable to load map '%s'", fileName));
return false;
}
if (!g_things.isOtbLoaded()/* || !g_things.isXmlLoaded()*/) { fin->cache();
g_logger.error("OTB and XML are not loaded yet to load a map."); if (!g_things.isOtbLoaded())
return false; 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(); 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(); uint32 headerVersion = root->getU32();
dump << headerVersion; if (!headerVersion || headerVersion > 3)
if (!headerVersion || headerVersion > 3) { stdext::throw_exception(stdext::format("Unknown OTBM version detected: %u.", headerVersion));
g_logger.error("Unknown OTBM version detected.");
return false; uint16 w = root->getU16(), h = root->getU16();
} dump << "Map size: " << w << "x" << h;
root->skip(1); // ??
uint32 headerMajorItems = root->getU8(); uint32 headerMajorItems = root->getU8();
dump << headerMajorItems; if (headerMajorItems < 3)
dump << "major: " << g_things.getOtbMajorVersion(); stdext::throw_exception(stdext::format("This map needs to be upgraded. read %d what it's supposed to be: %u",
if (headerMajorItems < 3) { headerMajorItems, g_things.getOtbMajorVersion()));
g_logger.error("This map needs to be upgraded.");
return false;
}
if (headerMajorItems > g_things.getOtbMajorVersion()) { if (headerMajorItems > g_things.getOtbMajorVersion())
g_logger.error("This map was saved with different OTB version."); stdext::throw_exception(stdext::format("This map was saved with different OTB version. read %d what it's supposed to be: %d",
return false; headerMajorItems, g_things.getOtbMajorVersion()));
}
root->skip(1); /// ?? root->skip(3);
uint32 headerMinorItems = root->getU8(); uint32 headerMinorItems = root->getU32();
dump << headerMinorItems;
dump << "minor: " << g_things.getOtbMinorVersion();
if (headerMinorItems > g_things.getOtbMinorVersion()) 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]; BinaryTreePtr node = root->getChildren()[0];
if (node->getU8() != OTBM_MAP_DATA) { if (node->getU8() != OTBM_MAP_DATA)
g_logger.error("Could not read data node."); stdext::throw_exception("Could not read root data node");
return false;
}
std::string tmp; Boolean<true> first;
uint8 attribute;
while (node->canRead()) { while (node->canRead()) {
attribute = node->getU8(); uint8 attribute = node->getU8();
tmp = node->getString(); std::string tmp = node->getString();
switch (attribute) { switch (attribute) {
case OTBM_ATTR_DESCRIPTION: case OTBM_ATTR_DESCRIPTION:
if (!m_description.empty()) if (first) {
m_description += "\n" + tmp; first = false;
else
m_description = tmp; m_description = tmp;
} else {
m_description += "\n" + tmp;
}
break; break;
case OTBM_ATTR_SPAWN_FILE: case OTBM_ATTR_SPAWN_FILE:
m_spawnFile = fileName.substr(0, fileName.rfind('/') + 1) + tmp; 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; m_houseFile = fileName.substr(0, fileName.rfind('/') + 1) + tmp;
break; break;
default: default:
g_logger.error(stdext::format("Invalid attribute '%c'", attribute)); stdext::throw_exception(stdext::format("Invalid attribute '%c'", attribute));
break;
} }
} }
dump << m_description;
dump << m_houseFile;
dump << m_spawnFile;
for (const BinaryTreePtr &nodeMapData : node->getChildren()) { for (const BinaryTreePtr &nodeMapData : node->getChildren()) {
uint8 mapDataType = nodeMapData->getU8(); uint8 mapDataType = nodeMapData->getU8();
dump << "mapData: " << (int)mapDataType;
if (mapDataType == OTBM_TILE_AREA) { if (mapDataType == OTBM_TILE_AREA) {
dump << "Tile: reading pos...";
uint16 baseX = nodeMapData->getU16(), baseY = nodeMapData->getU16(); uint16 baseX = nodeMapData->getU16(), baseY = nodeMapData->getU16();
uint8 pz = nodeMapData->getU8(); uint8 pz = nodeMapData->getU8();
for (const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) { for (const BinaryTreePtr &nodeTile : nodeMapData->getChildren()) {
uint8 type = nodeTile->getU8(); uint8 type = nodeTile->getU8();
if (type == OTBM_TILE || type == OTBM_HOUSETILE) { if (type == OTBM_TILE || type == OTBM_HOUSETILE) {
TilePtr tile = 0; TilePtr tile = nullptr;
ItemPtr ground = 0; ItemPtr ground = nullptr;
HousePtr house = nullptr;
uint32 flags = 0; 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); Position pos(px, py, pz);
// TODO: Houses.
if (type == OTBM_HOUSETILE) { if (type == OTBM_HOUSETILE) {
uint32 hId = nodeTile->getU32(); uint32 hId = nodeTile->getU32();
tile = createTile(pos); 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()) { while (nodeTile->canRead()) {
tileAttr = nodeTile->getU8(); uint8 tileAttr = nodeTile->getU8();
switch (tileAttr) { switch (tileAttr) {
case OTBM_ATTR_TILE_FLAGS: { case OTBM_ATTR_TILE_FLAGS: {
uint32 _flags = nodeTile->getU32(); 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) if ((_flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT)
flags |= TILESTATE_PROTECTIONZONE; flags |= TILESTATE_NOLOGOUT;
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) if ((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH)
flags |= TILESTATE_NOLOGOUT; flags |= TILESTATE_REFRESH;
if ((_flags & TILESTATE_REFRESH) == TILESTATE_REFRESH) break;
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;
} }
case OTBM_ATTR_ITEM: {
if (tile) { ItemPtr item = Item::createFromOtb(nodeTile->getU16());
tile->addThing(item); if (tile)
} else if (item->isGround()) { tile->addThing(item);
ground = item; else if (item->isGround())
} else { ground = item;
tile = createTile(pos); else {
tile->addThing(ground); tile = createTile(pos, ground);
tile->addThing(item); tile->addThing(item);
}
break;
} }
} default: { default:
g_logger.error(stdext::format("invalid tile attribute at pos %d, %d, %d", px, py, pz)); stdext::throw_exception(stdext::format("invalid tile attribute %d at pos %d, %d, %d",
return false; (int)tileAttr, px, py, pz));
}
} }
} }
for (const BinaryTreePtr &nodeItem : nodeTile->getChildren()) { for (const BinaryTreePtr &nodeItem : nodeTile->getChildren()) {
if (nodeItem->getU8() == OTBM_ITEM) { if (nodeItem->getU8() == OTBM_ITEM) {
ItemPtr item = Item::createFromOtb(nodeItem->getU16()); ItemPtr item = Item::createFromOtb(nodeItem->getU16());
if (!item) { item->unserializeItem(nodeItem);
g_logger.error(stdext::format("failed to create new item at pos %d, %d, %d", px, py, pz)); if (house && item->isMoveable()) {
return false; g_logger.warning(stdext::format("Moveable item found in house: %d at pos %d %d %d", item->getId(),
} px, py, pz));
item = nullptr;
if (item->unserializeItemNode(nodeItem)) { } else if (tile) {
if (/* house && */item->isMoveable()) { tile->addThing(item);
g_logger.warning(stdext::format("Moveable item found in house: %d at pos %d %d %d", item->getId(), } else if (item->isGround()) {
px, py, pz)); ground = item;
item = nullptr;
} else if (tile) {
tile->addThing(item);
} else if (item->isGround()) {
ground = item;
} else {
tile = createTile(pos);
tile->addThing(ground);
tile->addThing(item);
}
} else { } else {
g_logger.error(stdext::format("failed to unserialize item with %d at pos %d %d %d", item->getId(), tile = createTile(pos, ground);
px, py, pz)); tile->addThing(item);
return false;
} }
} else { } else
g_logger.error(stdext::format("Unknown item node type %d", type)); stdext::throw_exception("Unknown item node");
return false;
}
} }
if (!tile) { if (!tile)
tile = createTile(pos); tile = createTile(pos, ground);
tile->addThing(ground);
}
tile->setFlags((tileflags_t)flags); tile->setFlags((tileflags_t)flags);
} else { } else
g_logger.error(stdext::format("Unknown tile node type %d", type)); stdext::throw_exception(stdext::format("Unknown tile node type %d", type));
return false;
}
} }
} else if (mapDataType == OTBM_TOWNS) { } else if (mapDataType == OTBM_TOWNS) {
TownPtr town = nullptr;
for (const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) { for (const BinaryTreePtr &nodeTown : nodeMapData->getChildren()) {
if (nodeTown->getU8() == OTBM_TOWN) { if (nodeTown->getU8() == OTBM_TOWN) {
uint32 townId = nodeTown->getU32(); uint32 townId = nodeTown->getU32();
std::string townName = nodeTown->getString(); std::string townName = nodeTown->getString();
Position townCoords(nodeTown->getU16(), nodeTown->getU16(), nodeTown->getU8()); Position townCoords(nodeTown->getU16(), nodeTown->getU16(), nodeTown->getU8());
if (!(town = g_towns.getTown(townId)))
town = TownPtr(new Town(townId, townName, townCoords));
} else } else
return false; stdext::throw_exception("invalid town node");
} }
} else if (mapDataType == OTBM_WAYPOINTS && headerVersion > 1) { } else if (mapDataType == OTBM_WAYPOINTS && headerVersion > 1) {
for (const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) { for (const BinaryTreePtr &nodeWaypoint : nodeMapData->getChildren()) {
if (nodeWaypoint->getU8() == OTBM_WAYPOINT) { if (nodeWaypoint->getU8() == OTBM_WAYPOINT) {
std::string name = nodeWaypoint->getString(); std::string name = nodeWaypoint->getString();
Position waypointPos(nodeWaypoint->getU16(), nodeWaypoint->getU16(), nodeWaypoint->getU8()); 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 } else
return false; stdext::throw_exception("Unknown map data node");
} }
// TODO: Load house & spawns. g_logger.debug("OTBM read successfully.");
return true; fin->close();
/// TODO read XML Stuff (houses & spawns).
} }
bool Map::loadOtcm(const std::string& fileName) bool Map::loadOtcm(const std::string& fileName)
@ -300,7 +275,7 @@ bool Map::loadOtcm(const std::string& fileName)
fin->getString(); // world name fin->getString(); // world name
if(datSignature != g_things.getDatSignature()) 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; break;
} }
@ -417,6 +392,7 @@ void Map::clean()
{ {
cleanDynamicThings(); cleanDynamicThings();
m_tiles.clear(); m_tiles.clear();
m_waypoints.clear();
} }
void Map::cleanDynamicThings() void Map::cleanDynamicThings()
@ -538,9 +514,12 @@ bool Map::removeThingByPos(const Position& pos, int stackPos)
return false; return false;
} }
TilePtr Map::createTile(const Position& pos) TilePtr Map::createTile(const Position& pos, const ItemPtr &g)
{ {
TilePtr tile = TilePtr(new Tile(pos)); TilePtr tile = TilePtr(new Tile(pos));
if (g)
tile->addThing(g);
m_tiles[pos] = tile; m_tiles[pos] = tile;
return tile; return tile;
} }

View File

@ -42,7 +42,7 @@ enum OTBM_AttrTypes_t
OTBM_ATTR_SPAWN_FILE = 11, OTBM_ATTR_SPAWN_FILE = 11,
OTBM_ATTR_RUNE_CHARGES = 12, OTBM_ATTR_RUNE_CHARGES = 12,
OTBM_ATTR_HOUSE_FILE = 13, OTBM_ATTR_HOUSE_FILE = 13,
OTBM_ATTR_HPPOUSEDOORID = 14, OTBM_ATTR_HOUSEDOORID = 14,
OTBM_ATTR_COUNT = 15, OTBM_ATTR_COUNT = 15,
OTBM_ATTR_DURATION = 16, OTBM_ATTR_DURATION = 16,
OTBM_ATTR_DECAYING_STATE = 17, OTBM_ATTR_DECAYING_STATE = 17,
@ -77,7 +77,7 @@ enum OTBM_NodeTypes_t
enum { enum {
OTCM_SIGNATURE = 0x4D43544F, OTCM_SIGNATURE = 0x4D43544F,
OTCM_VERSION = 1, OTCM_VERSION = 1
}; };
//@bindsingleton g_map //@bindsingleton g_map
@ -93,7 +93,7 @@ public:
bool loadOtcm(const std::string& fileName); bool loadOtcm(const std::string& fileName);
void saveOtcm(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 saveOtbm(const std::string& fileName);
void clean(); void clean();
@ -106,7 +106,7 @@ public:
bool removeThingByPos(const Position& pos, int stackPos); bool removeThingByPos(const Position& pos, int stackPos);
// tile related // tile related
TilePtr createTile(const Position& pos); TilePtr createTile(const Position& pos, const ItemPtr &g = nullptr);
const TilePtr& getTile(const Position& pos); const TilePtr& getTile(const Position& pos);
TilePtr getOrCreateTile(const Position& pos); TilePtr getOrCreateTile(const Position& pos);
void cleanTile(const Position& pos); void cleanTile(const Position& pos);
@ -146,6 +146,7 @@ private:
std::vector<AnimatedTextPtr> m_animatedTexts; std::vector<AnimatedTextPtr> m_animatedTexts;
std::vector<StaticTextPtr> m_staticTexts; std::vector<StaticTextPtr> m_staticTexts;
std::vector<MapViewPtr> m_mapViews; std::vector<MapViewPtr> m_mapViews;
std::unordered_map<Position, std::string, PositionHasher> m_waypoints;
Light m_light; Light m_light;
Position m_centralPosition; Position m_centralPosition;

View File

@ -30,9 +30,6 @@
#include <framework/core/filestream.h> #include <framework/core/filestream.h>
#include <framework/core/binarytree.h> #include <framework/core/binarytree.h>
#define TIXML_USE_STL // use STL strings instead.
#include <framework/thirdparty/tinyxml.h>
ThingTypeManager g_things; ThingTypeManager g_things;
void ThingTypeManager::init() void ThingTypeManager::init()
@ -112,9 +109,11 @@ bool ThingTypeManager::loadOtb(const std::string& file)
root->getU32(); // build number root->getU32(); // build number
root->skip(128); // description root->skip(128); // description
m_otbTypes.resize(root->getChildren().size(), m_nullOtbType);
for(const BinaryTreePtr& node : root->getChildren()) { for(const BinaryTreePtr& node : root->getChildren()) {
ThingTypeOtbPtr otbType(new ThingTypeOtb); ThingTypeOtbPtr otbType(new ThingTypeOtb);
otbType->unserialize(node); otbType->unserialize(node);
addOtbType(otbType);
} }
m_otbLoaded = true; m_otbLoaded = true;

View File

@ -33,7 +33,7 @@ enum tileflags_t
TILESTATE_TRASHED = 1 << 1, TILESTATE_TRASHED = 1 << 1,
TILESTATE_OPTIONALZONE = 1 << 2, TILESTATE_OPTIONALZONE = 1 << 2,
TILESTATE_NOLOGOUT = 1 << 3, TILESTATE_NOLOGOUT = 1 << 3,
TILESTATE_HPPARDCOREZONE = 1 << 4, TILESTATE_HARDCOREZONE = 1 << 4,
TILESTATE_REFRESH = 1 << 5, TILESTATE_REFRESH = 1 << 5,
// internal usage // internal usage