diff options
author | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2011-01-06 23:59:59 +0100 |
---|---|---|
committer | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2011-01-06 23:59:59 +0100 |
commit | f704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d (patch) | |
tree | b5d8ea415a0bad26adf1e167d92948c23e92a93b /src | |
parent | 9ec38c1e381336df89e0f0eea84065cc537f9e4b (diff) | |
download | mana-f704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d.tar.gz mana-f704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d.tar.bz2 mana-f704b49c5972a9e40aa1f7dbe6f34a3ab7830c8d.tar.xz mana-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/being.cpp | 61 | ||||
-rw-r--r-- | src/localplayer.cpp | 11 |
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 |