summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog24
-rw-r--r--src/main.cpp3
-rw-r--r--src/npc.cpp28
-rw-r--r--src/particle.cpp30
-rw-r--r--src/resources/itemdb.cpp22
-rw-r--r--src/resources/mapreader.cpp14
-rw-r--r--src/resources/monsterdb.cpp29
-rw-r--r--src/resources/npcdb.cpp136
-rw-r--r--src/resources/npcdb.h61
-rw-r--r--src/resources/spritedef.cpp34
-rw-r--r--src/resources/spritedef.h6
-rw-r--r--src/utils/xml.cpp36
-rw-r--r--src/utils/xml.h37
13 files changed, 352 insertions, 108 deletions
diff --git a/ChangeLog b/ChangeLog
index 53a5022e..8a536e67 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,13 @@
clipping issues, but it would be better to fix those instead of using
this complicated workaround.
+2008-05-19 Philipp Sehmisch <tmw@crushnet.org>
+
+ * src/net/beinghandler.cpp: Implemented interpretation of names for
+ NPCs and monsters.
+ * src/npc.cpp, src/resources/npcdb.cpp, src/resources/npcdb.hpp: Added the
+ possibility to add particle effects to NPCs in npcs.xml.
+
2008-05-16 David Athay <ko2fan@gmail.com>
* src/gui/popupmenu.cpp: Applied QOAL's patch to fix popup bug.
@@ -183,15 +190,28 @@
2008-04-07 Bjørn Lindeijer <bjorn@lindeijer.nl>
+ * src/particle.cpp, src/utils/xml.cpp, src/utils/xml.h,
+ src/resources/mapreader.cpp, src/resources/spritedef.cpp,
+ src/resources/npcdb.h, src/resources/monsterdb.cpp,
+ src/resources/itemdb.cpp, src/resources/npcdb.cpp,
+ src/resources/spritedef.h: Added XML::Document class which simplifies
+ parsing an XML document and automatically cleans it up again.
+ * src/being.cpp: Fixed crash on trying to show out of range emoticon.
* src/winver.h, README, configure.ac, data/help/changes.txt,
data/help/header.txt, NEWS, CMakeLists.txt: Updated version, release
date and changes.
- * src/being.cpp: Fixed crash on trying to show out of range emoticon.
-
+
2008-04-03 David Athay <ko2fan@gmail.com>
* src/game.cpp: Tweaked disconnect dialog, hoping to fix a crash bug.
+2008-03-31 Philipp Sehmisch <tmw@crushnet.org>
+
+ * src/main.cpp, src/npc.cpp, src/npc.h, src/resources/npcdb.h,
+ src/resources/npcdb.cpp, data/npcs.xml, src/Makefile.am, tmc.cbp:
+ Implemented NPC XML database which maps NPC IDs to one or more
+ animation files and thus enables animated NPCs.
+
2008-03-30 Dennis Friis <peavey@placid.dk>
* configure.ac: Updated for tmwdata split.
diff --git a/src/main.cpp b/src/main.cpp
index 01250594..db9f85ac 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -78,6 +78,7 @@
#include "resources/image.h"
#include "resources/itemdb.h"
#include "resources/monsterdb.h"
+#include "resources/npcdb.h"
#include "resources/resourcemanager.h"
#include "utils/dtor.h"
@@ -357,6 +358,7 @@ void exit_engine()
// Unload XML databases
ItemDB::unload();
MonsterDB::unload();
+ NPCDB::unload();
ResourceManager::deleteInstance();
delete logger;
@@ -742,6 +744,7 @@ int main(int argc, char *argv[])
// Load XML databases
ItemDB::load();
MonsterDB::load();
+ NPCDB::load();
state = LOGIN_STATE;
break;
diff --git a/src/npc.cpp b/src/npc.cpp
index e490b3cf..2177aedc 100644
--- a/src/npc.cpp
+++ b/src/npc.cpp
@@ -25,9 +25,11 @@
#include "animatedsprite.h"
#include "graphics.h"
+#include "particle.h"
#include "net/messageout.h"
#include "net/protocol.h"
+#include "resources/npcdb.h"
#include "gui/gui.h"
@@ -36,8 +38,30 @@ NPC *current_npc = 0;
NPC::NPC(Uint32 id, Uint16 job, Map *map, Network *network):
Being(id, job, map), mNetwork(network)
{
- mSprites[BASE_SPRITE] = AnimatedSprite::load("graphics/sprites/npc.xml",
- job - 100);
+ NPCInfo info = NPCDB::get(job);
+
+ //setup NPC sprites
+ int c = BASE_SPRITE;
+ for (std::list<NPCsprite*>::const_iterator i = info.sprites.begin();
+ i != info.sprites.end();
+ i++)
+ {
+ if (c == VECTOREND_SPRITE) break;
+
+ std::string file = "graphics/sprites/" + (*i)->sprite;
+ int variant = (*i)->variant;
+ mSprites[c] = AnimatedSprite::load(file, variant);
+ c++;
+ }
+
+ //setup particle effects
+ for (std::list<std::string>::const_iterator i = info.particles.begin();
+ i != info.particles.end();
+ i++)
+ {
+ Particle *p = particleEngine->addEffect(*i, 0, 0);
+ this->controlParticle(p);
+ }
}
Being::Type
diff --git a/src/particle.cpp b/src/particle.cpp
index 3d6b723d..f58a26f1 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -217,35 +217,17 @@ Particle::addEffect(const std::string &particleEffectFile,
{
Particle *newParticle = NULL;
- // XML parser initialisation stuff
- int size;
- ResourceManager *resman = ResourceManager::getInstance();
- char *data = (char*) resman->loadFile(particleEffectFile.c_str(), size);
-
- if (!data) {
- logger->log("Warning: Particle engine could not find %s !",
- particleEffectFile.c_str());
- return NULL;
- }
-
- xmlDocPtr doc = xmlParseMemory(data, size);
- free(data);
+ XML::Document doc(particleEffectFile);
+ xmlNodePtr rootNode = doc.rootNode();
- if (!doc) {
- logger->log("Warning: Particle engine found syntax error in %s!",
- particleEffectFile.c_str());
- return NULL;
- }
-
- xmlNodePtr rootNode = xmlDocGetRootElement(doc);
if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "effect"))
{
- logger->log("Warning: %s is not a valid particle effect definition file!",
- particleEffectFile.c_str());
- xmlFreeDoc(doc);
+ logger->log("Error loading particle: %s", particleEffectFile.c_str());
return NULL;
}
+ ResourceManager *resman = ResourceManager::getInstance();
+
// Parse particles
for_each_xml_child_node(effectChildNode, rootNode)
{
@@ -302,8 +284,6 @@ Particle::addEffect(const std::string &particleEffectFile,
mChildParticles.push_back(newParticle);
}
- xmlFreeDoc(doc);
-
return newParticle;
}
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index 9d64534c..e8ad393b 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -59,26 +59,12 @@ void ItemDB::load()
mUnknown->setSprite("error.xml", 0);
mUnknown->setSprite("error.xml", 1);
- ResourceManager *resman = ResourceManager::getInstance();
- int size;
- char *data = (char*) resman->loadFile("items.xml", size);
+ XML::Document doc("items.xml");
+ xmlNodePtr rootNode = doc.rootNode();
- if (!data) {
- logger->error("ItemDB: Could not find items.xml!");
- }
-
- xmlDocPtr doc = xmlParseMemory(data, size);
- free(data);
-
- if (!doc)
- {
- logger->error("ItemDB: Error while parsing item database (items.xml)!");
- }
-
- xmlNodePtr rootNode = xmlDocGetRootElement(doc);
if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items"))
{
- logger->error("ItemDB: items.xml is not a valid database file!");
+ logger->error("ItemDB: Error while loading items.xml!");
}
for_each_xml_child_node(node, rootNode)
@@ -150,8 +136,6 @@ void ItemDB::load()
#undef CHECK_PARAM
}
- xmlFreeDoc(doc);
-
mLoaded = true;
}
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index 940ded36..2a080fb0 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -183,21 +183,19 @@ MapReader::readMap(const std::string &filename)
inflatedSize = fileSize;
}
- xmlDocPtr doc = xmlParseMemory((char*) inflated, inflatedSize);
+ XML::Document doc((char*) inflated, inflatedSize);
free(inflated);
- // Parse the inflated map data
- if (doc) {
- xmlNodePtr node = xmlDocGetRootElement(doc);
+ xmlNodePtr node = doc.rootNode();
- if (!node || !xmlStrEqual(node->name, BAD_CAST "map")) {
+ // Parse the inflated map data
+ if (node) {
+ if (!xmlStrEqual(node->name, BAD_CAST "map")) {
logger->log("Error: Not a map file (%s)!", filename.c_str());
}
- else
- {
+ else {
map = readMap(node, filename);
}
- xmlFreeDoc(doc);
} else {
logger->log("Error while parsing map file (%s)!", filename.c_str());
}
diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp
index e007eda0..0a98762f 100644
--- a/src/resources/monsterdb.cpp
+++ b/src/resources/monsterdb.cpp
@@ -50,27 +50,12 @@ MonsterDB::load()
logger->log("Initializing monster database...");
- ResourceManager *resman = ResourceManager::getInstance();
- int size;
- char *data = (char*)resman->loadFile("monsters.xml", size);
+ XML::Document doc("monsters.xml");
+ xmlNodePtr rootNode = doc.rootNode();
- if (!data)
- {
- logger->error("Monster Database: Could not find monsters.xml!");
- }
-
- xmlDocPtr doc = xmlParseMemory(data, size);
- free(data);
-
- if (!doc)
- {
- logger->error("Monster Database: Error while parsing monster database (monsters.xml)!");
- }
-
- xmlNodePtr rootNode = xmlDocGetRootElement(doc);
if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "monsters"))
{
- logger->error("Monster Database: monster.xml is not a valid database file!");
+ logger->error("Monster Database: Error while loading monster.xml!");
}
//iterate <monster>s
@@ -152,16 +137,14 @@ MonsterDB::load()
mMonsterInfos[XML::getProperty(monsterNode, "id", 0)] = currentInfo;
}
- xmlFreeDoc(doc);
-
mLoaded = true;
}
void
MonsterDB::unload()
{
- for_each ( mMonsterInfos.begin(), mMonsterInfos.end(),
- make_dtor(mMonsterInfos));
+ for_each(mMonsterInfos.begin(), mMonsterInfos.end(),
+ make_dtor(mMonsterInfos));
mMonsterInfos.clear();
mLoaded = false;
@@ -169,7 +152,7 @@ MonsterDB::unload()
const MonsterInfo&
-MonsterDB::get (int id)
+MonsterDB::get(int id)
{
MonsterInfoIterator i = mMonsterInfos.find(id);
diff --git a/src/resources/npcdb.cpp b/src/resources/npcdb.cpp
new file mode 100644
index 00000000..5869e295
--- /dev/null
+++ b/src/resources/npcdb.cpp
@@ -0,0 +1,136 @@
+/*
+ * The Mana World
+ * Copyright 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "npcdb.h"
+
+#include "resourcemanager.h"
+
+#include "../log.h"
+
+#include "../utils/dtor.h"
+#include "../utils/xml.h"
+
+namespace
+{
+ NPCInfos mNPCInfos;
+ NPCInfo mUnknown;
+ bool mLoaded = false;
+}
+
+void NPCDB::load()
+{
+ if (mLoaded)
+ return;
+
+ NPCsprite *unknownSprite = new NPCsprite;
+ unknownSprite->sprite = "error.xml";
+ unknownSprite->variant = 0;
+ mUnknown.sprites.push_back(unknownSprite);
+
+ logger->log("Initializing NPC database...");
+
+ XML::Document doc("npcs.xml");
+ xmlNodePtr rootNode = doc.rootNode();
+
+ if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "npcs"))
+ {
+ logger->error("NPC Database: Error while loading items.xml!");
+ }
+
+ //iterate <monster>s
+ for_each_xml_child_node(npcNode, rootNode)
+ {
+ if (!xmlStrEqual(npcNode->name, BAD_CAST "npc"))
+ continue;
+
+ int id = XML::getProperty(npcNode, "id", 0);
+ if (id == 0)
+ {
+ logger->log("NPC Database: NPC with missing ID in npcs.xml!");
+ continue;
+ }
+
+ NPCInfo *currentInfo = new NPCInfo;
+
+ for_each_xml_child_node(spriteNode, npcNode)
+ {
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
+ {
+ NPCsprite *currentSprite = new NPCsprite;
+ currentSprite->sprite = (const char*)spriteNode->xmlChildrenNode->content;
+ currentSprite->variant = XML::getProperty(spriteNode, "variant", 0);
+ currentInfo->sprites.push_back(currentSprite);
+ }
+ else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
+ {
+ std::string particlefx = (const char*)spriteNode->xmlChildrenNode->content;
+ currentInfo->particles.push_back(particlefx);
+ }
+ }
+ mNPCInfos[id] = currentInfo;
+ }
+
+ mLoaded = true;
+}
+
+void
+NPCDB::unload()
+{
+ for ( NPCInfosIterator i = mNPCInfos.begin();
+ i != mNPCInfos.end();
+ i++)
+ {
+ while (!i->second->sprites.empty())
+ {
+ delete i->second->sprites.front();
+ i->second->sprites.pop_front();
+ }
+ delete i->second;
+ }
+
+ mNPCInfos.clear();
+
+ while (!mUnknown.sprites.empty())
+ {
+ delete mUnknown.sprites.front();
+ mUnknown.sprites.pop_front();
+ }
+
+ mLoaded = false;
+}
+
+const NPCInfo&
+NPCDB::get(int id)
+{
+ NPCInfosIterator i = mNPCInfos.find(id);
+
+ if (i == mNPCInfos.end())
+ {
+ logger->log("NPCDB: Warning, unknown NPC ID %d requested", id);
+ return mUnknown;
+ }
+ else
+ {
+ return *(i->second);
+ }
+}
diff --git a/src/resources/npcdb.h b/src/resources/npcdb.h
new file mode 100644
index 00000000..2abf959b
--- /dev/null
+++ b/src/resources/npcdb.h
@@ -0,0 +1,61 @@
+/*
+ * The Mana World
+ * Copyright 2008 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_NPC_DB_H
+#define _TMW_NPC_DB_H
+
+#include <map>
+#include <list>
+#include <string>
+
+struct NPCsprite
+{
+ std::string sprite;
+ int variant;
+};
+
+struct NPCInfo
+{
+ std::list<NPCsprite*> sprites;
+ std::list<std::string> particles;
+};
+
+typedef std::map<int, NPCInfo*> NPCInfos;
+
+/**
+ * NPC information database.
+ */
+namespace NPCDB
+{
+ void
+ load();
+
+ void
+ unload();
+
+ const NPCInfo& get(int id);
+
+ typedef NPCInfos::iterator NPCInfosIterator;
+}
+
+#endif
diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp
index ee823c3f..3f95b3ec 100644
--- a/src/resources/spritedef.cpp
+++ b/src/resources/spritedef.cpp
@@ -51,7 +51,6 @@ SpriteDef::getAction(SpriteAction action) const
SpriteDef *SpriteDef::load(std::string const &animationFile, int variant)
{
- int size;
ResourceManager *resman = ResourceManager::getInstance();
std::string::size_type pos = animationFile.find('|');
@@ -59,29 +58,18 @@ SpriteDef *SpriteDef::load(std::string const &animationFile, int variant)
if (pos != std::string::npos)
palettes = animationFile.substr(pos + 1);
- char *data = (char*) resman->loadFile
- (animationFile.substr(0, pos).c_str(), size);
+ XML::Document doc(animationFile.substr(0, pos));
+ xmlNodePtr rootNode = doc.rootNode();
- if (!data && animationFile != "graphics/sprites/error.xml")
- {
- return load("graphics/sprites/error.xml", 0);
- }
-
- xmlDocPtr doc = xmlParseMemory(data, size);
- free(data);
-
- if (!doc)
- {
- logger->log("Error, failed to parse %s.", animationFile.c_str());
- return NULL;
- }
-
- xmlNodePtr rootNode = xmlDocGetRootElement(doc);
if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "sprite"))
{
- logger->log("Error, failed to parse %s.", animationFile.c_str());
- xmlFreeDoc(doc);
- return NULL;
+ logger->log("Error, failed to parse %s", animationFile.c_str());
+
+ if (animationFile != "graphics/sprites/error.xml") {
+ return load("graphics/sprites/error.xml", 0);
+ } else {
+ return NULL;
+ }
}
// Get the variant
@@ -111,8 +99,6 @@ SpriteDef *SpriteDef::load(std::string const &animationFile, int variant)
}
}
- xmlFreeDoc(doc);
-
def->substituteActions();
return def;
}
@@ -279,7 +265,7 @@ SpriteDef::loadAnimation(xmlNodePtr animationNode,
void
SpriteDef::includeSprite(xmlNodePtr includeNode)
{
- std::string filename = XML::getProperty(includeNode, "file", "");
+ const std::string filename = XML::getProperty(includeNode, "file", "");
ResourceManager *resman = ResourceManager::getInstance();
SpriteDef *sprite = resman->getSprite("graphics/sprites/" + filename);
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
index 4f316875..531dfb3d 100644
--- a/src/resources/spritedef.h
+++ b/src/resources/spritedef.h
@@ -81,11 +81,10 @@ class SpriteDef : public Resource
Action *getAction(SpriteAction action) const;
private:
-
/**
* Constructor.
*/
- SpriteDef(): mAction(NULL), mDirection(DIRECTION_DOWN), mLastTime(0) {}
+ SpriteDef() {}
/**
* Destructor.
@@ -149,9 +148,6 @@ class SpriteDef : public Resource
ImageSets mImageSets;
Actions mActions;
- Action *mAction;
- SpriteDirection mDirection;
- int mLastTime;
};
#endif
diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp
index e30450f0..98b474cb 100644
--- a/src/utils/xml.cpp
+++ b/src/utils/xml.cpp
@@ -22,9 +22,45 @@
*/
#include "xml.h"
+#include "../log.h"
+#include "../resources/resourcemanager.h"
namespace XML
{
+ Document::Document(const std::string &filename):
+ mDoc(NULL)
+ {
+ int size;
+ ResourceManager *resman = ResourceManager::getInstance();
+ char *data = (char*) resman->loadFile(filename.c_str(), size);
+
+ if (data) {
+ mDoc = xmlParseMemory(data, size);
+ free(data);
+
+ if (!mDoc)
+ logger->log("Error parsing XML file %s", filename.c_str());
+ } else {
+ logger->log("Error loading %s", filename.c_str());
+ }
+ }
+
+ Document::Document(const char *data, int size)
+ {
+ mDoc = xmlParseMemory(data, size);
+ }
+
+ Document::~Document()
+ {
+ if (mDoc)
+ xmlFreeDoc(mDoc);
+ }
+
+ xmlNodePtr Document::rootNode()
+ {
+ return mDoc ? xmlDocGetRootElement(mDoc) : 0;
+ }
+
int
getProperty(xmlNodePtr node, const char* name, int def)
{
diff --git a/src/utils/xml.h b/src/utils/xml.h
index ef3bad3d..5473b2ca 100644
--- a/src/utils/xml.h
+++ b/src/utils/xml.h
@@ -34,6 +34,43 @@
namespace XML
{
/**
+ * A helper class for parsing an XML document, which also cleans it up
+ * again (RAII).
+ */
+ class Document
+ {
+ public:
+ /**
+ * Constructor that attempts to load the given file through the
+ * resource manager. Logs errors.
+ */
+ Document(const std::string &filename);
+
+ /**
+ * Constructor that attempts to load an XML document from memory.
+ * Does not log errors.
+ *
+ * @param data the string to parse as XML
+ * @param size the length of the string in bytes
+ */
+ Document(const char *data, int size);
+
+ /**
+ * Destructor. Frees the loaded XML file.
+ */
+ ~Document();
+
+ /**
+ * Returns the root node of the document (or NULL if there was a
+ * load error).
+ */
+ xmlNodePtr rootNode();
+
+ private:
+ xmlDocPtr mDoc;
+ };
+
+ /**
* Gets an integer property from an xmlNodePtr.
*/
int