summaryrefslogtreecommitdiff
path: root/src/being.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/being.cpp')
-rw-r--r--src/being.cpp204
1 files changed, 203 insertions, 1 deletions
diff --git a/src/being.cpp b/src/being.cpp
index a267d033..d32ffa59 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -18,6 +18,7 @@
* along with The Mana World; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#include "being.h"
#include <cassert>
@@ -30,7 +31,10 @@
#include "log.h"
#include "map.h"
#include "particle.h"
+#include "sound.h"
+#include "localplayer.h"
+#include "resources/itemdb.h"
#include "resources/resourcemanager.h"
#include "resources/imageset.h"
#include "resources/iteminfo.h"
@@ -40,11 +44,18 @@
#include "utils/dtor.h"
#include "utils/tostring.h"
+#include "utils/xml.h"
namespace {
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;
@@ -57,6 +68,9 @@ Being::Being(int id, int job, Map *map):
mSpriteDirection(DIRECTION_DOWN), mDirection(DOWN),
mMap(NULL),
mEquippedWeapon(NULL),
+ mHairStyle(0),
+ mHairColor(0),
+ mGender(GENDER_UNSPECIFIED),
mSpeechTime(0),
mSprites(VECTOREND_SPRITE, NULL),
mSpriteIDs(VECTOREND_SPRITE, 0),
@@ -108,6 +122,7 @@ void Being::setPosition(const Vector &pos)
{
mPos = pos;
mDest = pos;
+ mPath.clear();
}
void Being::adjustCourse(int srcX, int srcY, int dstX, int dstY)
@@ -286,6 +301,12 @@ void Being::setPath(const Path &path)
mPath = path;
}
+void Being::setHairStyle(int style, int color)
+{
+ mHairStyle = style < 0 ? mHairStyle : style % getHairStylesNr();
+ mHairColor = color < 0 ? mHairColor : color % getHairColorsNr();
+}
+
void Being::setSprite(int slot, int id, const std::string &color)
{
assert(slot >= BASE_SPRITE && slot < VECTOREND_SPRITE);
@@ -512,7 +533,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);
@@ -596,3 +617,184 @@ int Being::getHeight() const
return 0;
}
}
+
+
+
+
+static int hairStylesNr;
+static int hairColorsNr;
+static std::vector<std::string> hairColors;
+
+static void
+initializeHair(void);
+
+int
+Being::getHairStylesNr(void)
+{
+ initializeHair();
+ return hairStylesNr;
+}
+
+int
+Being::getHairColorsNr(void)
+{
+ initializeHair();
+ return hairColorsNr;
+}
+
+std::string
+Being::getHairColor(int index)
+{
+ initializeHair();
+ if (index < 0 || index >= hairColorsNr)
+ return "#000000";
+
+ return hairColors[index];
+}
+
+static bool hairInitialized = false;
+
+static void
+initializeHair(void)
+{
+ if (hairInitialized)
+ return;
+
+ // Hairstyles are encoded as negative numbers. Count how far negative we can go.
+ int hairstylesCtr = -1;
+ while (ItemDB::get(hairstylesCtr).getSprite(GENDER_MALE) != "error.xml")
+ --hairstylesCtr;
+
+ hairStylesNr = -hairstylesCtr; // done.
+ if (hairStylesNr == 0)
+ hairStylesNr = 1; // No hair style -> no hair
+
+ hairColorsNr = 0;
+
+ XML::Document doc(HAIR_FILE);
+ xmlNodePtr root = doc.rootNode();
+
+ if (!root || !xmlStrEqual(root->name, BAD_CAST "colors"))
+ {
+ logger->log("Error loading being hair configuration file");
+ } else {
+ for_each_xml_child_node(node, root)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "color"))
+ {
+ int index = atoi(XML::getProperty(node, "id", "-1").c_str());
+ std::string value = XML::getProperty(node, "value", "");
+
+ if (index >= 0 && value != "") {
+ if (index >= hairColorsNr) {
+ hairColorsNr = index + 1;
+ hairColors.resize(hairColorsNr, "#000000");
+ }
+ hairColors[index] = value;
+ }
+ }
+ }
+ } // done initializing
+
+ if (hairColorsNr == 0) { // No colours -> black only
+ hairColorsNr = 1;
+ hairColors.resize(hairColorsNr, "#000000");
+ }
+
+ 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);
+ }
+}