summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer>2011-01-06 23:59:59 +0100
committerYohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer>2011-01-06 23:59:59 +0100
commitf704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d (patch)
treeb5d8ea415a0bad26adf1e167d92948c23e92a93b
parent9ec38c1e381336df89e0f0eea84065cc537f9e4b (diff)
downloadmana-client-f704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d.tar.gz
mana-client-f704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d.tar.bz2
mana-client-f704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d.tar.xz
mana-client-f704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d.zip
Made the beings avoid changing direction at their path's end.
I had to let the keyboard path not be resend when the player released the movement keys and work on conditions used to update the beings direction to avoid conflicts. Resolves: Mana-mantis #154. Reviewed-by: Thorbjorn.
-rw-r--r--src/being.cpp61
-rw-r--r--src/localplayer.cpp11
2 files changed, 46 insertions, 26 deletions
diff --git a/src/being.cpp b/src/being.cpp
index 543b16d0..570d8b22 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -715,24 +715,32 @@ void Being::logic()
mText = 0;
}
- if ((Net::getNetworkType() == ServerInfo::MANASERV) && (mAction != DEAD))
+ if ((Net::getNetworkType() == ServerInfo::MANASERV) && (mAction != DEAD)
+ && !mWalkSpeed.isNull())
{
const Vector dest = (mPath.empty()) ?
mDest : Vector(mPath.front().x,
mPath.front().y);
- // This is a hack that stops NPCs from running off the map...
+ // Avoid going to flawed destinations
if (mDest.x <= 0 && mDest.y <= 0)
+ {
+ // We make the being stop move in that case.
+ mDest = mPos;
+ mPath.clear();
+ // By returning now, we're losing one tick for the rest of the logic
+ // but as we have reset the destination, the next tick will be fine.
return;
+ }
// The Vector representing the difference between current position
// and the next destination path node.
Vector dir = dest - mPos;
- const float nominalLength = dir.length();
+ float distance = dir.length();
// When we've not reached our destination, move to it.
- if (nominalLength > 0.0f && !mWalkSpeed.isNull())
+ if (distance > 0.0f)
{
// The deplacement of a point along a vector is calculated
// using the Unit Vector (รข) multiplied by the point speed.
@@ -743,7 +751,7 @@ void Being::logic()
normalizedDir.y * mWalkSpeed.y);
// Test if we don't miss the destination by a move too far:
- if (diff.length() > nominalLength)
+ if (diff.length() > distance)
{
setPosition(mPos + dir);
@@ -752,32 +760,43 @@ void Being::logic()
if (!mPath.empty())
mPath.pop_front();
}
- // Otherwise, go to it using the nominal speed.
else
+ {
+ // Otherwise, go to it using the nominal speed.
setPosition(mPos + diff);
+ // And reset the nominalLength to the actual move length
+ distance = diff.length();
+ }
if (mAction != MOVE)
setAction(MOVE);
// Update the player sprite direction.
- // N.B.: We only change this if the distance is more than one pixel.
- if (nominalLength > 1.0f)
+ // N.B.: We only change this if the distance is more than one pixel
+ // to avoid flawing the ending direction.
+ if (distance > 1.0f)
{
- int direction = 0;
- const float dx = std::abs(dir.x);
- float dy = std::abs(dir.y);
-
- // When not using mouse for the player, we slightly prefer
- // UP and DOWN position, especially when walking diagonally.
- if (this == player_node && !player_node->isPathSetByMouse())
- dy = dy + 2;
+ // The player direction is handled for keyboard
+ // by LocalPlayer::startWalking(), we shouldn't get
+ // in the way here for other cases.
+ // Hence, we set the direction in Being::logic() only when:
+ // 1. It is not the localPlayer
+ // 2. When it is the localPlayer but only by mouse
+ // (because in that case, the path can have more than one tile.)
+ if ((player_node == this && player_node->isPathSetByMouse())
+ || player_node != this)
+ {
+ int direction = 0;
+ const float dx = std::abs(dir.x);
+ float dy = std::abs(dir.y);
- if (dx > dy)
- direction |= (dir.x > 0) ? RIGHT : LEFT;
- else
- direction |= (dir.y > 0) ? DOWN : UP;
+ if (dx > dy)
+ direction |= (dir.x > 0) ? RIGHT : LEFT;
+ else
+ direction |= (dir.y > 0) ? DOWN : UP;
- setDirection(direction);
+ setDirection(direction);
+ }
}
}
else if (!mPath.empty())
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index a4560030..7d427b82 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -745,13 +745,10 @@ void LocalPlayer::setWalkingDir(int dir)
// Else, he is not pressing a key,
// and the current path hasn't been sent by mouse,
- // then, stop (sending to server).
+ // then let the path die (1/2 tile after that.)
+ // This permit to avoid desyncs with other clients.
else if (!dir)
- {
- if (!mPathSetByMouse)
- player_node->stopWalking(true);
return;
- }
// If the delay to send another walk message to the server hasn't expired,
// don't do anything or we could get disconnected for spamming the server
@@ -802,6 +799,10 @@ void LocalPlayer::startWalking(unsigned char dir)
if (dir & RIGHT)
dx++;
+ // Update the direction when the walk just start
+ if (Net::getNetworkType() == ServerInfo::MANASERV)
+ setDirection(dir);
+
if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
// Prevent skipping corners over colliding tiles