diff options
author | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2011-03-15 17:28:16 +0100 |
---|---|---|
committer | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2011-03-15 17:28:16 +0100 |
commit | 21e8d502d07c6cae9580a34dde7587d58e6d3a28 (patch) | |
tree | fd8c9fa711d0e2e60f50333f82dbe43ebd9214a5 /src | |
parent | 25a2abd09e3b76115ed0b6b1a02cdddc6c1c5bfc (diff) | |
download | mana-21e8d502d07c6cae9580a34dde7587d58e6d3a28.tar.gz mana-21e8d502d07c6cae9580a34dde7587d58e6d3a28.tar.bz2 mana-21e8d502d07c6cae9580a34dde7587d58e6d3a28.tar.xz mana-21e8d502d07c6cae9580a34dde7587d58e6d3a28.zip |
Basically merged the two movement algorithms into one.
This was made in favour of the manaserv way of doing things.
I also added a way to keep the original server speed value
so the pixel value can be recomputed at each map change, as this
was necessary since the speed is given before the first map
is loaded.
The code is much more simpler now about movement handling,
and we can already see improvements on other characters
movements in The Mana World with this.
Everything can't be perfect the first time; here are bugs
identified so far:
- Monsters direction isn't updated on TmwAthena for obscure reasons.
- Remote players walking animation is sometimes reset on each steps.
- When changing map, the local player sometimes walks randomly
until the player reacts.
Stay tuned!
Diffstat (limited to 'src')
-rw-r--r-- | src/actor.h | 2 | ||||
-rw-r--r-- | src/being.cpp | 249 | ||||
-rw-r--r-- | src/being.h | 79 | ||||
-rw-r--r-- | src/gui/viewport.cpp | 119 | ||||
-rw-r--r-- | src/localplayer.cpp | 301 | ||||
-rw-r--r-- | src/net/manaserv/beinghandler.cpp | 39 | ||||
-rw-r--r-- | src/net/manaserv/beinghandler.h | 8 | ||||
-rw-r--r-- | src/net/manaserv/playerhandler.cpp | 33 | ||||
-rw-r--r-- | src/net/manaserv/playerhandler.h | 4 | ||||
-rw-r--r-- | src/net/playerhandler.h | 13 | ||||
-rw-r--r-- | src/net/tmwa/beinghandler.cpp | 57 | ||||
-rw-r--r-- | src/net/tmwa/beinghandler.h | 3 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.cpp | 6 | ||||
-rw-r--r-- | src/net/tmwa/gamehandler.cpp | 15 | ||||
-rw-r--r-- | src/net/tmwa/gamehandler.h | 7 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.cpp | 75 | ||||
-rw-r--r-- | src/net/tmwa/playerhandler.h | 4 | ||||
-rw-r--r-- | src/sound.cpp | 7 | ||||
-rw-r--r-- | src/sound.h | 4 |
19 files changed, 377 insertions, 648 deletions
diff --git a/src/actor.h b/src/actor.h index 367bcd75..1442d4b3 100644 --- a/src/actor.h +++ b/src/actor.h @@ -112,7 +112,7 @@ public: */ virtual void setAlpha(float alpha) = 0; - void setMap(Map *map); + virtual void setMap(Map *map); Map* getMap() const { return mMap; } diff --git a/src/being.cpp b/src/being.cpp index 4d682ab8..86bebea2 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -71,7 +71,6 @@ static const int DEFAULT_BEING_WIDTH = 32; static const int DEFAULT_BEING_HEIGHT = 32; int Being::mNumberOfHairstyles = 1; -// TODO: mWalkTime used by eAthena only Being::Being(int id, Type type, int subtype, Map *map): ActorSprite(id), mInfo(BeingInfo::Unknown), @@ -91,7 +90,7 @@ Being::Being(int id, Type type, int subtype, Map *map): mParty(NULL), mIsGM(false), mType(type), - mX(0), mY(0), + mSpeedPixelsPerTick(Vector(0.0f, 0.0f, 0.0f)), mDamageTaken(0), mIp(0) { @@ -100,7 +99,7 @@ Being::Being(int id, Type type, int subtype, Map *map): mSpeechBubble = new SpeechBubble; - mWalkSpeed = Net::getPlayerHandler()->getDefaultWalkSpeed(); + mMoveSpeed = Net::getPlayerHandler()->getDefaultMoveSpeed(); if (getType() == PLAYER) mShowName = config.getBoolValue("visiblenames"); @@ -168,6 +167,15 @@ Map::BlockType Being::getBlockType() const return mInfo->getBlockType(); } +void Being::setMoveSpeed(Vector speed) +{ + mMoveSpeed = speed; + // If we already can, recalculate the system speed right away. + if (mMap) + mSpeedPixelsPerTick = + Net::getPlayerHandler()->getPixelsPerTickMoveSpeed(speed); +} + void Being::setPosition(const Vector &pos) { Actor::setPosition(pos); @@ -181,21 +189,12 @@ void Being::setPosition(const Vector &pos) void Being::setDestination(int dstX, int dstY) { - if (Net::getNetworkType() == ServerInfo::TMWATHENA) - { - if (mMap) - setPath(mMap->findPath(mX, mY, dstX, dstY, getWalkMask())); - return; - } - - // Manaserv's part: - // We can't calculate anything without a map anyway. if (!mMap) return; // Don't handle flawed destinations from server... - if (dstX == 0 || dstY == 0) + if (dstX <= 0 || dstY <= 0) return; // If the destination is unwalkable, don't bother trying to get there @@ -237,13 +236,6 @@ void Being::clearPath() void Being::setPath(const Path &path) { mPath = path; - - if ((Net::getNetworkType() == ServerInfo::TMWATHENA) && - mAction != MOVE && mAction != DEAD) - { - nextTile(); - mActionTime = tick_time; - } } void Being::setSpeech(const std::string &text, int time) @@ -398,14 +390,9 @@ void Being::handleAttack(Being *victim, int damage, AttackType type) else fireMissile(victim, mInfo->getAttack(mAttackType)->missileParticle); - if (Net::getNetworkType() == ServerInfo::TMWATHENA) - { - reset(); - mActionTime = tick_time; - } - sound.playSfx(mInfo->getSound((damage > 0) ? - SOUND_EVENT_HIT : SOUND_EVENT_MISS), mX, mY); + SOUND_EVENT_HIT : SOUND_EVENT_MISS), + getPixelX(), getPixelY()); } void Being::setName(const std::string &name) @@ -597,28 +584,26 @@ void Being::setAction(Action action, int attackType) currentAction = mInfo->getAttack(attackType)->action; reset(); - if (Net::getNetworkType() == ServerInfo::MANASERV) + int rotation = 0; + //attack particle effect + std::string particleEffect = mInfo->getAttack(attackType) + ->particleEffect; + if (!particleEffect.empty() && Particle::enabled) { - int rotation = 0; - //attack particle effect - std::string particleEffect = mInfo->getAttack(attackType) - ->particleEffect; - if (!particleEffect.empty() && Particle::enabled) + switch (mSpriteDirection) { - switch (mSpriteDirection) - { - case DIRECTION_DOWN: rotation = 0; break; - case DIRECTION_LEFT: rotation = 90; break; - case DIRECTION_UP: rotation = 180; break; - case DIRECTION_RIGHT: rotation = 270; break; - default: break; - } - Particle *p; - p = particleEngine->addEffect(particleEffect, 0, 0, - rotation); - controlParticle(p); + case DIRECTION_DOWN: rotation = 0; break; + case DIRECTION_LEFT: rotation = 90; break; + case DIRECTION_UP: rotation = 180; break; + case DIRECTION_RIGHT: rotation = 270; break; + default: break; } + Particle *p; + p = particleEngine->addEffect(particleEffect, 0, 0, + rotation); + controlParticle(p); } + } break; @@ -630,7 +615,8 @@ void Being::setAction(Action action, int attackType) break; case DEAD: currentAction = SpriteAction::DEAD; - sound.playSfx(mInfo->getSound(SOUND_EVENT_DIE), mX, mY); + sound.playSfx(mInfo->getSound(SOUND_EVENT_DIE), + getPixelX(), getPixelY()); break; case STAND: currentAction = SpriteAction::STAND; @@ -649,11 +635,8 @@ void Being::setAction(Action action, int attackType) void Being::setDirection(Uint8 direction) { - if (Net::getNetworkType() == ServerInfo::MANASERV) - { - if (mDirection == direction) - return; - } + if (mDirection == direction) + return; mDirection = direction; @@ -671,45 +654,9 @@ void Being::setDirection(Uint8 direction) CompoundSprite::setDirection(dir); } -/** Note: Used by Tmw-Athena only */ -void Being::nextTile() -{ - if (mPath.empty()) - { - setAction(STAND); - return; - } - - Position pos = mPath.front(); - mPath.pop_front(); - - int dir = 0; - if (pos.x > mX) - dir |= RIGHT; - else if (pos.x < mX) - dir |= LEFT; - if (pos.y > mY) - dir |= DOWN; - else if (pos.y < mY) - dir |= UP; - - setDirection(dir); - - if (!mMap->getWalk(pos.x, pos.y, getWalkMask())) - { - setAction(STAND); - return; - } - - mX = pos.x; - mY = pos.y; - setAction(MOVE); - mActionTime += (int)(mWalkSpeed.x / 10); -} - int Being::getCollisionRadius() const { - // FIXME: Get this from XML file + // FIXME: Get this from XML file once a better pathfinding algorithm is up. return 16; } @@ -726,8 +673,7 @@ void Being::logic() mText = 0; } - if ((Net::getNetworkType() == ServerInfo::MANASERV) && (mAction != DEAD) - && !mWalkSpeed.isNull()) + if ((mAction != DEAD) && !mSpeedPixelsPerTick.isNull()) { const Vector dest = (mPath.empty()) ? mDest : Vector(mPath.front().x, @@ -758,8 +704,8 @@ void Being::logic() // รข = a / ||a|| (||a|| is the a length.) // Then, diff = (dir/||dir||) * speed. const Vector normalizedDir = dir.normalized(); - Vector diff(normalizedDir.x * mWalkSpeed.x, - normalizedDir.y * mWalkSpeed.y); + Vector diff(normalizedDir.x * mSpeedPixelsPerTick.x, + normalizedDir.y * mSpeedPixelsPerTick.y); // Test if we don't miss the destination by a move too far: if (diff.length() > distance) @@ -821,75 +767,6 @@ void Being::logic() setAction(STAND); } } - else if (Net::getNetworkType() == ServerInfo::TMWATHENA) - { - int frameCount = getFrameCount(); - - switch (mAction) - { - case STAND: - case SIT: - case DEAD: - case HURT: - break; - - case MOVE: - if ((int) ((get_elapsed_time(mActionTime) * frameCount) - / getWalkSpeed().x) >= frameCount) - nextTile(); - break; - - case ATTACK: - int rotation = 0; - std::string particleEffect = ""; - - int curFrame = (get_elapsed_time(mActionTime) * frameCount) - / mAttackSpeed; - - //attack particle effect - if (mEquippedWeapon) - { - particleEffect = mEquippedWeapon->getParticleEffect(); - - if (!particleEffect.empty() && - findSameSubstring(particleEffect, - paths.getStringValue("particles")).empty()) - particleEffect = paths.getStringValue("particles") - + particleEffect; - } - else - { - particleEffect = mInfo->getAttack(mAttackType) - ->particleEffect; - } - - if (!particleEffect.empty() && Particle::enabled - && curFrame == 1) - { - switch (mDirection) - { - case DOWN: rotation = 0; break; - case LEFT: rotation = 90; break; - case UP: rotation = 180; break; - case RIGHT: rotation = 270; break; - default: break; - } - Particle *p; - p = particleEngine->addEffect(particleEffect, 0, 0, - rotation); - controlParticle(p); - } - - if (curFrame >= frameCount) - nextTile(); - - break; - } - - // Update pixel coordinates - setPosition(mX * 32 + 16 + getXOffset(), - mY * 32 + 32 + getYOffset()); - } ActorSprite::logic(); @@ -897,9 +774,9 @@ void Being::logic() if (frameCount < 10) frameCount = 10; + // Remove it after 3 secs. TODO: Just play the dead animation before removing if (!isAlive() && Net::getGameHandler()->removeDeadBeings() && - (int) ((get_elapsed_time(mActionTime) - / getWalkSpeed().x) >= frameCount)) + get_elapsed_time(mActionTime) > 3000) { if (getType() != PLAYER) actorSpriteManager->destroy(this); @@ -960,36 +837,6 @@ void Being::drawSpeech(int offsetX, int offsetY) } } -/** Note: Used by Tmw-Athena only */ -int Being::getOffset(char pos, char neg) const -{ - // Check whether we're walking in the requested direction - if (mAction != MOVE || !(mDirection & (pos | neg))) - return 0; - - int offset = 0; - - if (mMap) - { - offset = (pos == LEFT && neg == RIGHT) ? - (int)((get_elapsed_time(mActionTime) - * mMap->getTileWidth()) / mWalkSpeed.x) : - (int)((get_elapsed_time(mActionTime) - * mMap->getTileHeight()) / mWalkSpeed.y); - } - - // We calculate the offset _from_ the _target_ location - offset -= 32; - if (offset > 0) - offset = 0; - - // Going into negative direction? Invert the offset. - if (mDirection & pos) - offset = -offset; - - return offset; -} - int Being::getWidth() const { return std::max(CompoundSprite::getWidth(), DEFAULT_BEING_WIDTH); @@ -1229,8 +1076,8 @@ void Being::talkTo() void Being::event(Channels channel, const Mana::Event &event) { if (channel == CHANNEL_CHAT && - (event.getName() == EVENT_BEING || event.getName() == EVENT_PLAYER) && - event.getInt("permissions") & PlayerRelation::SPEECH_FLOAT) + (event.getName() == EVENT_BEING || event.getName() == EVENT_PLAYER) + && event.getInt("permissions") & PlayerRelation::SPEECH_FLOAT) { try { @@ -1252,3 +1099,15 @@ void Being::event(Channels channel, const Mana::Event &event) } } + +void Being::setMap(Map *map) +{ + Actor::setMap(map); + + // Recalculate pixel/tick speed + if (map && !mMoveSpeed.isNull()) + { + mSpeedPixelsPerTick = + Net::getPlayerHandler()->getPixelsPerTickMoveSpeed(mMoveSpeed, map); + } +} diff --git a/src/being.h b/src/being.h index 7f6f8007..fcd2b8f8 100644 --- a/src/being.h +++ b/src/being.h @@ -118,7 +118,8 @@ class Being : public ActorSprite, public Mana::Listener virtual ~Being(); - Type getType() const { return mType; } + Type getType() const + { return mType; } /** * Removes all path nodes from this being. @@ -126,37 +127,6 @@ class Being : public ActorSprite, public Mana::Listener void clearPath(); /** - * Returns the time spent in the current action. - */ - int getActionTime() const { return mActionTime; } - - /** - * Set the current action time. - * @see Ea::BeingHandler that set it to tick time. - */ - void setActionTime(int actionTime) { mActionTime = actionTime; } - - /** - * Makes this being take the next tile of its path. - * TODO: Used by eAthena only? - */ - virtual void nextTile(); - - /** - * Get the current X pixel offset. - * TODO: Used by eAthena only? - */ - int getXOffset() const - { return getOffset(LEFT, RIGHT); } - - /** - * Get the current Y pixel offset. - * TODO: Used by eAthena only? - */ - int getYOffset() const - { return getOffset(UP, DOWN); } - - /** * Creates a path for the being from current position to ex and ey */ void setDestination(int ex, int ey); @@ -164,25 +134,20 @@ class Being : public ActorSprite, public Mana::Listener /** * Returns the destination for this being. */ - const Vector &getDestination() const { return mDest; } + const Vector &getDestination() const + { return mDest; } /** * Returns the tile x coord */ int getTileX() const - { return mX; } + { return mPos.x / mMap->getTileWidth(); } /** * Returns the tile y coord */ int getTileY() const - { return mY; } - - /** - * Sets the tile x and y coord - */ - void setTileCoords(int x, int y) - { mX = x; mY = y; } + { return mPos.y / mMap->getTileHeight(); } /** * Puts a "speech balloon" above this being for the specified amount @@ -343,18 +308,18 @@ class Being : public ActorSprite, public Mana::Listener Map::BlockType getBlockType() const; /** - * Sets the walk speed. - * in pixels per second for eAthena, + * Sets the move speed. + * in ticks per tile for eAthena, * in tiles per second for Manaserv. */ - void setWalkSpeed(Vector speed) { mWalkSpeed = speed; } + void setMoveSpeed(Vector speed); /** - * Gets the walk speed. - * in pixels per second for eAthena, + * Gets the original Move speed. + * in ticks per tile for eAthena, * in tiles per second for Manaserv (0.1 precision). */ - Vector getWalkSpeed() const { return mWalkSpeed; } + Vector getMoveSpeed() const { return mMoveSpeed; } /** * Sets the attack speed. @@ -483,6 +448,8 @@ class Being : public ActorSprite, public Mana::Listener void event(Channels channel, const Mana::Event &event); + void setMap(Map *map); + protected: /** * Sets the new path for this being. @@ -500,7 +467,7 @@ class Being : public ActorSprite, public Mana::Listener BeingInfo *mInfo; - int mActionTime; /**< Time spent in current action */ + int mActionTime; /**< Time spent in current action. TODO: Remove use of it */ /** Time until the last speech sentence disappears */ int mSpeechTime; @@ -547,13 +514,6 @@ class Being : public ActorSprite, public Mana::Listener private: - /** - * Calculates the offset in the given directions. - * If walking in direction 'neg' the value is negated. - * TODO: Used by eAthena only? - */ - int getOffset(char pos, char neg) const; - const Type mType; /** Speech Bubble components */ @@ -561,13 +521,16 @@ class Being : public ActorSprite, public Mana::Listener /** * Walk speed for x and y movement values. - * In pixels per second for eAthena, + * In ticks per tile for eAthena, * In pixels per ticks for Manaserv. * @see MILLISECONDS_IN_A_TICK */ - Vector mWalkSpeed; + Vector mMoveSpeed; - int mX, mY; /**< Position in tile */ + /** + * Being speed in pixel per ticks. Used internally for the being logic. + */ + Vector mSpeedPixelsPerTick; int mDamageTaken; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index ac910d5f..459edab5 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -261,43 +261,27 @@ void Viewport::_drawDebugPath(Graphics *graphics) Path debugPath; - if (Net::getNetworkType() == ServerInfo::TMWATHENA) - { - const int mouseTileX = (mMouseX + (int) mPixelViewX) / 32; - const int mouseTileY = (mMouseY + (int) mPixelViewY) / 32; - const Vector &playerPos = player_node->getPosition(); - - debugPath = mMap->findPath( - (int) (playerPos.x - 16) / 32, - (int) (playerPos.y - 32) / 32, - mouseTileX, mouseTileY, 0xFF); - - _drawPath(graphics, debugPath); - } - else if (Net::getNetworkType() == ServerInfo::MANASERV) - { - const Vector &playerPos = player_node->getPosition(); - const int playerRadius = player_node->getCollisionRadius(); - // Draw player collision rectangle - graphics->setColor(gcn::Color(128, 128, 0, 120)); - graphics->fillRectangle( - gcn::Rectangle((int) playerPos.x - (int) mPixelViewX - playerRadius, - (int) playerPos.y - (int) mPixelViewY - playerRadius, - playerRadius * 2, playerRadius * 2)); - - debugPath = mMap->findPixelPath( - (int) playerPos.x, - (int) playerPos.y, - mMouseX + (int) mPixelViewX, - mMouseY + (int) mPixelViewY, - playerRadius, 0xFF); - - // We draw the path proposed by mouse - _drawPath(graphics, debugPath, gcn::Color(128, 0, 128)); - - // But also the one currently walked on. - _drawPath(graphics, player_node->getPath(), gcn::Color(0, 0, 255)); - } + const Vector &playerPos = player_node->getPosition(); + const int playerRadius = player_node->getCollisionRadius(); + // Draw player collision rectangle + graphics->setColor(gcn::Color(128, 128, 0, 120)); + graphics->fillRectangle( + gcn::Rectangle((int) playerPos.x - (int) mPixelViewX - playerRadius, + (int) playerPos.y - (int) mPixelViewY - playerRadius, + playerRadius * 2, playerRadius * 2)); + + debugPath = mMap->findPixelPath( + (int) playerPos.x, + (int) playerPos.y, + mMouseX + (int) mPixelViewX, + mMouseY + (int) mPixelViewY, + playerRadius, 0xFF); + + // We draw the path proposed by mouse + _drawPath(graphics, debugPath, gcn::Color(128, 0, 128)); + + // But also the one currently walked on. + _drawPath(graphics, player_node->getPath(), gcn::Color(0, 0, 255)); } void Viewport::_drawPath(Graphics *graphics, const Path &path, @@ -305,33 +289,16 @@ void Viewport::_drawPath(Graphics *graphics, const Path &path, { graphics->setColor(color); - if (Net::getNetworkType() == ServerInfo::TMWATHENA) + for (Path::const_iterator i = path.begin(); i != path.end(); ++i) { - for (Path::const_iterator i = path.begin(); i != path.end(); ++i) - { - int squareX = i->x * 32 - (int) mPixelViewX + 12; - int squareY = i->y * 32 - (int) mPixelViewY + 12; - - graphics->fillRectangle(gcn::Rectangle(squareX, squareY, 8, 8)); - graphics->drawText( - toString(mMap->getMetaTile(i->x, i->y)->Gcost), - squareX + 4, squareY + 12, gcn::Graphics::CENTER); - } - } - else if (Net::getNetworkType() == ServerInfo::MANASERV) - { - for (Path::const_iterator i = path.begin(); i != path.end(); ++i) - { - int squareX = i->x - (int) mPixelViewX; - int squareY = i->y - (int) mPixelViewY; - - graphics->fillRectangle(gcn::Rectangle(squareX - 4, squareY - 4, - 8, 8)); - graphics->drawText( - toString(mMap->getMetaTile(i->x / 32, i->y / 32)->Gcost), - squareX + 4, squareY + 12, gcn::Graphics::CENTER); - } - + int squareX = i->x - (int) mPixelViewX; + int squareY = i->y - (int) mPixelViewY; + + graphics->fillRectangle(gcn::Rectangle(squareX - 4, squareY - 4, + 8, 8)); + graphics->drawText( + toString(mMap->getMetaTile(i->x / 32, i->y / 32)->Gcost), + squareX + 4, squareY + 12, gcn::Graphics::CENTER); } } @@ -441,25 +408,12 @@ void Viewport::mouseDragged(gcn::MouseEvent &event) if (mPlayerFollowMouse && !event.isShiftPressed()) { - if (Net::getNetworkType() == ServerInfo::MANASERV) + if (get_elapsed_time(mLocalWalkTime) >= walkingMouseDelay) { - if (get_elapsed_time(mLocalWalkTime) >= walkingMouseDelay) - { - mLocalWalkTime = tick_time; - player_node->setDestination(event.getX() + (int) mPixelViewX, - event.getY() + (int) mPixelViewY); - player_node->pathSetByMouse(); - } - } - else - { - if (mLocalWalkTime != player_node->getActionTime()) - { - mLocalWalkTime = player_node->getActionTime(); - int destX = (event.getX() + mPixelViewX) / mMap->getTileWidth(); - int destY = (event.getY() + mPixelViewY) / mMap->getTileHeight(); - player_node->setDestination(destX, destY); - } + mLocalWalkTime = tick_time; + player_node->setDestination(event.getX() + (int) mPixelViewX, + event.getY() + (int) mPixelViewY); + player_node->pathSetByMouse(); } } } @@ -467,9 +421,6 @@ void Viewport::mouseDragged(gcn::MouseEvent &event) void Viewport::mouseReleased(gcn::MouseEvent &event) { mPlayerFollowMouse = false; - - // Only useful for eAthena but doesn't hurt under ManaServ - mLocalWalkTime = -1; } void Viewport::showPopup(Window *parent, int x, int y, Item *item, diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 3e59e794..52168237 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -157,15 +157,8 @@ void LocalPlayer::logic() else { // Find whether target is in range - // TODO: Make this nicer, probably using getPosition() only - const int rangeX = - (Net::getNetworkType() == ServerInfo::MANASERV) ? - abs(mTarget->getPosition().x - getPosition().x) : - abs(mTarget->getTileX() - getTileX()); - const int rangeY = - (Net::getNetworkType() == ServerInfo::MANASERV) ? - abs(mTarget->getPosition().y - getPosition().y) : - abs(mTarget->getTileY() - getTileY()); + const int rangeX = abs(mTarget->getPosition().x - getPosition().x); + const int rangeY = abs(mTarget->getPosition().y - getPosition().y); const int attackRange = getAttackRange(); const TargetCursorType targetType = rangeX > attackRange || @@ -549,56 +542,22 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir) void LocalPlayer::nextTile(unsigned char dir = 0) { - if (Net::getNetworkType() == ServerInfo::TMWATHENA) - { - // TODO: Fix picking up when reaching target (this method is obsolete) - // TODO: Fix holding walking button to keep walking smoothly - if (mPath.empty()) - { - if (mPickUpTarget) - pickUp(mPickUpTarget); - - if (mWalkingDir) - startWalking(mWalkingDir); - } - - // TODO: Fix automatically walking within range of target, when wanted - if (mGoingToTarget && mTarget && withinAttackRange(mTarget)) - { - mAction = Being::STAND; - attack(mTarget, true); - mGoingToTarget = false; - mPath.clear(); - return; - } - else if (mGoingToTarget && !mTarget) - { - mGoingToTarget = false; - mPath.clear(); - } + if (!mMap || !dir) + return; + const Vector &pos = getPosition(); + Position destination = getNextWalkPosition(dir); - Being::nextTile(); + if ((int)pos.x != destination.x + || (int)pos.y != destination.y) + { + setDestination(destination.x, destination.y); } - else + else if (dir != mDirection) { - if (!mMap || !dir) - return; - - const Vector &pos = getPosition(); - Position destination = getNextWalkPosition(dir); - - if ((int)pos.x != destination.x - || (int)pos.y != destination.y) - { - setDestination(destination.x, destination.y); - } - else if (dir != mDirection) - { - // If the being can't move, just change direction - Net::getPlayerHandler()->setDirection(dir); - setDirection(dir); - } + // If the being can't move, just change direction + Net::getPlayerHandler()->setDirection(dir); + setDirection(dir); } } @@ -637,9 +596,10 @@ void LocalPlayer::pickUp(FloorItem *item) if (!item) return; - int dx = item->getTileX() - (int) getPosition().x / mMap->getTileWidth(); - int dy = item->getTileY() - ((int) getPosition().y - 1) - / mMap->getTileHeight(); + int tileWidth = mMap->getTileWidth(); + int tileHeight = mMap->getTileHeight(); + int dx = item->getTileX() - (int) getPosition().x / tileWidth; + int dy = item->getTileY() - ((int) getPosition().y - 1) / tileHeight; if (dx * dx + dy * dy < 4) { @@ -648,17 +608,9 @@ void LocalPlayer::pickUp(FloorItem *item) } else { - if (Net::getNetworkType() == ServerInfo::MANASERV) - { - setDestination(item->getPixelX() + 16, item->getPixelY() + 16); - mPickUpTarget = item; - } - else - { - setDestination(item->getTileX(), item->getTileY()); - mPickUpTarget = item; - stopAttack(); - } + setDestination(item->getPixelX() + tileWidth / 2, + item->getPixelY() + tileHeight / 2); + mPickUpTarget = item; } } @@ -716,12 +668,10 @@ void LocalPlayer::setDestination(int x, int y) { Being::setDestination(x, y); - // Manaserv: // If the destination given to being class is accepted, // we inform the Server. - if ((x == mDest.x && y == mDest.y) - || Net::getNetworkType() == ServerInfo::TMWATHENA) - Net::getPlayerHandler()->setDestination(x, y, mDirection); + if ((x == mDest.x && y == mDest.y)) + Net::getPlayerHandler()->setDestination(x, y, mDirection); } mPickUpTarget = NULL; @@ -732,29 +682,26 @@ void LocalPlayer::setWalkingDir(int dir) { // This function is called by Game::handleInput() - if (Net::getNetworkType() == ServerInfo::MANASERV) - { - // 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, - // and the current path hasn't been sent by mouse, - // then let the path die (1/2 tile after that.) - // This permit to avoid desyncs with other clients. - else if (!dir) - return; + // First if player is pressing key for the direction he is already + // going, do nothing more... - // 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; - } + // 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, + // and the current path hasn't been sent by mouse, + // then let the path die (1/2 tile after that.) + // This permit to avoid desyncs with other clients. + else if (!dir) + 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; mWalkingDir = dir; @@ -763,7 +710,7 @@ void LocalPlayer::setWalkingDir(int dir) { startWalking(dir); } - else if (mAction == MOVE && (Net::getNetworkType() == ServerInfo::MANASERV)) + else if (mAction == MOVE) { nextTile(dir); } @@ -779,13 +726,8 @@ void LocalPlayer::startWalking(unsigned char dir) if (mAction == MOVE && !mPath.empty()) { // Just finish the current action, otherwise we get out of sync - if (Net::getNetworkType() == ServerInfo::MANASERV) - { - const Vector &pos = getPosition(); - Being::setDestination(pos.x, pos.y); - } - else - Being::setDestination(getTileX(), getTileY()); + const Vector &pos = getPosition(); + Being::setDestination(pos.x, pos.y); return; } @@ -800,37 +742,9 @@ void LocalPlayer::startWalking(unsigned char dir) dx++; // Update the direction when the walk just start - if (Net::getNetworkType() == ServerInfo::MANASERV) - setDirection(dir); + setDirection(dir); - if (Net::getNetworkType() == ServerInfo::TMWATHENA) - { - // Prevent skipping corners over colliding tiles - if (dx && !mMap->getWalk(getTileX() + dx, getTileY(), getWalkMask())) - dx = 0; - if (dy && !mMap->getWalk(getTileX(), getTileY() + dy, getWalkMask())) - dy = 0; - - // Choose a straight direction when diagonal target is blocked - 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); - } - else if (dir != mDirection) - { - // If the being can't move, just change direction - Net::getPlayerHandler()->setDirection(dir); - setDirection(dir); - } - } - else - nextTile(dir); + nextTile(dir); } void LocalPlayer::stopWalking(bool sendToServer) @@ -881,15 +795,12 @@ void LocalPlayer::emote(Uint8 emotion) void LocalPlayer::attack(Being *target, bool keep) { - if (Net::getNetworkType() == ServerInfo::MANASERV) - { - if (mLastAction != -1) - return; + if (mLastAction != -1) + return; - // Can only attack when standing still - if (mAction != STAND && mAction != ATTACK) - return; - } + // Can only attack when standing still + if (mAction != STAND && mAction != ATTACK) + return; mKeepAttacking = keep; @@ -902,61 +813,28 @@ void LocalPlayer::attack(Being *target, bool keep) setTarget(target); } - if (Net::getNetworkType() == ServerInfo::MANASERV) - { - Vector plaPos = this->getPosition(); - Vector tarPos = mTarget->getPosition(); - int dist_x = plaPos.x - tarPos.x; - int dist_y = plaPos.y - tarPos.y; + Vector plaPos = this->getPosition(); + Vector tarPos = mTarget->getPosition(); + int dist_x = plaPos.x - tarPos.x; + int dist_y = plaPos.y - tarPos.y; - if (abs(dist_y) >= abs(dist_x)) - { - if (dist_y < 0) - setDirection(DOWN); - else - setDirection(UP); - } + if (abs(dist_y) >= abs(dist_x)) + { + if (dist_y < 0) + setDirection(DOWN); else - { - if (dist_x < 0) - setDirection(RIGHT); - else - setDirection(LEFT); - } - - mLastAction = tick_time; + setDirection(UP); } else { - int dist_x = target->getTileX() - getTileX(); - int dist_y = target->getTileY() - getTileY(); - - // Must be standing to attack - if (mAction != STAND) - return; - - Uint8 direction = 0; - if (abs(dist_y) >= abs(dist_x)) - { - if (dist_y > 0) - direction = DOWN; - else - direction = UP; - } + if (dist_x < 0) + setDirection(RIGHT); else - { - if (dist_x > 0) - direction = RIGHT; - else - direction = LEFT; - } - Net::getPlayerHandler()->setDirection(direction); - setDirection(direction); - - mActionTime = tick_time; - mTargetTime = tick_time; + setDirection(LEFT); } + mLastAction = tick_time; + setAction(ATTACK); if (mEquippedWeapon) @@ -966,11 +844,11 @@ void LocalPlayer::attack(Being *target, bool keep) sound.playSfx(soundFile); } else + { sound.playSfx(paths.getValue("attackSfxFile", "fist-swish.ogg")); + } Net::getPlayerHandler()->attack(target->getId()); - if ((Net::getNetworkType() == ServerInfo::TMWATHENA) && !keep) - stopAttack(); } void LocalPlayer::stopAttack() @@ -1060,44 +938,23 @@ int LocalPlayer::getAttackRange() bool LocalPlayer::withinAttackRange(Being *target) { - if (Net::getNetworkType() == ServerInfo::MANASERV) - { - const Vector &targetPos = target->getPosition(); - const Vector &pos = getPosition(); - const int dx = abs(targetPos.x - pos.x); - const int dy = abs(targetPos.y - pos.y); - const int range = getAttackRange(); - - return !(dx > range || dy > range); - } - else - { - int dist_x = abs(target->getTileX() - getTileX()); - int dist_y = abs(target->getTileY() - getTileY()); - - if (dist_x > getAttackRange() || dist_y > getAttackRange()) - return false; + const Vector &targetPos = target->getPosition(); + const Vector &pos = getPosition(); + const int dx = abs(targetPos.x - pos.x); + const int dy = abs(targetPos.y - pos.y); + const int range = getAttackRange(); - return true; - } + return !(dx > range || dy > range); } void LocalPlayer::setGotoTarget(Being *target) { mLastTarget = -1; - if (Net::getNetworkType() == ServerInfo::MANASERV) - { - mTarget = target; - mGoingToTarget = true; - const Vector &targetPos = target->getPosition(); - setDestination(targetPos.x, targetPos.y); - } - else - { - setTarget(target); - mGoingToTarget = true; - setDestination(target->getTileX(), target->getTileY()); - } + + mTarget = target; + mGoingToTarget = true; + const Vector &targetPos = target->getPosition(); + setDestination(targetPos.x, targetPos.y); } void LocalPlayer::addMessageToQueue(const std::string &message, int color) diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index 6e9b3645..220ecfba 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -89,37 +89,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) } } -Vector BeingHandler::giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds) -{ - Vector speedInTicks; - Game *game = Game::instance(); - Map *map = 0; - if (game) - { - map = game->getCurrentMap(); - if (map) - { - speedInTicks.x = speedInTilesPerSeconds - * (float)map->getTileWidth() - / 1000 * (float) MILLISECONDS_IN_A_TICK; - speedInTicks.y = speedInTilesPerSeconds - * (float)map->getTileHeight() - / 1000 * (float) MILLISECONDS_IN_A_TICK; - } - } - - if (!game || !map) - { - speedInTicks.x = speedInTicks.y = 0; - logger->log("Manaserv::BeingHandler: Speed wasn't given back" - " because game/Map not initialized."); - } - // We don't use z for now. - speedInTicks.z = 0; - - return speedInTicks; -} - static void handleLooks(Being *being, Net::MessageIn &msg) { // Order of sent slots. Has to be in sync with the server code. @@ -237,12 +206,10 @@ void BeingHandler::handleBeingsMoveMessage(Net::MessageIn &msg) * The being's speed is transfered in tiles per second * 10 * to keep it transferable in a Byte. * We set it back to tiles per second and in a float. - * Then, we translate it in pixels per ticks, to correspond - * with the Being::logic() function calls - * @see MILLISECONDS_IN_A_TICK */ - being->setWalkSpeed( - giveSpeedInPixelsPerTicks((float) speed / 10)); + float speedTilesSeconds = (float) speed / 10; + being->setMoveSpeed(Vector(speedTilesSeconds, speedTilesSeconds, + 0)); } // Ignore messages from the server for the local player diff --git a/src/net/manaserv/beinghandler.h b/src/net/manaserv/beinghandler.h index 2e9eb333..04c766d9 100644 --- a/src/net/manaserv/beinghandler.h +++ b/src/net/manaserv/beinghandler.h @@ -35,14 +35,6 @@ class BeingHandler : public MessageHandler void handleMessage(Net::MessageIn &msg); - /** - * Translate a given speed in tiles per seconds - * into pixels per ticks. - * Used to optimize Being::logic() calls. - * @see MILLISECONDS_IN_A_TICKS - */ - static Vector giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds); - private: void handleBeingAttackMessage(Net::MessageIn &msg); void handleBeingEnterMessage(Net::MessageIn &msg); diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp index c071ca04..38eb2678 100644 --- a/src/net/manaserv/playerhandler.cpp +++ b/src/net/manaserv/playerhandler.cpp @@ -412,10 +412,37 @@ int PlayerHandler::getJobLocation() return -1; } -Vector PlayerHandler::getDefaultWalkSpeed() +Vector PlayerHandler::getDefaultMoveSpeed() { - // Return translation in pixels per ticks. - return ManaServ::BeingHandler::giveSpeedInPixelsPerTicks(6.0f); + // Return default speed at 6 tiles per second. + return Vector(6.0f, 6.0f, 0.0f); +} + +Vector PlayerHandler::getPixelsPerTickMoveSpeed(Vector speed, Map *map) +{ + // We don't use z for now. + speed.z = 0; + + Game *game = Game::instance(); + if (game && !map) + map = game->getCurrentMap(); + + if (!map) + { + logger->log("Manaserv::PlayerHandler: Speed wasn't given back" + " because Map not initialized."); + speed.x = speed.y = 0; + return speed; + } + + speed.x = speed.x + * (float)map->getTileWidth() + / 1000 * (float) MILLISECONDS_IN_A_TICK; + speed.y = speed.y + * (float)map->getTileHeight() + / 1000 * (float) MILLISECONDS_IN_A_TICK; + + return speed; } } // namespace ManaServ diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h index 5796b0d3..6069c6da 100644 --- a/src/net/manaserv/playerhandler.h +++ b/src/net/manaserv/playerhandler.h @@ -65,7 +65,9 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler int getJobLocation(); - Vector getDefaultWalkSpeed(); + Vector getDefaultMoveSpeed(); + + Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0); private: void handleMapChangeMessage(Net::MessageIn &msg); diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index d7676a92..23277062 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -62,7 +62,18 @@ class PlayerHandler virtual int getJobLocation() = 0; - virtual Vector getDefaultWalkSpeed() = 0; + /** + * Get the original default movement speed. + * Example: + * In ticks per tiles for eAthena + * In pixels per second for Manaserv + */ + virtual Vector getDefaultMoveSpeed() = 0; + + /** + * Convert the original speed in pixel per tick for internal use. + */ + virtual Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0) = 0; }; } // namespace Net diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 61491692..ddb15428 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -20,11 +20,13 @@ */ #include "net/tmwa/beinghandler.h" +#include "net/tmwa/playerhandler.h" #include "actorspritemanager.h" #include "being.h" #include "client.h" #include "effectmanager.h" +#include "game.h" #include "guild.h" #include "localplayer.h" #include "log.h" @@ -101,7 +103,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) return; int id; - short job, speed, gender; + short job, gender; + float speed; Uint16 headTop, headMid, headBottom; Uint16 shoes, gloves; Uint16 weapon, shield; @@ -114,13 +117,18 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Being *srcBeing, *dstBeing; int hairStyle, hairColor, flag; + // Prepare useful translation variables + Map *map = Game::instance()->getCurrentMap(); + int tileWidth = map->getTileWidth(); + int tileHeight = map->getTileHeight(); + switch (msg.getId()) { case SMSG_BEING_VISIBLE: case SMSG_BEING_MOVE: // Information about a being in range id = msg.readInt32(); - speed = msg.readInt16(); + speed = (float)msg.readInt16(); stunMode = msg.readInt16(); // opt1 statusEffects = msg.readInt16(); // opt2 statusEffects |= ((Uint32)msg.readInt16()) << 16; // option @@ -146,15 +154,14 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) if (msg.getId() == SMSG_BEING_VISIBLE) { dstBeing->clearPath(); - dstBeing->setActionTime(tick_time); dstBeing->setAction(Being::STAND); } - // Prevent division by 0 when calculating frame - if (speed == 0) { speed = 150; } + if (speed == 0) + speed = 150.0f; // In ticks per tile * 10 - dstBeing->setWalkSpeed(Vector(speed, speed, 0)); + dstBeing->setMoveSpeed(Vector(speed / 10, speed / 10)); dstBeing->setSubtype(job); hairStyle = msg.readInt16(); weapon = msg.readInt16(); @@ -206,7 +213,12 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); dstBeing->setAction(Being::STAND); - dstBeing->setTileCoords(srcX, srcY); + Vector pos(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2); + dstBeing->setPosition(pos); + // We turn the destination back to a pixel one. + dstX = dstX * tileWidth + tileWidth / 2; + dstY = dstY * tileHeight + tileHeight / 2; dstBeing->setDestination(dstX, dstY); } else @@ -214,7 +226,9 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Uint8 dir; Uint16 x, y; msg.readCoordinates(x, y, dir); - dstBeing->setTileCoords(x, y); + Vector pos(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2); + dstBeing->setPosition(pos); dstBeing->setDirection(dir); } @@ -256,9 +270,10 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) msg.readInt32(); // Server tick dstBeing->setAction(Being::STAND); - dstBeing->setTileCoords(srcX, srcY); - dstBeing->setDestination(dstX, dstY); - + dstBeing->setPosition(Vector(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2)); + dstBeing->setDestination(dstX * tileWidth + tileWidth / 2, + dstY * tileHeight + tileHeight / 2); break; case SMSG_BEING_REMOVE: @@ -519,7 +534,12 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) } } - dstBeing->setWalkSpeed(Vector(speed, speed, 0)); + // The original speed is ticks per tile * 10 + if (speed) + dstBeing->setMoveSpeed(Vector(speed / 10, speed / 10)); + else + dstBeing->setMoveSpeed(Net::getPlayerHandler()->getDefaultMoveSpeed()); + dstBeing->setSubtype(job); hairStyle = msg.readInt16(); weapon = msg.readInt16(); @@ -561,15 +581,18 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - dstBeing->setTileCoords(srcX, srcY); - dstBeing->setDestination(dstX, dstY); + dstBeing->setPosition(Vector(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2)); + dstBeing->setDestination(dstX * tileWidth + tileWidth / 2, + dstY * tileHeight + tileHeight / 2); } else { Uint8 dir; Uint16 x, y; msg.readCoordinates(x, y, dir); - dstBeing->setTileCoords(x, y); + dstBeing->setPosition(Vector(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2)); dstBeing->setDirection(dir); } @@ -598,7 +621,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) msg.readInt8(); // Lv msg.readInt8(); // unknown - dstBeing->setActionTime(tick_time); dstBeing->reset(); dstBeing->setStunMode(stunMode); @@ -628,7 +650,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Uint16 x, y; x = msg.readInt16(); y = msg.readInt16(); - dstBeing->setTileCoords(x, y); + dstBeing->setPosition(Vector(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2)); if (dstBeing->getCurrentAction() == Being::MOVE) dstBeing->setAction(Being::STAND); } diff --git a/src/net/tmwa/beinghandler.h b/src/net/tmwa/beinghandler.h index ab833af0..32b4a7bd 100644 --- a/src/net/tmwa/beinghandler.h +++ b/src/net/tmwa/beinghandler.h @@ -22,6 +22,9 @@ #ifndef NET_TA_BEINGHANDLER_H #define NET_TA_BEINGHANDLER_H +#include "vector.h" + +#include "net/net.h" #include "net/tmwa/messagehandler.h" namespace TmwAthena { diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index 1063ee39..e6dc84a2 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -185,7 +185,11 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg) mNetwork->disconnect(); Client::setState(STATE_CHANGE_MAP); - player_node->setTileCoords(x, y); + Map *map = player_node->getMap(); + int tileWidth = map->getTileWidth(); + int tileHeight = map->getTileHeight(); + player_node->setPosition(Vector(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2)); player_node->setMap(0); } break; diff --git a/src/net/tmwa/gamehandler.cpp b/src/net/tmwa/gamehandler.cpp index 63f5fcec..a72c12da 100644 --- a/src/net/tmwa/gamehandler.cpp +++ b/src/net/tmwa/gamehandler.cpp @@ -76,7 +76,8 @@ void GameHandler::handleMessage(Net::MessageIn &msg) x, y, direction); // Switch now or we'll have problems Client::setState(STATE_GAME); - player_node->setTileCoords(x, y); + // Stores the position until the map is loaded. + mTileX = x; mTileY = y; } break; case SMSG_SERVER_PING: @@ -111,7 +112,17 @@ void GameHandler::event(Channels channel, const Mana::Event &event) { if (event.getName() == EVENT_ENGINESINITALIZED) { - Game::instance()->changeMap(mMap); + Game *game = Game::instance(); + game->changeMap(mMap); + Map *map = game->getCurrentMap(); + int tileWidth = map->getTileWidth(); + int tileHeight = map->getTileHeight(); + if (mTileX && mTileY) + { + player_node->setPosition(Vector(mTileX * tileWidth + tileWidth / 2, + mTileY * tileHeight + tileHeight / 2)); + mTileX = mTileY = 0; + } } else if (event.getName() == EVENT_MAPLOADED) { diff --git a/src/net/tmwa/gamehandler.h b/src/net/tmwa/gamehandler.h index 18317445..7aa18b12 100644 --- a/src/net/tmwa/gamehandler.h +++ b/src/net/tmwa/gamehandler.h @@ -65,8 +65,13 @@ class GameHandler : public MessageHandler, public Net::GameHandler, bool canUseMagicBar() const { return true; } private: - std::string mMap; + std::string mMap; ///< Keeps the map filename. int mCharID; /// < Saved for map-server switching + /** + * Keeps the local character position until the map is loaded + * to permit the translation in pixels. + */ + int mTileX, mTileY; }; } // namespace TmwAthena diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index b82968a3..181ff39c 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -20,7 +20,9 @@ */ #include "net/tmwa/playerhandler.h" +#include "net/tmwa/beinghandler.h" +#include "client.h" #include "event.h" #include "game.h" #include "localplayer.h" @@ -198,20 +200,23 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) float scrollOffsetX = 0.0f; float scrollOffsetY = 0.0f; - /* Scroll if neccessary */ + /* Scroll if necessary */ + Map *map = game->getCurrentMap(); + int tileWidth = map->getTileWidth(); + int tileHeight = map->getTileHeight(); + int tileX = player_node->getTileX(); + int tileY = player_node->getTileY(); if (!sameMap - || (abs(x - player_node->getTileX()) > MAP_TELEPORT_SCROLL_DISTANCE) - || (abs(y - player_node->getTileY()) > MAP_TELEPORT_SCROLL_DISTANCE)) + || (abs(x - tileX) > MAP_TELEPORT_SCROLL_DISTANCE) + || (abs(y - tileY) > MAP_TELEPORT_SCROLL_DISTANCE)) { - Map *map = game->getCurrentMap(); - scrollOffsetX = (x - player_node->getTileX()) - * map->getTileWidth(); - scrollOffsetY = (y - player_node->getTileY()) - * map->getTileHeight(); + scrollOffsetX = (x - tileX) * tileWidth; + scrollOffsetY = (y - tileY) * tileHeight; } player_node->setAction(Being::STAND); - player_node->setTileCoords(x, y); + player_node->setPosition(Vector(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2)); logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX, (int) scrollOffsetY); @@ -228,7 +233,8 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) switch (type) { case 0x0000: - player_node->setWalkSpeed(Vector(value, value, 0)); + player_node->setMoveSpeed(Vector(value / 10, + value / 10, 0)); break; case 0x0004: break; // manner case 0x0005: PlayerInfo::setAttribute(HP, value); break; @@ -552,8 +558,12 @@ void PlayerHandler::setDirection(char direction) void PlayerHandler::setDestination(int x, int y, int direction) { + // The destination coordinates are received in pixel, so we translate them + // into tiles. + Map *map = Game::instance()->getCurrentMap(); MessageOut outMsg(CMSG_PLAYER_CHANGE_DEST); - outMsg.writeCoordinates(x, y, direction); + outMsg.writeCoordinates(x / map->getTileWidth(), y / map->getTileHeight(), + direction); } void PlayerHandler::changeAction(Being::Action action) @@ -602,11 +612,50 @@ int PlayerHandler::getJobLocation() return JOB; } -Vector PlayerHandler::getDefaultWalkSpeed() +Vector PlayerHandler::getDefaultMoveSpeed() { // Return an normalized speed for any side // as the offset is calculated elsewhere. - return Vector(150, 150, 0); + // in ticks per tile. + return Vector(15.0f, 15.0f, 0.0f); +} + +Vector PlayerHandler::getPixelsPerTickMoveSpeed(Vector speed, Map *map) +{ + Game *game = Game::instance(); + + if (game && !map) + map = game->getCurrentMap(); + + if (!map) + { + logger->log("TmwAthena::PlayerHandler: Speed not given back" + " because Map not yet initialized."); + return Vector(0.0f, 0.0f, 0.0f); + } + + if (speed.x == 0 || speed.y == 0) + { + logger->log("TmwAthena::PlayerHandler: " + "Invalid Speed given from server."); + speed = getDefaultMoveSpeed(); + } + + Vector speedInTicks; + + // We don't use z for now. + speedInTicks.z = 0; + + speedInTicks.x = ((1 / speed.x) * 1000) / MILLISECONDS_IN_A_TICK; + speedInTicks.x = speedInTicks.x + * (float)map->getTileWidth() + / 1000 * (float) MILLISECONDS_IN_A_TICK; + speedInTicks.y = ((1 / speed.y) * 1000) / MILLISECONDS_IN_A_TICK; + speedInTicks.y = speedInTicks.y + * (float)map->getTileHeight() + / 1000 * (float) MILLISECONDS_IN_A_TICK; + + return speedInTicks; } } // namespace TmwAthena diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h index cb352110..4df74350 100644 --- a/src/net/tmwa/playerhandler.h +++ b/src/net/tmwa/playerhandler.h @@ -58,7 +58,9 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler int getJobLocation(); - Vector getDefaultWalkSpeed(); + Vector getDefaultMoveSpeed(); + + Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0); }; } // namespace TmwAthena diff --git a/src/sound.cpp b/src/sound.cpp index c64e10d8..4f84d4b9 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -22,6 +22,7 @@ #include <SDL.h> #include "configuration.h" +#include "game.h" #include "localplayer.h" #include "log.h" #include "sound.h" @@ -246,8 +247,10 @@ void Sound::playSfx(const std::string &path, int x, int y) int vol = 120; if (player_node && x > 0 && y > 0) { - int dx = player_node->getTileX() - x; - int dy = player_node->getTileY() - y; + Vector pos = player_node->getPosition(); + Map *map = Game::instance()->getCurrentMap(); + int dx = ((int)pos.x - x) / map->getTileWidth(); + int dy = ((int)pos.y - y) / map->getTileHeight(); if (dx < 0) dx = -dx; if (dy < 0) diff --git a/src/sound.h b/src/sound.h index bfb3837b..b619ab6b 100644 --- a/src/sound.h +++ b/src/sound.h @@ -86,8 +86,8 @@ class Sound * Plays an item. * * @param path The resource path to the sound file. - * @param x The vertical distance of the sound in tiles. - * @param y The horizontal distance of the sound in tiles. + * @param x The vertical distance of the sound in pixels. + * @param y The horizontal distance of the sound in pixels. */ void playSfx(const std::string &path, int x = 0, int y = 0); |