summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actor.h2
-rw-r--r--src/being.cpp249
-rw-r--r--src/being.h79
-rw-r--r--src/gui/viewport.cpp119
-rw-r--r--src/localplayer.cpp301
-rw-r--r--src/net/manaserv/beinghandler.cpp39
-rw-r--r--src/net/manaserv/beinghandler.h8
-rw-r--r--src/net/manaserv/playerhandler.cpp33
-rw-r--r--src/net/manaserv/playerhandler.h4
-rw-r--r--src/net/playerhandler.h13
-rw-r--r--src/net/tmwa/beinghandler.cpp57
-rw-r--r--src/net/tmwa/beinghandler.h3
-rw-r--r--src/net/tmwa/charserverhandler.cpp6
-rw-r--r--src/net/tmwa/gamehandler.cpp15
-rw-r--r--src/net/tmwa/gamehandler.h7
-rw-r--r--src/net/tmwa/playerhandler.cpp75
-rw-r--r--src/net/tmwa/playerhandler.h4
-rw-r--r--src/sound.cpp7
-rw-r--r--src/sound.h4
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);