diff options
-rw-r--r-- | src/being.cpp | 32 | ||||
-rw-r--r-- | src/gui/viewport.cpp | 39 | ||||
-rw-r--r-- | src/map.cpp | 34 | ||||
-rw-r--r-- | src/map.h | 8 | ||||
-rw-r--r-- | src/net/manaserv/playerhandler.h | 3 | ||||
-rw-r--r-- | src/net/playerhandler.h | 6 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.h | 3 |
7 files changed, 111 insertions, 14 deletions
diff --git a/src/being.cpp b/src/being.cpp index 2c8414d8..6b971dbf 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -198,21 +198,37 @@ void Being::setDestination(int dstX, int dstY) return; // If the destination is unwalkable, don't bother trying to get there - if (!mMap->getWalk(dstX / 32, dstY / 32)) + int tileWidth = mMap->getTileWidth(); + int tileHeight = mMap->getTileHeight(); + if (!mMap->getWalk(dstX / tileWidth, dstY / tileHeight)) return; - Position dest = mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(), - dstX, dstY); - Path thisPath = mMap->findPixelPath((int) mPos.x, (int) mPos.y, - dest.x, dest.y, - getCollisionRadius(), getWalkMask()); + Position dest(dstX, dstY); + Path thisPath; + if (Net::getPlayerHandler()->usePixelPrecision()) + { + dest = mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(), + dstX, dstY); + thisPath = mMap->findPixelPath((int) mPos.x, (int) mPos.y, + dest.x, dest.y, + getCollisionRadius(), getWalkMask()); + } + else + { + // We center the destination. + dest.x = (dstX / tileWidth) * tileWidth + tileWidth / 2; + dest.y = (dstY / tileHeight) * tileHeight + tileHeight / 2; + // and find a tile centered pixel path + thisPath = mMap->findTilePath((int) mPos.x, (int) mPos.y, + dest.x, dest.y, getWalkMask()); + } if (thisPath.empty()) { // If there is no path but the destination is on the same walkable tile, // we accept it. - if ((int)mPos.x / 32 == dest.x / 32 - && (int)mPos.y / 32 == dest.y / 32) + if ((int)mPos.x / tileWidth == dest.x / tileWidth + && (int)mPos.y / tileHeight == dest.y / tileHeight) { mDest.x = dest.x; mDest.y = dest.y; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 459edab5..19bed735 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -37,6 +37,7 @@ #include "gui/beingpopup.h" #include "net/net.h" +#include "net/playerhandler.h" #include "resources/resourcemanager.h" @@ -270,12 +271,38 @@ void Viewport::_drawDebugPath(Graphics *graphics) (int) playerPos.y - (int) mPixelViewY - playerRadius, playerRadius * 2, playerRadius * 2)); - debugPath = mMap->findPixelPath( - (int) playerPos.x, - (int) playerPos.y, - mMouseX + (int) mPixelViewX, - mMouseY + (int) mPixelViewY, - playerRadius, 0xFF); + // Prepare the walkmask corresponding to the protocol + unsigned char walkMask = 0; + switch (Net::getNetworkType()) + { + case ServerInfo::TMWATHENA: + walkMask = Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER; + break; + case ServerInfo::MANASERV: + default: + walkMask = Map::BLOCKMASK_WALL; + break; + } + + // Adapt the path finding to the precision requested + if (Net::getPlayerHandler()->usePixelPrecision()) + { + debugPath = mMap->findPixelPath( + (int) playerPos.x, + (int) playerPos.y, + mMouseX + (int) mPixelViewX, + mMouseY + (int) mPixelViewY, + playerRadius, walkMask); + } + else + { + debugPath = mMap->findTilePath( + (int) playerPos.x, + (int) playerPos.y, + mMouseX + (int) mPixelViewX, + mMouseY + (int) mPixelViewY, + walkMask); + } // We draw the path proposed by mouse _drawPath(graphics, debugPath, gcn::Color(128, 0, 128)); diff --git a/src/map.cpp b/src/map.cpp index 87c902f6..69793299 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -710,6 +710,40 @@ Position Map::checkNodeOffsets(int radius, unsigned char walkMask, return Position(tx * 32 + fx, ty * 32 + fy); } +Path Map::findTilePath(int startPixelX, int startPixelY, int endPixelX, + int endPixelY, unsigned char walkMask, int maxCost) +{ + Path myPath = findPath(startPixelX / mTileWidth, startPixelY / mTileHeight, + endPixelX / mTileWidth, endPixelY / mTileHeight, + walkMask, maxCost); + + // Don't compute empty coordinates. + if (myPath.empty()) + return myPath; + + // Convert the map path to pixels over tiles + // And add interpolation between the starting and ending offsets + Path::iterator it = myPath.begin(); + while (it != myPath.end()) + { + // A position that is valid on the start and end tile is not + // necessarily valid on all the tiles in between, so check the offsets. + *it = Position(it->x * mTileWidth + mTileWidth / 2, + it->y * mTileHeight + mTileHeight / 2); + it++; + } + + // Remove the last path node, as it's more clever to go to the destination. + // It also permit to avoid zigzag at the end of the path, + // especially with mouse. + Position destination((endPixelX / mTileWidth) * mTileWidth + mTileWidth / 2, + (endPixelY / mTileHeight) * mTileHeight + mTileHeight / 2); + myPath.pop_back(); + myPath.push_back(destination); + + return myPath; +} + Path Map::findPixelPath(int startPixelX, int startPixelY, int endPixelX, int endPixelY, int radius, unsigned char walkMask, int maxCost) @@ -287,6 +287,14 @@ class Map : public Properties /** * Find a pixel path from one location to the next. + * Path node are centered on their corresponding tiles in that case. + */ + Path findTilePath(int startPixelX, int startPixelY, int endPixelX, + int endPixelY, unsigned char walkMask, + int maxCost = 20); + + /** + * Find a pixel path from one location to the next. */ Path findPixelPath(int startPixelX, int startPixelY, int destPixelX, int destPixelY, diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h index 6069c6da..8bba1580 100644 --- a/src/net/manaserv/playerhandler.h +++ b/src/net/manaserv/playerhandler.h @@ -69,6 +69,9 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0); + bool usePixelPrecision() + { return true; } + private: void handleMapChangeMessage(Net::MessageIn &msg); }; diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index 23277062..5d94a093 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -74,6 +74,12 @@ class PlayerHandler * Convert the original speed in pixel per tick for internal use. */ virtual Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0) = 0; + + /** + * Tells whether the client has to use pixel paths. + * Return false when tiles-center positions only are to be used. + */ + virtual bool usePixelPrecision() = 0; }; } // namespace Net diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h index 4df74350..42eb85f2 100644 --- a/src/net/tmwa/playerhandler.h +++ b/src/net/tmwa/playerhandler.h @@ -61,6 +61,9 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler Vector getDefaultMoveSpeed(); Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0); + + bool usePixelPrecision() + { return false; } }; } // namespace TmwAthena |