diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2008-08-28 18:32:11 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2008-08-28 18:32:11 +0000 |
commit | 566a6fb8d0fc35267b43721f7e1802ba3475af3d (patch) | |
tree | f5d3e09bda9e8e66be885b581f28cad4130ca645 | |
parent | b506fe0ff8a2039167aa7c349087af4dd03e1921 (diff) | |
download | mana-566a6fb8d0fc35267b43721f7e1802ba3475af3d.tar.gz mana-566a6fb8d0fc35267b43721f7e1802ba3475af3d.tar.bz2 mana-566a6fb8d0fc35267b43721f7e1802ba3475af3d.tar.xz mana-566a6fb8d0fc35267b43721f7e1802ba3475af3d.zip |
Added support for being effects through the eAthena levelup message, and check
whether the being exists before referencing it. Re-enabled proper MP bar
display. Improved handling of a warp to the same map.
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | src/being.cpp | 103 | ||||
-rw-r--r-- | src/being.h | 20 | ||||
-rw-r--r-- | src/engine.cpp | 1 | ||||
-rw-r--r-- | src/engine.h | 5 | ||||
-rw-r--r-- | src/gui/ministatus.cpp | 2 | ||||
-rw-r--r-- | src/net/beinghandler.cpp | 34 | ||||
-rw-r--r-- | src/net/playerhandler.cpp | 19 | ||||
-rw-r--r-- | src/net/protocol.h | 2 | ||||
-rw-r--r-- | src/particle.h | 9 | ||||
-rw-r--r-- | src/player.h | 8 |
11 files changed, 187 insertions, 25 deletions
@@ -1,3 +1,12 @@ +2008-08-28 Fate <fate.tmw@googlemail.com> + + * src/engine.h, src/gui/ministatus.cpp, src/engine.cpp, + src/particle.h, src/being.cpp, src/player.h, src/net/beinghandler.cpp, + src/net/protocol.h, src/net/playerhandler.cpp, src/being.h: Added + support for being effects through the eAthena levelup message, and + check whether the being exists before referencing it. Re-enabled + proper MP bar display. Improved handling of a warp to the same map. + 2008-08-28 Bjørn Lindeijer <bjorn@lindeijer.nl> * src/game.cpp, src/net/beinghandler.cpp, diff --git a/src/being.cpp b/src/being.cpp index 625b0eef..1880e7c0 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -32,6 +32,8 @@ #include "log.h" #include "map.h" #include "particle.h" +#include "sound.h" +#include "localplayer.h" #include "resources/resourcemanager.h" #include "resources/imageset.h" @@ -42,6 +44,10 @@ #include "utils/dtor.h" #include "utils/tostring.h" +#include "utils/xml.h" + +#define BEING_EFFECTS_FILE "effects.xml" + int Being::instances = 0; ImageSet *Being::emotionSet = NULL; @@ -386,7 +392,7 @@ Being::logic() ) { (*i)->setPosition((float)mPx + 16.0f, (float)mPy + 32.0f); - if (!(*i)->isAlive()) + if ((*i)->isExtinct()) { (*i)->kill(); i = mChildParticleEffects.erase(i); @@ -496,3 +502,98 @@ Being::getHeight() const return 0; } } + + + +struct EffectDescription { + std::string mGFXEffect; + std::string mSFXEffect; +}; + +static EffectDescription *default_effect = NULL; +static std::map<int, EffectDescription *> effects; +static bool effects_initialized = false; + +static EffectDescription * +getEffectDescription(xmlNodePtr node, int *id) +{ + EffectDescription *ed = new EffectDescription; + + *id = atoi(XML::getProperty(node, "id", "-1").c_str()); + ed->mSFXEffect = XML::getProperty(node, "audio", ""); + ed->mGFXEffect = XML::getProperty(node, "particle", ""); + + return ed; +} + +static EffectDescription * +getEffectDescription(int effectId) +{ + if (!effects_initialized) + { + XML::Document doc(BEING_EFFECTS_FILE); + xmlNodePtr root = doc.rootNode(); + + if (!root || !xmlStrEqual(root->name, BAD_CAST "being-effects")) + { + logger->log("Error loading being effects file: " + BEING_EFFECTS_FILE); + return NULL; + } + + for_each_xml_child_node(node, root) + { + int id; + + if (xmlStrEqual(node->name, BAD_CAST "effect")) + { + EffectDescription *EffectDescription = + getEffectDescription(node, &id); + effects[id] = EffectDescription; + } else if (xmlStrEqual(node->name, BAD_CAST "default")) + { + EffectDescription *EffectDescription = + getEffectDescription(node, &id); + + if (default_effect) + delete default_effect; + + default_effect = EffectDescription; + } + } + + effects_initialized = true; + } // done initializing + + EffectDescription *ed = effects[effectId]; + + if (!ed) + return default_effect; + else + return ed; +} + +void +Being::internalTriggerEffect(int effectId, bool sfx, bool gfx) +{ + logger->log("Special effect #%d on %s", effectId, + getId() == player_node->getId() ? "self" : "other"); + + EffectDescription *ed = getEffectDescription(effectId); + + if (!ed) { + logger->log("Unknown special effect and no default recorded"); + return; + } + + if (gfx && ed->mGFXEffect != "") { + Particle *selfFX; + + selfFX = particleEngine->addEffect(ed->mGFXEffect, 0, 0); + controlParticle(selfFX); + } + + if (sfx && ed->mSFXEffect != "") { + sound.playSfx(ed->mSFXEffect); + } +} diff --git a/src/being.h b/src/being.h index 046f7b9a..c4f34503 100644 --- a/src/being.h +++ b/src/being.h @@ -365,6 +365,16 @@ class Being : public Sprite void setEmote(Uint8 emotion, Uint8 emote_time) { mEmotion = emotion; mEmotionTime = emote_time; } + /** + * Triggers a visual effect, such as `level up' + * + * Only draws the visual effect, does not play sound effects + * + * \param effectId ID of the effect to trigger + */ + virtual void + triggerEffect(int effectId) { internalTriggerEffect(effectId, false, true); } + const std::auto_ptr<Equipment> mEquipment; protected: @@ -378,6 +388,16 @@ class Being : public Sprite */ SpriteDirection getSpriteDirection() const; + /** + * Trigger visual effect, with components + * + * \param effectId ID of the effect to trigger + * \param sfx Whether to trigger sound effects + * \param gfx Whether to trigger graphical effects + */ + void + internalTriggerEffect(int effectId, bool sfx, bool gfx); + Uint32 mId; /**< Unique sprite id */ Uint16 mWalkSpeed; /**< Walking speed */ Uint8 mDirection; /**< Facing direction */ diff --git a/src/engine.cpp b/src/engine.cpp index d4033193..b53608be 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -120,6 +120,7 @@ void Engine::changeMap(const std::string &mapPath) } mCurrentMap = newMap; + mMapName = mapPath; // Send "map loaded" MessageOut outMsg(mNetwork); diff --git a/src/engine.h b/src/engine.h index 4575051e..52f1e63a 100644 --- a/src/engine.h +++ b/src/engine.h @@ -25,6 +25,7 @@ #define _ENGINE_H #include <iosfwd> +#include <string> class Map; class Network; @@ -51,6 +52,9 @@ class Engine */ Map *getCurrentMap() { return mCurrentMap; } + const std::string &getCurrentMapName() { return mMapName; } + + /** * Sets the currently active map. */ @@ -64,6 +68,7 @@ class Engine private: Map *mCurrentMap; Network *mNetwork; + std::string mMapName; }; extern Engine *engine; diff --git a/src/gui/ministatus.cpp b/src/gui/ministatus.cpp index 8f121368..077e2331 100644 --- a/src/gui/ministatus.cpp +++ b/src/gui/ministatus.cpp @@ -98,7 +98,7 @@ void MiniStatusWindow::update() } mHpBar->setProgress((float) player_node->mHp / player_node->mMaxHp); - // mMpBar->setProgress((float) player_node->mMp / player_node->mMaxMp); + mMpBar->setProgress((float) player_node->mMp / player_node->mMaxMp); mXpBar->setProgress( (float) player_node->getXp() / player_node->mXpForNextLevel); diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index c43c674f..7a0be952 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -36,7 +36,9 @@ #include "../main.h" #include "../particle.h" #include "../sound.h" +#include <iostream> #include "../player_relations.h" +#include "../npc.h" const int EMOTION_TIME = 150; /**< Duration of emotion icon */ @@ -49,7 +51,7 @@ BeingHandler::BeingHandler(bool enableSync): SMSG_BEING_MOVE2, SMSG_BEING_REMOVE, SMSG_BEING_ACTION, - SMSG_BEING_LEVELUP, + SMSG_BEING_SELFEFFECT, SMSG_BEING_EMOTION, SMSG_BEING_CHANGE_LOOKS, SMSG_BEING_CHANGE_LOOKS2, @@ -208,6 +210,9 @@ void BeingHandler::handleMessage(MessageIn *msg) player_node->stopAttack(); } + if (dstBeing == current_npc) + current_npc = NULL; + if (msg->readInt8() == 1) { dstBeing->setAction(Being::DEAD); @@ -258,27 +263,17 @@ void BeingHandler::handleMessage(MessageIn *msg) } break; - case SMSG_BEING_LEVELUP: + case SMSG_BEING_SELFEFFECT: { id = (Uint32)msg->readInt32(); + if (!beingManager->findBeing(id)) + break; + + int effectType = msg->readInt32(); + + beingManager->findBeing(id)->triggerEffect(effectType); - if (id == player_node->getId()) { - logger->log("Level up"); - sound.playSfx("sfx/levelup.ogg"); - } - else { - logger->log("Someone else went level up"); - } - Particle *levelupFX; - if (msg->readInt32() == 0) { // type - levelupFX = particleEngine->addEffect( - "graphics/particles/levelup.particle.xml", 0, 0); - } - else { - levelupFX = particleEngine->addEffect( - "graphics/particles/skillup.particle.xml", 0, 0); - } - beingManager->findBeing(id)->controlParticle(levelupFX); break; + } case SMSG_BEING_EMOTION: if (!(dstBeing = beingManager->findBeing(msg->readInt32()))) @@ -513,3 +508,4 @@ void BeingHandler::handleMessage(MessageIn *msg) break; } } + diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index 463868db..27d4e601 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -52,6 +52,9 @@ extern BuyDialog *buyDialog; extern SellDialog *sellDialog; extern Window *buySellDialog; +static const int MAP_TELEPORT_SCROLL_DISTANCE = 8; /* Max. distance we are willing to scroll after a teleport; + ** everything beyond will reset the port hard. */ + /** * Listener used for handling the overweigth message. */ @@ -118,6 +121,7 @@ void PlayerHandler::handleMessage(MessageIn *msg) case SMSG_PLAYER_WARP: { std::string mapPath = msg->readString(16); + bool nearby; Uint16 x = msg->readInt16(); Uint16 y = msg->readInt16(); @@ -129,13 +133,22 @@ void PlayerHandler::handleMessage(MessageIn *msg) */ player_node->stopAttack(); - // Switch the actual map, deleting the previous one + nearby = (engine->getCurrentMapName() == mapPath); + // Switch the actual map, deleting the previous one if necessary engine->changeMap(mapPath); current_npc = 0; - float scrollOffsetX = (x - player_node->mX) * 32; - float scrollOffsetY = (y - player_node->mY) * 32; + float scrollOffsetX = 0.0f; + float scrollOffsetY = 0.0f; + + /* Scroll if neccessary */ + if (!nearby + || (abs(x - player_node->mX) > MAP_TELEPORT_SCROLL_DISTANCE) + || (abs(y - player_node->mY) > MAP_TELEPORT_SCROLL_DISTANCE)) { + scrollOffsetX = (x - player_node->mX) * 32; + scrollOffsetY = (y - player_node->mY) * 32; + } player_node->setAction(Being::STAND); player_node->mFrame = 0; diff --git a/src/net/protocol.h b/src/net/protocol.h index a2aa50c3..49c177a2 100644 --- a/src/net/protocol.h +++ b/src/net/protocol.h @@ -63,7 +63,7 @@ #define SMSG_BEING_REMOVE 0x0080 #define SMSG_BEING_CHANGE_LOOKS 0x00c3 #define SMSG_BEING_CHANGE_LOOKS2 0x01d7 /**< Same as 0x00c3, but 16 bit ID */ -#define SMSG_BEING_LEVELUP 0x019b +#define SMSG_BEING_SELFEFFECT 0x019b #define SMSG_BEING_EMOTION 0x00c0 #define SMSG_BEING_ACTION 0x008a /**< Attack, sit, stand up, ... */ #define SMSG_BEING_CHAT 0x008d /**< A being talks */ diff --git a/src/particle.h b/src/particle.h index d9b8c6b7..f281864d 100644 --- a/src/particle.h +++ b/src/particle.h @@ -161,6 +161,9 @@ class Particle : public Sprite { mPos.x += x; mPos.y += y; mPos.z += z; } void + moveChildren(Vector change); + + void moveBy (Vector change) { mPos += change; } @@ -271,6 +274,12 @@ class Particle : public Sprite { return mAlive; } /** + * Determines whether the particle and its children are all dead + */ + bool isExtinct() + { return !isAlive() && mChildParticles.empty(); } + + /** * Manually marks the particle for deletion. */ void kill() diff --git a/src/player.h b/src/player.h index f43a6039..fe24ceed 100644 --- a/src/player.h +++ b/src/player.h @@ -94,6 +94,14 @@ class Player : public Being virtual PlayerNameDrawStrategy * getNameDrawStrategy(void) const { return mDrawStrategy; } + /** + * Triggers a visual/audio effect, such as `level up' + * + * \param effect_id ID of the effect to trigger + */ + virtual void + triggerEffect(int effectId) { internalTriggerEffect(effectId, true, true); } + private: PlayerNameDrawStrategy *mDrawStrategy; }; |