diff options
author | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2011-03-15 17:28:16 +0100 |
---|---|---|
committer | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2011-03-15 17:28:16 +0100 |
commit | 21e8d502d07c6cae9580a34dde7587d58e6d3a28 (patch) | |
tree | fd8c9fa711d0e2e60f50333f82dbe43ebd9214a5 /src/being.cpp | |
parent | 25a2abd09e3b76115ed0b6b1a02cdddc6c1c5bfc (diff) | |
download | mana-21e8d502d07c6cae9580a34dde7587d58e6d3a28.tar.gz mana-21e8d502d07c6cae9580a34dde7587d58e6d3a28.tar.bz2 mana-21e8d502d07c6cae9580a34dde7587d58e6d3a28.tar.xz mana-21e8d502d07c6cae9580a34dde7587d58e6d3a28.zip |
Basically merged the two movement algorithms into one.
This was made in favour of the manaserv way of doing things.
I also added a way to keep the original server speed value
so the pixel value can be recomputed at each map change, as this
was necessary since the speed is given before the first map
is loaded.
The code is much more simpler now about movement handling,
and we can already see improvements on other characters
movements in The Mana World with this.
Everything can't be perfect the first time; here are bugs
identified so far:
- Monsters direction isn't updated on TmwAthena for obscure reasons.
- Remote players walking animation is sometimes reset on each steps.
- When changing map, the local player sometimes walks randomly
until the player reacts.
Stay tuned!
Diffstat (limited to 'src/being.cpp')
-rw-r--r-- | src/being.cpp | 249 |
1 files changed, 54 insertions, 195 deletions
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); + } +} |