New lightweight minimap format, finish #15
This commit is contained in:
parent
cf0ecf418d
commit
e81dd31ae3
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,19 +46,32 @@ 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;
|
||||||
|
|
||||||
|
@ -90,7 +80,6 @@ void MinimapBlock::updateTile(int x, int y, const MinimapTile& 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()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue