summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2008-08-28 18:32:11 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2008-08-28 18:32:11 +0000
commit566a6fb8d0fc35267b43721f7e1802ba3475af3d (patch)
treef5d3e09bda9e8e66be885b581f28cad4130ca645
parentb506fe0ff8a2039167aa7c349087af4dd03e1921 (diff)
downloadmana-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--ChangeLog9
-rw-r--r--src/being.cpp103
-rw-r--r--src/being.h20
-rw-r--r--src/engine.cpp1
-rw-r--r--src/engine.h5
-rw-r--r--src/gui/ministatus.cpp2
-rw-r--r--src/net/beinghandler.cpp34
-rw-r--r--src/net/playerhandler.cpp19
-rw-r--r--src/net/protocol.h2
-rw-r--r--src/particle.h9
-rw-r--r--src/player.h8
11 files changed, 187 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index ec86e312..a5a11cf0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
};