diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2008-08-28 18:32:11 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2008-12-13 20:21:56 +0100 |
commit | 0a2fc4d340911b28b9dc6b3b23c69e9fe7729082 (patch) | |
tree | bddecd4581bb8591d0ac079a48eec3a66c411238 | |
parent | 5c4b6363d5065fb98a53b6981f5a590aaa37829b (diff) | |
download | mana-0a2fc4d340911b28b9dc6b3b23c69e9fe7729082.tar.gz mana-0a2fc4d340911b28b9dc6b3b23c69e9fe7729082.tar.bz2 mana-0a2fc4d340911b28b9dc6b3b23c69e9fe7729082.tar.xz mana-0a2fc4d340911b28b9dc6b3b23c69e9fe7729082.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.
(patch by Fate)
(cherry picked from eAthena client, the part about the levelup message
doesn't apply, and we now seem to have a second "effect manager"...)
Conflicts:
ChangeLog
src/being.cpp
src/being.h
src/engine.cpp
src/engine.h
src/gui/ministatus.cpp
src/net/beinghandler.cpp
src/net/playerhandler.cpp
src/net/protocol.h
-rw-r--r-- | src/being.cpp | 103 | ||||
-rw-r--r-- | src/being.h | 19 | ||||
-rw-r--r-- | src/engine.cpp | 1 | ||||
-rw-r--r-- | src/engine.h | 5 | ||||
-rw-r--r-- | src/net/beinghandler.cpp | 4 | ||||
-rw-r--r-- | src/net/playerhandler.cpp | 18 | ||||
-rw-r--r-- | src/particle.h | 9 | ||||
-rw-r--r-- | src/player.h | 8 |
8 files changed, 163 insertions, 4 deletions
diff --git a/src/being.cpp b/src/being.cpp index fbee967f..3a84ccd0 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -30,6 +30,8 @@ #include "log.h" #include "map.h" #include "particle.h" +#include "sound.h" +#include "localplayer.h" #include "resources/itemdb.h" #include "resources/resourcemanager.h" @@ -49,6 +51,10 @@ const bool debug_movement = true; #define HAIR_FILE "hair.xml" +#include "utils/xml.h" + +#define BEING_EFFECTS_FILE "effects.xml" + int Being::instances = 0; ImageSet *Being::emotionSet = NULL; @@ -525,7 +531,7 @@ void Being::logic() i != mChildParticleEffects.end();) { (*i)->setPosition(mPos.x, mPos.y); - if (!(*i)->isAlive()) + if ((*i)->isExtinct()) { (*i)->kill(); i = mChildParticleEffects.erase(i); @@ -695,3 +701,98 @@ initializeHair(void) hairInitialized = 1; } + + + +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 5e8cb2dc..9bf88d82 100644 --- a/src/being.h +++ b/src/being.h @@ -360,6 +360,15 @@ class Being : public Sprite */ const Path &getPath() const { return mPath; } + /** + * 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); } static int getHairColorsNr(void); @@ -379,6 +388,16 @@ class Being : public Sprite virtual Map::BlockType getBlockType() const { return Map::BLOCKTYPE_NONE; } + /** + * 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); + Uint16 mId; /**< Unique being id */ Uint8 mSpriteDirection; /**< Facing direction */ Uint8 mDirection; /**< Walking direction */ diff --git a/src/engine.cpp b/src/engine.cpp index db1ac3bd..f191280e 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -119,6 +119,7 @@ void Engine::changeMap(const std::string &mapPath) } mCurrentMap = newMap; + mMapName = mapPath; } void Engine::logic() diff --git a/src/engine.h b/src/engine.h index dbee1258..f676a271 100644 --- a/src/engine.h +++ b/src/engine.h @@ -23,6 +23,7 @@ #define _ENGINE_H #include <iosfwd> +#include <string> class Map; @@ -48,6 +49,9 @@ class Engine */ Map *getCurrentMap() { return mCurrentMap; } + const std::string &getCurrentMapName() { return mMapName; } + + /** * Sets the currently active map. */ @@ -60,6 +64,7 @@ class Engine private: Map *mCurrentMap; + std::string mMapName; }; extern Engine *engine; diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp index 72371da5..f96cdcd5 100644 --- a/src/net/beinghandler.cpp +++ b/src/net/beinghandler.cpp @@ -32,6 +32,7 @@ #include "../localplayer.h" #include "../log.h" #include "../main.h" +#include "../npc.h" #include "../particle.h" #include "../sound.h" @@ -268,7 +269,7 @@ void BeingHandler::handleBeingAttackMessage(MessageIn &msg) int attackType = msg.readInt8(); if (!being) return; - + switch (direction) { case DIRECTION_UP: being->setDirection(Being::UP); break; @@ -347,3 +348,4 @@ void BeingHandler::handleBeingDirChangeMessage(MessageIn &msg) case DIRECTION_RIGHT: being->setDirection(Being::RIGHT); break; } } + diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp index ad271f15..beb59250 100644 --- a/src/net/playerhandler.cpp +++ b/src/net/playerhandler.cpp @@ -50,6 +50,11 @@ extern BuyDialog *buyDialog; extern SellDialog *sellDialog; extern Window *buySellDialog; +/* Max. distance we are willing to scroll after a teleport; + * everything beyond will reset the port hard. + */ +static const int MAP_TELEPORT_SCROLL_DISTANCE = 8 * 32; + /** * Listener used for handling the overweigth message. */ @@ -292,6 +297,7 @@ PlayerHandler::handleMapChangeMessage(MessageIn &msg) const std::string mapName = msg.readString(); const unsigned short x = msg.readInt16(); const unsigned short y = msg.readInt16(); + const bool nearby = (engine->getCurrentMapName() == mapName); logger->log("Changing map to %s (%d, %d)", mapName.c_str(), x, y); @@ -301,8 +307,16 @@ PlayerHandler::handleMapChangeMessage(MessageIn &msg) current_npc = 0; const Vector &playerPos = player_node->getPosition(); - const float scrollOffsetX = x - (int) playerPos.x; - const float scrollOffsetY = y - (int) playerPos.y; + float scrollOffsetX = 0.0f; + float scrollOffsetY = 0.0f; + + /* Scroll if neccessary */ + if (!nearby + || (abs(x - (int) playerPos.x) > MAP_TELEPORT_SCROLL_DISTANCE) + || (abs(y - (int) playerPos.y) > MAP_TELEPORT_SCROLL_DISTANCE)) { + scrollOffsetX = x - (int) playerPos.x; + scrollOffsetY = y - (int) playerPos.y; + } player_node->setAction(Being::STAND); player_node->setPosition(x, y); diff --git a/src/particle.h b/src/particle.h index 4a11c4cb..d98f2c39 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 12f9d268..6880ca20 100644 --- a/src/player.h +++ b/src/player.h @@ -116,6 +116,14 @@ class Player : public Being // Character guild information std::map<int, Guild*> mGuilds; + /** + * 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: bool mInParty; }; |