From 21e8d502d07c6cae9580a34dde7587d58e6d3a28 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Tue, 15 Mar 2011 17:28:16 +0100 Subject: 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! --- src/net/tmwa/beinghandler.cpp | 57 ++++++++++++++++++++--------- src/net/tmwa/beinghandler.h | 3 ++ src/net/tmwa/charserverhandler.cpp | 6 ++- src/net/tmwa/gamehandler.cpp | 15 +++++++- src/net/tmwa/gamehandler.h | 7 +++- src/net/tmwa/playerhandler.cpp | 75 +++++++++++++++++++++++++++++++------- src/net/tmwa/playerhandler.h | 4 +- 7 files changed, 132 insertions(+), 35 deletions(-) (limited to 'src/net/tmwa') 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 -- cgit v1.2.3-70-g09d2 From 911444a5b910691816acfccf65151296042fb724 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Tue, 15 Mar 2011 18:11:01 +0100 Subject: Simplify the tmwAthena calculation of the pixel/tick speed. --- src/net/tmwa/playerhandler.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index 181ff39c..b05c11d7 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -643,17 +643,9 @@ Vector PlayerHandler::getPixelsPerTickMoveSpeed(Vector speed, Map *map) 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; + speedInTicks.z = 0; // We don't use z for now. + speedInTicks.x = 1 / speed.x * (float)map->getTileWidth(); + speedInTicks.y = 1 / speed.y * (float)map->getTileHeight(); return speedInTicks; } -- cgit v1.2.3-70-g09d2 From 6265ef44e8308ac9a27abec68839c2a884a8f09e Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Tue, 15 Mar 2011 18:22:41 +0100 Subject: Reset destination to position at warp time for TmwAthena. This fix the following bug: When changing map, the local player sometimes walks randomly until the player reacts. --- src/net/tmwa/playerhandler.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index b05c11d7..9210de6e 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -215,8 +215,11 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) } player_node->setAction(Being::STAND); - player_node->setPosition(Vector(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2)); + Vector pos(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2); + player_node->setPosition(pos); + // Stop movement + player_node->setDestination(pos.x, pos.y); logger->log("Adjust scrolling by %d:%d", (int) scrollOffsetX, (int) scrollOffsetY); -- cgit v1.2.3-70-g09d2 From d61c66a34b1fbb88267cf2ef9adf8bc03d52cb84 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Tue, 15 Mar 2011 19:18:46 +0100 Subject: Add a tolerance check on current position to limit desyncs. Also removed dead code. --- src/being.cpp | 4 ---- src/net/tmwa/beinghandler.cpp | 53 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 15 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/being.cpp b/src/being.cpp index 86bebea2..fc2f2f2d 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -770,10 +770,6 @@ void Being::logic() ActorSprite::logic(); - int frameCount = getFrameCount(); - if (frameCount < 10) - frameCount = 10; - // Remove it after 3 secs. TODO: Just play the dead animation before removing if (!isAlive() && Net::getGameHandler()->removeDeadBeings() && get_elapsed_time(mActionTime) > 3000) diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index ddb15428..40c1107b 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -39,9 +39,13 @@ #include "resources/emotedb.h" #include +#include namespace TmwAthena { +// Number of pixels where we decide that the position doesn't need to be reset. +static const float POS_DEST_DIFF_TOLERANCE = 48.0f; + BeingHandler::BeingHandler(bool enableSync): mSync(enableSync) { @@ -215,10 +219,17 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) dstBeing->setAction(Being::STAND); 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; + // Don't set the position as the movement algorithm can guess + // it and it would break the animation played, when we're + // close enough. + if (std::abs((float)dstX - pos.x) > POS_DEST_DIFF_TOLERANCE + || std::abs((float)dstY - pos.y) > POS_DEST_DIFF_TOLERANCE) + dstBeing->setPosition(pos); + + // We turn the destination back to a pixel one. dstBeing->setDestination(dstX, dstY); } else @@ -249,6 +260,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) break; case SMSG_BEING_MOVE2: + { /* * A simplified movement packet, used by the * later versions of eAthena for both mobs and @@ -269,11 +281,21 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) msg.readCoordinatePair(srcX, srcY, dstX, dstY); msg.readInt32(); // Server tick - dstBeing->setAction(Being::STAND); - dstBeing->setPosition(Vector(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2)); - dstBeing->setDestination(dstX * tileWidth + tileWidth / 2, - dstY * tileHeight + tileHeight / 2); + //dstBeing->setAction(Being::STAND); <-- Not needed anymore. + + Vector pos(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2); + Vector dest(dstX * tileWidth + tileWidth / 2, + dstY * tileHeight + tileHeight / 2); + // Don't set the position as the movement algorithm can guess + // it and it would break the animation played, when we're + // close enough. + if (std::abs((float)dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE + || std::abs((float)dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) + dstBeing->setPosition(pos); + + dstBeing->setDestination(dest.x, dest.y); + } break; case SMSG_BEING_REMOVE: @@ -581,10 +603,19 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - dstBeing->setPosition(Vector(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2)); - dstBeing->setDestination(dstX * tileWidth + tileWidth / 2, - dstY * tileHeight + tileHeight / 2); + Vector pos(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2); + Vector dest(dstX * tileWidth + tileWidth / 2, + dstY * tileHeight + tileHeight / 2); + + // Don't set the position as the movement algorithm can guess + // it and it would break the animation played, when we're + // close enough. + if (std::abs((float)dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE + || std::abs((float)dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) + dstBeing->setPosition(pos); + + dstBeing->setDestination(dest.x, dest.y); } else { -- cgit v1.2.3-70-g09d2 From 29259f72663e0eb1820b4d4a0f018acef61bfb2c Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Tue, 15 Mar 2011 23:09:17 +0100 Subject: Made the tA Beinghandler avoid dealing with flawed coordinates. Also fixed again a condition in Being::logic(). I'll beautify the code in tmwAthena:Beinghandler once everything will be working better. Note: I also suspect current clients to flood the server with keyboard messages, hence blocking the animation when they are remote. I'll need to test that with someone having the same client than here.. --- src/being.cpp | 6 +- src/net/tmwa/beinghandler.cpp | 132 ++++++++++++++++++++++++++---------------- 2 files changed, 84 insertions(+), 54 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/being.cpp b/src/being.cpp index 8c7f45bb..b79b65b3 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -673,6 +673,8 @@ void Being::logic() mText = 0; } + ActorSprite::logic(); + if ((mAction != DEAD) && !mSpeedPixelsPerTick.isNull()) { const Vector dest = (mPath.empty()) ? @@ -680,7 +682,7 @@ void Being::logic() mPath.front().y); // Avoid going to flawed destinations - if (mDest.x <= 0 || mDest.y <= 0) + if (dest.x <= 0 || dest.y <= 0) { // We make the being stop move in that case. mDest = mPos; @@ -768,8 +770,6 @@ void Being::logic() } } - ActorSprite::logic(); - // Remove it after 3 secs. TODO: Just play the dead animation before removing if (!isAlive() && Net::getGameHandler()->removeDeadBeings() && get_elapsed_time(mActionTime) > 3000) diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 40c1107b..40dfe083 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -216,31 +216,40 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - dstBeing->setAction(Being::STAND); - Vector pos(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2); - - dstX = dstX * tileWidth + tileWidth / 2; - dstY = dstY * tileHeight + tileHeight / 2; - // Don't set the position as the movement algorithm can guess - // it and it would break the animation played, when we're - // close enough. - if (std::abs((float)dstX - pos.x) > POS_DEST_DIFF_TOLERANCE - || std::abs((float)dstY - pos.y) > POS_DEST_DIFF_TOLERANCE) - dstBeing->setPosition(pos); - - // We turn the destination back to a pixel one. - dstBeing->setDestination(dstX, dstY); + //dstBeing->setAction(Being::STAND); Useless + // Avoid dealing with flawed destination + if (srcX && srcY && dstX && dstY) + { + Vector pos(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2); + + Vector dest(dstX * tileWidth + tileWidth / 2, + dstY * tileHeight + tileHeight / 2); + // Don't set the position as the movement algorithm + // can guess it and it would break the animation played, + // when we're close enough. + if (std::abs(dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE + || std::abs(dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) + dstBeing->setPosition(pos); + + // We turn the destination back to a pixel one. + dstBeing->setDestination(dest.x, dest.y); + } } else { Uint8 dir; Uint16 x, y; msg.readCoordinates(x, y, dir); - Vector pos(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2); - dstBeing->setPosition(pos); - dstBeing->setDirection(dir); + + // Avoid dealing with flawed destination + if (x && y) + { + Vector pos(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2); + dstBeing->setPosition(pos); + dstBeing->setDirection(dir); + } } msg.readInt8(); // unknown @@ -281,20 +290,23 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) msg.readCoordinatePair(srcX, srcY, dstX, dstY); msg.readInt32(); // Server tick - //dstBeing->setAction(Being::STAND); <-- Not needed anymore. - - Vector pos(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2); - Vector dest(dstX * tileWidth + tileWidth / 2, - dstY * tileHeight + tileHeight / 2); - // Don't set the position as the movement algorithm can guess - // it and it would break the animation played, when we're - // close enough. - if (std::abs((float)dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE - || std::abs((float)dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) - dstBeing->setPosition(pos); + //dstBeing->setAction(Being::STAND); // Useless. + // Avoid dealing with flawed destination + if (srcX && srcY && dstX && dstY) + { + Vector pos(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2); + Vector dest(dstX * tileWidth + tileWidth / 2, + dstY * tileHeight + tileHeight / 2); + // Don't set the position as the movement algorithm can guess + // it and it would break the animation played, when we're + // close enough. + if (std::abs(dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE + || std::abs(dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) + dstBeing->setPosition(pos); - dstBeing->setDestination(dest.x, dest.y); + dstBeing->setDestination(dest.x, dest.y); + } } break; @@ -603,28 +615,39 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - Vector pos(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2); - Vector dest(dstX * tileWidth + tileWidth / 2, - dstY * tileHeight + tileHeight / 2); - // Don't set the position as the movement algorithm can guess - // it and it would break the animation played, when we're - // close enough. - if (std::abs((float)dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE - || std::abs((float)dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) - dstBeing->setPosition(pos); - - dstBeing->setDestination(dest.x, dest.y); + //dstBeing->setAction(Being::STAND); // Useless. + // Avoid dealing with flawed destination + if (srcX && srcY && dstX && dstY) + { + Vector pos(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2); + Vector dest(dstX * tileWidth + tileWidth / 2, + dstY * tileHeight + tileHeight / 2); + + // Don't set the position as the movement algorithm + // can guess it and it would break the animation played, + // when we're close enough. + if (std::abs(dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE + || std::abs(dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) + dstBeing->setPosition(pos); + + dstBeing->setDestination(dest.x, dest.y); + } } else { Uint8 dir; Uint16 x, y; msg.readCoordinates(x, y, dir); - dstBeing->setPosition(Vector(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2)); - dstBeing->setDirection(dir); + // Avoid dealing with flawed destination + if (x && y) + { + Vector pos(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2); + dstBeing->setPosition(pos); + dstBeing->setDirection(dir); + } } gmstatus = msg.readInt16(); @@ -681,10 +704,17 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Uint16 x, y; x = msg.readInt16(); y = msg.readInt16(); - dstBeing->setPosition(Vector(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2)); - if (dstBeing->getCurrentAction() == Being::MOVE) - dstBeing->setAction(Being::STAND); + // Avoid dealing with flawed destination + if (x && y) + { + Vector pos(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2); + dstBeing->setPosition(pos); + if (dstBeing->getCurrentAction() == Being::MOVE) + { + dstBeing->setAction(Being::STAND); + } + } } } break; -- cgit v1.2.3-70-g09d2 From 786df24ec5d10e4251fa69426c53f9c2e5d545f4 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Wed, 16 Mar 2011 00:37:34 +0100 Subject: Fixed the attack range handling for both servers. The attack range is always the default for manaserv, as proper equipment handling is to be added. Anyway, now the proper attack range is handled in tmwAthena and is always set a proper minimum for both protocols. --- src/localplayer.cpp | 57 ++++++++++++++++++++++++++------------- src/localplayer.h | 2 +- src/net/tmwa/inventoryhandler.cpp | 23 +++++++++++++++- src/resources/iteminfo.h | 2 +- 4 files changed, 62 insertions(+), 22 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 52168237..5ce21916 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -69,7 +69,7 @@ LocalPlayer *player_node = NULL; LocalPlayer::LocalPlayer(int id, int subtype): Being(id, PLAYER, subtype, 0), - mAttackRange(0), + mAttackRange(-1), mTargetTime(-1), mLastTarget(-1), mTarget(NULL), @@ -114,14 +114,10 @@ void LocalPlayer::logic() { if (mMessageTime == 0) { - //const Vector &pos = getPosition(); - MessagePair info = mMessages.front(); particleEngine->addTextRiseFadeOutEffect( info.first, - /*(int) pos.x, - (int) pos.y - 48,*/ getPixelX(), getPixelY() - 48, &userPalette->getColor(info.second), @@ -913,27 +909,50 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount, } } -int LocalPlayer::getAttackRange() +void LocalPlayer::setAttackRange(int range) { - if (mAttackRange > -1) + // Still no map, so don't do anything for now. + if (!mMap) + return; + // When the range is more than the minimal, we accept it + int unarmedRange = mMap->getTileWidth() / 2 * 3; + if (range >= unarmedRange) { - return mAttackRange; + mAttackRange = range; } - else + else if (Net::getNetworkType() == ServerInfo::TMWATHENA) { - if (Net::getNetworkType() == ServerInfo::TMWATHENA) + // TODO: Fix this to be more generic + Item *weapon = PlayerInfo::getEquipment( + TmwAthena::EQUIP_FIGHT1_SLOT); + if (weapon) { - // TODO: Fix this to be more generic - Item *weapon = PlayerInfo::getEquipment( - TmwAthena::EQUIP_FIGHT1_SLOT); - if (weapon) - { - const ItemInfo info = weapon->getInfo(); - return info.getAttackRange(); - } + const ItemInfo info = weapon->getInfo(); + if (info.getAttackRange() >= unarmedRange) + mAttackRange = info.getAttackRange(); + else + mAttackRange = unarmedRange; } - return 48; // unarmed range } + else + { + mAttackRange = unarmedRange; + } +} + +int LocalPlayer::getAttackRange() +{ + // Still no map, so don't return anything for now. + if (!mMap) + return -1; + // When the range is realistic, we return it + int unarmedRange = mMap->getTileWidth() / 2 * 3; + if (mAttackRange < unarmedRange) + { + // This will set a proper value to the attack range. + setAttackRange(unarmedRange); + } + return mAttackRange; } bool LocalPlayer::withinAttackRange(Being *target) diff --git a/src/localplayer.h b/src/localplayer.h index b1a41697..696211ee 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -111,7 +111,7 @@ class LocalPlayer : public Being /** * Sets the attack range. */ - void setAttackRange(int range) { mAttackRange = range; } + void setAttackRange(int range); /** * Gets the attack range. diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp index 1d99eca4..8ec97a38 100644 --- a/src/net/tmwa/inventoryhandler.cpp +++ b/src/net/tmwa/inventoryhandler.cpp @@ -24,6 +24,7 @@ #include "configuration.h" #include "equipment.h" #include "event.h" +#include "game.h" #include "inventory.h" #include "item.h" #include "itemshortcut.h" @@ -408,13 +409,33 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) flag = msg.readInt8(); if (!flag) + { SERVER_NOTICE(_("Unable to unequip.")) + } else + { mEquips.setEquipment(getSlot(equipType), -1); + // Reset the attack range to unarmed. + player_node->setAttackRange(-1); + } break; case SMSG_PLAYER_ATTACK_RANGE: - player_node->setAttackRange(msg.readInt16()); + { + // The range is in tiles, so we translate it back to pixels + Map *map = Game::instance()->getCurrentMap(); + if (map) + { + player_node->setAttackRange(msg.readInt16() + * map->getTileWidth()); + } + else + { + logger->log("Couldn't set attacke range due to the lack" + "of an initialized map."); + player_node->setAttackRange(-1); + } + } break; case SMSG_PLAYER_ARROW_EQUIP: diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index 50633f71..c7e97b3c 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -163,7 +163,7 @@ class ItemInfo * Attack action sub-types (bow, sword, ...) are defined in items.xml. */ std::string mAttackAction; - int mAttackRange; /**< Attack range, will be zero if non weapon. */ + int mAttackRange; /**< Attack range, will be -1 if no weapon. */ // Particle to be shown when weapon attacks std::string mMissileParticle; -- cgit v1.2.3-70-g09d2 From 6846acdcf0159423c188b56fc4a5f4c19f123eb7 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Wed, 16 Mar 2011 21:37:31 +0100 Subject: Fixed the bug with remote player movement animation, by removing a now useless reset in the beinghandler. Also added checks for flawed directions. --- src/being.cpp | 2 +- src/net/tmwa/beinghandler.cpp | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/being.cpp b/src/being.cpp index 465cb088..2c8414d8 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -635,7 +635,7 @@ void Being::setAction(Action action, int attackType) void Being::setDirection(Uint8 direction) { - if (mDirection == direction) + if (!direction || mDirection == direction) return; mDirection = direction; diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 40dfe083..cee915c7 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -248,7 +248,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Vector pos(x * tileWidth + tileWidth / 2, y * tileHeight + tileHeight / 2); dstBeing->setPosition(pos); - dstBeing->setDirection(dir); + if (dir) + dstBeing->setDirection(dir); } } @@ -528,15 +529,17 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) } break; case SMSG_BEING_CHANGE_DIRECTION: + { if (!(dstBeing = actorSpriteManager->findBeing(msg.readInt32()))) { break; } msg.readInt16(); // unused - - dstBeing->setDirection(msg.readInt8()); - + Uint8 dir = msg.readInt8(); + if (dir) + dstBeing->setDirection(dir); + } break; case SMSG_PLAYER_UPDATE_1: @@ -646,7 +649,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Vector pos(x * tileWidth + tileWidth / 2, y * tileHeight + tileHeight / 2); dstBeing->setPosition(pos); - dstBeing->setDirection(dir); + if (dir) + dstBeing->setDirection(dir); } } @@ -675,8 +679,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) msg.readInt8(); // Lv msg.readInt8(); // unknown - dstBeing->reset(); - dstBeing->setStunMode(stunMode); dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff); dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); -- cgit v1.2.3-70-g09d2 From 452dc7f163749de0b5d698af2f022ca22c1aabb0 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Thu, 17 Mar 2011 00:02:23 +0100 Subject: Now the client centers the pixel positions when using tA. I made it so that the behaviour can be changed with only a boolean setting in the playerhandler. --- src/being.cpp | 32 ++++++++++++++++++++++++-------- src/gui/viewport.cpp | 39 +++++++++++++++++++++++++++++++++------ src/map.cpp | 34 ++++++++++++++++++++++++++++++++++ src/map.h | 8 ++++++++ src/net/manaserv/playerhandler.h | 3 +++ src/net/playerhandler.h | 6 ++++++ src/net/tmwa/playerhandler.h | 3 +++ 7 files changed, 111 insertions(+), 14 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/being.cpp b/src/being.cpp index 2c8414d8..6b971dbf 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -198,21 +198,37 @@ void Being::setDestination(int dstX, int dstY) return; // If the destination is unwalkable, don't bother trying to get there - if (!mMap->getWalk(dstX / 32, dstY / 32)) + int tileWidth = mMap->getTileWidth(); + int tileHeight = mMap->getTileHeight(); + if (!mMap->getWalk(dstX / tileWidth, dstY / tileHeight)) return; - Position dest = mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(), - dstX, dstY); - Path thisPath = mMap->findPixelPath((int) mPos.x, (int) mPos.y, - dest.x, dest.y, - getCollisionRadius(), getWalkMask()); + Position dest(dstX, dstY); + Path thisPath; + if (Net::getPlayerHandler()->usePixelPrecision()) + { + dest = mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(), + dstX, dstY); + thisPath = mMap->findPixelPath((int) mPos.x, (int) mPos.y, + dest.x, dest.y, + getCollisionRadius(), getWalkMask()); + } + else + { + // We center the destination. + dest.x = (dstX / tileWidth) * tileWidth + tileWidth / 2; + dest.y = (dstY / tileHeight) * tileHeight + tileHeight / 2; + // and find a tile centered pixel path + thisPath = mMap->findTilePath((int) mPos.x, (int) mPos.y, + dest.x, dest.y, getWalkMask()); + } if (thisPath.empty()) { // If there is no path but the destination is on the same walkable tile, // we accept it. - if ((int)mPos.x / 32 == dest.x / 32 - && (int)mPos.y / 32 == dest.y / 32) + if ((int)mPos.x / tileWidth == dest.x / tileWidth + && (int)mPos.y / tileHeight == dest.y / tileHeight) { mDest.x = dest.x; mDest.y = dest.y; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 459edab5..19bed735 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -37,6 +37,7 @@ #include "gui/beingpopup.h" #include "net/net.h" +#include "net/playerhandler.h" #include "resources/resourcemanager.h" @@ -270,12 +271,38 @@ void Viewport::_drawDebugPath(Graphics *graphics) (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); + // Prepare the walkmask corresponding to the protocol + unsigned char walkMask = 0; + switch (Net::getNetworkType()) + { + case ServerInfo::TMWATHENA: + walkMask = Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER; + break; + case ServerInfo::MANASERV: + default: + walkMask = Map::BLOCKMASK_WALL; + break; + } + + // Adapt the path finding to the precision requested + if (Net::getPlayerHandler()->usePixelPrecision()) + { + debugPath = mMap->findPixelPath( + (int) playerPos.x, + (int) playerPos.y, + mMouseX + (int) mPixelViewX, + mMouseY + (int) mPixelViewY, + playerRadius, walkMask); + } + else + { + debugPath = mMap->findTilePath( + (int) playerPos.x, + (int) playerPos.y, + mMouseX + (int) mPixelViewX, + mMouseY + (int) mPixelViewY, + walkMask); + } // We draw the path proposed by mouse _drawPath(graphics, debugPath, gcn::Color(128, 0, 128)); diff --git a/src/map.cpp b/src/map.cpp index 87c902f6..69793299 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -710,6 +710,40 @@ Position Map::checkNodeOffsets(int radius, unsigned char walkMask, return Position(tx * 32 + fx, ty * 32 + fy); } +Path Map::findTilePath(int startPixelX, int startPixelY, int endPixelX, + int endPixelY, unsigned char walkMask, int maxCost) +{ + Path myPath = findPath(startPixelX / mTileWidth, startPixelY / mTileHeight, + endPixelX / mTileWidth, endPixelY / mTileHeight, + walkMask, maxCost); + + // Don't compute empty coordinates. + if (myPath.empty()) + return myPath; + + // Convert the map path to pixels over tiles + // And add interpolation between the starting and ending offsets + Path::iterator it = myPath.begin(); + while (it != myPath.end()) + { + // A position that is valid on the start and end tile is not + // necessarily valid on all the tiles in between, so check the offsets. + *it = Position(it->x * mTileWidth + mTileWidth / 2, + it->y * mTileHeight + mTileHeight / 2); + it++; + } + + // Remove the last path node, as it's more clever to go to the destination. + // It also permit to avoid zigzag at the end of the path, + // especially with mouse. + Position destination((endPixelX / mTileWidth) * mTileWidth + mTileWidth / 2, + (endPixelY / mTileHeight) * mTileHeight + mTileHeight / 2); + myPath.pop_back(); + myPath.push_back(destination); + + return myPath; +} + Path Map::findPixelPath(int startPixelX, int startPixelY, int endPixelX, int endPixelY, int radius, unsigned char walkMask, int maxCost) diff --git a/src/map.h b/src/map.h index 22ca68c4..fae8af50 100644 --- a/src/map.h +++ b/src/map.h @@ -285,6 +285,14 @@ class Map : public Properties int x, int y) const { return checkNodeOffsets(radius, walkMask, Position(x, y)); } + /** + * Find a pixel path from one location to the next. + * Path node are centered on their corresponding tiles in that case. + */ + Path findTilePath(int startPixelX, int startPixelY, int endPixelX, + int endPixelY, unsigned char walkMask, + int maxCost = 20); + /** * Find a pixel path from one location to the next. */ diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h index 6069c6da..8bba1580 100644 --- a/src/net/manaserv/playerhandler.h +++ b/src/net/manaserv/playerhandler.h @@ -69,6 +69,9 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0); + bool usePixelPrecision() + { return true; } + private: void handleMapChangeMessage(Net::MessageIn &msg); }; diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index 23277062..5d94a093 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -74,6 +74,12 @@ class PlayerHandler * Convert the original speed in pixel per tick for internal use. */ virtual Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0) = 0; + + /** + * Tells whether the client has to use pixel paths. + * Return false when tiles-center positions only are to be used. + */ + virtual bool usePixelPrecision() = 0; }; } // namespace Net diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h index 4df74350..42eb85f2 100644 --- a/src/net/tmwa/playerhandler.h +++ b/src/net/tmwa/playerhandler.h @@ -61,6 +61,9 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler Vector getDefaultMoveSpeed(); Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0); + + bool usePixelPrecision() + { return false; } }; } // namespace TmwAthena -- cgit v1.2.3-70-g09d2 From c6462143d107c35846cadc45e205d8ecedb6bf7a Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Thu, 17 Mar 2011 00:55:59 +0100 Subject: Handle ta move and position message in a more generic way. This avoids code duplication. --- src/net/tmwa/beinghandler.cpp | 133 +++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 86 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index cee915c7..b7f702c0 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -101,6 +101,44 @@ Being *createBeing(int id, short job) return being; } +void handleMoveMessage(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY, + Being *dstBeing, int tileWidth, int tileHeight) +{ + // Avoid dealing with flawed destination + if (srcX && srcY && dstX && dstY) + { + Vector pos(srcX * tileWidth + tileWidth / 2, + srcY * tileHeight + tileHeight / 2); + + Vector dest(dstX * tileWidth + tileWidth / 2, + dstY * tileHeight + tileHeight / 2); + + // Don't set the position as the movement algorithm + // can guess it and it would break the animation played, + // when we're close enough. + if (std::abs(dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE + || std::abs(dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) + dstBeing->setPosition(pos); + + // We turn the destination back to a pixel one. + dstBeing->setDestination(dest.x, dest.y); + } +} + +void handlePosMessage(Uint16 x, Uint16 y, Being *dstBeing, + int tileWidth, int tileHeight, Uint8 dir = 0) +{ + // Avoid dealing with flawed destination + if (x && y) + { + Vector pos(x * tileWidth + tileWidth / 2, + y * tileHeight + tileHeight / 2); + dstBeing->setPosition(pos); + if (dir) + dstBeing->setDirection(dir); + } +} + void BeingHandler::handleMessage(Net::MessageIn &msg) { if (!actorSpriteManager) @@ -216,41 +254,15 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - //dstBeing->setAction(Being::STAND); Useless - // Avoid dealing with flawed destination - if (srcX && srcY && dstX && dstY) - { - Vector pos(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2); - - Vector dest(dstX * tileWidth + tileWidth / 2, - dstY * tileHeight + tileHeight / 2); - // Don't set the position as the movement algorithm - // can guess it and it would break the animation played, - // when we're close enough. - if (std::abs(dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE - || std::abs(dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) - dstBeing->setPosition(pos); - - // We turn the destination back to a pixel one. - dstBeing->setDestination(dest.x, dest.y); - } + handleMoveMessage(srcX, srcY, dstX, dstY, dstBeing, + tileWidth, tileHeight); } else { Uint8 dir; Uint16 x, y; msg.readCoordinates(x, y, dir); - - // Avoid dealing with flawed destination - if (x && y) - { - Vector pos(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2); - dstBeing->setPosition(pos); - if (dir) - dstBeing->setDirection(dir); - } + handlePosMessage(x, y, dstBeing, tileWidth, tileHeight, dir); } msg.readInt8(); // unknown @@ -290,24 +302,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); msg.readInt32(); // Server tick - - //dstBeing->setAction(Being::STAND); // Useless. - // Avoid dealing with flawed destination - if (srcX && srcY && dstX && dstY) - { - Vector pos(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2); - Vector dest(dstX * tileWidth + tileWidth / 2, - dstY * tileHeight + tileHeight / 2); - // Don't set the position as the movement algorithm can guess - // it and it would break the animation played, when we're - // close enough. - if (std::abs(dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE - || std::abs(dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) - dstBeing->setPosition(pos); - - dstBeing->setDestination(dest.x, dest.y); - } + handleMoveMessage(srcX, srcY, dstX, dstY, dstBeing, + tileWidth, tileHeight); } break; @@ -618,40 +614,15 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - - //dstBeing->setAction(Being::STAND); // Useless. - // Avoid dealing with flawed destination - if (srcX && srcY && dstX && dstY) - { - Vector pos(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2); - Vector dest(dstX * tileWidth + tileWidth / 2, - dstY * tileHeight + tileHeight / 2); - - // Don't set the position as the movement algorithm - // can guess it and it would break the animation played, - // when we're close enough. - if (std::abs(dest.x - pos.x) > POS_DEST_DIFF_TOLERANCE - || std::abs(dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) - dstBeing->setPosition(pos); - - dstBeing->setDestination(dest.x, dest.y); - } + handleMoveMessage(srcX, srcY, dstX, dstY, dstBeing, + tileWidth, tileHeight); } else { Uint8 dir; Uint16 x, y; msg.readCoordinates(x, y, dir); - // Avoid dealing with flawed destination - if (x && y) - { - Vector pos(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2); - dstBeing->setPosition(pos); - if (dir) - dstBeing->setDirection(dir); - } + handlePosMessage(x, y, dstBeing, tileWidth, tileHeight, dir); } gmstatus = msg.readInt16(); @@ -706,17 +677,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Uint16 x, y; x = msg.readInt16(); y = msg.readInt16(); - // Avoid dealing with flawed destination - if (x && y) - { - Vector pos(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2); - dstBeing->setPosition(pos); - if (dstBeing->getCurrentAction() == Being::MOVE) - { - dstBeing->setAction(Being::STAND); - } - } + handlePosMessage(x, y, dstBeing, tileWidth, tileHeight); } } break; -- cgit v1.2.3-70-g09d2 From 45c3f943b42423dbe162bfac4a57cad013ba0630 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Thu, 17 Mar 2011 02:05:52 +0100 Subject: Simplified the get/setAttackRange() functions as requested. The attack range is still hardcoded for Manaserv as long as generic equipment handling hasn't been implemented. --- src/localplayer.cpp | 34 ++++------------------------------ src/localplayer.h | 9 ++++++++- src/net/manaserv/gamehandler.cpp | 3 ++- src/net/tmwa/inventoryhandler.cpp | 4 ++-- src/resources/iteminfo.h | 4 +++- 5 files changed, 19 insertions(+), 35 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 5ce21916..7daceb0f 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -69,7 +69,7 @@ LocalPlayer *player_node = NULL; LocalPlayer::LocalPlayer(int id, int subtype): Being(id, PLAYER, subtype, 0), - mAttackRange(-1), + mAttackRange(ATTACK_RANGE_NOT_SET), mTargetTime(-1), mLastTarget(-1), mTarget(NULL), @@ -911,48 +911,22 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount, void LocalPlayer::setAttackRange(int range) { - // Still no map, so don't do anything for now. - if (!mMap) - return; // When the range is more than the minimal, we accept it - int unarmedRange = mMap->getTileWidth() / 2 * 3; - if (range >= unarmedRange) + if (range > ATTACK_RANGE_NOT_SET) { mAttackRange = range; } else if (Net::getNetworkType() == ServerInfo::TMWATHENA) { // TODO: Fix this to be more generic - Item *weapon = PlayerInfo::getEquipment( - TmwAthena::EQUIP_FIGHT1_SLOT); + Item *weapon = PlayerInfo::getEquipment(TmwAthena::EQUIP_FIGHT1_SLOT); if (weapon) { const ItemInfo info = weapon->getInfo(); - if (info.getAttackRange() >= unarmedRange) + if (info.getAttackRange() > ATTACK_RANGE_NOT_SET) mAttackRange = info.getAttackRange(); - else - mAttackRange = unarmedRange; } } - else - { - mAttackRange = unarmedRange; - } -} - -int LocalPlayer::getAttackRange() -{ - // Still no map, so don't return anything for now. - if (!mMap) - return -1; - // When the range is realistic, we return it - int unarmedRange = mMap->getTileWidth() / 2 * 3; - if (mAttackRange < unarmedRange) - { - // This will set a proper value to the attack range. - setAttackRange(unarmedRange); - } - return mAttackRange; } bool LocalPlayer::withinAttackRange(Being *target) diff --git a/src/localplayer.h b/src/localplayer.h index 696211ee..01f31e01 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -58,6 +58,11 @@ enum PICKUP_DROP_STEAL, }; +/** + * Attack range not set value + */ +enum { ATTACK_RANGE_NOT_SET = -1 }; + /** * The local player character. @@ -116,7 +121,9 @@ class LocalPlayer : public Being /** * Gets the attack range. */ - int getAttackRange(); + int getAttackRange() + { return mAttackRange; } + void attack(Being *target = NULL, bool keep = false); void setGMLevel(int level); diff --git a/src/net/manaserv/gamehandler.cpp b/src/net/manaserv/gamehandler.cpp index 040a5e6c..63f84fd1 100644 --- a/src/net/manaserv/gamehandler.cpp +++ b/src/net/manaserv/gamehandler.cpp @@ -141,7 +141,8 @@ void GameHandler::gameLoading() chatHandler->connect(); // Attack range from item DB - player_node->setAttackRange(-1); + // TODO: Deharcode it through equipment handling + player_node->setAttackRange(48); } } // namespace ManaServ diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp index 8ec97a38..88c72ed6 100644 --- a/src/net/tmwa/inventoryhandler.cpp +++ b/src/net/tmwa/inventoryhandler.cpp @@ -416,7 +416,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) { mEquips.setEquipment(getSlot(equipType), -1); // Reset the attack range to unarmed. - player_node->setAttackRange(-1); + player_node->setAttackRange(ATTACK_RANGE_NOT_SET); } break; @@ -433,7 +433,7 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) { logger->log("Couldn't set attacke range due to the lack" "of an initialized map."); - player_node->setAttackRange(-1); + player_node->setAttackRange(ATTACK_RANGE_NOT_SET); } } break; diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index c7e97b3c..2fbcc228 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -163,7 +163,9 @@ class ItemInfo * Attack action sub-types (bow, sword, ...) are defined in items.xml. */ std::string mAttackAction; - int mAttackRange; /**< Attack range, will be -1 if no weapon. */ + + /** Attack range, will be equal to ATTACK_RANGE_NOT_SET if no weapon. */ + int mAttackRange; // Particle to be shown when weapon attacks std::string mMissileParticle; -- cgit v1.2.3-70-g09d2 From 25bfbc30fb4958a3a754d74bbe971dec717f831c Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Mon, 28 Mar 2011 20:13:17 +0200 Subject: Added some tolerance on the tA being position message. Also made the destination equal to the desired position in that case since it's what the tA server expects. This fixes monsters going to strange destinations while fighting them, and makes it all much smoother. --- src/net/tmwa/beinghandler.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/net/tmwa') diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index b7f702c0..5ae11423 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -133,7 +133,17 @@ void handlePosMessage(Uint16 x, Uint16 y, Being *dstBeing, { Vector pos(x * tileWidth + tileWidth / 2, y * tileHeight + tileHeight / 2); - dstBeing->setPosition(pos); + Vector beingPos = dstBeing->getPosition(); + // Don't set the position as the movement algorithm + // can guess it and it would break the animation played, + // when we're close enough. + if (std::abs(beingPos.x - pos.x) > POS_DEST_DIFF_TOLERANCE + || std::abs(beingPos.y - pos.y) > POS_DEST_DIFF_TOLERANCE) + dstBeing->setPosition(pos); + + // Set also the destination to the desired position. + dstBeing->setDestination(pos.x, pos.y); + if (dir) dstBeing->setDirection(dir); } -- cgit v1.2.3-70-g09d2 From e7e550c863c3bb5d5e8697ecce1ea37ad248e362 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Mon, 28 Mar 2011 20:37:05 +0200 Subject: Random code cleanups requested righteously by Thorbjorn - part 1. - Fixed bogus documentation. - Fixed Vector parameters to const Vector& where releavant. - Removed a false comment. - Removed superfluous headers in src/net/tmwa/beinghandler.h. - Optimize a bit the tmwa::beingHandler::getPixelsPerTickMoveSpeed() function. --- src/actorsprite.cpp | 1 - src/being.cpp | 2 +- src/being.h | 8 ++++---- src/net/manaserv/playerhandler.cpp | 17 +++++++++-------- src/net/manaserv/playerhandler.h | 4 ++-- src/net/playerhandler.h | 7 ++++--- src/net/tmwa/beinghandler.h | 3 --- src/net/tmwa/playerhandler.cpp | 21 +++++++-------------- src/net/tmwa/playerhandler.h | 4 ++-- 9 files changed, 29 insertions(+), 38 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp index 0b1dfd39..b2f921cd 100644 --- a/src/actorsprite.cpp +++ b/src/actorsprite.cpp @@ -71,7 +71,6 @@ bool ActorSprite::draw(Graphics *graphics, int offsetX, int offsetY) const // these translations aren't necessary anymore. The sprites know // best where their base point should be. const int px = getPixelX() + offsetX - 16; - // Temporary fix to the Y offset. const int py = getPixelY() + offsetY - 16; if (mUsedTargetCursor) diff --git a/src/being.cpp b/src/being.cpp index 7429a95d..36646006 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -167,7 +167,7 @@ Map::BlockType Being::getBlockType() const return mInfo->getBlockType(); } -void Being::setMoveSpeed(Vector speed) +void Being::setMoveSpeed(const Vector &speed) { mMoveSpeed = speed; // If we already can, recalculate the system speed right away. diff --git a/src/being.h b/src/being.h index fcd2b8f8..f19e3df4 100644 --- a/src/being.h +++ b/src/being.h @@ -310,9 +310,9 @@ class Being : public ActorSprite, public Mana::Listener /** * Sets the move speed. * in ticks per tile for eAthena, - * in tiles per second for Manaserv. + * in tiles per second for Manaserv (0.1 precision). */ - void setMoveSpeed(Vector speed); + void setMoveSpeed(const Vector &speed); /** * Gets the original Move speed. @@ -522,13 +522,13 @@ class Being : public ActorSprite, public Mana::Listener /** * Walk speed for x and y movement values. * In ticks per tile for eAthena, - * In pixels per ticks for Manaserv. - * @see MILLISECONDS_IN_A_TICK + * In pixels per second for Manaserv. */ Vector mMoveSpeed; /** * Being speed in pixel per ticks. Used internally for the being logic. + * @see MILLISECONDS_IN_A_TICK */ Vector mSpeedPixelsPerTick; diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp index 38eb2678..317481ab 100644 --- a/src/net/manaserv/playerhandler.cpp +++ b/src/net/manaserv/playerhandler.cpp @@ -412,16 +412,18 @@ int PlayerHandler::getJobLocation() return -1; } -Vector PlayerHandler::getDefaultMoveSpeed() +Vector PlayerHandler::getDefaultMoveSpeed() const { // Return default speed at 6 tiles per second. return Vector(6.0f, 6.0f, 0.0f); } -Vector PlayerHandler::getPixelsPerTickMoveSpeed(Vector speed, Map *map) +Vector PlayerHandler::getPixelsPerTickMoveSpeed(const Vector &speed, Map *map) { // We don't use z for now. - speed.z = 0; + Vector speedInTicks; + // speedInTicks.x = speedInTicks.y = speedInTicks.z = 0; + // ^ Done by constructor Game *game = Game::instance(); if (game && !map) @@ -431,18 +433,17 @@ Vector PlayerHandler::getPixelsPerTickMoveSpeed(Vector speed, Map *map) { logger->log("Manaserv::PlayerHandler: Speed wasn't given back" " because Map not initialized."); - speed.x = speed.y = 0; - return speed; + return speedInTicks; } - speed.x = speed.x + speedInTicks.x = speed.x * (float)map->getTileWidth() / 1000 * (float) MILLISECONDS_IN_A_TICK; - speed.y = speed.y + speedInTicks.y = speed.y * (float)map->getTileHeight() / 1000 * (float) MILLISECONDS_IN_A_TICK; - return speed; + return speedInTicks; } } // namespace ManaServ diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h index 8bba1580..3e3f8aad 100644 --- a/src/net/manaserv/playerhandler.h +++ b/src/net/manaserv/playerhandler.h @@ -65,9 +65,9 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler int getJobLocation(); - Vector getDefaultMoveSpeed(); + Vector getDefaultMoveSpeed() const; - Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0); + Vector getPixelsPerTickMoveSpeed(const Vector &speed, Map *map = 0); bool usePixelPrecision() { return true; } diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index 5d94a093..f9396caf 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -66,14 +66,15 @@ class PlayerHandler * Get the original default movement speed. * Example: * In ticks per tiles for eAthena - * In pixels per second for Manaserv + * In tiles per second for Manaserv */ - virtual Vector getDefaultMoveSpeed() = 0; + virtual Vector getDefaultMoveSpeed() const = 0; /** * Convert the original speed in pixel per tick for internal use. */ - virtual Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0) = 0; + virtual Vector getPixelsPerTickMoveSpeed(const Vector &speed, + Map *map = 0) = 0; /** * Tells whether the client has to use pixel paths. diff --git a/src/net/tmwa/beinghandler.h b/src/net/tmwa/beinghandler.h index 32b4a7bd..ab833af0 100644 --- a/src/net/tmwa/beinghandler.h +++ b/src/net/tmwa/beinghandler.h @@ -22,9 +22,6 @@ #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/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index 9210de6e..9d97dc73 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -615,7 +615,7 @@ int PlayerHandler::getJobLocation() return JOB; } -Vector PlayerHandler::getDefaultMoveSpeed() +Vector PlayerHandler::getDefaultMoveSpeed() const { // Return an normalized speed for any side // as the offset is calculated elsewhere. @@ -623,30 +623,23 @@ Vector PlayerHandler::getDefaultMoveSpeed() return Vector(15.0f, 15.0f, 0.0f); } -Vector PlayerHandler::getPixelsPerTickMoveSpeed(Vector speed, Map *map) +Vector PlayerHandler::getPixelsPerTickMoveSpeed(const Vector &speed, Map *map) { Game *game = Game::instance(); if (game && !map) map = game->getCurrentMap(); - if (!map) + if (!map || speed.x == 0 || speed.y == 0) { - 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(); + logger->log("TmwAthena::PlayerHandler: Speed set to default: " + "Map not yet initialized or invalid speed."); + return getDefaultMoveSpeed(); } Vector speedInTicks; - speedInTicks.z = 0; // We don't use z for now. + // speedInTicks.z = 0; // We don't use z for now. speedInTicks.x = 1 / speed.x * (float)map->getTileWidth(); speedInTicks.y = 1 / speed.y * (float)map->getTileHeight(); diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h index 42eb85f2..63812f47 100644 --- a/src/net/tmwa/playerhandler.h +++ b/src/net/tmwa/playerhandler.h @@ -58,9 +58,9 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler int getJobLocation(); - Vector getDefaultMoveSpeed(); + Vector getDefaultMoveSpeed() const; - Vector getPixelsPerTickMoveSpeed(Vector speed, Map *map = 0); + Vector getPixelsPerTickMoveSpeed(const Vector &speed, Map *map = 0); bool usePixelPrecision() { return false; } -- cgit v1.2.3-70-g09d2 From ce94f62be91c98310281b33dbc7f4b79fd4e8052 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Mon, 28 Mar 2011 20:46:50 +0200 Subject: Random cleanups - Part 2 - Removed another bogus comment. - Made functions used only in the tA::beinghandler static. - Don't init the destination to an irrelevant value in being::setDestination() --- src/being.cpp | 2 +- src/net/tmwa/beinghandler.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/being.cpp b/src/being.cpp index 36646006..3f375e03 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -203,7 +203,7 @@ void Being::setDestination(int dstX, int dstY) if (!mMap->getWalk(dstX / tileWidth, dstY / tileHeight)) return; - Position dest(dstX, dstY); + Position dest(0, 0); Path thisPath; if (Net::getPlayerHandler()->usePixelPrecision()) { diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 5ae11423..d61559f8 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -101,8 +101,9 @@ Being *createBeing(int id, short job) return being; } -void handleMoveMessage(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY, - Being *dstBeing, int tileWidth, int tileHeight) +static void handleMoveMessage(Uint16 srcX, Uint16 srcY, + Uint16 dstX, Uint16 dstY, + Being *dstBeing, int tileWidth, int tileHeight) { // Avoid dealing with flawed destination if (srcX && srcY && dstX && dstY) @@ -120,13 +121,12 @@ void handleMoveMessage(Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY, || std::abs(dest.y - pos.y) > POS_DEST_DIFF_TOLERANCE) dstBeing->setPosition(pos); - // We turn the destination back to a pixel one. dstBeing->setDestination(dest.x, dest.y); } } -void handlePosMessage(Uint16 x, Uint16 y, Being *dstBeing, - int tileWidth, int tileHeight, Uint8 dir = 0) +static void handlePosMessage(Uint16 x, Uint16 y, Being *dstBeing, + int tileWidth, int tileHeight, Uint8 dir = 0) { // Avoid dealing with flawed destination if (x && y) -- cgit v1.2.3-70-g09d2 From 15c69030f987bd7d67fdbaf2158b2c3ae430143f Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Tue, 29 Mar 2011 01:26:56 +0200 Subject: Added the Map::getTileCenter() convenience function. and made use of it through the tA code. I also remove the obsolete TODO in the flooritem class. --- src/flooritem.cpp | 6 +----- src/map.cpp | 12 ++++++++++++ src/map.h | 8 ++++++++ src/net/tmwa/beinghandler.cpp | 41 ++++++++++++++++------------------------- src/net/tmwa/playerhandler.cpp | 9 +++------ 5 files changed, 40 insertions(+), 36 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/flooritem.cpp b/src/flooritem.cpp index c5a031fe..8805ba88 100644 --- a/src/flooritem.cpp +++ b/src/flooritem.cpp @@ -38,11 +38,7 @@ FloorItem::FloorItem(int id, { setMap(map); - // TODO: Eventually, we probably should fix all sprite offsets so that - // these translations aren't necessary anymore. The sprites know - // best where their base point should be. - mPos.x = x * map->getTileWidth() + 16; - mPos.y = y * map->getTileHeight() + 16; + mPos = map->getTileCenter(x, y); setupSpriteDisplay(itemDb->get(itemId).getDisplay()); } diff --git a/src/map.cpp b/src/map.cpp index 78171ca9..949b00bd 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -607,6 +607,18 @@ bool Map::occupied(int x, int y) const return false; } +Vector Map::getTileCenter(int x, int y) +{ + Vector tileCenterPos; + + if (!contains(x, y)) + return tileCenterPos; + + tileCenterPos.x = x * mTileWidth + mTileWidth / 2; + tileCenterPos.y = y * mTileHeight + mTileHeight / 2; + return tileCenterPos; +} + bool Map::contains(int x, int y) const { return x >= 0 && y >= 0 && x < mWidth && y < mHeight; diff --git a/src/map.h b/src/map.h index fae8af50..e807e2ae 100644 --- a/src/map.h +++ b/src/map.h @@ -267,6 +267,14 @@ class Map : public Properties int getTileHeight() const { return mTileHeight; } + /** + * Returns the nearest tile center position in pixels coordinates. + * + * @param x the horizontal tile position + * @param y the vertical tile position + */ + Vector getTileCenter(int x, int y); + const std::string getMusicFile() const; const std::string getName() const; diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index d61559f8..960f08ed 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -101,18 +101,15 @@ Being *createBeing(int id, short job) return being; } -static void handleMoveMessage(Uint16 srcX, Uint16 srcY, - Uint16 dstX, Uint16 dstY, - Being *dstBeing, int tileWidth, int tileHeight) +static void handleMoveMessage(Map *map, Being *dstBeing, + Uint16 srcX, Uint16 srcY, + Uint16 dstX, Uint16 dstY) { // Avoid dealing with flawed destination - if (srcX && srcY && dstX && dstY) + if (map && dstBeing && srcX && srcY && dstX && dstY) { - Vector pos(srcX * tileWidth + tileWidth / 2, - srcY * tileHeight + tileHeight / 2); - - Vector dest(dstX * tileWidth + tileWidth / 2, - dstY * tileHeight + tileHeight / 2); + Vector pos = map->getTileCenter(srcX, srcY); + Vector dest = map->getTileCenter(dstX, dstY); // Don't set the position as the movement algorithm // can guess it and it would break the animation played, @@ -125,14 +122,13 @@ static void handleMoveMessage(Uint16 srcX, Uint16 srcY, } } -static void handlePosMessage(Uint16 x, Uint16 y, Being *dstBeing, - int tileWidth, int tileHeight, Uint8 dir = 0) +static void handlePosMessage(Map *map, Being *dstBeing, Uint16 x, Uint16 y, + Uint8 dir = 0) { // Avoid dealing with flawed destination - if (x && y) + if (map && dstBeing && x && y) { - Vector pos(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2); + Vector pos = map->getTileCenter(x, y); Vector beingPos = dstBeing->getPosition(); // Don't set the position as the movement algorithm // can guess it and it would break the animation played, @@ -171,8 +167,6 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) // Prepare useful translation variables Map *map = Game::instance()->getCurrentMap(); - int tileWidth = map->getTileWidth(); - int tileHeight = map->getTileHeight(); switch (msg.getId()) { @@ -264,15 +258,14 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - handleMoveMessage(srcX, srcY, dstX, dstY, dstBeing, - tileWidth, tileHeight); + handleMoveMessage(map, dstBeing, srcX, srcY, dstX, dstY); } else { Uint8 dir; Uint16 x, y; msg.readCoordinates(x, y, dir); - handlePosMessage(x, y, dstBeing, tileWidth, tileHeight, dir); + handlePosMessage(map, dstBeing, x, y, dir); } msg.readInt8(); // unknown @@ -312,8 +305,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); msg.readInt32(); // Server tick - handleMoveMessage(srcX, srcY, dstX, dstY, dstBeing, - tileWidth, tileHeight); + handleMoveMessage(map, dstBeing, srcX, srcY, dstX, dstY); } break; @@ -624,15 +616,14 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) { Uint16 srcX, srcY, dstX, dstY; msg.readCoordinatePair(srcX, srcY, dstX, dstY); - handleMoveMessage(srcX, srcY, dstX, dstY, dstBeing, - tileWidth, tileHeight); + handleMoveMessage(map, dstBeing, srcX, srcY, dstX, dstY); } else { Uint8 dir; Uint16 x, y; msg.readCoordinates(x, y, dir); - handlePosMessage(x, y, dstBeing, tileWidth, tileHeight, dir); + handlePosMessage(map, dstBeing, x, y, dir); } gmstatus = msg.readInt16(); @@ -687,7 +678,7 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) Uint16 x, y; x = msg.readInt16(); y = msg.readInt16(); - handlePosMessage(x, y, dstBeing, tileWidth, tileHeight); + handlePosMessage(map, dstBeing, x, y); } } break; diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index 9d97dc73..f7a211d1 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -202,21 +202,18 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) /* 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 - tileX) > MAP_TELEPORT_SCROLL_DISTANCE) || (abs(y - tileY) > MAP_TELEPORT_SCROLL_DISTANCE)) { - scrollOffsetX = (x - tileX) * tileWidth; - scrollOffsetY = (y - tileY) * tileHeight; + scrollOffsetX = (x - tileX) * map->getTileWidth(); + scrollOffsetY = (y - tileY) * map->getTileHeight(); } player_node->setAction(Being::STAND); - Vector pos(x * tileWidth + tileWidth / 2, - y * tileHeight + tileHeight / 2); + Vector pos = map->getTileCenter(x, y); player_node->setPosition(pos); // Stop movement player_node->setDestination(pos.x, pos.y); -- cgit v1.2.3-70-g09d2 From f90aa61947641f3db809e047f80fc7b8c865cb94 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Tue, 29 Mar 2011 01:50:58 +0200 Subject: Made the flooritems position set back in pixels. The position is centered to the nearest tile center in tA. --- src/actorspritemanager.cpp | 4 ++-- src/actorspritemanager.h | 6 +++++- src/flooritem.cpp | 16 ++++++++++------ src/flooritem.h | 12 +++++------- src/net/manaserv/itemhandler.cpp | 18 +----------------- src/net/tmwa/itemhandler.cpp | 14 +++++++++++--- 6 files changed, 34 insertions(+), 36 deletions(-) (limited to 'src/net/tmwa') diff --git a/src/actorspritemanager.cpp b/src/actorspritemanager.cpp index a4b61ed3..2437f7f7 100644 --- a/src/actorspritemanager.cpp +++ b/src/actorspritemanager.cpp @@ -124,9 +124,9 @@ Being *ActorSpriteManager::createBeing(int id, ActorSprite::Type type, int subty return being; } -FloorItem *ActorSpriteManager::createItem(int id, int itemId, int x, int y) +FloorItem *ActorSpriteManager::createItem(int id, int itemId, const Vector &pos) { - FloorItem *floorItem = new FloorItem(id, itemId, x, y, mMap); + FloorItem *floorItem = new FloorItem(id, itemId, pos, mMap); mActors.insert(floorItem); return floorItem; diff --git a/src/actorspritemanager.h b/src/actorspritemanager.h index d6aa609b..64703396 100644 --- a/src/actorspritemanager.h +++ b/src/actorspritemanager.h @@ -59,8 +59,12 @@ class ActorSpriteManager /** * Create a FloorItem and add it to the list of ActorSprites. + * + * @param id the unique ID of this item instance + * @param itemId the item ID + * @param position the position in pixels */ - FloorItem *createItem(int id, int itemId, int x, int y); + FloorItem *createItem(int id, int itemId, const Vector &position); /** * Destroys the given ActorSprite at the end of diff --git a/src/flooritem.cpp b/src/flooritem.cpp index 8805ba88..07903a79 100644 --- a/src/flooritem.cpp +++ b/src/flooritem.cpp @@ -22,23 +22,27 @@ #include "flooritem.h" #include "net/net.h" +#include "net/playerhandler.h" #include "resources/itemdb.h" #include "resources/iteminfo.h" FloorItem::FloorItem(int id, int itemId, - int x, - int y, + const Vector &position, Map *map): ActorSprite(id), mItemId(itemId), - mX(x), - mY(y) + mX(0), mY(0) { - setMap(map); + mPos = position; - mPos = map->getTileCenter(x, y); + setMap(map); + if (map) + { + mX = (int)position.x / map->getTileWidth(); + mY = (int)position.y / map->getTileHeight(); + } setupSpriteDisplay(itemDb->get(itemId).getDisplay()); } diff --git a/src/flooritem.h b/src/flooritem.h index e599c939..0bcc380f 100644 --- a/src/flooritem.h +++ b/src/flooritem.h @@ -35,16 +35,14 @@ class FloorItem : public ActorSprite /** * Constructor. * - * @param id the unique ID of this item instance - * @param itemId the item ID - * @param x the x position in tiles - * @param y the y position in tiles - * @param map the map this item is on + * @param id the unique ID of this item instance + * @param itemId the item ID + * @param position the position in pixels + * @param map the map this item is on */ FloorItem(int id, int itemId, - int x, - int y, + const Vector &position, Map *map); Type getType() const { return FLOOR_ITEM; } diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp index af3457db..d8365d79 100644 --- a/src/net/manaserv/itemhandler.cpp +++ b/src/net/manaserv/itemhandler.cpp @@ -26,8 +26,6 @@ #include "net/manaserv/manaserv_protocol.h" #include "net/manaserv/messagein.h" -#include "game.h" -#include "map.h" #include "log.h" namespace ManaServ { @@ -58,21 +56,7 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) if (itemId) { - if (Game *game = Game::instance()) - { - if (Map *map = game->getCurrentMap()) - { - actorSpriteManager->createItem(id, itemId, - x / map->getTileWidth(), - y / map->getTileHeight()); - } - else - { - logger->log( - "ItemHandler: An item wasn't created " - "because of Game/Map not initialized..."); - } - } + actorSpriteManager->createItem(id, itemId, Vector(x, y)); } else if (FloorItem *item = actorSpriteManager->findItem(id)) { diff --git a/src/net/tmwa/itemhandler.cpp b/src/net/tmwa/itemhandler.cpp index a8e98860..e452ccf2 100644 --- a/src/net/tmwa/itemhandler.cpp +++ b/src/net/tmwa/itemhandler.cpp @@ -21,12 +21,14 @@ #include "net/tmwa/itemhandler.h" -#include "actorspritemanager.h" - #include "net/messagein.h" #include "net/tmwa/protocol.h" +#include "actorspritemanager.h" +#include "game.h" +#include "map.h" + namespace TmwAthena { ItemHandler::ItemHandler() @@ -54,7 +56,13 @@ void ItemHandler::handleMessage(Net::MessageIn &msg) int y = msg.readInt16(); msg.skip(4); // amount,subX,subY / subX,subY,amount - actorSpriteManager->createItem(id, itemId, x, y); + Game *game = Game::instance(); + if (!game) + break; + + if (Map *map = game->getCurrentMap()) + actorSpriteManager->createItem(id, itemId, + map->getTileCenter(x, y)); } break; -- cgit v1.2.3-70-g09d2