New lightweight minimap format, finish #15

This commit is contained in:
Eduardo Bart 2013-01-27 14:06:47 -02:00
parent cf0ecf418d
commit e81dd31ae3
14 changed files with 261 additions and 124 deletions

View File

@ -530,7 +530,10 @@ function processChannelTabMenu(tab, mousePos, mouseButton)
--menu:addOption(tr('Show Server Messages'), function() --[[TODO]] end) --menu:addOption(tr('Show Server Messages'), function() --[[TODO]] end)
menu:addSeparator() menu:addSeparator()
end end
menu:addOption(tr('Clear Messages'), function() clearChannel(consoleTabBar) end)
if consoleTabBar:getCurrentTab() == tab then
menu:addOption(tr('Clear Messages'), function() clearChannel(consoleTabBar) end)
end
--menu:addOption(tr('Save Messages'), function() --[[TODO]] end) --menu:addOption(tr('Save Messages'), function() --[[TODO]] end)
menu:display(mousePos) menu:display(mousePos)

View File

@ -551,9 +551,8 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
player:stopAutoWalk() player:stopAutoWalk()
if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then
if not player:autoWalk(autoWalkPos) then player.onAutoWalkFail = function() modules.game_textmessage.displayStatusMessage(tr('There is no way.')) end
modules.game_textmessage.displayStatusMessage(tr('There is no way.')) player:autoWalk(autoWalkPos)
end
return true return true
end end

View File

@ -6,7 +6,7 @@ navigating = false
minimapWidget = nil minimapWidget = nil
minimapButton = nil minimapButton = nil
minimapWindow = nil minimapWindow = nil
otmm = false
flagsPanel = nil flagsPanel = nil
flagWindow = nil flagWindow = nil
nextFlagId = 0 nextFlagId = 0
@ -49,6 +49,7 @@ function init()
reset() reset()
minimapWindow:setup() minimapWindow:setup()
loadMapFlags() loadMapFlags()
useOTMM()
if g_game.isOnline() then if g_game.isOnline() then
addEvent(function() updateMapFlags() end) addEvent(function() updateMapFlags() end)
@ -263,17 +264,32 @@ end
function loadMap() function loadMap()
local protocolVersion = g_game.getProtocolVersion() local protocolVersion = g_game.getProtocolVersion()
local minimapFile = '/minimap_' .. protocolVersion .. '.otcm' g_map.clean()
if g_resources.fileExists(minimapFile) then g_minimap.clean()
g_map.clean()
g_map.loadOtcm(minimapFile) if otmm then
local minimapFile = '/minimap.otmm'
if g_resources.fileExists(minimapFile) then
g_minimap.loadOtmm(minimapFile)
end
else
local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
if g_resources.fileExists(minimapFile) then
g_map.loadOtcm(minimapFile)
end
end end
end end
function saveMap() function saveMap()
local protocolVersion = g_game.getProtocolVersion() local protocolVersion = g_game.getProtocolVersion()
local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
g_map.saveOtcm(minimapFile) if otmm then
local minimapFile = '/minimap.otmm'
g_minimap.saveOtmm(minimapFile)
else
local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
g_map.saveOtcm(minimapFile)
end
end end
function toggle() function toggle()
@ -286,6 +302,10 @@ function toggle()
end end
end end
function useOTMM()
otmm = true
end
function isClickInRange(position, fromPosition, toPosition) function isClickInRange(position, fromPosition, toPosition)
return (position.x >= fromPosition.x and position.y >= fromPosition.y and position.x <= toPosition.x and position.y <= toPosition.y) return (position.x >= fromPosition.x and position.y >= fromPosition.y and position.x <= toPosition.x and position.y <= toPosition.y)
end end

View File

@ -363,11 +363,10 @@ namespace Otc
}; };
enum PathFindFlags { enum PathFindFlags {
PathFindAllowNullTiles = 1, PathFindAllowNotSeenTiles = 1,
PathFindAllowCreatures = 2, PathFindAllowCreatures = 2,
PathFindAllowNonPathable = 4, PathFindAllowNonPathable = 4,
PathFindAllowNonWalkable = 8, PathFindAllowNonWalkable = 8
PathFindAllowChangeFloor = 16
}; };
enum AutomapFlags enum AutomapFlags

View File

@ -193,9 +193,11 @@ bool LocalPlayer::autoWalk(const Position& destination)
limitedPath.resize(127); limitedPath.resize(127);
} else { } else {
// no known path found, try to discover one // no known path found, try to discover one
result = g_map.findPath(m_position, destination, 1000, Otc::PathFindAllowNullTiles); result = g_map.findPath(m_position, destination, 1000, Otc::PathFindAllowNotSeenTiles);
if(std::get<1>(result) != Otc::PathFindResultOk) if(std::get<1>(result) != Otc::PathFindResultOk) {
callLuaField("onAutoWalkFail");
return false; return false;
}
Position currentPos = m_position; Position currentPos = m_position;
for(auto dir : std::get<0>(result)) { for(auto dir : std::get<0>(result)) {

View File

@ -36,6 +36,7 @@
#include "player.h" #include "player.h"
#include "localplayer.h" #include "localplayer.h"
#include "map.h" #include "map.h"
#include "minimap.h"
#include "thingtypemanager.h" #include "thingtypemanager.h"
#include "spritemanager.h" #include "spritemanager.h"
#include "shadermanager.h" #include "shadermanager.h"
@ -116,7 +117,12 @@ void Client::registerLuaFunctions()
g_lua.bindSingletonFunction("g_map", "getSpawnFile", &Map::getSpawnFile, &g_map); g_lua.bindSingletonFunction("g_map", "getSpawnFile", &Map::getSpawnFile, &g_map);
g_lua.bindSingletonFunction("g_map", "setSpawnFile", &Map::setSpawnFile, &g_map); g_lua.bindSingletonFunction("g_map", "setSpawnFile", &Map::setSpawnFile, &g_map);
g_lua.bindSingletonFunction("g_map", "createTile", &Map::createTile, &g_map); g_lua.bindSingletonFunction("g_map", "createTile", &Map::createTile, &g_map);
g_lua.bindSingletonFunction("g_map", "getSize", &Map::getSize, &g_map);; g_lua.bindSingletonFunction("g_map", "getSize", &Map::getSize, &g_map);
g_lua.registerSingletonClass("g_minimap");
g_lua.bindSingletonFunction("g_minimap", "clean", &Minimap::clean, &g_minimap);
g_lua.bindSingletonFunction("g_minimap", "loadOtmm", &Minimap::loadOtmm, &g_minimap);
g_lua.bindSingletonFunction("g_minimap", "saveOtmm", &Minimap::saveOtmm, &g_minimap);
g_lua.registerSingletonClass("g_creatures"); g_lua.registerSingletonClass("g_creatures");
g_lua.bindSingletonFunction("g_creatures", "getCreatures", &CreatureManager::getCreatures, &g_creatures); g_lua.bindSingletonFunction("g_creatures", "getCreatures", &CreatureManager::getCreatures, &g_creatures);

View File

@ -600,27 +600,39 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
if(i == 0 && j == 0) if(i == 0 && j == 0)
continue; continue;
bool wasSeen = false;
bool hasCreature = false;
bool isNotWalkable = true;
bool isNotPathable = true;
int speed = 100;
Position neighborPos = currentNode->pos.translated(i, j); Position neighborPos = currentNode->pos.translated(i, j);
const TilePtr& tile = getTile(neighborPos); if(g_map.isAwareOfPosition(neighborPos)) {
wasSeen = true;
if(const TilePtr& tile = getTile(neighborPos)) {
hasCreature = tile->hasCreature();
isNotWalkable = !tile->isWalkable();
isNotPathable = !tile->isPathable();
speed = tile->getGroundSpeed();
}
} else {
const MinimapTile& mtile = g_minimap.getTile(neighborPos);
wasSeen = mtile.hasFlag(MinimapTileWasSeen);
isNotWalkable = mtile.hasFlag(MinimapTileNotWalkable);
isNotPathable = mtile.hasFlag(MinimapTileNotPathable);
speed = mtile.getSpeed();
}
float walkFactor = 0; float walkFactor = 0;
if(neighborPos != goalPos) { if(neighborPos != goalPos) {
/* if(!(flags & Otc::PathFindAllowNotSeenTiles) && !wasSeen)
Known Issue with Otc::PathFindAllowNullTiles flag:
If you are above ground floor this will attempt to path over null
tiles, need to rework this for "fly servers" and blank map click,
but it is breaking normal path finding.
*/
if(!(flags & Otc::PathFindAllowNullTiles) && (!tile || tile->isEmpty()))
continue; continue;
if(tile) { if(wasSeen) {
if(!(flags & Otc::PathFindAllowCreatures) && tile->hasCreature()) if(!(flags & Otc::PathFindAllowCreatures) && hasCreature)
continue; continue;
if(!(flags & Otc::PathFindAllowNonPathable) && !tile->isPathable()) if(!(flags & Otc::PathFindAllowNonPathable) && isNotPathable)
continue; continue;
if(!(flags & Otc::PathFindAllowNonWalkable) && !tile->isWalkable()) if(!(flags & Otc::PathFindAllowNonWalkable) && isNotWalkable)
continue;
if(!(flags & Otc::PathFindAllowChangeFloor) && tile->changesFloor())
continue; continue;
} }
} }
@ -631,8 +643,7 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
else else
walkFactor += 1.0f; walkFactor += 1.0f;
int groundSpeed = tile ? tile->getGroundSpeed() : 100; float cost = currentNode->cost + (speed * walkFactor) / 100.0f;
float cost = currentNode->cost + (groundSpeed * walkFactor) / 100.0f;
Node *neighborNode; Node *neighborNode;
if(nodes.find(neighborPos) == nodes.end()) { if(nodes.find(neighborPos) == nodes.end()) {

View File

@ -382,7 +382,6 @@ bool Map::loadOtcm(const std::string& fileName)
if(!fin) if(!fin)
stdext::throw_exception("unable to open file"); stdext::throw_exception("unable to open file");
stdext::timer loadTimer;
fin->cache(); fin->cache();
uint32 signature = fin->getU32(); uint32 signature = fin->getU32();
@ -446,8 +445,6 @@ bool Map::loadOtcm(const std::string& fileName)
fin->close(); fin->close();
// well, this is really slow
g_logger.debug(stdext::format("Otcm load time: %.2f seconds", loadTimer.elapsed_seconds()));
return true; return true;
} catch(stdext::exception& e) { } catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to load OTCM map: %s", e.what())); g_logger.error(stdext::format("failed to load OTCM map: %s", e.what()));
@ -519,7 +516,6 @@ void Map::saveOtcm(const std::string& fileName)
fin->flush(); fin->flush();
fin->close(); fin->close();
//g_logger.debug(stdext::format("Otcm save time: %.2f seconds", saveTimer.elapsed_seconds()));
} catch(stdext::exception& e) { } catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to save OTCM map: %s", e.what())); g_logger.error(stdext::format("failed to save OTCM map: %s", e.what()));
} }

View File

@ -27,40 +27,17 @@
#include <framework/graphics/texture.h> #include <framework/graphics/texture.h>
#include <framework/graphics/painter.h> #include <framework/graphics/painter.h>
#include <framework/graphics/framebuffermanager.h> #include <framework/graphics/framebuffermanager.h>
#include <framework/core/resourcemanager.h>
#include <framework/core/filestream.h>
#include <boost/concept_check.hpp> #include <boost/concept_check.hpp>
#include <zlib.h>
Minimap g_minimap; Minimap g_minimap;
void MinimapBlock::updateImage()
{
if(!m_image)
m_image = ImagePtr(new Image(Size(MMBLOCK_SIZE, MMBLOCK_SIZE)));
else
m_image->resize(Size(MMBLOCK_SIZE, MMBLOCK_SIZE));
for(int x=0;x<MMBLOCK_SIZE;++x)
for(int y=0;y<MMBLOCK_SIZE;++y)
m_image->setPixel(x, y, Color::from8bit(getTile(x, y).color).rgba());
}
void MinimapBlock::updateTexture()
{
if(!m_image)
return;
if(!m_texture) {
m_texture = TexturePtr(new Texture(m_image, true));
} else {
m_texture->uploadPixels(m_image, true);
}
}
void MinimapBlock::clean() void MinimapBlock::clean()
{ {
m_tiles.fill(MinimapTile()); m_tiles.fill(MinimapTile());
m_image.reset();
m_texture.reset(); m_texture.reset();
m_shouldDraw = false;
m_mustUpdate = false; m_mustUpdate = false;
} }
@ -69,28 +46,40 @@ void MinimapBlock::update()
if(!m_mustUpdate) if(!m_mustUpdate)
return; return;
if(m_shouldDraw) { ImagePtr image(new Image(Size(MMBLOCK_SIZE, MMBLOCK_SIZE)));
updateImage();
updateTexture(); bool shouldDraw = false;
for(int x=0;x<MMBLOCK_SIZE;++x) {
for(int y=0;y<MMBLOCK_SIZE;++y) {
uint32 col = Color::from8bit(getTile(x, y).color).rgba();
image->setPixel(x, y, col);
if(col != 0)
shouldDraw = true;
}
} }
if(shouldDraw) {
if(!m_texture) {
m_texture = TexturePtr(new Texture(image, true));
} else {
m_texture->uploadPixels(image, true);
}
} else
m_texture.reset();
m_mustUpdate = false; m_mustUpdate = false;
} }
void MinimapBlock::updateTile(int x, int y, const MinimapTile& tile) void MinimapBlock::updateTile(int x, int y, const MinimapTile& tile)
{ {
if(tile.color != 0)
m_shouldDraw = true;
if(m_tiles[getTileIndex(x,y)].color != tile.color) if(m_tiles[getTileIndex(x,y)].color != tile.color)
m_mustUpdate = true; m_mustUpdate = true;
m_tiles[getTileIndex(x,y)] = tile; m_tiles[getTileIndex(x,y)] = tile;
} }
void Minimap::init() void Minimap::init()
{ {
} }
void Minimap::terminate() void Minimap::terminate()
@ -141,13 +130,17 @@ void Minimap::draw(const Rect& screenRect, const Position& mapCenter, float scal
if(x < 0 || x >= 65536 - MMBLOCK_SIZE) if(x < 0 || x >= 65536 - MMBLOCK_SIZE)
continue; continue;
Position blockPos(x, y, mapCenter.z);
if(!hasBlock(blockPos))
continue;
MinimapBlock& block = getBlock(Position(x, y, mapCenter.z)); MinimapBlock& block = getBlock(Position(x, y, mapCenter.z));
block.update(); block.update();
if(block.shouldDraw()) { const TexturePtr& tex = block.getTexture();
if(tex) {
Rect src(0, 0, MMBLOCK_SIZE, MMBLOCK_SIZE); Rect src(0, 0, MMBLOCK_SIZE, MMBLOCK_SIZE);
Rect dest(Point(xs,ys), src.size() * scale); Rect dest(Point(xs,ys), src.size() * scale);
const TexturePtr& tex = block.getTexture();
tex->setSmooth(scale < 1.0f); tex->setSmooth(scale < 1.0f);
g_painter->drawTexturedRect(dest, tex, src); g_painter->drawTexturedRect(dest, tex, src);
@ -186,36 +179,151 @@ Position Minimap::getPosition(const Point& point, const Rect& screenRect, const
void Minimap::updateTile(const Position& pos, const TilePtr& tile) void Minimap::updateTile(const Position& pos, const TilePtr& tile)
{ {
MinimapBlock& block = getBlock(pos);
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
MinimapTile minimapTile; MinimapTile minimapTile;
if(tile) { if(tile) {
minimapTile.color = tile->getMinimapColorByte(); minimapTile.color = tile->getMinimapColorByte();
if(tile->isWalkable()) minimapTile.flags |= MinimapTileWasSeen;
minimapTile.flags |= MinimapTileWalkable; if(!tile->isWalkable(true))
if(tile->isPathable()) minimapTile.flags |= MinimapTileNotWalkable;
minimapTile.flags |= MinimapTilePathable; if(!tile->isPathable())
if(tile->changesFloor()) minimapTile.flags |= MinimapTileNotPathable;
minimapTile.flags |= MinimapTileChangesFloor; minimapTile.speed = std::min((int)std::ceil(tile->getGroundSpeed() / 10.0f), 255);
} }
block.updateTile(pos.x - offsetPos.x, pos.y - offsetPos.y, minimapTile); if(minimapTile != MinimapTile()) {
MinimapBlock& block = getBlock(pos);
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
block.updateTile(pos.x - offsetPos.x, pos.y - offsetPos.y, minimapTile);
}
} }
bool Minimap::checkTileProperty(const Position& pos, int flags) const MinimapTile& Minimap::getTile(const Position& pos)
{ {
MinimapBlock& block = getBlock(pos); static MinimapTile nulltile;
Point offsetPos = getBlockOffset(Point(pos.x, pos.y)); if(pos.z <= Otc::MAX_Z && hasBlock(pos)) {
return block.getTile(pos.x - offsetPos.x, pos.y - offsetPos.y).flags & flags; MinimapBlock& block = getBlock(pos);
Point offsetPos = getBlockOffset(Point(pos.x, pos.y));
return block.getTile(pos.x - offsetPos.x, pos.y - offsetPos.y);
}
return nulltile;
} }
void Minimap::loadOtmm(const std::string& fileName) bool Minimap::loadOtmm(const std::string& fileName)
{ {
try {
FileStreamPtr fin = g_resources.openFile(fileName);
if(!fin)
stdext::throw_exception("unable to open file");
fin->cache();
uint32 signature = fin->getU32();
if(signature != OTMM_SIGNATURE)
stdext::throw_exception("invalid OTMM file");
uint16 start = fin->getU16();
uint16 version = fin->getU16();
fin->getU32(); // flags
switch(version) {
case 1: {
fin->getString(); // description
break;
}
default:
stdext::throw_exception("OTMM version not supported");
}
fin->seek(start);
uint blockSize = MMBLOCK_SIZE * MMBLOCK_SIZE * sizeof(MinimapTile);
std::vector<uchar> compressBuffer(compressBound(blockSize));
while(true) {
Position pos;
pos.x = fin->getU16();
pos.y = fin->getU16();
pos.z = fin->getU8();
// end of file
if(!pos.isValid())
break;
MinimapBlock& block = getBlock(pos);
ulong len = fin->getU16();
ulong destLen = blockSize;
fin->read(compressBuffer.data(), len);
int ret = uncompress((uchar*)&block.getTiles(), &destLen, compressBuffer.data(), len);
assert(ret == Z_OK);
assert(destLen == blockSize);
block.mustUpdate();
}
fin->close();
return true;
} catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to load OTMM minimap: %s", e.what()));
return false;
}
} }
void Minimap::saveOtmm(const std::string& fileName) void Minimap::saveOtmm(const std::string& fileName)
{ {
try {
stdext::timer saveTimer;
FileStreamPtr fin = g_resources.createFile(fileName);
fin->cache();
//TODO: compression flag with zlib
uint32 flags = 0;
// header
fin->addU32(OTMM_SIGNATURE);
fin->addU16(0); // data start, will be overwritten later
fin->addU16(OTMM_VERSION);
fin->addU32(flags);
// version 1 header
fin->addString("OTMM 1.0"); // description
// go back and rewrite where the map data starts
uint32 start = fin->tell();
fin->seek(4);
fin->addU16(start);
fin->seek(start);
uint blockSize = MMBLOCK_SIZE * MMBLOCK_SIZE * sizeof(MinimapTile);
std::vector<uchar> compressBuffer(compressBound(blockSize));
const int COMPRESS_LEVEL = 3;
for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) {
for(auto& it : m_tileBlocks[z]) {
int index = it.first;
MinimapBlock& block = it.second;
Position pos = getIndexPosition(index, z);
fin->addU16(pos.x);
fin->addU16(pos.y);
fin->addU8(pos.z);
ulong len = blockSize;
int ret = compress2(compressBuffer.data(), &len, (uchar*)&block.getTiles(), blockSize, COMPRESS_LEVEL);
assert(ret == Z_OK);
fin->addU16(len);
fin->write(compressBuffer.data(), len);
}
}
// end of file
Position invalidPos;
fin->addU16(invalidPos.x);
fin->addU16(invalidPos.y);
fin->addU8(invalidPos.z);
fin->flush();
fin->close();
} catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to save OTMM minimap: %s", e.what()));
}
} }

View File

@ -28,31 +28,33 @@
#include <framework/graphics/declarations.h> #include <framework/graphics/declarations.h>
enum { enum {
MMBLOCK_SIZE = 64 MMBLOCK_SIZE = 64,
OTMM_SIGNATURE = 0x4D4d544F,
OTMM_VERSION = 1
}; };
enum MinimapTileFlags { enum MinimapTileFlags {
MinimapTilePathable = 1, MinimapTileWasSeen = 1,
MinimapTileWalkable = 2, MinimapTileNotPathable = 2,
MinimapTileChangesFloor = 4 MinimapTileNotWalkable = 4
}; };
#pragma pack(push,1) // disable memory alignment #pragma pack(push,1) // disable memory alignment
struct MinimapTile struct MinimapTile
{ {
MinimapTile() : flags(0), color(0) { } MinimapTile() : flags(0), color(0), speed(100) { }
uint8 flags; uint8 flags;
uint8 color; uint8 color;
uint8 speed;
bool operator==(const MinimapTile& other) { return color == other.color && flags == other.flags; } bool hasFlag(MinimapTileFlags flag) const { return flags & flag; }
int getSpeed() const { return speed * 10; }
bool operator==(const MinimapTile& other) const { return color == other.color && flags == other.flags && speed == other.speed; }
bool operator!=(const MinimapTile& other) const { return !(*this == other); }
}; };
#pragma pack(pop)
class MinimapBlock class MinimapBlock
{ {
public: public:
void updateImage();
void updateTexture();
void clean(); void clean();
void update(); void update();
void updateTile(int x, int y, const MinimapTile& tile); void updateTile(int x, int y, const MinimapTile& tile);
@ -60,17 +62,16 @@ public:
void resetTile(int x, int y) { m_tiles[getTileIndex(x,y)] = MinimapTile(); } void resetTile(int x, int y) { m_tiles[getTileIndex(x,y)] = MinimapTile(); }
uint getTileIndex(int x, int y) { return ((y % MMBLOCK_SIZE) * MMBLOCK_SIZE) + (x % MMBLOCK_SIZE); } uint getTileIndex(int x, int y) { return ((y % MMBLOCK_SIZE) * MMBLOCK_SIZE) + (x % MMBLOCK_SIZE); }
const TexturePtr& getTexture() { return m_texture; } const TexturePtr& getTexture() { return m_texture; }
std::array<MinimapTile, MMBLOCK_SIZE *MMBLOCK_SIZE> getTiles() { return m_tiles; } std::array<MinimapTile, MMBLOCK_SIZE *MMBLOCK_SIZE>& getTiles() { return m_tiles; }
bool shouldDraw() { return m_shouldDraw; } void mustUpdate() { m_mustUpdate = true; }
private: private:
ImagePtr m_image;
TexturePtr m_texture; TexturePtr m_texture;
stdext::boolean<false> m_shouldDraw;
std::array<MinimapTile, MMBLOCK_SIZE *MMBLOCK_SIZE> m_tiles; std::array<MinimapTile, MMBLOCK_SIZE *MMBLOCK_SIZE> m_tiles;
stdext::boolean<true> m_mustUpdate; stdext::boolean<true> m_mustUpdate;
}; };
#pragma pack(pop)
class Minimap class Minimap
{ {
@ -84,15 +85,18 @@ public:
Position getPosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale); Position getPosition(const Point& point, const Rect& screenRect, const Position& mapCenter, float scale);
void updateTile(const Position& pos, const TilePtr& tile); void updateTile(const Position& pos, const TilePtr& tile);
bool checkTileProperty(const Position& pos, int flags); const MinimapTile& getTile(const Position& pos);
void loadOtmm(const std::string& fileName); bool loadOtmm(const std::string& fileName);
void saveOtmm(const std::string& fileName); void saveOtmm(const std::string& fileName);
private: private:
bool hasBlock(const Position& pos) { return m_tileBlocks[pos.z].find(getBlockIndex(pos)) != m_tileBlocks[pos.z].end(); }
MinimapBlock& getBlock(const Position& pos) { return m_tileBlocks[pos.z][getBlockIndex(pos)]; } MinimapBlock& getBlock(const Position& pos) { return m_tileBlocks[pos.z][getBlockIndex(pos)]; }
Point getBlockOffset(const Point& pos) { return Point(pos.x - pos.x % MMBLOCK_SIZE, Point getBlockOffset(const Point& pos) { return Point(pos.x - pos.x % MMBLOCK_SIZE,
pos.y - pos.y % MMBLOCK_SIZE); } pos.y - pos.y % MMBLOCK_SIZE); }
Position getIndexPosition(int index, int z) { return Position((index % (65536 / MMBLOCK_SIZE))*MMBLOCK_SIZE,
(index / (65536 / MMBLOCK_SIZE))*MMBLOCK_SIZE, z); }
uint getBlockIndex(const Position& pos) { return ((pos.y / MMBLOCK_SIZE) * (65536 / MMBLOCK_SIZE)) + (pos.x / MMBLOCK_SIZE); } uint getBlockIndex(const Position& pos) { return ((pos.y / MMBLOCK_SIZE) * (65536 / MMBLOCK_SIZE)) + (pos.x / MMBLOCK_SIZE); }
std::unordered_map<uint, MinimapBlock> m_tileBlocks[Otc::MAX_Z+1]; std::unordered_map<uint, MinimapBlock> m_tileBlocks[Otc::MAX_Z+1];
}; };

View File

@ -563,7 +563,6 @@ void ProtocolGame::sendCloseRuleViolation(const std::string& reporter)
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientCloseRuleViolation); msg->addU8(Proto::ClientCloseRuleViolation);
msg->addString(reporter); msg->addString(reporter);
dump << "ProtocolGame::sendCloseRuleViolation" << reporter;
send(msg); send(msg);
} }
@ -571,7 +570,6 @@ void ProtocolGame::sendCancelRuleViolation()
{ {
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientCancelRuleViolation); msg->addU8(Proto::ClientCancelRuleViolation);
dump << "ProtocolGame::sendCancelRuleViolation";
send(msg); send(msg);
} }

View File

@ -72,7 +72,6 @@ bool ThingTypeManager::loadDat(std::string file)
m_datSignature = fin->getU32(); m_datSignature = fin->getU32();
int numThings[ThingLastCategory];
for(int category = 0; category < ThingLastCategory; ++category) { for(int category = 0; category < ThingLastCategory; ++category) {
int count = fin->getU16() + 1; int count = fin->getU16() + 1;
m_thingTypes[category].clear(); m_thingTypes[category].clear();

View File

@ -476,7 +476,7 @@ ThingPtr Tile::getTopMultiUseThing()
return m_things[0]; return m_things[0];
} }
bool Tile::isWalkable() bool Tile::isWalkable(bool ignoreCreatures)
{ {
if(!getGround()) if(!getGround())
return false; return false;
@ -485,24 +485,17 @@ bool Tile::isWalkable()
if(thing->isNotWalkable()) if(thing->isNotWalkable())
return false; return false;
if(thing->isCreature()) { if(!ignoreCreatures) {
CreaturePtr creature = thing->static_self_cast<Creature>(); if(thing->isCreature()) {
if(!creature->isPassable() && creature->canBeSeen()) CreaturePtr creature = thing->static_self_cast<Creature>();
return false; if(!creature->isPassable() && creature->canBeSeen())
return false;
}
} }
} }
return true; return true;
} }
bool Tile::changesFloor()
{
for(const ThingPtr& thing : m_things) {
if(thing->isTranslucent() || (thing->isOnBottom() && thing->hasElevation()))
return true;
}
return false;
}
bool Tile::isPathable() bool Tile::isPathable()
{ {
for(const ThingPtr& thing : m_things) { for(const ThingPtr& thing : m_things) {

View File

@ -94,8 +94,7 @@ public:
uint8 getMinimapColorByte(); uint8 getMinimapColorByte();
int getThingCount() { return m_things.size() + m_effects.size(); } int getThingCount() { return m_things.size() + m_effects.size(); }
bool isPathable(); bool isPathable();
bool isWalkable(); bool isWalkable(bool ignoreCreatures = false);
bool changesFloor();
bool isFullGround(); bool isFullGround();
bool isFullyOpaque(); bool isFullyOpaque();
bool isSingleDimension(); bool isSingleDimension();