diff options
-rw-r--r-- | src/game.cpp | 63 | ||||
-rw-r--r-- | src/localplayer.cpp | 212 |
2 files changed, 147 insertions, 128 deletions
diff --git a/src/game.cpp b/src/game.cpp index 357092ae..60b13a06 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -147,7 +147,15 @@ EffectManager *effectManager = NULL; ChatTab *localChatTab = NULL; -const int MAX_TIME = 10000; +/** + * Tells the max tick value, + * setting it back to zero (and start again). + */ +const int MAX_TICK_VALUE = 10000; +/** + * Set the milliseconds value of a tick time. + */ +const int MILLISECONDS_IN_A_TICK = 10; /** * Listener used for exiting handling. @@ -167,16 +175,19 @@ namespace { /** * Advances game logic counter. + * Called every 10 milliseconds by SDL_AddTimer() + * @see MILLISECONDS_IN_A_TICK value */ Uint32 nextTick(Uint32 interval, void *param) { tick_time++; - if (tick_time == MAX_TIME) tick_time = 0; + if (tick_time == MAX_TICK_VALUE) tick_time = 0; return interval; } /** * Updates fps. + * Called every seconds by SDL_AddTimer() */ Uint32 nextSecond(Uint32 interval, void *param) { @@ -186,12 +197,17 @@ Uint32 nextSecond(Uint32 interval, void *param) return interval; } +/** + * @return the elapsed time in milliseconds + * between two tick values. + */ int get_elapsed_time(int start_time) { if (start_time <= tick_time) - return (tick_time - start_time) * 10; + return (tick_time - start_time) * MILLISECONDS_IN_A_TICK; else - return (tick_time + (MAX_TIME - start_time)) * 10; + return (tick_time + (MAX_TICK_VALUE - start_time)) + * MILLISECONDS_IN_A_TICK; } /** @@ -302,7 +318,7 @@ Game::Game(): // Initialize logic and seconds counters tick_time = 0; - mLogicCounterId = SDL_AddTimer(10, nextTick, NULL); + mLogicCounterId = SDL_AddTimer(MILLISECONDS_IN_A_TICK, nextTick, NULL); mSecondsCounterId = SDL_AddTimer(1000, nextSecond, NULL); // Initialize frame limiting @@ -421,7 +437,7 @@ void Game::optionChanged(const std::string &name) mMinFrameTime = fpsLimit ? 1000 / fpsLimit : 0; // Reset draw time to current time - mDrawTime = tick_time * 10; + mDrawTime = tick_time * MILLISECONDS_IN_A_TICK; } void Game::logic() @@ -429,7 +445,7 @@ void Game::logic() // mDrawTime has a higher granularity than gameTime in order to be able to // work with minimum frame durations in milliseconds. int gameTime = tick_time; - mDrawTime = tick_time * 10; + mDrawTime = tick_time * MILLISECONDS_IN_A_TICK; while (!done) { @@ -461,18 +477,18 @@ void Game::logic() mDrawTime += mMinFrameTime; // Make sure to wrap mDrawTime, since tick_time will wrap. - if (mDrawTime > MAX_TIME * 10) - mDrawTime -= MAX_TIME * 10; + if (mDrawTime > MAX_TICK_VALUE * MILLISECONDS_IN_A_TICK) + mDrawTime -= MAX_TICK_VALUE * MILLISECONDS_IN_A_TICK; } else { - SDL_Delay(10); + SDL_Delay(MILLISECONDS_IN_A_TICK); } } else { - SDL_Delay(10); - mDrawTime = tick_time * 10; + SDL_Delay(MILLISECONDS_IN_A_TICK); + mDrawTime = tick_time * MILLISECONDS_IN_A_TICK; } // Handle network stuff @@ -959,29 +975,8 @@ void Game::handleInput() direction |= Being::RIGHT; } -#ifdef TMWSERV_SUPPORT - // First if player is pressing key for the direction he is already - // going - if (direction == player_node->getWalkingDir()) - { - player_node->setWalkingDir(direction); - } - // Else if he is pressing a key, and its different from what he has - // been pressing, stop (do not send this stop to the server) and - // start in the new direction - else if (direction && direction != player_node->getWalkingDir()) - { - player_node->stopWalking(false); - player_node->setWalkingDir(direction); - } - // Else, he is not pressing a key, stop (sending to server) - else - { - player_node->stopWalking(true); - } -#else player_node->setWalkingDir(direction); -#endif + // Attacking monsters if (keyboard.isKeyActive(keyboard.KEY_ATTACK) || (joystick && joystick->buttonPressed(0))) diff --git a/src/localplayer.cpp b/src/localplayer.cpp index b5ad79eb..14f85bfe 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -360,96 +360,6 @@ void LocalPlayer::pickUp(FloorItem *item) } } -void LocalPlayer::walk(unsigned char dir) -{ - // TODO: Evaluate the implementation of this method for tmwserv - if (!mMap || !dir) - return; - -#ifdef TMWSERV_SUPPORT - const Vector &pos = getPosition(); -#endif - - if (mAction == WALK && !mPath.empty()) - { - // Just finish the current action, otherwise we get out of sync -#ifdef TMWSERV_SUPPORT - Being::setDestination(pos.x, pos.y); -#else - Being::setDestination(getTileX(), getTileY()); -#endif - return; - } - - 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 -#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; - - // Walk to where the player can actually go - if ((dx || dy) && mMap->getWalk(getTileX() + dx, getTileY() + dy, getWalkMask())) - { - setDestination(getTileX() + dx, getTileY() + dy); - } -#endif - else if (dir) - { - // If the being can't move, just change direction - Net::getPlayerHandler()->setDirection(dir); - setDirection(dir); - } -} - Being *LocalPlayer::getTarget() const { return mTarget; @@ -550,16 +460,130 @@ void LocalPlayer::setDestination(Uint16 x, Uint16 y) void LocalPlayer::setWalkingDir(int dir) { + // This function is called by Game::handleInput() + +#ifdef TMWSERV_SUPPORT + // First if player is pressing key for the direction he is already + // going, do nothing more... + + // Else if he is pressing a key, and its different from what he has + // been pressing, stop (do not send this stop to the server) and + // start in the new direction + if (dir && (dir != getWalkingDir())) + player_node->stopWalking(false); + + // Else, he is not pressing a key, stop (sending to server) + else if (!dir) + { + 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 + if (get_elapsed_time(mLocalWalkTime) < walkingKeyboardDelay) + return; +#endif + mWalkingDir = dir; // If we're not already walking, start walking. - if (mAction != WALK && dir + if (mAction != WALK && dir) + { + walk(dir); + } +} + +void LocalPlayer::walk(unsigned char dir) +{ + // This function is called by setWalkingDir(), + // but also by nextStep() for eAthena... + + // TODO: Evaluate the implementation of this method for tmwserv + if (!mMap || !dir) + return; + #ifdef TMWSERV_SUPPORT - && get_elapsed_time(mLocalWalkTime) >= walkingKeyboardDelay + const Vector &pos = getPosition(); #endif - ) + + if (mAction == WALK && !mPath.empty()) { - walk(dir); + // Just finish the current action, otherwise we get out of sync +#ifdef TMWSERV_SUPPORT + Being::setDestination(pos.x, pos.y); +#else + Being::setDestination(getTileX(), getTileY()); +#endif + return; + } + + 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 +#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; + + // Walk to where the player can actually go + if ((dx || dy) && mMap->getWalk(getTileX() + dx, getTileY() + dy, getWalkMask())) + { + setDestination(getTileX() + dx, getTileY() + dy); + } +#endif + else if (dir) + { + // If the being can't move, just change direction + Net::getPlayerHandler()->setDirection(dir); + setDirection(dir); } } |