summaryrefslogtreecommitdiff
path: root/src/localplayer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/localplayer.cpp')
-rw-r--r--src/localplayer.cpp950
1 files changed, 274 insertions, 676 deletions
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 4d0ad17e..1a7f20e1 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -23,30 +23,19 @@
#include "client.h"
#include "configuration.h"
-#include "effectmanager.h"
-#include "equipment.h"
+#include "event.h"
#include "flooritem.h"
#include "graphics.h"
#include "guild.h"
-#include "inventory.h"
#include "item.h"
-#include "log.h"
#include "map.h"
-#include "monster.h"
#include "particle.h"
+#include "playerinfo.h"
#include "simpleanimation.h"
#include "sound.h"
-#include "statuseffect.h"
-#include "text.h"
#include "gui/gui.h"
-#include "gui/inventorywindow.h"
-#include "gui/ministatus.h"
#include "gui/okdialog.h"
-#include "gui/skilldialog.h"
-#include "gui/statuswindow.h"
-#include "gui/theme.h"
-#include "gui/userpalette.h"
#include "gui/widgets/chattab.h"
@@ -61,9 +50,8 @@
#include "resources/animation.h"
#include "resources/imageset.h"
-#include "resources/itemdb.h"
#include "resources/iteminfo.h"
-#include "resources/resourcemanager.h"
+#include "resources/userpalette.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
@@ -80,70 +68,45 @@ const short walkingKeyboardDelay = 1000;
LocalPlayer *player_node = NULL;
LocalPlayer::LocalPlayer(int id, int subtype):
- Player(id, subtype, 0),
- mEquipment(new Equipment),
- mAttackRange(0),
+ Being(id, PLAYER, subtype, 0),
+ mAttackRange(ATTACK_RANGE_NOT_SET),
mTargetTime(-1),
mLastTarget(-1),
- mCharacterPoints(0),
- mCorrectionPoints(0),
- mSpecialRechargeUpdateNeeded(0),
- mLevel(1),
- mExp(0), mExpNeeded(0),
- mMp(0), mMaxMp(0),
- mMoney(0),
- mTotalWeight(1), mMaxWeight(1),
- mHp(1), mMaxHp(1),
- mSkillPoints(0),
mTarget(NULL),
mPickUpTarget(NULL),
- mTrading(false), mGoingToTarget(false), mKeepAttacking(false),
+ mGoingToTarget(false), mKeepAttacking(false),
mLastAction(-1),
mWalkingDir(0),
mPathSetByMouse(false),
- mInventory(new Inventory(Inventory::INVENTORY)),
mLocalWalkTime(-1),
mMessageTime(0),
+ mShowIp(false),
mAwayDialog(0),
mAfkTime(0),
- mAwayMode(false),
- mShowIp(false)
+ mAwayMode(false)
{
+ listen(Event::AttributesChannel);
+
mAwayListener = new AwayListener();
mUpdateName = true;
- mTextColor = &Theme::getThemeColor(Theme::PLAYER);
- mNameColor = &userPalette->getColor(UserPalette::SELF);
-
- initTargetCursor();
-
- config.addListener("showownname", this);
setShowName(config.getValue("showownname", 1));
+
+ listen(Event::ConfigChannel);
+ listen(Event::ActorSpriteChannel);
}
LocalPlayer::~LocalPlayer()
{
- delete mInventory;
-
- config.removeListener("showownname", this);
-
- for (int i = Being::TC_SMALL; i < Being::NUM_TC; i++)
- {
- delete mTargetCursor[0][i];
- delete mTargetCursor[1][i];
- mTargetCursorImages[0][i]->decRef();
- mTargetCursorImages[1][i]->decRef();
- }
-
delete mAwayDialog;
delete mAwayListener;
}
void LocalPlayer::logic()
{
- // Actions are allowed once per second
- if (get_elapsed_time(mLastAction) >= 1000)
+ // Actions are allowed at 5.5 per second
+ if (get_elapsed_time(mLastAction) >= 182)
mLastAction = -1;
// Show XP messages
@@ -151,16 +114,12 @@ 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,
+ getPixelY() - 32 - 16,
&userPalette->getColor(info.second),
gui->getInfoParticleFont(), true);
@@ -170,21 +129,7 @@ void LocalPlayer::logic()
mMessageTime--;
}
- if ((mSpecialRechargeUpdateNeeded%11) == 0)
- {
- mSpecialRechargeUpdateNeeded = 0;
- for (std::map<int, Special>::iterator i = mSpecials.begin();
- i != mSpecials.end();
- i++)
- {
- i->second.currentMana += i->second.recharge;
- if (i->second.currentMana > i->second.neededMana)
- {
- i->second.currentMana = i->second.neededMana;
- }
- }
- }
- mSpecialRechargeUpdateNeeded++;
+ PlayerInfo::logic();
// Targeting allowed 4 times a second
if (get_elapsed_time(mLastTarget) >= 250)
@@ -200,30 +145,22 @@ void LocalPlayer::logic()
if (mTarget)
{
- if (mTarget->getType() == Being::NPC)
+ if (mTarget->getType() == ActorSprite::NPC)
{
// NPCs are always in range
- mTarget->setTargetAnimation(
- mTargetCursor[0][mTarget->getTargetCursorSize()]);
+ mTarget->setTargetType(TCT_IN_RANGE);
}
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 int inRange = rangeX > attackRange || rangeY > attackRange
- ? 1 : 0;
- mTarget->setTargetAnimation(
- mTargetCursor[inRange][mTarget->getTargetCursorSize()]);
+ const TargetCursorType targetType = rangeX > attackRange ||
+ rangeY > attackRange ?
+ TCT_NORMAL : TCT_IN_RANGE;
+ mTarget->setTargetType(targetType);
if (!mTarget->isAlive())
stopAttack();
@@ -233,10 +170,10 @@ void LocalPlayer::logic()
}
}
- Player::logic();
+ Being::logic();
}
-void LocalPlayer::setAction(Action action, int attackType)
+void LocalPlayer::setAction(Action action, int attackId)
{
if (action == DEAD)
{
@@ -244,12 +181,7 @@ void LocalPlayer::setAction(Action action, int attackType)
setTarget(NULL);
}
- Player::setAction(action, attackType);
-}
-
-void LocalPlayer::setGM(bool gm)
-{
- mIsGM = gm;
+ Being::setAction(action, attackId);
}
void LocalPlayer::setGMLevel(int level)
@@ -281,11 +213,14 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
if (!mMap || (!dx && !dy))
return Position((int)pos.x, (int)pos.y);
+ const int tileW = mMap->getTileWidth();
+ const int tileH = mMap->getTileHeight();
+
// Get the current tile pos and its offset
- int tileX = (int)pos.x / mMap->getTileWidth();
- int tileY = (int)pos.y / mMap->getTileHeight();
- int offsetX = (int)pos.x % mMap->getTileWidth();
- int offsetY = (int)pos.y % mMap->getTileHeight();
+ const int tileX = (int)pos.x / tileW;
+ const int tileY = (int)pos.y / tileH;
+ int offsetX = (int)pos.x % tileW;
+ int offsetY = (int)pos.y % tileH;
// Get the walkability of every surrounding tiles.
bool wTopLeft = mMap->getWalk(tileX - 1, tileY - 1, getWalkMask());
@@ -330,14 +265,14 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
else if (wTop && !wRight)
dx = 0;
else if (!wTop && !wRight)
- return Position(tileX * 32 + 32 - getCollisionRadius(),
- tileY * 32 + getCollisionRadius());
+ return Position(tileX * tileW + tileW
+ - getCollisionRadius(),
+ tileY * tileH + getCollisionRadius());
else // Both straight direction are walkable
{
// Go right when below the corner
- if (offsetY >= (offsetX / mMap->getTileHeight()
- - (offsetX / mMap->getTileWidth()
- * mMap->getTileHeight()) ))
+ if (offsetY >=
+ (offsetX / tileH - (offsetX / tileW * tileH)))
dy = 0;
else // Go up otherwise
dx = 0;
@@ -346,7 +281,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
else // The diagonal is walkable
return mMap->checkNodeOffsets(getCollisionRadius(),
getWalkMask(),
- Position((int)pos.x + 32, (int)pos.y - 32));
+ Position((int)pos.x + tileW,
+ (int)pos.y - tileH));
}
// Going top-left
@@ -360,8 +296,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
else if (wTop && !wLeft)
dx = 0;
else if (!wTop && !wLeft)
- return Position(tileX * 32 + getCollisionRadius(),
- tileY * 32 + getCollisionRadius());
+ return Position(tileX * tileW + getCollisionRadius(),
+ tileY * tileH + getCollisionRadius());
else // Both straight direction are walkable
{
// Go left when below the corner
@@ -375,7 +311,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
else // The diagonal is walkable
return mMap->checkNodeOffsets(getCollisionRadius(),
getWalkMask(),
- Position((int)pos.x - 32, (int)pos.y - 32));
+ Position((int)pos.x - tileW,
+ (int)pos.y - tileH));
}
// Going bottom-left
@@ -389,8 +326,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
else if (wBottom && !wLeft)
dx = 0;
else if (!wBottom && !wLeft)
- return Position(tileX * 32 + getCollisionRadius(),
- tileY * 32 + 32 - getCollisionRadius());
+ return Position(tileX * tileW + getCollisionRadius(),
+ tileY * tileH + tileH - getCollisionRadius());
else // Both straight direction are walkable
{
// Go down when below the corner
@@ -405,7 +342,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
else // The diagonal is walkable
return mMap->checkNodeOffsets(getCollisionRadius(),
getWalkMask(),
- Position((int)pos.x - 32, (int)pos.y + 32));
+ Position((int)pos.x - tileW,
+ (int)pos.y + tileH));
}
// Going bottom-right
@@ -419,8 +357,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
else if (wBottom && !wRight)
dx = 0;
else if (!wBottom && !wRight)
- return Position(tileX * 32 + 32 - getCollisionRadius(),
- tileY * 32 + 32 - getCollisionRadius());
+ return Position(tileX * tileW + tileW - getCollisionRadius(),
+ tileY * tileH + tileH - getCollisionRadius());
else // Both straight direction are walkable
{
// Go down when below the corner
@@ -434,7 +372,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
else // The diagonal is walkable
return mMap->checkNodeOffsets(getCollisionRadius(),
getWalkMask(),
- Position((int)pos.x + 32, (int)pos.y + 32));
+ Position((int)pos.x + tileW,
+ (int)pos.y + tileH));
}
} // End of diagonal cases
@@ -446,7 +385,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
// If the straight destination is blocked,
// Make the player go the closest possible.
if (!wRight)
- return Position(tileX * 32 + 32 - getCollisionRadius(), (int)pos.y);
+ return Position(tileX * tileW + tileW - getCollisionRadius(),
+ (int)pos.y);
else
{
if (!wTopRight)
@@ -456,8 +396,9 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
{
// We make the player corrects its offset
// before going further
- return Position(tileX * 32 + 32 - getCollisionRadius(),
- tileY * 32 + getCollisionRadius());
+ return Position(tileX * tileW
+ + tileW - getCollisionRadius(),
+ tileY * tileH + getCollisionRadius());
}
}
@@ -465,18 +406,21 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
if (!wBottomRight)
{
// If we're going to collide with the bottom-right corner
- if (offsetY + getCollisionRadius() > 32)
+ if (offsetY + getCollisionRadius() > tileH)
{
// We make the player corrects its offset
// before going further
- return Position(tileX * 32 + 32 - getCollisionRadius(),
- tileY * 32 + 32 - getCollisionRadius());
+ return Position(tileX * tileW
+ + tileW - getCollisionRadius(),
+ tileY * tileH
+ + tileH - getCollisionRadius());
}
}
// If the way is clear, step up one checked tile ahead.
return mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(),
- Position((int)pos.x + 32, (int)pos.y));
+ Position((int)pos.x + tileW,
+ (int)pos.y));
}
}
@@ -486,7 +430,7 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
// If the straight destination is blocked,
// Make the player go the closest possible.
if (!wLeft)
- return Position(tileX * 32 + getCollisionRadius(), (int)pos.y);
+ return Position(tileX * tileW + getCollisionRadius(), (int)pos.y);
else
{
if (!wTopLeft)
@@ -496,8 +440,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
{
// We make the player corrects its offset
// before going further
- return Position(tileX * 32 + getCollisionRadius(),
- tileY * 32 + getCollisionRadius());
+ return Position(tileX * tileW + getCollisionRadius(),
+ tileY * tileH + getCollisionRadius());
}
}
@@ -505,18 +449,20 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
if (!wBottomLeft)
{
// If we're going to collide with the bottom-left corner
- if (offsetY + getCollisionRadius() > 32)
+ if (offsetY + getCollisionRadius() > tileH)
{
// We make the player corrects its offset
// before going further
- return Position(tileX * 32 + getCollisionRadius(),
- tileY * 32 + 32 - getCollisionRadius());
+ return Position(tileX * tileW + getCollisionRadius(),
+ tileY * tileH
+ + tileH - getCollisionRadius());
}
}
// If the way is clear, step up one checked tile ahead.
return mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(),
- Position((int)pos.x - 32, (int)pos.y));
+ Position((int)pos.x - tileW,
+ (int)pos.y));
}
}
@@ -526,7 +472,7 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
// If the straight destination is blocked,
// Make the player go the closest possible.
if (!wTop)
- return Position((int)pos.x, tileY * 32 + getCollisionRadius());
+ return Position((int)pos.x, tileY * tileH + getCollisionRadius());
else
{
if (!wTopLeft)
@@ -536,8 +482,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
{
// We make the player corrects its offset
// before going further
- return Position(tileX * 32 + getCollisionRadius(),
- tileY * 32 + getCollisionRadius());
+ return Position(tileX * tileW + getCollisionRadius(),
+ tileY * tileH + getCollisionRadius());
}
}
@@ -545,18 +491,20 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
if (!wTopRight)
{
// If we're going to collide with the top-right corner
- if (offsetX + getCollisionRadius() > 32)
+ if (offsetX + getCollisionRadius() > tileW)
{
// We make the player corrects its offset
// before going further
- return Position(tileX * 32 + 32 - getCollisionRadius(),
- tileY * 32 + getCollisionRadius());
+ return Position(tileX * tileW
+ + tileW - getCollisionRadius(),
+ tileY * tileH + getCollisionRadius());
}
}
// If the way is clear, step up one checked tile ahead.
return mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(),
- Position((int)pos.x, (int)pos.y - 32));
+ Position((int)pos.x,
+ (int)pos.y - tileH));
}
}
@@ -566,7 +514,8 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
// If the straight destination is blocked,
// Make the player go the closest possible.
if (!wBottom)
- return Position((int)pos.x, tileY * 32 + 32 - getCollisionRadius());
+ return Position((int)pos.x, tileY * tileH
+ + tileH - getCollisionRadius());
else
{
if (!wBottomLeft)
@@ -576,27 +525,30 @@ Position LocalPlayer::getNextWalkPosition(unsigned char dir)
{
// We make the player corrects its offset
// before going further
- return Position(tileX * 32 + getCollisionRadius(),
- tileY * 32 + 32 - getCollisionRadius());
-
+ return Position(tileX * tileW + getCollisionRadius(),
+ tileY * tileH
+ + tileH - getCollisionRadius());
}
}
if (!wBottomRight)
{
// If we're going to collide with the bottom-right corner
- if (offsetX + getCollisionRadius() > 32)
+ if (offsetX + getCollisionRadius() > tileW)
{
// We make the player corrects its offset
// before going further
- return Position(tileX * 32 + 32 - getCollisionRadius(),
- tileY * 32 + 32 - getCollisionRadius());
+ return Position(tileX * tileW
+ + tileW - getCollisionRadius(),
+ tileY * tileH
+ + tileH - getCollisionRadius());
}
}
// If the way is clear, step up one checked tile ahead.
return mMap->checkNodeOffsets(getCollisionRadius(), getWalkMask(),
- Position((int)pos.x, (int)pos.y + 32));
+ Position((int)pos.x,
+ (int)pos.y + tileH));
}
}
@@ -606,56 +558,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);
- Player::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);
}
}
@@ -674,7 +592,6 @@ void LocalPlayer::inviteToGuild(Being *being)
{
if (being->getType() != PLAYER)
return;
- Player *player = static_cast<Player*>(being);
// TODO: Allow user to choose which guild to invite being to
// For now, just invite to the first guild you have permissions to invite with
@@ -684,31 +601,21 @@ void LocalPlayer::inviteToGuild(Being *being)
{
if (checkInviteRights(itr->second->getName()))
{
- Net::getGuildHandler()->invite(itr->second->getId(), player);
+ Net::getGuildHandler()->invite(itr->second->getId(), being);
return;
}
}
}
-void LocalPlayer::clearInventory()
-{
- mEquipment->clear();
- mInventory->clear();
-}
-
-void LocalPlayer::setInvItem(int index, int id, int amount)
-{
- bool equipment = false;
- int itemType = ItemDB::get(id).getType();
- if (itemType != ITEM_UNUSABLE && itemType != ITEM_USABLE)
- equipment = true;
- mInventory->setItem(index, id, amount, equipment);
-}
-
void LocalPlayer::pickUp(FloorItem *item)
{
- int dx = item->getX() - getTileX();
- int dy = item->getY() - getTileY();
+ if (!item)
+ return;
+
+ 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)
{
@@ -717,17 +624,9 @@ void LocalPlayer::pickUp(FloorItem *item)
}
else
{
- if (Net::getNetworkType() == ServerInfo::MANASERV)
- {
- setDestination(item->getX() * 32 + 16, item->getY() * 32 + 16);
- mPickUpTarget = item;
- }
- else
- {
- setDestination(item->getX(), item->getY());
- mPickUpTarget = item;
- stopAttack();
- }
+ setDestination(item->getTileX() * tileWidth + tileWidth / 2,
+ item->getTileY() * tileHeight + tileHeight / 2);
+ mPickUpTarget = item;
}
}
@@ -757,31 +656,63 @@ void LocalPlayer::setTarget(Being *target)
mTargetTime = -1;
}
+ Being *oldTarget = 0;
if (mTarget)
+ {
mTarget->untarget();
+ oldTarget = mTarget;
+ }
- if (mTarget && mTarget->getType() == Being::MONSTER)
+ if (mTarget && mTarget->getType() == ActorSprite::MONSTER)
mTarget->setShowName(false);
mTarget = target;
- if (target && target->getType() == Being::MONSTER)
+ if (oldTarget)
+ oldTarget->updateName();
+ if (mTarget)
+ mTarget->updateName();
+
+ if (target && target->getType() == ActorSprite::MONSTER)
target->setShowName(true);
}
void LocalPlayer::setDestination(int x, int y)
{
+ int srcX = x;
+ int srcY = y;
+ int dstX = (int)mDest.x;
+ int dstY = (int)mDest.y;
+ int tileWidth = mMap->getTileWidth();
+ int tileHeight = mMap->getTileHeight();
+ if (!Net::getPlayerHandler()->usePixelPrecision())
+ {
+ // For tile-based clients, we accept positions on the same tile.
+ srcX = srcX / tileWidth;
+ srcY = srcY / tileHeight;
+ dstX = dstX / tileWidth;
+ dstY = dstY / tileHeight;
+ }
+
// Only send a new message to the server when destination changes
- if (x != mDest.x || y != mDest.y)
+ if (srcX != dstX || srcY != dstY)
{
Being::setDestination(x, y);
+ // Note: Being::setDestination() updates mDest, so we get the new
+ // destination.
+ dstX = (int)mDest.x;
+ dstY = (int)mDest.y;
+
+ if (!Net::getPlayerHandler()->usePixelPrecision())
+ {
+ dstX = dstX / tileWidth;
+ dstY = dstY / tileHeight;
+ }
- // 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 (srcX == dstX && srcY == dstY)
+ Net::getPlayerHandler()->setDestination(x, y, mDirection);
}
mPickUpTarget = NULL;
@@ -792,41 +723,35 @@ 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, stop (sending to server).
- else if (!dir)
- {
- if (!mPathSetByMouse)
- player_node->stopWalking(true);
- 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;
// If we're not already walking, start walking.
- if (mAction != WALK && dir)
+ if (mAction != MOVE && dir)
{
startWalking(dir);
}
- else if (mAction == WALK && (Net::getNetworkType() == ServerInfo::MANASERV))
+ else if (mAction == MOVE)
{
nextTile(dir);
}
@@ -839,16 +764,11 @@ void LocalPlayer::startWalking(unsigned char dir)
if (!mMap || !dir)
return;
- if (mAction == WALK && !mPath.empty())
+ 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;
}
@@ -862,39 +782,15 @@ void LocalPlayer::startWalking(unsigned char dir)
if (dir & RIGHT)
dx++;
- 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);
+ // Update the direction when the walk just start
+ setDirection(dir);
+
+ nextTile(dir);
}
void LocalPlayer::stopWalking(bool sendToServer)
{
- if (mAction == WALK && mWalkingDir)
+ if (mAction == MOVE && mWalkingDir)
{
mWalkingDir = 0;
mLocalWalkTime = 0;
@@ -938,97 +834,55 @@ void LocalPlayer::emote(Uint8 emotion)
Net::getPlayerHandler()->emote(emotion);
}
-void LocalPlayer::useSpecial(int special)
-{
- Net::getSpecialHandler()->use(special);
-}
-
-void LocalPlayer::setSpecialStatus(int id, int current, int max, int recharge)
-{
- logger->log("SpecialUpdate Skill #%d -- (%d/%d) -> %d", id, current, max,
- recharge);
- mSpecials[id].currentMana = current;
- mSpecials[id].neededMana = max;
- mSpecials[id].recharge = recharge;
-}
-
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;
+ if (!target || target->getType() == ActorSprite::NPC)
+ return;
- if (!target || target->getType() == Being::NPC)
+ // Can't attack more times than its attack speed
+ static int lastAttackTime = 0;
+ if (get_elapsed_time(lastAttackTime) < mAttackSpeed)
return;
+ lastAttackTime = tick_time;
+
+ mKeepAttacking = keep;
+
if (mTarget != target || !mTarget)
{
mLastTarget = -1;
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;
- if (abs(dist_y) >= abs(dist_x))
- {
- if (dist_y < 0)
- setDirection(DOWN);
- else
- setDirection(UP);
- }
- else
- {
- if (dist_x < 0)
- setDirection(RIGHT);
- else
- setDirection(LEFT);
- }
+ Vector plaPos = this->getPosition();
+ Vector tarPos = mTarget->getPosition();
+ int dist_x = plaPos.x - tarPos.x;
+ int dist_y = plaPos.y - tarPos.y;
- mLastAction = tick_time;
+ if (abs(dist_y) >= abs(dist_x))
+ {
+ if (dist_y < 0)
+ setDirection(DOWN);
+ else
+ 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);
-
- mWalkTime = tick_time;
- mTargetTime = tick_time;
+ setDirection(LEFT);
}
+ mLastAction = tick_time;
+
setAction(ATTACK);
if (mEquippedWeapon)
@@ -1038,11 +892,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()
@@ -1056,190 +910,6 @@ void LocalPlayer::stopAttack()
mLastTarget = -1;
}
-void LocalPlayer::raiseAttribute(int attr)
-{
- // we assume that the server allows the change.
- // When not we will undo it later.
- mCharacterPoints--;
- IntMap::iterator it = mAttributeBase.find(attr);
- if (it != mAttributeBase.end())
- (*it).second++;
- Net::getPlayerHandler()->increaseAttribute(attr);
-}
-
-void LocalPlayer::lowerAttribute(int attr)
-{
- // we assume that the server allows the change.
- // When not we will undo it later.
- mCorrectionPoints--;
- mCharacterPoints++;
- IntMap::iterator it = mAttributeBase.find(attr);
- if (it != mAttributeBase.end())
- (*it).second--;
- Net::getPlayerHandler()->decreaseAttribute(attr);
-}
-
-void LocalPlayer::setTotalWeight(int value)
-{
- mTotalWeight = value;
-
- inventoryWindow->updateWeight();
-}
-
-void LocalPlayer::setMaxWeight(int value)
-{
- mMaxWeight = value;
-
- if (inventoryWindow)
- inventoryWindow->updateWeight();
-}
-
-void LocalPlayer::setAttributeBase(int num, int value, bool notify)
-{
- int old = mAttributeBase[num];
-
- mAttributeBase[num] = value;
- if (skillDialog)
- {
- if (skillDialog->update(num).empty() || !(value > old))
- return;
-
- if (old != 0 && notify)
- effectManager->trigger(1, this);
- }
-
- if (statusWindow)
- statusWindow->update(num);
-}
-
-void LocalPlayer::setAttributeEffective(int num, int value)
-{
- mAttributeEffective[num] = value;
- if (skillDialog)
- skillDialog->update(num);
-
- if (statusWindow)
- statusWindow->update(num);
-}
-
-void LocalPlayer::setCharacterPoints(int n)
-{
- mCharacterPoints = n;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::CHAR_POINTS);
-}
-
-void LocalPlayer::setCorrectionPoints(int n)
-{
- mCorrectionPoints = n;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::CHAR_POINTS);
-}
-
-void LocalPlayer::setSkillPoints(int points)
-{
- mSkillPoints = points;
- if (skillDialog)
- skillDialog->update();
-}
-
-void LocalPlayer::setExperience(int skill, int current, int next, bool notify)
-{
- std::pair<int, int> cur = getExperience(skill);
- int diff = current - cur.first;
-
- cur = std::pair<int, int>(current, next);
-
- mSkillExp[skill] = cur;
-
- std::string name;
- if (skillDialog)
- name = skillDialog->update(skill);
-
- if (mMap && notify && cur.first != -1 && diff > 0 && !name.empty())
- {
- addMessageToQueue(strprintf("%d %s xp", diff, name.c_str()));
- }
-
- if (statusWindow)
- statusWindow->update(skill);
-}
-
-std::pair<int, int> LocalPlayer::getExperience(int skill)
-{
- return mSkillExp[skill];
-}
-
-void LocalPlayer::setHp(int value)
-{
- mHp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::HP);
-}
-
-void LocalPlayer::setMaxHp(int value)
-{
- mMaxHp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::HP);
-}
-
-void LocalPlayer::setLevel(int value)
-{
- mLevel = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::LEVEL);
-}
-
-void LocalPlayer::setExp(int value, bool notify)
-{
- if (mMap && notify && value > mExp)
- {
- addMessageToQueue(toString(value - mExp) + " xp");
- }
- mExp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::EXP);
-}
-
-void LocalPlayer::setExpNeeded(int value)
-{
- mExpNeeded = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::EXP);
-}
-
-void LocalPlayer::setMP(int value)
-{
- mMp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
-}
-
-void LocalPlayer::setMaxMP(int value)
-{
- mMaxMp = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MP);
-}
-
-void LocalPlayer::setMoney(int value)
-{
- mMoney = value;
-
- if (statusWindow)
- statusWindow->update(StatusWindow::MONEY);
-}
-
void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount,
unsigned char fail)
{
@@ -1260,9 +930,9 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount,
}
if (config.getValue("showpickupchat", 1))
{
- localChatTab->chatLog(_(msg), BY_SERVER);
+ SERVER_NOTICE(_(msg))
}
- if (mMap && config.getValue("showpickupparticle", 0))
+ if (mMap && config.getBoolValue("showpickupparticle"))
{
// Show pickup notification
addMessageToQueue(_(msg), UserPalette::PICKUP_INFO);
@@ -1270,17 +940,16 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount,
}
else
{
- if (config.getValue("showpickupchat", 1))
+ if (config.getBoolValue("showpickupchat"))
{
// TRANSLATORS: This sentence may be translated differently
// for different grammatical numbers (singular, plural, ...)
- localChatTab->chatLog(strprintf(ngettext("You picked up %d "
+ SERVER_NOTICE(strprintf(ngettext("You picked up %d "
"[@@%d|%s@@].", "You picked up %d [@@%d|%s@@].", amount),
- amount, itemInfo.getId(), itemInfo.getName().c_str()),
- BY_SERVER);
+ amount, itemInfo.getId(), itemInfo.getName().c_str()))
}
- if (mMap && config.getValue("showpickupparticle", 0))
+ if (mMap && config.getBoolValue("showpickupparticle"))
{
// Show pickup notification
std::string msg = "";
@@ -1292,162 +961,91 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount,
}
}
-int LocalPlayer::getAttackRange()
+void LocalPlayer::setAttackRange(int range)
{
- if (mAttackRange > -1)
+ // When the range is more than the minimal, we accept it
+ if (range > ATTACK_RANGE_NOT_SET)
{
- return mAttackRange;
+ mAttackRange = range;
}
- else
+ else if (Net::getNetworkType() == ServerInfo::TMWATHENA)
{
- Item *weapon = mEquipment->getEquipment(EQUIP_FIGHT1_SLOT);
+ // 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();
+ if (info.getAttackRange() > ATTACK_RANGE_NOT_SET)
+ mAttackRange = info.getAttackRange();
}
- return 48; // unarmed range
}
}
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();
+ 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;
-
- 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());
- }
-}
-extern MiniStatusWindow *miniStatusWindow;
+ mTarget = target;
+ mGoingToTarget = true;
+ const Vector &targetPos = target->getPosition();
+ setDestination(targetPos.x, targetPos.y);
+}
-void LocalPlayer::handleStatusEffect(StatusEffect *effect, int effectId)
+void LocalPlayer::addMessageToQueue(const std::string &message, int color)
{
- Being::handleStatusEffect(effect, effectId);
+ mMessages.push_back(MessagePair(message, color));
+}
- if (effect)
+void LocalPlayer::event(Event::Channel channel, const Event &event)
+{
+ if (channel == Event::ActorSpriteChannel)
{
- effect->deliverMessage();
- effect->playSFX();
+ if (event.getType() == Event::Destroyed)
+ {
+ ActorSprite *actor = event.getActor("source");
- AnimatedSprite *sprite = effect->getIcon();
+ if (mPickUpTarget == actor)
+ mPickUpTarget = 0;
- if (!sprite)
- {
- // delete sprite, if necessary
- for (unsigned int i = 0; i < mStatusEffectIcons.size();)
- if (mStatusEffectIcons[i] == effectId)
- {
- mStatusEffectIcons.erase(mStatusEffectIcons.begin() + i);
- miniStatusWindow->eraseIcon(i);
- }
- else
- i++;
+ if (mTarget == actor)
+ mTarget = 0;
}
- else
+ }
+ else if (channel == Event::AttributesChannel)
+ {
+ if (event.getType() == Event::UpdateAttribute)
{
- // replace sprite or append
- bool found = false;
-
- for (unsigned int i = 0; i < mStatusEffectIcons.size(); i++)
- if (mStatusEffectIcons[i] == effectId)
- {
- miniStatusWindow->setIcon(i, sprite);
- found = true;
- break;
- }
+ if (event.getInt("id") == EXP)
+ {
+ int change = event.getInt("newValue")
+ - event.getInt("oldValue");
- if (!found)
- { // add new
- int offset = mStatusEffectIcons.size();
- miniStatusWindow->setIcon(offset, sprite);
- mStatusEffectIcons.push_back(effectId);
+ addMessageToQueue(toString(change) + " xp");
}
}
}
-}
-
-void LocalPlayer::initTargetCursor()
-{
- // Load target cursors
- loadTargetCursor("target-cursor-blue-s.png", 44, 35, false, TC_SMALL);
- loadTargetCursor("target-cursor-red-s.png", 44, 35, true, TC_SMALL);
- loadTargetCursor("target-cursor-blue-m.png", 62, 44, false, TC_MEDIUM);
- loadTargetCursor("target-cursor-red-m.png", 62, 44, true, TC_MEDIUM);
- loadTargetCursor("target-cursor-blue-l.png", 82, 60, false, TC_LARGE);
- loadTargetCursor("target-cursor-red-l.png", 82, 60, true, TC_LARGE);
-}
-
-void LocalPlayer::loadTargetCursor(const std::string &filename,
- int width, int height,
- bool outRange, TargetCursorSize size)
-{
- assert(size > -1);
- assert(size < 3);
-
- ImageSet *currentImageSet = Theme::getImageSetFromTheme(filename,
- width, height);
- Animation *anim = new Animation;
-
- for (unsigned int i = 0; i < currentImageSet->size(); ++i)
+ else if (channel == Event::ConfigChannel)
{
- anim->addFrame(currentImageSet->get(i), 75,
- (16 - (currentImageSet->getWidth() / 2)),
- (16 - (currentImageSet->getHeight() / 2)));
- }
-
- SimpleAnimation *currentCursor = new SimpleAnimation(anim);
-
- const int index = outRange ? 1 : 0;
-
- mTargetCursorImages[index][size] = currentImageSet;
- mTargetCursor[index][size] = currentCursor;
-}
-
-void LocalPlayer::addMessageToQueue(const std::string &message, int color)
-{
- mMessages.push_back(MessagePair(message, color));
-}
+ if (event.getType() == Event::ConfigOptionChanged &&
+ event.getString("option") == "showownname")
+ {
+ setShowName(config.getValue("showownname", 1));
+ }
-void LocalPlayer::optionChanged(const std::string &value)
-{
- if (value == "showownname")
- {
- setShowName(config.getValue("showownname", 1));
}
+
+ Being::event(channel, event);
}
void LocalPlayer::changeAwayMode()