From 0a3e2c75c5fcc359e257548267d5ffae6726e2db Mon Sep 17 00:00:00 2001 From: Bertram Date: Fri, 9 Oct 2009 03:43:13 +0200 Subject: Mostly fixed keyboard movement on TMWserv. - Making sure that keyboard and mouse are fully working on eAthena. - Making sure the mouse code isn't broken again. There are some glitches left but it's coming! What's left to be fixed: - Come a little closer to walls (localPlyer::nextStep() improvement to be done). - Adapt the next Step range according to the being speed. (again in nextStep()). - Handle more nicely player's direction when walking diagonally. - Get player's speed from server. Enjoy :) --- src/being.cpp | 33 ++++++++++---- src/localplayer.cpp | 125 +++++++++++++++++++++++++++++++++------------------- src/localplayer.h | 9 ++-- 3 files changed, 108 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/being.cpp b/src/being.cpp index d15c27b3..ef71b748 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -528,12 +528,24 @@ void Being::logic() Vector dir = dest - mPos; const float length = dir.length(); - // When we're over 2 pixels from our destination, move to it - // TODO: Should be possible to make it even pixel exact, but this solves - // the jigger caused by moving too far. - if (length > 2.0f) { + // When we've not reached our destination, move to it. + if (length > 0.0f) + { const float speed = mWalkSpeed / 100.0f; - setPosition(mPos + (dir / (length / speed))); + + // Test if we don't miss the destination by a move too far: + if ((dir / (length / speed)).length() > dir.length()) + { + setPosition(mPos + dir); + + // Also, if the destination is reached, try to get the next + // path point, if existing. + if (!mPath.empty()) + mPath.pop_front(); + } + // Otherwise, go to it using the nominal speed. + else + setPosition(mPos + (dir / (length / speed))); if (mAction != WALK) setAction(WALK); @@ -548,11 +560,14 @@ void Being::logic() direction |= (dir.y > 0) ? DOWN : UP; setDirection(direction); } - else if (!mPath.empty()) { - // TODO: Pop as soon as there is a direct unblocked line to the next - // point on the path. + else if (!mPath.empty()) + { + // If the current path node has been reached, + // remove it and go to the next one. mPath.pop_front(); - } else if (mAction == WALK) { + } + else if (mAction == WALK) + { setAction(STAND); } } diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 2744f106..65f1fcc7 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -73,10 +73,10 @@ #include #ifdef TMWSERV_SUPPORT -// This is shorter then it really needs to be for normal use -// But if we ever wanted to increase player speed, having this lower -// Won't hurt -const short walkingKeyboardDelay = 40; +// This is the minimal delay between to permitted +// setDestination() calls using the keyboard. +// TODO: This can fine tuned later on when running is added... +const short walkingKeyboardDelay = 1000; #endif LocalPlayer *player_node = NULL; @@ -263,9 +263,10 @@ void LocalPlayer::setGMLevel(int level) setGM(true); } -#ifdef EATHENA_SUPPORT -void LocalPlayer::nextStep() + +void LocalPlayer::nextStep(unsigned char dir = 0) { +#ifdef EATHENA_SUPPORT // TODO: Fix picking up when reaching target (this method is obsolete) // TODO: Fix holding walking button to keep walking smoothly if (mPath.empty()) @@ -274,7 +275,7 @@ void LocalPlayer::nextStep() pickUp(mPickUpTarget); if (mWalkingDir) - walk(mWalkingDir); + startWalking(mWalkingDir); } // TODO: Fix automatically walking within range of target, when wanted @@ -294,8 +295,66 @@ void LocalPlayer::nextStep() Player::nextStep(); -} +#else // TMWSERV_SUPPORT + if (!mMap || !dir) + return; + + const Vector &pos = getPosition(); + + // Compute where the next step will set. + + int dx = 0, dy = 0; + if (dir & UP) + dy--; + if (dir & DOWN) + dy++; + if (dir & LEFT) + dx--; + if (dir & RIGHT) + dx++; + + // Prevent skipping corners over colliding tiles + if (dx && !mMap->getWalk(((int) pos.x + dx) / 32, + (int) pos.y / 32, getWalkMask())) + dx = 16 - (int) pos.x % 32; + if (dy && !mMap->getWalk((int) pos.x / 32, + ((int) pos.y + dy) / 32, getWalkMask())) + dy = 16 - (int) pos.y % 32; + + // Choose a straight direction when diagonal target is blocked + if (dx && dy && !mMap->getWalk((pos.x + dx) / 32, + (pos.y + dy) / 32, getWalkMask())) + dx = 16 - (int) pos.x % 32; + + int dScaler; // Distance to walk + + // Checks our path up to 1 tiles, if a blocking tile is found + // We go to the last good tile, and break out of the loop + for (dScaler = 1; dScaler <= 32; dScaler++) + { + if ( (dx || dy) && + !mMap->getWalk( ((int) pos.x + (dx * dScaler)) / 32, + ((int) pos.y + (dy * dScaler)) / 32, getWalkMask()) ) + { + dScaler--; + break; + } + } + + if (dScaler >= 0) + { + //effectManager->trigger(15, (int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); + setDestination((int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); + } + else if (dir) + { + // If the being can't move, just change direction + Net::getPlayerHandler()->setDirection(dir); + setDirection(dir); + } #endif +} + #ifdef TMWSERV_SUPPORT bool LocalPlayer::checkInviteRights(const std::string &guildName) @@ -497,11 +556,17 @@ void LocalPlayer::setWalkingDir(int dir) // If we're not already walking, start walking. if (mAction != WALK && dir) { - walk(dir); + startWalking(dir); + } +#ifdef TMWSERV_SUPPORT + else if (mAction == WALK) + { + nextStep(dir); } +#endif } -void LocalPlayer::walk(unsigned char dir) +void LocalPlayer::startWalking(unsigned char dir) { // This function is called by setWalkingDir(), // but also by nextStep() for eAthena... @@ -535,48 +600,14 @@ void LocalPlayer::walk(unsigned char dir) if (dir & RIGHT) dx++; +#ifdef EATHENA_SUPPORT // Prevent skipping corners over colliding tiles -#ifdef TMWSERV_SUPPORT - if (dx && !mMap->getWalk(((int) pos.x + dx) / 32, - (int) pos.y / 32, getWalkMask())) - dx = 16 - (int) pos.x % 32; - if (dy && !mMap->getWalk((int) pos.x / 32, - ((int) pos.y + dy) / 32, getWalkMask())) - dy = 16 - (int) pos.y % 32; -#else if (dx && !mMap->getWalk(getTileX() + dx, getTileY(), getWalkMask())) dx = 0; if (dy && !mMap->getWalk(getTileX(), getTileY() + dy, getWalkMask())) dy = 0; -#endif // Choose a straight direction when diagonal target is blocked -#ifdef TMWSERV_SUPPORT - if (dx && dy && !mMap->getWalk((pos.x + dx) / 32, - (pos.y + dy) / 32, getWalkMask())) - dx = 16 - (int) pos.x % 32; - - int dScaler; // Distance to walk - - // Checks our path up to 2 tiles, if a blocking tile is found - // We go to the last good tile, and break out of the loop - for (dScaler = 1; dScaler <= 32 * 2; dScaler++) - { - if ( (dx || dy) && - !mMap->getWalk( ((int) pos.x + (dx * dScaler)) / 32, - ((int) pos.y + (dy * dScaler)) / 32, getWalkMask()) ) - { - dScaler--; - break; - } - } - - if (dScaler >= 0) - { - effectManager->trigger(15, (int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); - setDestination((int) pos.x + (dx * dScaler), (int) pos.y + (dy * dScaler)); - } -#else if (dx && dy && !mMap->getWalk(getTileX() + dx, getTileY() + dy, getWalkMask())) dx = 0; @@ -585,13 +616,15 @@ void LocalPlayer::walk(unsigned char dir) { setDestination(getTileX() + dx, getTileY() + dy); } -#endif else if (dir) { // If the being can't move, just change direction Net::getPlayerHandler()->setDirection(dir); setDirection(dir); } +#else // TMWSERV_SUPPORT + nextStep(dir); +#endif } void LocalPlayer::stopWalking(bool sendToServer) diff --git a/src/localplayer.h b/src/localplayer.h index e0d5675d..28a1c286 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -122,13 +122,14 @@ class LocalPlayer : public Player virtual void setAction(Action action, int attackType = 0); -#ifdef EATHENA_SUPPORT /** * Adds a new step when walking before calling super. Also, when * specified it picks up an item at the end of a path. */ - virtual void nextStep(); -#endif + virtual void nextStep() + { nextStep(0); } + + virtual void nextStep(unsigned char dir); /** * Returns the player's inventory. @@ -386,7 +387,7 @@ class LocalPlayer : public Player // Colors don't change for local player virtual void updateColors() {} - void walk(unsigned char dir); + void startWalking(unsigned char dir); bool mInStorage; /**< Whether storage is currently accessible */ -- cgit v1.2.3-60-g2f50