Fix issue #77 and improve findPath
This commit is contained in:
parent
3d7e80ea7a
commit
64d607b59e
|
@ -405,7 +405,7 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
|||
end
|
||||
|
||||
if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then
|
||||
local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), autoWalkPos, 127)
|
||||
local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), autoWalkPos, 127, PathFindFlags.AllowNullTiles)
|
||||
if #dirs == 0 then
|
||||
modules.game_textmessage.displayStatusMessage(tr('There is no way.'))
|
||||
return true
|
||||
|
|
|
@ -160,9 +160,9 @@ function onMinimapMouseRelease(self, mousePosition, mouseButton)
|
|||
navigating = false
|
||||
return
|
||||
end
|
||||
local tile = self:getTile(mousePosition)
|
||||
if tile and mouseButton == MouseLeftButton and self:isPressed() then
|
||||
local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), tile:getPosition(), 127)
|
||||
local pos = self:getPosition(mousePosition)
|
||||
if pos and mouseButton == MouseLeftButton and self:isPressed() then
|
||||
local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), pos, 127, PathFindFlags.AllowNullTiles)
|
||||
if #dirs == 0 then
|
||||
modules.game_textmessage.displayStatusMessage(tr('There is no way.'))
|
||||
return true
|
||||
|
|
|
@ -156,4 +156,19 @@ OsTypes = {
|
|||
OtclientMac = 12
|
||||
}
|
||||
|
||||
PathFindResults = {
|
||||
Ok = 0,
|
||||
Position = 1,
|
||||
Impossipble = 2,
|
||||
TooFar = 3,
|
||||
NoWay = 4
|
||||
}
|
||||
|
||||
PathFindFlags = {
|
||||
AllowNullTiles = 1,
|
||||
AllowCreatures = 2,
|
||||
AllowNonPathable = 4,
|
||||
AllowNonWalkable = 8
|
||||
}
|
||||
|
||||
-- @}
|
||||
|
|
|
@ -341,11 +341,18 @@ namespace Otc
|
|||
};
|
||||
|
||||
enum PathFindResult {
|
||||
PATHFIND_OK = 0,
|
||||
PATHFIND_SAME_POSITION,
|
||||
PATHFIND_IMPOSSIBLE,
|
||||
PATHFIND_TOO_FAR,
|
||||
PATHFIND_NO_WAY
|
||||
PATHFIND_RESULT_OK = 0,
|
||||
PATHFIND_RESULT_SAME_POSITION,
|
||||
PATHFIND_RESULT_IMPOSSIBLE,
|
||||
PATHFIND_RESULT_TOO_FAR,
|
||||
PATHFIND_RESULT_NO_WAY
|
||||
};
|
||||
|
||||
enum PathFindFlag {
|
||||
PATHFIND_ALLOW_NULLTILES = 1,
|
||||
PATHFIND_ALLOW_CREATURES = 2,
|
||||
PATHFIND_ALLOW_NONPATHABLE = 4,
|
||||
PATHFIND_ALLOW_NONWALKABLE = 8
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -428,7 +428,7 @@ int Map::getLastAwareFloor()
|
|||
return Otc::SEA_FLOOR;
|
||||
}
|
||||
|
||||
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const Position& startPos, const Position& goalPos, int maxSteps)
|
||||
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const Position& startPos, const Position& goalPos, int maxSteps, int flags)
|
||||
{
|
||||
// pathfinding using A* search algorithm
|
||||
// as described in http://en.wikipedia.org/wiki/A*_search_algorithm
|
||||
|
@ -455,20 +455,20 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
|
|||
std::vector<Otc::Direction>& dirs = std::get<0>(ret);
|
||||
Otc::PathFindResult& result = std::get<1>(ret);
|
||||
|
||||
result = Otc::PATHFIND_OK;
|
||||
result = Otc::PATHFIND_RESULT_NO_WAY;
|
||||
|
||||
if(startPos == goalPos) {
|
||||
result = Otc::PATHFIND_SAME_POSITION;
|
||||
result = Otc::PATHFIND_RESULT_SAME_POSITION;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(startPos.z != goalPos.z) {
|
||||
result = Otc::PATHFIND_IMPOSSIBLE;
|
||||
result = Otc::PATHFIND_RESULT_IMPOSSIBLE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(startPos.distance(goalPos) > maxSteps) {
|
||||
result = Otc::PATHFIND_TOO_FAR;
|
||||
result = Otc::PATHFIND_RESULT_TOO_FAR;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -479,10 +479,18 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
|
|||
currentNode->pos = startPos;
|
||||
nodes[startPos] = currentNode;
|
||||
Node *foundNode = nullptr;
|
||||
while(currentNode && currentNode->steps < maxSteps) {
|
||||
while(currentNode) {
|
||||
// too far
|
||||
if(currentNode->steps >= maxSteps) {
|
||||
result = Otc::PATHFIND_RESULT_TOO_FAR;
|
||||
break;
|
||||
}
|
||||
|
||||
// path found
|
||||
if(currentNode->pos == goalPos && (!foundNode || currentNode->cost < foundNode->cost))
|
||||
foundNode = currentNode;
|
||||
|
||||
// cost too high
|
||||
if(foundNode && currentNode->totalCost >= foundNode->cost)
|
||||
break;
|
||||
|
||||
|
@ -493,8 +501,19 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
|
|||
|
||||
Position neighborPos = currentNode->pos.translated(i, j);
|
||||
const TilePtr& tile = getTile(neighborPos);
|
||||
if(!tile || (!tile->isPathable() && neighborPos != goalPos) || (!tile->isWalkable() && neighborPos == goalPos))
|
||||
continue;
|
||||
|
||||
if(neighborPos != goalPos) {
|
||||
if(!(flags & Otc::PATHFIND_ALLOW_NULLTILES) && !tile)
|
||||
continue;
|
||||
if(tile) {
|
||||
if(!(flags & Otc::PATHFIND_ALLOW_CREATURES) && tile->hasCreature())
|
||||
continue;
|
||||
if(!(flags & Otc::PATHFIND_ALLOW_NONPATHABLE) && !tile->isPathable())
|
||||
continue;
|
||||
if(!(flags & Otc::PATHFIND_ALLOW_NONWALKABLE) && !tile->isWalkable())
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
float walkFactor;
|
||||
Otc::Direction walkDir = currentNode->pos.getDirectionFromPosition(neighborPos);
|
||||
|
@ -503,7 +522,8 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
|
|||
else
|
||||
walkFactor = 1.0f;
|
||||
|
||||
float cost = currentNode->cost + (tile->getGroundSpeed() * walkFactor) / 100.0f;
|
||||
int groundSpeed = tile ? tile->getGroundSpeed() : 100;
|
||||
float cost = currentNode->cost + (groundSpeed * walkFactor) / 100.0f;
|
||||
|
||||
Node *neighborNode;
|
||||
if(nodes.find(neighborPos) == nodes.end()) {
|
||||
|
@ -544,8 +564,8 @@ std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> Map::findPath(const
|
|||
}
|
||||
dirs.pop_back();
|
||||
std::reverse(dirs.begin(), dirs.end());
|
||||
} else
|
||||
result = Otc::PATHFIND_NO_WAY;
|
||||
result = Otc::PATHFIND_RESULT_OK;
|
||||
}
|
||||
|
||||
for(auto it : nodes)
|
||||
delete it.second;
|
||||
|
|
|
@ -253,7 +253,7 @@ public:
|
|||
std::vector<AnimatedTextPtr> getAnimatedTexts() { return m_animatedTexts; }
|
||||
std::vector<StaticTextPtr> getStaticTexts() { return m_staticTexts; }
|
||||
|
||||
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> findPath(const Position& start, const Position& goal, int maxSteps);
|
||||
std::tuple<std::vector<Otc::Direction>, Otc::PathFindResult> findPath(const Position& start, const Position& goal, int maxSteps, int flags = 0);
|
||||
|
||||
private:
|
||||
uint getBlockIndex(const Position& pos) { return ((pos.y / BLOCK_SIZE) * (65536 / BLOCK_SIZE)) + (pos.x / BLOCK_SIZE); }
|
||||
|
|
|
@ -469,11 +469,8 @@ bool Tile::changesFloor()
|
|||
|
||||
bool Tile::isPathable()
|
||||
{
|
||||
if(!isWalkable())
|
||||
return false;
|
||||
|
||||
for(const ThingPtr& thing : m_things) {
|
||||
if(thing->isNotPathable() || thing->isCreature())
|
||||
if(thing->isNotPathable())
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue