summaryrefslogtreecommitdiff
path: root/src/resources
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2006-12-11 15:47:35 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2006-12-11 15:47:35 +0000
commit8da32105732949b4b0273c718d118bcfae70a1c9 (patch)
tree0a354974d48268cfaafcdb1e06b498fa26a59c1e /src/resources
parentf9ce4e302cb3ed203d89a7a18e10b7ad4f11519c (diff)
downloadmana-client-8da32105732949b4b0273c718d118bcfae70a1c9.tar.gz
mana-client-8da32105732949b4b0273c718d118bcfae70a1c9.tar.bz2
mana-client-8da32105732949b4b0273c718d118bcfae70a1c9.tar.xz
mana-client-8da32105732949b4b0273c718d118bcfae70a1c9.zip
Merged 0.0 changes from revision 2825 to 2898 to trunk.
Diffstat (limited to 'src/resources')
-rw-r--r--src/resources/equipmentdb.cpp158
-rw-r--r--src/resources/equipmentdb.h52
-rw-r--r--src/resources/equipmentinfo.h52
-rw-r--r--src/resources/image.cpp10
-rw-r--r--src/resources/itemdb.cpp (renamed from src/resources/itemmanager.cpp)343
-rw-r--r--src/resources/itemdb.h (renamed from src/resources/itemmanager.h)112
-rw-r--r--src/resources/iteminfo.h12
-rw-r--r--src/resources/mapreader.cpp32
-rw-r--r--src/resources/monsterdb.cpp151
-rw-r--r--src/resources/monsterdb.h45
-rw-r--r--src/resources/monsterinfo.cpp70
-rw-r--r--src/resources/monsterinfo.h74
-rw-r--r--src/resources/resourcemanager.cpp61
-rw-r--r--src/resources/resourcemanager.h17
-rw-r--r--src/resources/soundeffect.cpp19
-rw-r--r--src/resources/spritedef.cpp381
-rw-r--r--src/resources/spritedef.h158
-rw-r--r--src/resources/spriteset.h6
18 files changed, 1466 insertions, 287 deletions
diff --git a/src/resources/equipmentdb.cpp b/src/resources/equipmentdb.cpp
new file mode 100644
index 00000000..78ae3b6a
--- /dev/null
+++ b/src/resources/equipmentdb.cpp
@@ -0,0 +1,158 @@
+/*
+ * The Mana World
+ * Copyright 2006 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 "equipmentdb.h"
+
+#include "resourcemanager.h"
+
+#include "../log.h"
+
+#include "../utils/dtor.h"
+#include "../utils/xml.h"
+
+namespace
+{
+ EquipmentDB::EquipmentInfos mEquipmentInfos;
+ EquipmentInfo mUnknown;
+ bool mLoaded = false;
+}
+
+void
+EquipmentDB::load()
+{
+ logger->log("Initializing equipment database...");
+ mUnknown.setSprite("error.xml", 0);
+ mUnknown.setSprite("error.xml", 1);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+ int size;
+ char *data = (char*)resman->loadFile("equipment.xml", size);
+
+ if (!data)
+ {
+ logger->error("Equipment Database: Could not find equipment.xml!");
+ }
+
+ xmlDocPtr doc = xmlParseMemory(data, size);
+ free(data);
+
+ if (!doc)
+ {
+ logger->error("Equipment Database: Error while parsing equipment database (equipment.xml)!");
+ }
+
+ xmlNodePtr rootNode = xmlDocGetRootElement(doc);
+ if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "equipments"))
+ {
+ logger->error("Equipment Database: equipment.xml is not a valid database file!");
+ }
+
+ //iterate <equipment>s
+ for ( xmlNodePtr equipmentNode = rootNode->xmlChildrenNode;
+ equipmentNode != NULL;
+ equipmentNode = equipmentNode->next)
+ {
+
+ if (!xmlStrEqual(equipmentNode->name, BAD_CAST "equipment"))
+ {
+ continue;
+ }
+
+ EquipmentInfo *currentInfo = new EquipmentInfo();
+
+ currentInfo->setSlot (XML::getProperty(equipmentNode, "slot", 0));
+
+ //iterate <sprite>s
+ for ( xmlNodePtr spriteNode = equipmentNode->xmlChildrenNode;
+ spriteNode != NULL;
+ spriteNode = spriteNode->next)
+ {
+ if (!xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
+ {
+ continue;
+ }
+
+ std::string gender = XML::getProperty(spriteNode, "gender", "unisex");
+ std::string filename = (const char*) spriteNode->xmlChildrenNode->content;
+
+ if (gender == "male" || gender == "unisex")
+ {
+ currentInfo->setSprite(filename, 0);
+ }
+
+ if (gender == "female" || gender == "unisex")
+ {
+ currentInfo->setSprite(filename, 1);
+ }
+ }
+
+ setEquipment( XML::getProperty(equipmentNode, "id", 0),
+ currentInfo);
+ }
+
+ mLoaded = true;
+}
+
+void
+EquipmentDB::unload()
+{
+ // kill EquipmentInfos
+ for_each ( mEquipmentInfos.begin(), mEquipmentInfos.end(),
+ make_dtor(mEquipmentInfos));
+ mEquipmentInfos.clear();
+
+ mLoaded = false;
+}
+
+EquipmentInfo*
+EquipmentDB::get(int id)
+{
+ if (!mLoaded) {
+ logger->error("Error: Equipment database used before initialization!");
+ }
+
+ EquipmentInfoIterator i = mEquipmentInfos.find(id);
+
+ if (i == mEquipmentInfos.end() )
+ {
+ logger->log("EquipmentDB: Error, unknown equipment ID# %d", id);
+ return &mUnknown;
+ }
+ else
+ {
+ return i->second;
+ }
+}
+
+void
+EquipmentDB::setEquipment(int id, EquipmentInfo* equipmentInfo)
+{
+ if (mEquipmentInfos.find(id) != mEquipmentInfos.end()) {
+ logger->log("Warning: Equipment Piece with ID %d defined multiple times",
+ id);
+ delete equipmentInfo;
+ }
+ else {
+ mEquipmentInfos[id] = equipmentInfo;
+ };
+}
diff --git a/src/resources/equipmentdb.h b/src/resources/equipmentdb.h
new file mode 100644
index 00000000..b8618f5f
--- /dev/null
+++ b/src/resources/equipmentdb.h
@@ -0,0 +1,52 @@
+/*
+ * The Mana World
+ * Copyright 2006 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_EQUIPMENT_DB_H
+#define _TMW_EQUIPMENT_DB_H
+
+#include <map>
+
+#include "equipmentinfo.h"
+
+namespace EquipmentDB
+{
+ /**
+ * Loads the equipment info from Items.xml
+ */
+ void load();
+
+ /**
+ * Frees equipment data
+ */
+ void unload();
+
+ void setEquipment(int id, EquipmentInfo* equipmentInfo);
+
+ EquipmentInfo* get(int id);
+
+ // Equipment database types
+ typedef std::map<int, EquipmentInfo*> EquipmentInfos;
+ typedef EquipmentInfos::iterator EquipmentInfoIterator;
+}
+
+#endif
diff --git a/src/resources/equipmentinfo.h b/src/resources/equipmentinfo.h
new file mode 100644
index 00000000..93a1cb42
--- /dev/null
+++ b/src/resources/equipmentinfo.h
@@ -0,0 +1,52 @@
+/*
+ * The Mana World
+ * Copyright 2006 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_EQUIPMENTINFO_H_
+#define _TMW_EQUIPMENTINFO_H_
+
+#include <string>
+#include <map>
+
+class EquipmentInfo
+{
+ public:
+ EquipmentInfo():
+ mSlot (0)
+ {
+ };
+
+ void
+ setSlot (int slot) { mSlot = slot; };
+
+ const std::string&
+ getSprite(int gender) {return animationFiles[gender]; };
+
+ void
+ setSprite(std::string animationFile, int gender) {animationFiles[gender] = animationFile; };
+
+ private:
+ int mSlot; //not used at the moment but maybe useful on our own server
+ std::map<int, std::string> animationFiles;
+};
+
+#endif
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index eb3a2409..48818f6f 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -68,9 +68,17 @@ Image* Image::load(void *buffer, unsigned int bufferSize,
{
// Load the raw file data from the buffer in an RWops structure
SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize);
+ SDL_Surface *tmpImage;
// Use SDL_Image to load the raw image data and have it free the data
- SDL_Surface *tmpImage = IMG_Load_RW(rw, 1);
+ if (!idPath.compare(idPath.length() - 4, 4, ".tga"))
+ {
+ tmpImage = IMG_LoadTyped_RW(rw, 1, const_cast<char*>("TGA"));
+ }
+ else
+ {
+ tmpImage = IMG_Load_RW(rw, 1);
+ }
if (tmpImage == NULL) {
logger->log("Error, image load failed: %s", IMG_GetError());
diff --git a/src/resources/itemmanager.cpp b/src/resources/itemdb.cpp
index 7d0b13f2..b91e34cc 100644
--- a/src/resources/itemmanager.cpp
+++ b/src/resources/itemdb.cpp
@@ -1,173 +1,170 @@
-/*
- * The Mana World
- * Copyright 2004 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 "itemmanager.h"
-
-#include <libxml/tree.h>
-
-#include "iteminfo.h"
-#include "resourcemanager.h"
-
-#include "../log.h"
-
-#include "../utils/dtor.h"
-
-#define READ_PROP(node, prop, name, target, cast) \
- prop = xmlGetProp(node, BAD_CAST name); \
- if (prop) { \
- target = cast((const char*)prop); \
- xmlFree(prop); \
- }
-
-ItemManager::ItemManager()
-{
- mUnknown.setName("Unknown item");
-
- ResourceManager *resman = ResourceManager::getInstance();
- int size;
- char *data = (char*)resman->loadFile("items.xml", size);
-
- if (!data) {
- logger->error("Item Manager: Could not find items.xml!");
- }
-
- xmlDocPtr doc = xmlParseMemory(data, size);
- free(data);
-
- if (!doc)
- {
- logger->error("Item Manager: Error while parsing item database (items.xml)!");
- }
-
- xmlNodePtr node = xmlDocGetRootElement(doc);
- if (!node || !xmlStrEqual(node->name, BAD_CAST "items"))
- {
- logger->error("Item Manager: items.xml is not a valid database file!");
- }
-
- for (node = node->xmlChildrenNode; node != NULL; node = node->next)
- {
- int id = 0, art = 0, type = 0, weight = 0, slot = 0;
- std::string name = "", description = "", effect = "", image = "";
-
- if (!xmlStrEqual(node->name, BAD_CAST "item")) {
- continue;
- }
-
- xmlChar *prop = NULL;
- READ_PROP(node, prop, "id", id, atoi);
- READ_PROP(node, prop, "image", image, );
- READ_PROP(node, prop, "art", art, atoi);
- READ_PROP(node, prop, "name", name, );
- READ_PROP(node, prop, "description", description, );
- READ_PROP(node, prop, "effect", effect, );
- READ_PROP(node, prop, "type", type, atoi);
- READ_PROP(node, prop, "weight", weight, atoi);
- READ_PROP(node, prop, "slot", slot, atoi);
-
-
- if (id && name != "")
- {
- ItemInfo *itemInfo = new ItemInfo();
- itemInfo->setImage(image);
- itemInfo->setArt(art);
- itemInfo->setName(name);
- itemInfo->setDescription(description);
- itemInfo->setEffect(effect);
- itemInfo->setType(type);
- itemInfo->setWeight(weight);
- itemInfo->setSlot(slot);
- mItemInfos[id] = itemInfo;
- }
-
-
- if (id == 0)
- {
- logger->log("Item Manager: An item has no ID in items.xml!");
- }
- if (name == "")
- {
- logger->log("Item Manager: An item has no name in items.xml!");
- }
-
- if (image == "")
- {
- logger->log("Item Manager: Missing image parameter for item: %i. %s",
- id, name.c_str());
- }
- /*if (art == 0)
- {
- logger->log("Item Manager: Missing art parameter for item: %i. %s",
- id, name.c_str());
- }*/
- if (description == "")
- {
- logger->log("Item Manager: Missing description parameter for item: %i. %s",
- id, name.c_str());
- }
- if (effect == "")
- {
- logger->log("Item Manager: Missing effect parameter for item: %i. %s",
- id, name.c_str());
- }
- /*if (type == 0)
- {
- logger->log("Item Manager: Missing type parameter for item: %i. %s",
- id, name.c_str());
- }*/
- if (weight == 0)
- {
- logger->log("Item Manager: Missing weight parameter for item: %i. %s",
- id, name.c_str());
- }
- if (slot == 0)
- {
- logger->log("Item Manager: Missing slot parameter for item: %i. %s",
- id, name.c_str());
- }
-
- /*logger->log("Item: %i %i %i %s %s %i %i %i", id,
- getImage(id), getArt(id), getName(id).c_str(),
- getDescription(id).c_str(), getType(id), getWeight(id),
- getSlot(id));*/
- }
-
- xmlFreeDoc(doc);
-}
-
-ItemManager::~ItemManager()
-{
- for (ItemInfoIterator i = mItemInfos.begin(); i != mItemInfos.end(); i++)
- {
- delete i->second;
- }
- mItemInfos.clear();
-}
-
-const ItemInfo&
-ItemManager::getItemInfo(int id)
-{
- ItemInfoIterator i = mItemInfos.find(id);
-
- return (i != mItemInfos.end()) ? *(i->second) : mUnknown;
-}
+/*
+ * The Mana World
+ * Copyright 2004 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 "itemdb.h"
+
+#include <libxml/tree.h>
+
+#include "iteminfo.h"
+#include "resourcemanager.h"
+
+#include "../log.h"
+
+#include "../utils/dtor.h"
+#include "../utils/xml.h"
+
+namespace
+{
+ ItemDB::ItemInfos mItemInfos;
+ ItemInfo mUnknown;
+}
+
+
+void ItemDB::load()
+{
+ logger->log("Initializing item database...");
+ mUnknown.setName("Unknown item");
+
+ ResourceManager *resman = ResourceManager::getInstance();
+ int size;
+ char *data = (char*)resman->loadFile("items.xml", size);
+
+ 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 node = xmlDocGetRootElement(doc);
+ if (!node || !xmlStrEqual(node->name, BAD_CAST "items"))
+ {
+ logger->error("ItemDB: items.xml is not a valid database file!");
+ }
+
+ for (node = node->xmlChildrenNode; node != NULL; node = node->next)
+ {
+ if (!xmlStrEqual(node->name, BAD_CAST "item")) {
+ continue;
+ }
+
+ int id = XML::getProperty(node, "id", 0);
+ int art = XML::getProperty(node, "art", 0);
+ int type = XML::getProperty(node, "type", 0);
+ int weight = XML::getProperty(node, "weight", 0);
+ int slot = XML::getProperty(node, "slot", 0);
+
+ std::string name = XML::getProperty(node, "name", "");
+ std::string image = XML::getProperty(node, "image", "");
+ std::string description = XML::getProperty(node, "description", "");
+ std::string effect = XML::getProperty(node, "effect", "");
+
+ if (id && name != "")
+ {
+ ItemInfo *itemInfo = new ItemInfo();
+ itemInfo->setImage(image);
+ itemInfo->setArt(art);
+ itemInfo->setName(name);
+ itemInfo->setDescription(description);
+ itemInfo->setEffect(effect);
+ itemInfo->setType(type);
+ itemInfo->setWeight(weight);
+ itemInfo->setSlot(slot);
+ mItemInfos[id] = itemInfo;
+ }
+
+
+ if (id == 0)
+ {
+ logger->log("ItemDB: An item has no ID in items.xml!");
+ }
+ if (name == "")
+ {
+ logger->log("ItemDB: Missing name for item %d!", id);
+ }
+
+ if (image == "")
+ {
+ logger->log("ItemDB: Missing image parameter for item: %i. %s",
+ id, name.c_str());
+ }
+ /*
+ if (art == 0)
+ {
+ logger->log("Item Manager: Missing art parameter for item: %i. %s",
+ id, name.c_str());
+ }
+ if (description == "")
+ {
+ logger->log("ItemDB: Missing description parameter for item: %i. %s",
+ id, name.c_str());
+ }
+ if (effect == "")
+ {
+ logger->log("ItemDB: Missing effect parameter for item: %i. %s",
+ id, name.c_str());
+ }
+ if (type == 0)
+ {
+ logger->log("Item Manager: Missing type parameter for item: %i. %s",
+ id, name.c_str());
+ }
+ */
+ if (weight == 0)
+ {
+ logger->log("Item Manager: Missing weight parameter for item: %i. %s",
+ id, name.c_str());
+ }
+ /*
+ if (slot == 0)
+ {
+ logger->log("Item Manager: Missing slot parameter for item: %i. %s",
+ id, name.c_str());
+ }
+ */
+ }
+
+ xmlFreeDoc(doc);
+}
+
+void ItemDB::unload()
+{
+ for (ItemInfoIterator i = mItemInfos.begin(); i != mItemInfos.end(); i++)
+ {
+ delete i->second;
+ }
+ mItemInfos.clear();
+}
+
+const ItemInfo&
+ItemDB::get(int id)
+{
+ ItemInfoIterator i = mItemInfos.find(id);
+
+ return (i != mItemInfos.end()) ? *(i->second) : mUnknown;
+}
diff --git a/src/resources/itemmanager.h b/src/resources/itemdb.h
index b1f2b95c..5922984a 100644
--- a/src/resources/itemmanager.h
+++ b/src/resources/itemdb.h
@@ -1,59 +1,53 @@
-/*
- * The Mana World
- * Copyright 2004 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_ITEM_MANAGER_H
-#define _TMW_ITEM_MANAGER_H
-
-#include "iteminfo.h"
-
-#include <map>
-
-/**
- * Defines a class to load items database.
- */
-class ItemManager
-{
- public:
- /**
- * Constructor.
- */
- ItemManager();
-
- /**
- * Destructor.
- */
- ~ItemManager();
-
- const ItemInfo& getItemInfo(int id);
-
- protected:
- // Items database
- typedef std::map<int, ItemInfo*> ItemInfos;
- typedef ItemInfos::iterator ItemInfoIterator;
- ItemInfos mItemInfos;
- ItemInfo mUnknown;
-};
-
-extern ItemManager *itemDb;
-
-#endif
+/*
+ * The Mana World
+ * Copyright 2004 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: itemdb.h 2650 2006-09-03 15:00:47Z b_lindeijer $
+ */
+
+#ifndef _TMW_ITEM_MANAGER_H
+#define _TMW_ITEM_MANAGER_H
+
+#include "iteminfo.h"
+
+#include <map>
+
+/**
+ * The namespace that holds the item information
+ */
+namespace ItemDB
+{
+ /**
+ * Loads the item data from Items.xml
+ */
+ void load();
+
+ /**
+ * Frees item data
+ */
+ void unload();
+
+ const ItemInfo& get(int id);
+
+ // Items database
+ typedef std::map<int, ItemInfo*> ItemInfos;
+ typedef ItemInfos::iterator ItemInfoIterator;
+}
+
+#endif
diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h
index 9a04bb2e..e4f851bb 100644
--- a/src/resources/iteminfo.h
+++ b/src/resources/iteminfo.h
@@ -33,8 +33,6 @@ class Image;
*/
class ItemInfo
{
- friend class ItemManager;
-
public:
/**
* Constructor.
@@ -49,6 +47,11 @@ class ItemInfo
{
}
+ /**
+ * Destructor.
+ */
+ ~ItemInfo();
+
void
setArt(short art) { mArt = art; }
@@ -101,11 +104,6 @@ class ItemInfo
getSlot() const { return mSlot; }
protected:
- /**
- * Destructor.
- */
- ~ItemInfo();
-
std::string mImageName;
/* TODO (BL): I do not think the item info should keep a reference to
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index 2aea3dc5..09a6eb74 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -36,6 +36,7 @@
#include "../tileset.h"
#include "../utils/tostring.h"
+#include "../utils/xml.h"
const unsigned int DEFAULT_TILE_WIDTH = 32;
const unsigned int DEFAULT_TILE_HEIGHT = 32;
@@ -205,10 +206,10 @@ MapReader::readMap(xmlNodePtr node, const std::string &path)
prop = xmlGetProp(node, BAD_CAST "version");
xmlFree(prop);
- int w = getProperty(node, "width", 0);
- int h = getProperty(node, "height", 0);
- int tilew = getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH);
- int tileh = getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT);
+ int w = XML::getProperty(node, "width", 0);
+ int h = XML::getProperty(node, "height", 0);
+ int tilew = XML::getProperty(node, "tilewidth", DEFAULT_TILE_WIDTH);
+ int tileh = XML::getProperty(node, "tileheight", DEFAULT_TILE_HEIGHT);
int layerNr = 0;
Map *map = new Map(w, h, tilew, tileh);
@@ -308,7 +309,7 @@ MapReader::readLayer(xmlNodePtr node, Map *map, int layer)
int binLen;
unsigned char *binData =
- php_base64_decode(charData, strlen((char*)charData), &binLen);
+ php3_base64_decode(charData, strlen((char*)charData), &binLen);
delete[] charData;
@@ -354,7 +355,7 @@ MapReader::readLayer(xmlNodePtr node, Map *map, int layer)
if (!xmlStrEqual(n2->name, BAD_CAST "tile"))
continue;
- int gid = getProperty(n2, "gid", -1);
+ int gid = XML::getProperty(n2, "gid", -1);
map->setTileWithGid(x, y, layer, gid);
x++;
@@ -387,9 +388,9 @@ MapReader::readTileset(xmlNodePtr node,
return NULL;
}
- int firstGid = getProperty(node, "firstgid", 0);
- int tw = getProperty(node, "tilewidth", map->getTileWidth());
- int th = getProperty(node, "tileheight", map->getTileHeight());
+ int firstGid = XML::getProperty(node, "firstgid", 0);
+ int tw = XML::getProperty(node, "tilewidth", map->getTileWidth());
+ int th = XML::getProperty(node, "tileheight", map->getTileHeight());
for (node = node->xmlChildrenNode; node; node = node->next) {
if (!xmlStrEqual(node->name, BAD_CAST "image"))
@@ -422,16 +423,3 @@ MapReader::readTileset(xmlNodePtr node,
return NULL;
}
-
-int
-MapReader::getProperty(xmlNodePtr node, const char* name, int def)
-{
- int &ret = def;
-
- xmlChar *prop = xmlGetProp(node, BAD_CAST name);
- if (prop) {
- ret = atoi((char*)prop);
- xmlFree(prop);
- }
- return ret;
-}
diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp
new file mode 100644
index 00000000..fb03f6c1
--- /dev/null
+++ b/src/resources/monsterdb.cpp
@@ -0,0 +1,151 @@
+/*
+ * The Mana World
+ * Copyright 2004 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 "monsterdb.h"
+
+#include "resourcemanager.h"
+
+#include "../log.h"
+
+#include "../utils/dtor.h"
+#include "../utils/xml.h"
+
+namespace
+{
+ MonsterDB::MonsterInfos mMonsterInfos;
+ MonsterInfo mUnknown;
+}
+
+void
+MonsterDB::load()
+{
+ mUnknown.setSprite("error.xml");
+ mUnknown.setName("unnamed");
+
+ logger->log("Initializing monster database...");
+
+ ResourceManager *resman = ResourceManager::getInstance();
+ int size;
+ char *data = (char*)resman->loadFile("monsters.xml", size);
+
+ 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!");
+ }
+
+ //iterate <monster>s
+ for ( xmlNodePtr monsterNode = rootNode->xmlChildrenNode;
+ monsterNode != NULL;
+ monsterNode = monsterNode->next)
+ {
+
+ if (!xmlStrEqual(monsterNode->name, BAD_CAST "monster"))
+ {
+ continue;
+ }
+
+ MonsterInfo *currentInfo = new MonsterInfo();
+
+ currentInfo->setName (XML::getProperty(monsterNode, "name", "unnamed"));
+
+ //iterate <sprite>s and <sound>s
+ for ( xmlNodePtr spriteNode = monsterNode->xmlChildrenNode;
+ spriteNode != NULL;
+ spriteNode = spriteNode->next)
+ {
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
+ {
+ currentInfo->setSprite((const char*) spriteNode->xmlChildrenNode->content);
+ }
+
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "sound"))
+ {
+ std::string event = XML::getProperty(spriteNode, "event", "");
+ const char *filename;
+ filename = (const char*) spriteNode->xmlChildrenNode->content;
+
+ if (event == "hit")
+ {
+ currentInfo->addSound(EVENT_HIT, filename);
+ }
+ else if (event == "miss")
+ {
+ currentInfo->addSound(EVENT_MISS, filename);
+ }
+ else if (event == "hurt")
+ {
+ currentInfo->addSound(EVENT_HURT, filename);
+ }
+ else if (event == "die")
+ {
+ currentInfo->addSound(EVENT_DIE, filename);
+ }
+ else
+ {
+ logger->log("MonsterDB: Warning, sound effect %s for unknown event %s of monster %s",
+ filename, event.c_str(), currentInfo->getName().c_str());
+ }
+ }
+ }
+ mMonsterInfos[XML::getProperty(monsterNode, "id", 0)] = currentInfo;
+ }
+}
+
+void
+MonsterDB::unload()
+{
+ for_each ( mMonsterInfos.begin(), mMonsterInfos.end(),
+ make_dtor(mMonsterInfos));
+ mMonsterInfos.clear();
+}
+
+
+const MonsterInfo&
+MonsterDB::get (int id)
+{
+ MonsterInfoIterator i = mMonsterInfos.find(id);
+
+ if (i == mMonsterInfos.end())
+ {
+ logger->log("MonsterDB: Warning, unknown monster ID %d requested", id);
+ return mUnknown;
+ }
+ else
+ {
+ return *(i->second);
+ }
+}
diff --git a/src/resources/monsterdb.h b/src/resources/monsterdb.h
new file mode 100644
index 00000000..b105665a
--- /dev/null
+++ b/src/resources/monsterdb.h
@@ -0,0 +1,45 @@
+/*
+ * The Mana World
+ * Copyright 2004 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_MONSTER_DB_H
+#define _TMW_MONSTER_DB_H
+
+#include <map>
+
+#include "monsterinfo.h"
+
+namespace MonsterDB
+{
+ void
+ load();
+
+ void
+ unload();
+
+ const MonsterInfo& get (int id);
+
+ typedef std::map<int, MonsterInfo*> MonsterInfos;
+ typedef MonsterInfos::iterator MonsterInfoIterator;
+}
+
+#endif
diff --git a/src/resources/monsterinfo.cpp b/src/resources/monsterinfo.cpp
new file mode 100644
index 00000000..43aac32a
--- /dev/null
+++ b/src/resources/monsterinfo.cpp
@@ -0,0 +1,70 @@
+/*
+ * The Mana World
+ * Copyright 2004 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: monsterinfo.cpp 2650 2006-09-03 15:00:47Z b_lindeijer $
+ */
+
+#include "monsterinfo.h"
+
+#include "../utils/dtor.h"
+
+MonsterInfo::MonsterInfo():
+ mSprite("error.xml")
+{
+
+}
+
+MonsterInfo::~MonsterInfo()
+{
+ //kill vectors in mSoundEffects
+ for_each ( mSounds.begin(), mSounds.end(),
+ make_dtor(mSounds));
+ mSounds.clear();
+}
+
+
+void
+MonsterInfo::addSound (SoundEvent event, std::string filename)
+{
+ if (mSounds.find(event) == mSounds.end())
+ {
+ mSounds[event] = new std::vector<std::string>;
+ }
+
+ mSounds[event]->push_back("sfx/" + filename);
+}
+
+
+std::string
+MonsterInfo::getSound (SoundEvent event) const
+{
+ std::map<SoundEvent, std::vector<std::string>* >::const_iterator i;
+
+ i = mSounds.find(event);
+
+ if (i == mSounds.end())
+ {
+ return "";
+ }
+ else
+ {
+ return i->second->at(rand()%i->second->size());
+ }
+}
diff --git a/src/resources/monsterinfo.h b/src/resources/monsterinfo.h
new file mode 100644
index 00000000..413dafa0
--- /dev/null
+++ b/src/resources/monsterinfo.h
@@ -0,0 +1,74 @@
+/*
+ * The Mana World
+ * Copyright 2004 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: monsterinfo.h 2650 2006-09-03 15:00:47Z b_lindeijer $
+ */
+
+#ifndef _TMW_MONSTERINFO_H_
+#define _TMW_MONSTERINFO_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+
+enum SoundEvent
+{
+ EVENT_HIT,
+ EVENT_MISS,
+ EVENT_HURT,
+ EVENT_DIE
+};
+
+
+class MonsterInfo
+{
+ public:
+ MonsterInfo();
+
+ ~MonsterInfo();
+
+ void
+ setName(std::string name) { mName = name; } ;
+
+ void
+ setSprite(std::string filename) { mSprite = filename; }
+
+ void
+ addSound (SoundEvent event, std::string filename);
+
+ const std::string&
+ getName () const { return mName; };
+
+ const std::string&
+ getSprite () const { return mSprite; };
+
+ std::string
+ getSound (SoundEvent event) const;
+
+ private:
+
+ std::string mName;
+ std::string mSprite;
+
+ std::map<SoundEvent, std::vector<std::string>* > mSounds;
+};
+
+#endif
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index bb51d023..45067302 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -32,6 +32,7 @@
#include "music.h"
#include "soundeffect.h"
#include "spriteset.h"
+#include "spritedef.h"
#include "../log.h"
@@ -40,15 +41,33 @@ ResourceManager *ResourceManager::instance = NULL;
ResourceManager::ResourceManager()
{
+ logger->log("Initializing resource manager...");
}
ResourceManager::~ResourceManager()
{
- // Release any remaining spritesets first because they depend on images
+ // Release any remaining spritedefs first because they depend on spritesets
ResourceIterator iter = mResources.begin();
while (iter != mResources.end())
{
- if (dynamic_cast<Spriteset*>(iter->second) != NULL)
+ if (dynamic_cast<SpriteDef*>(iter->second) != 0)
+ {
+ cleanUp(iter->second);
+ ResourceIterator toErase = iter;
+ ++iter;
+ mResources.erase(toErase);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+
+ // Release any remaining spritesets first because they depend on images
+ iter = mResources.begin();
+ while (iter != mResources.end())
+ {
+ if (dynamic_cast<Spriteset*>(iter->second) != 0)
{
cleanUp(iter->second);
ResourceIterator toErase = iter;
@@ -83,7 +102,7 @@ ResourceManager::cleanUp(Resource *res)
bool
ResourceManager::setWriteDir(const std::string &path)
{
- return (bool)PHYSFS_setWriteDir(path.c_str());
+ return (bool) PHYSFS_setWriteDir(path.c_str());
}
void
@@ -96,7 +115,7 @@ ResourceManager::addToSearchPath(const std::string &path, bool append)
bool
ResourceManager::mkdir(const std::string &path)
{
- return (bool)PHYSFS_mkdir(path.c_str());
+ return (bool) PHYSFS_mkdir(path.c_str());
}
bool
@@ -158,9 +177,9 @@ ResourceManager::get(const E_RESOURCE_TYPE &type, const std::string &idPath)
free(buffer);
- if (resource) {
+ if (resource)
+ {
resource->incRef();
-
mResources[idPath] = resource;
}
@@ -215,6 +234,27 @@ ResourceManager::getSpriteset(const std::string &imagePath, int w, int h)
return spriteset;
}
+SpriteDef*
+ResourceManager::getSprite(const std::string &path, int variant)
+{
+ std::stringstream ss;
+ ss << path << "[" << variant << "]";
+ const std::string idPath = ss.str();
+
+ ResourceIterator resIter = mResources.find(idPath);
+
+ if (resIter != mResources.end()) {
+ resIter->second->incRef();
+ return dynamic_cast<SpriteDef*>(resIter->second);
+ }
+
+ SpriteDef *sprite = new SpriteDef(idPath, path, variant);
+ sprite->incRef();
+ mResources[idPath] = sprite;
+
+ return sprite;
+}
+
void
ResourceManager::release(const std::string &idPath)
{
@@ -246,18 +286,13 @@ ResourceManager::deleteInstance()
void*
ResourceManager::loadFile(const std::string &fileName, int &fileSize)
{
- // If the file doesn't exist indicate failure
- if (!PHYSFS_exists(fileName.c_str())) {
- logger->log("Warning: %s not found!", fileName.c_str());
- return NULL;
- }
-
// Attempt to open the specified file using PhysicsFS
PHYSFS_file *file = PHYSFS_openRead(fileName.c_str());
// If the handler is an invalid pointer indicate failure
if (file == NULL) {
- logger->log("Warning: %s failed to load!", fileName.c_str());
+ logger->log("Warning: Failed to load %s: %s",
+ fileName.c_str(), PHYSFS_getLastError());
return NULL;
}
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index 0086b167..d458f96e 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -34,6 +34,7 @@ class Image;
class Music;
class SoundEffect;
class Spriteset;
+class SpriteDef;
/**
* A class for loading and managing resources.
@@ -113,21 +114,21 @@ class ResourceManager
get(const E_RESOURCE_TYPE &type, const std::string &idPath);
/**
- * Convenience wrapper around ResourceManager::create for loading
+ * Convenience wrapper around ResourceManager::get for loading
* images.
*/
Image*
getImage(const std::string &idPath);
/**
- * Convenience wrapper around ResourceManager::create for loading
+ * Convenience wrapper around ResourceManager::get for loading
* songs.
*/
Music*
getMusic(const std::string &idPath);
/**
- * Convenience wrapper around ResourceManager::create for loading
+ * Convenience wrapper around ResourceManager::get for loading
* samples.
*/
SoundEffect*
@@ -137,7 +138,15 @@ class ResourceManager
* Creates a spriteset based on the image referenced by the given
* path and the supplied sprite sizes
*/
- Spriteset* getSpriteset(const std::string &imagePath, int w, int h);
+ Spriteset*
+ getSpriteset(const std::string &imagePath, int w, int h);
+
+ /**
+ * Creates a sprite definition based on a given path and the supplied
+ * variant.
+ */
+ SpriteDef*
+ getSprite(const std::string &path, int variant = 0);
/**
* Releases a resource, removing it from the set of loaded resources.
diff --git a/src/resources/soundeffect.cpp b/src/resources/soundeffect.cpp
index 3340e5ea..bb35218e 100644
--- a/src/resources/soundeffect.cpp
+++ b/src/resources/soundeffect.cpp
@@ -23,6 +23,8 @@
#include "soundeffect.h"
+#include "../log.h"
+
SoundEffect::SoundEffect(const std::string &idPath, Mix_Chunk *soundEffect):
Resource(idPath),
mChunk(soundEffect)
@@ -41,13 +43,18 @@ SoundEffect::load(void *buffer, unsigned int bufferSize,
// Load the raw file data from the buffer in an RWops structure
SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize);
- // Use Mix_LoadWAV_RW to load the raw music data
- Mix_Chunk *tmpSoundEffect = Mix_LoadWAV_RW(rw, 0);
-
- // Now free the SDL_RWops data
- SDL_FreeRW(rw);
+ // Load the music data and free the RWops structure
+ Mix_Chunk *tmpSoundEffect = Mix_LoadWAV_RW(rw, 1);
- return new SoundEffect(idPath, tmpSoundEffect);
+ if (tmpSoundEffect)
+ {
+ return new SoundEffect(idPath, tmpSoundEffect);
+ }
+ else
+ {
+ logger->log("Error while loading sound effect (%s)", idPath.c_str());
+ return NULL;
+ }
}
bool
diff --git a/src/resources/spritedef.cpp b/src/resources/spritedef.cpp
new file mode 100644
index 00000000..bd273b3b
--- /dev/null
+++ b/src/resources/spritedef.cpp
@@ -0,0 +1,381 @@
+/*
+ * The Mana World
+ * Copyright 2004 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 "spritedef.h"
+
+#include "../animation.h"
+#include "../action.h"
+#include "../graphics.h"
+#include "../log.h"
+
+#include "resourcemanager.h"
+#include "spriteset.h"
+#include "image.h"
+
+#include "../utils/xml.h"
+
+SpriteDef::SpriteDef(const std::string &idPath,
+ const std::string &file, int variant):
+ Resource(idPath),
+ mAction(NULL),
+ mDirection(DIRECTION_DOWN),
+ mLastTime(0)
+{
+ load(file, variant);
+}
+
+Action*
+SpriteDef::getAction(SpriteAction action) const
+{
+ Actions::const_iterator i = mActions.find(action);
+
+ if (i == mActions.end())
+ {
+ logger->log("Warning: no action \"%u\" defined!", action);
+ return NULL;
+ }
+
+ return i->second;
+}
+
+void
+SpriteDef::load(const std::string &animationFile, int variant)
+{
+ int size;
+ ResourceManager *resman = ResourceManager::getInstance();
+ char *data = (char*) resman->loadFile(animationFile.c_str(), size);
+
+ if (!data) {
+ logger->error("Animation: Could not find " + animationFile + "!");
+ }
+
+ xmlDocPtr doc = xmlParseMemory(data, size);
+ free(data);
+
+ if (!doc) {
+ logger->error(
+ "Animation: Error while parsing animation definition file!");
+ }
+
+ xmlNodePtr node = xmlDocGetRootElement(doc);
+ if (!node || !xmlStrEqual(node->name, BAD_CAST "sprite")) {
+ logger->error(
+ "Animation: this is not a valid animation definition file!");
+ }
+
+ // Get the variant
+ int variant_num = XML::getProperty(node, "variants", 0);
+ int variant_offset = 0;
+
+ if (variant_num > 0 && variant < variant_num)
+ {
+ variant_offset = variant * XML::getProperty(node, "variant_offset", 0);
+ }
+
+ for (node = node->xmlChildrenNode; node != NULL; node = node->next)
+ {
+ if (xmlStrEqual(node->name, BAD_CAST "imageset"))
+ {
+ loadImageSet(node);
+ }
+ else if (xmlStrEqual(node->name, BAD_CAST "action"))
+ {
+ loadAction(node, variant_offset);
+ }
+ else if (xmlStrEqual(node->name, BAD_CAST "include"))
+ {
+ includeSprite(node);
+ }
+ }
+
+ xmlFreeDoc(doc);
+
+ // Complete missing actions
+ substituteAction(ACTION_STAND, ACTION_DEFAULT);
+ substituteAction(ACTION_WALK, ACTION_STAND);
+ substituteAction(ACTION_WALK, ACTION_RUN);
+ substituteAction(ACTION_ATTACK, ACTION_STAND);
+ substituteAction(ACTION_ATTACK_SWING, ACTION_ATTACK);
+ substituteAction(ACTION_ATTACK_STAB, ACTION_ATTACK_SWING);
+ substituteAction(ACTION_ATTACK_BOW, ACTION_ATTACK_STAB);
+ substituteAction(ACTION_ATTACK_THROW, ACTION_ATTACK_SWING);
+ substituteAction(ACTION_CAST_MAGIC, ACTION_ATTACK_SWING);
+ substituteAction(ACTION_USE_ITEM, ACTION_CAST_MAGIC);
+ substituteAction(ACTION_SIT, ACTION_STAND);
+ substituteAction(ACTION_SLEEP, ACTION_SIT);
+ substituteAction(ACTION_HURT, ACTION_STAND);
+ substituteAction(ACTION_DEAD, ACTION_HURT);
+}
+
+void
+SpriteDef::loadImageSet(xmlNodePtr node)
+{
+ int width = XML::getProperty(node, "width", 0);
+ int height = XML::getProperty(node, "height", 0);
+ std::string name = XML::getProperty(node, "name", "");
+ std::string imageSrc = XML::getProperty(node, "src", "");
+
+ ResourceManager *resman = ResourceManager::getInstance();
+ Spriteset *spriteset = resman->getSpriteset(imageSrc, width, height);
+
+ if (!spriteset)
+ {
+ logger->error("Couldn't load imageset!");
+ }
+
+ mSpritesets[name] = spriteset;
+}
+
+void
+SpriteDef::loadAction(xmlNodePtr node, int variant_offset)
+{
+ const std::string actionName = XML::getProperty(node, "name", "");
+ const std::string imagesetName = XML::getProperty(node, "imageset", "");
+
+ SpritesetIterator si = mSpritesets.find(imagesetName);
+ if (si == mSpritesets.end())
+ {
+ logger->log("Warning: imageset \"%s\" not defined in %s",
+ imagesetName.c_str(), getIdPath().c_str());
+ return;
+ }
+ Spriteset *imageset = si->second;
+
+ SpriteAction actionType = makeSpriteAction(actionName);
+ if (actionType == ACTION_INVALID)
+ {
+ logger->log("Warning: Unknown action \"%s\" defined in %s",
+ actionName.c_str(), getIdPath().c_str());
+ return;
+ }
+ Action *action = new Action();
+ mActions[actionType] = action;
+
+ // When first action set it as default direction
+ if (mActions.empty())
+ {
+ mActions[ACTION_DEFAULT] = action;
+ }
+
+ // Load animations
+ for (xmlNodePtr animationNode = node->xmlChildrenNode;
+ animationNode != NULL;
+ animationNode = animationNode->next)
+ {
+ if (xmlStrEqual(animationNode->name, BAD_CAST "animation"))
+ {
+ loadAnimation(animationNode, action, imageset, variant_offset);
+ }
+ }
+}
+
+void
+SpriteDef::loadAnimation(xmlNodePtr animationNode,
+ Action *action, Spriteset *imageset,
+ int variant_offset)
+{
+ std::string directionName =
+ XML::getProperty(animationNode, "direction", "");
+ SpriteDirection directionType = makeSpriteDirection(directionName);
+
+ if (directionType == DIRECTION_INVALID)
+ {
+ logger->log("Warning: Unknown direction \"%s\" used in %s",
+ directionName.c_str(), getIdPath().c_str());
+ return;
+ }
+
+ Animation *animation = new Animation();
+ action->setAnimation(directionType, animation);
+
+ // Get animation phases
+ for (xmlNodePtr phaseNode = animationNode->xmlChildrenNode;
+ phaseNode != NULL;
+ phaseNode = phaseNode->next)
+ {
+ int delay = XML::getProperty(phaseNode, "delay", 0);
+ int offsetX = XML::getProperty(phaseNode, "offsetX", 0);
+ int offsetY = XML::getProperty(phaseNode, "offsetY", 0);
+ offsetY -= imageset->getHeight() - 32;
+ offsetX -= imageset->getWidth() / 2 - 16;
+
+ if (xmlStrEqual(phaseNode->name, BAD_CAST "frame"))
+ {
+ int index = XML::getProperty(phaseNode, "index", -1);
+
+ if (index < 0)
+ {
+ logger->log("No valid value for 'index'");
+ continue;
+ }
+
+ Image *img = imageset->get(index + variant_offset);
+
+ if (!img)
+ {
+ logger->log("No image at index " + (index + variant_offset));
+ continue;
+ }
+
+ animation->addPhase(img, delay, offsetX, offsetY);
+ }
+ else if (xmlStrEqual(phaseNode->name, BAD_CAST "sequence"))
+ {
+ int start = XML::getProperty(phaseNode, "start", -1);
+ int end = XML::getProperty(phaseNode, "end", -1);
+
+ if (start < 0 || end < 0)
+ {
+ logger->log("No valid value for 'start' or 'end'");
+ continue;
+ }
+
+ while (end >= start)
+ {
+ Image *img = imageset->get(start + variant_offset);
+
+ if (!img)
+ {
+ logger->log("No image at index " +
+ (start + variant_offset));
+ continue;
+ }
+
+ animation->addPhase(img, delay, offsetX, offsetY);
+ start++;
+ }
+ }
+ else if (xmlStrEqual(phaseNode->name, BAD_CAST "end"))
+ {
+ animation->addTerminator();
+ }
+ } // for phaseNode
+}
+
+void
+SpriteDef::includeSprite(xmlNodePtr includeNode)
+{
+ std::string filename = XML::getProperty(includeNode, "file", "");
+ ResourceManager *resman = ResourceManager::getInstance();
+ SpriteDef *sprite = resman->getSprite("graphics/sprites/" + filename);
+
+ // TODO: Somehow implement actually including it
+ sprite->decRef();
+}
+
+void
+SpriteDef::substituteAction(SpriteAction complete, SpriteAction with)
+{
+ if (mActions.find(complete) == mActions.end())
+ {
+ Actions::iterator i = mActions.find(with);
+ if (i != mActions.end()) {
+ mActions[complete] = i->second;
+ }
+ }
+}
+
+SpriteDef::~SpriteDef()
+{
+ for (SpritesetIterator i = mSpritesets.begin();
+ i != mSpritesets.end(); ++i)
+ {
+ i->second->decRef();
+ }
+}
+
+SpriteAction
+SpriteDef::makeSpriteAction(const std::string& action)
+{
+ if (action == "" || action == "default") {
+ return ACTION_DEFAULT;
+ }
+ if (action == "stand") {
+ return ACTION_STAND;
+ }
+ else if (action == "walk") {
+ return ACTION_WALK;
+ }
+ else if (action == "run") {
+ return ACTION_RUN;
+ }
+ else if (action == "attack") {
+ return ACTION_ATTACK;
+ }
+ else if (action == "attack_swing") {
+ return ACTION_ATTACK_SWING;
+ }
+ else if (action == "attack_stab") {
+ return ACTION_ATTACK_STAB;
+ }
+ else if (action == "attack_bow") {
+ return ACTION_ATTACK_BOW;
+ }
+ else if (action == "attack_throw") {
+ return ACTION_ATTACK_THROW;
+ }
+ else if (action == "cast_magic") {
+ return ACTION_CAST_MAGIC;
+ }
+ else if (action == "use_item") {
+ return ACTION_USE_ITEM;
+ }
+ else if (action == "sit") {
+ return ACTION_SIT;
+ }
+ else if (action == "sleep") {
+ return ACTION_SLEEP;
+ }
+ else if (action == "hurt") {
+ return ACTION_HURT;
+ }
+ else if (action == "dead") {
+ return ACTION_DEAD;
+ }
+ else {
+ return ACTION_INVALID;
+ }
+}
+
+SpriteDirection
+SpriteDef::makeSpriteDirection(const std::string& direction)
+{
+ if (direction == "" || direction == "default") {
+ return DIRECTION_DEFAULT;
+ }
+ else if (direction == "up") {
+ return DIRECTION_UP;
+ }
+ else if (direction == "left") {
+ return DIRECTION_LEFT;
+ }
+ else if (direction == "right") {
+ return DIRECTION_RIGHT;
+ }
+ else if (direction == "down") {
+ return DIRECTION_DOWN;
+ }
+ else {
+ return DIRECTION_INVALID;
+ };
+}
diff --git a/src/resources/spritedef.h b/src/resources/spritedef.h
new file mode 100644
index 00000000..64414259
--- /dev/null
+++ b/src/resources/spritedef.h
@@ -0,0 +1,158 @@
+/*
+ * The Mana World
+ * Copyright 2004 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_SPRITEDEF_H
+#define _TMW_SPRITEDEF_H
+
+#include "resource.h"
+
+#include <map>
+#include <string>
+
+#include <libxml/tree.h>
+
+class Action;
+class Graphics;
+class Spriteset;
+struct AnimationPhase;
+class Animation;
+
+enum SpriteAction
+{
+ ACTION_DEFAULT = 0,
+ ACTION_STAND,
+ ACTION_WALK,
+ ACTION_RUN,
+ ACTION_ATTACK,
+ ACTION_ATTACK_SWING,
+ ACTION_ATTACK_STAB,
+ ACTION_ATTACK_BOW,
+ ACTION_ATTACK_THROW,
+ ACTION_CAST_MAGIC,
+ ACTION_USE_ITEM,
+ ACTION_SIT,
+ ACTION_SLEEP,
+ ACTION_HURT,
+ ACTION_DEAD,
+ ACTION_INVALID
+};
+
+enum SpriteDirection
+{
+ DIRECTION_DEFAULT = 0,
+ DIRECTION_DOWN,
+ DIRECTION_UP,
+ DIRECTION_LEFT,
+ DIRECTION_RIGHT,
+ DIRECTION_INVALID
+};
+
+/**
+ * Defines a class to load an animation.
+ */
+class SpriteDef : public Resource
+{
+ public:
+ /**
+ * Constructor.
+ */
+ SpriteDef(const std::string &idPath,
+ const std::string &file, int variant);
+
+ /**
+ * Destructor.
+ */
+ ~SpriteDef();
+
+ /**
+ * Returns the specified action.
+ */
+ Action*
+ getAction(SpriteAction action) const;
+
+ private:
+ /**
+ * Loads a sprite definition file.
+ */
+ void
+ load(const std::string &file, int variant);
+
+ /**
+ * Loads an imageset element.
+ */
+ void
+ loadImageSet(xmlNodePtr node);
+
+ /**
+ * Loads an action element.
+ */
+ void
+ loadAction(xmlNodePtr node, int variant_offset);
+
+ /**
+ * Loads an animation element.
+ */
+ void
+ loadAnimation(xmlNodePtr animationNode,
+ Action *action, Spriteset *imageset,
+ int variant_offset);
+
+ /**
+ * Include another sprite into this one.
+ */
+ void
+ includeSprite(xmlNodePtr includeNode);
+
+ /**
+ * When there are no animations defined for the action "complete", its
+ * animations become a copy of those of the action "with".
+ */
+ void
+ substituteAction(SpriteAction complete, SpriteAction with);
+
+ /**
+ * Converts a string into a SpriteAction enum.
+ */
+ static SpriteAction
+ makeSpriteAction(const std::string &action);
+
+ /**
+ * Converts a string into a SpriteDirection enum.
+ */
+ static SpriteDirection
+ makeSpriteDirection(const std::string &direction);
+
+
+ typedef std::map<std::string, Spriteset*> Spritesets;
+ typedef Spritesets::iterator SpritesetIterator;
+
+ typedef std::map<SpriteAction, Action*> Actions;
+
+ Spritesets mSpritesets;
+ Actions mActions;
+ Action *mAction;
+ SpriteDirection mDirection;
+ int mLastTime;
+};
+
+#endif
diff --git a/src/resources/spriteset.h b/src/resources/spriteset.h
index c51e6a75..7f6b42df 100644
--- a/src/resources/spriteset.h
+++ b/src/resources/spriteset.h
@@ -32,7 +32,9 @@ class Image;
/**
- * Stores a complete set of sprites.
+ * Stores a set of subimages originating from a single image.
+ *
+ * TODO: Should probably be renamed to ImageSet or TileSet.
*/
class Spriteset : public Resource
{
@@ -40,7 +42,7 @@ class Spriteset : public Resource
/*
* Cuts the passed image in a grid of sub images.
*/
- Spriteset(const std::string& idPath, Image *img, int w, int h);
+ Spriteset(const std::string &idPath, Image *img, int w, int h);
/**
* Destructor.