summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/being.cpp64
-rw-r--r--src/being.h9
-rw-r--r--src/localplayer.cpp60
3 files changed, 77 insertions, 56 deletions
diff --git a/src/being.cpp b/src/being.cpp
index 247e193a..ce6c9e1b 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -127,6 +127,48 @@ void Being::setPosition(const Vector &pos)
(int)pos.y - getHeight() - mText->getHeight() - 6);
}
+Position Being::checkNodeOffsets(Position position)
+{
+ // Pre-computing character's position in tiles
+ const int tx = position.x / 32;
+ const int ty = position.y / 32;
+
+ // Pre-computing character's position offsets.
+ int fx = position.x % 32;
+ int fy = position.y % 32;
+
+ // Compute the being radius:
+ // FIXME: the beings' radius should be obtained from xml values
+ // and stored into the Being ojects.
+ int radius = getWidth() / 2;
+ // FIXME: Hande beings with more than 1/2 tile radius by not letting them
+ // go or spawn in too narrow places. The server will have to be aware
+ // of being's radius value (in tiles) to handle this gracefully.
+ if (radius > 32 / 2) radius = 32 / 2;
+ // set a default value if no value returned.
+ if (radius < 1) radius = 32 / 3;
+
+ // Fix coordinates so that the player does not seem to dig into walls.
+ if (fx > (32 - radius) && !mMap->getWalk(tx + 1, ty, getWalkMask()))
+ fx = 32 - radius;
+ else if (fx < radius && !mMap->getWalk(tx - 1, ty, getWalkMask()))
+ fx = radius;
+ else if (fy > (32 - radius) && !mMap->getWalk(tx, ty + 1, getWalkMask()))
+ fy = 32 - radius;
+ else if (fy < radius && !mMap->getWalk(tx, ty - 1, getWalkMask()))
+ fy = radius;
+
+ // FIXME: Check also diagonal positions.
+
+ // Test also the current character's position, to avoid the corner case
+ // where a player can approach an obstacle by walking from slightly
+ // under, diagonally. First part to the walk on water bug.
+ //if (offsetY < 16 && !mMap->getWalk(posX, posY - 1, getWalkMask()))
+ //fy = 16;
+
+ return Position(tx * 32 + fx, ty * 32 + fy);
+}
+
void Being::setDestination(int dstX, int dstY)
{
if (Net::getNetworkType() == ServerInfo::EATHENA)
@@ -136,12 +178,22 @@ void Being::setDestination(int dstX, int dstY)
return;
}
- mDest.x = dstX;
- mDest.y = dstY;
+ // Check the walkability of the destination:
+ // If the destination is unwalkable,
+ // don't bother finding a path or set a destination.
+ if (!mMap->getWalk(dstX / 32, dstY / 32))
+ return;
+
+ // We check the destination in order to handle
+ // surrounding blocking tiles gracefully...
+ Position dest = checkNodeOffsets(dstX, dstY);
+ mDest.x = dest.x;
+ mDest.y = dest.y;
int srcX = mPos.x;
int srcY = mPos.y;
- Path thisPath;
+ // We initialize an empty path...
+ Path thisPath = Path();
if (mMap)
{
@@ -175,6 +227,12 @@ void Being::setDestination(int dstX, int dstY)
{
it->x = (it->x * 32) + startX + (changeX * i);
it->y = (it->y * 32) + startY + (changeY * i);
+
+ // We check each path node and correct the
+ // tile position's offsets whenever needed.
+ Position pos = checkNodeOffsets(*it);
+ it->x = pos.x;
+ it->y = pos.y;
i++;
it++;
}
diff --git a/src/being.h b/src/being.h
index 3b63b02d..5140717c 100644
--- a/src/being.h
+++ b/src/being.h
@@ -647,6 +647,15 @@ class Being : public Sprite, public ConfigListener
Vector mDest; /**< destination coordinates. */
+ /**
+ * Check the current position against surrounding
+ * blocking tiles, and correct the position offset within
+ * tile when needed.
+ */
+ Position checkNodeOffsets(Position position);
+ Position checkNodeOffsets(int x, int y)
+ { return checkNodeOffsets(Position(x, y)); }
+
private:
/**
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 6f63d799..d7f64113 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -462,63 +462,17 @@ void LocalPlayer::setTarget(Being *target)
void LocalPlayer::setDestination(int x, int y)
{
- if (Net::getNetworkType() == ServerInfo::MANASERV)
- {
- // Pre-computing character's destination in tiles
- const int tx = x / 32;
- const int ty = y / 32;
-
- // Check the walkability of the destination
- // If the destination is a wall, don't go there!
- if (!mMap->getWalk(tx, ty))
- return;
-
- // Pre-computing character's position useful variables.
- Vector playerPosition = getPosition();
- const int posX = (int)(playerPosition.x / 32);
- const int posY = (int)(playerPosition.y / 32);
- const int offsetY = (int)playerPosition.y % 32;
-
- // check if we're finding a path to the seeked destination
- // If the path is empty... and isn't on the same tile,
- // then, it's an unvalid one.
- if (posX != tx || posY != ty)
- {
- Path evaluatedPath = mMap->findPath(posX, posY, tx, ty,
- getWalkMask());
- if (evaluatedPath.empty())
- return;
- }
-
- // Pre-computing character's destination offsets.
- int fx = x % 32;
- int fy = y % 32;
-
- // Fix coordinates so that the player does not seem to dig into walls.
- if (fx > 16 && !mMap->getWalk(tx + 1, ty, getWalkMask()))
- fx = 16;
- else if (fx < 16 && !mMap->getWalk(tx - 1, ty, getWalkMask()))
- fx = 16;
- else if (fy > 16 && !mMap->getWalk(tx, ty + 1, getWalkMask()))
- fy = 16;
- else if (fy < 16 && !mMap->getWalk(tx, ty - 1, getWalkMask()))
- fy = 16;
-
- // Test also the current character's position, to avoid the corner case
- // where a player can approach an obstacle by walking from slightly
- // under, diagonally. First part to the walk on water bug.
- if (offsetY < 16 && !mMap->getWalk(posX, posY - 1, getWalkMask()))
- fy = 16;
-
- x = tx * 32 + fx;
- y = ty * 32 + fy;
- }
-
// Only send a new message to the server when destination changes
if (x != mDest.x || y != mDest.y)
{
Being::setDestination(x, y);
- Net::getPlayerHandler()->setDestination(x, y, mDirection);
+
+ // Manaserv:
+ // If the destination given to being class is accepted,
+ // we inform the Server.
+ if ((x == mDest.x && y == mDest.y)
+ || Net::getNetworkType() == ServerInfo::EATHENA)
+ Net::getPlayerHandler()->setDestination(x, y, mDirection);
}
mPickUpTarget = NULL;