diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2006-12-11 15:47:35 +0000 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2006-12-11 15:47:35 +0000 |
commit | 8da32105732949b4b0273c718d118bcfae70a1c9 (patch) | |
tree | 0a354974d48268cfaafcdb1e06b498fa26a59c1e /src/resources | |
parent | f9ce4e302cb3ed203d89a7a18e10b7ad4f11519c (diff) | |
download | mana-8da32105732949b4b0273c718d118bcfae70a1c9.tar.gz mana-8da32105732949b4b0273c718d118bcfae70a1c9.tar.bz2 mana-8da32105732949b4b0273c718d118bcfae70a1c9.tar.xz mana-8da32105732949b4b0273c718d118bcfae70a1c9.zip |
Merged 0.0 changes from revision 2825 to 2898 to trunk.
Diffstat (limited to 'src/resources')
-rw-r--r-- | src/resources/equipmentdb.cpp | 158 | ||||
-rw-r--r-- | src/resources/equipmentdb.h | 52 | ||||
-rw-r--r-- | src/resources/equipmentinfo.h | 52 | ||||
-rw-r--r-- | src/resources/image.cpp | 10 | ||||
-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.h | 12 | ||||
-rw-r--r-- | src/resources/mapreader.cpp | 32 | ||||
-rw-r--r-- | src/resources/monsterdb.cpp | 151 | ||||
-rw-r--r-- | src/resources/monsterdb.h | 45 | ||||
-rw-r--r-- | src/resources/monsterinfo.cpp | 70 | ||||
-rw-r--r-- | src/resources/monsterinfo.h | 74 | ||||
-rw-r--r-- | src/resources/resourcemanager.cpp | 61 | ||||
-rw-r--r-- | src/resources/resourcemanager.h | 17 | ||||
-rw-r--r-- | src/resources/soundeffect.cpp | 19 | ||||
-rw-r--r-- | src/resources/spritedef.cpp | 381 | ||||
-rw-r--r-- | src/resources/spritedef.h | 158 | ||||
-rw-r--r-- | src/resources/spriteset.h | 6 |
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. |