diff options
Diffstat (limited to 'src/resources/db')
-rw-r--r-- | src/resources/db/avatardb.cpp | 121 | ||||
-rw-r--r-- | src/resources/db/avatardb.h | 39 | ||||
-rw-r--r-- | src/resources/db/chardb.cpp | 155 | ||||
-rw-r--r-- | src/resources/db/chardb.h | 68 | ||||
-rw-r--r-- | src/resources/db/colordb.cpp | 200 | ||||
-rw-r--r-- | src/resources/db/colordb.h | 88 | ||||
-rw-r--r-- | src/resources/db/deaddb.cpp | 81 | ||||
-rw-r--r-- | src/resources/db/deaddb.h | 44 | ||||
-rw-r--r-- | src/resources/db/emotedb.cpp | 257 | ||||
-rw-r--r-- | src/resources/db/emotedb.h | 87 | ||||
-rw-r--r-- | src/resources/db/itemdb.cpp | 889 | ||||
-rw-r--r-- | src/resources/db/itemdb.h | 75 | ||||
-rw-r--r-- | src/resources/db/mapdb.cpp | 176 | ||||
-rw-r--r-- | src/resources/db/mapdb.h | 78 | ||||
-rw-r--r-- | src/resources/db/monsterdb.cpp | 273 | ||||
-rw-r--r-- | src/resources/db/monsterdb.h | 46 | ||||
-rw-r--r-- | src/resources/db/npcdb.cpp | 158 | ||||
-rw-r--r-- | src/resources/db/npcdb.h | 50 | ||||
-rw-r--r-- | src/resources/db/palettedb.cpp | 108 | ||||
-rw-r--r-- | src/resources/db/palettedb.h | 39 | ||||
-rw-r--r-- | src/resources/db/petdb.cpp | 137 | ||||
-rw-r--r-- | src/resources/db/petdb.h | 39 | ||||
-rw-r--r-- | src/resources/db/sounddb.cpp | 79 | ||||
-rw-r--r-- | src/resources/db/sounddb.h | 37 |
24 files changed, 3324 insertions, 0 deletions
diff --git a/src/resources/db/avatardb.cpp b/src/resources/db/avatardb.cpp new file mode 100644 index 000000000..516234928 --- /dev/null +++ b/src/resources/db/avatardb.cpp @@ -0,0 +1,121 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/avatardb.h" + +#include "logger.h" + +#include "resources/beinginfo.h" + +#include "utils/dtor.h" +#include "utils/gettext.h" + +#include "configuration.h" + +#include "debug.h" + +namespace +{ + BeingInfos mAvatarInfos; + bool mLoaded = false; +} + +void AvatarDB::load() +{ + if (mLoaded) + unload(); + + XML::Document doc(paths.getStringValue("avatarsFile")); + const XmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlNameEqual(rootNode, "avatars")) + { + logger->log("Avatars Database: Error while loading %s!", + paths.getStringValue("avatarsFile").c_str()); + mLoaded = true; + return; + } + + for_each_xml_child_node(avatarNode, rootNode) + { + if (!xmlNameEqual(avatarNode, "avatar")) + continue; + + BeingInfo *const currentInfo = new BeingInfo; + + currentInfo->setName(XML::langProperty( + // TRANSLATORS: unknown info name + avatarNode, "name", _("unnamed"))); + + currentInfo->setTargetOffsetX(XML::getProperty(avatarNode, + "targetOffsetX", 0)); + + currentInfo->setTargetOffsetY(XML::getProperty(avatarNode, + "targetOffsetY", 0)); + + currentInfo->setWidth(XML::getProperty(avatarNode, + "width", 0)); + currentInfo->setHeight(XML::getProperty(avatarNode, + "height", 0)); + + SpriteDisplay display; + + // iterate <sprite>s and <sound>s + for_each_xml_child_node(spriteNode, avatarNode) + { + if (xmlNameEqual(spriteNode, "sprite")) + { + if (!spriteNode->xmlChildrenNode) + continue; + + SpriteReference *const currentSprite = new SpriteReference; + currentSprite->sprite = reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content); + + currentSprite->variant = XML::getProperty( + spriteNode, "variant", 0); + display.sprites.push_back(currentSprite); + } + } + currentInfo->setDisplay(display); + + mAvatarInfos[XML::getProperty(avatarNode, "id", 0)] = currentInfo; + } + + mLoaded = true; +} + +void AvatarDB::unload() +{ + delete_all(mAvatarInfos); + mAvatarInfos.clear(); + mLoaded = false; +} + +BeingInfo *AvatarDB::get(const int id) +{ + BeingInfoIterator i = mAvatarInfos.find(id); + if (i == mAvatarInfos.end()) + return BeingInfo::unknown; + else + return i->second; +} diff --git a/src/resources/db/avatardb.h b/src/resources/db/avatardb.h new file mode 100644 index 000000000..e5af78ff7 --- /dev/null +++ b/src/resources/db/avatardb.h @@ -0,0 +1,39 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_AVATARDB_H +#define RESOURCES_AVATARDB_H + +#include "localconsts.h" + +class BeingInfo; + +namespace AvatarDB +{ + void load(); + + void unload(); + + BeingInfo *get(const int id) A_WARN_UNUSED; +} + +#endif // RESOURCES_AVATARDB_H diff --git a/src/resources/db/chardb.cpp b/src/resources/db/chardb.cpp new file mode 100644 index 000000000..1c2e0ec82 --- /dev/null +++ b/src/resources/db/chardb.cpp @@ -0,0 +1,155 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 Aethyra Development Team + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/chardb.h" + +#include "configuration.h" +#include "logger.h" + +#include "debug.h" + +namespace +{ + bool mLoaded = false; + unsigned mMinHairColor = 0; + unsigned mMaxHairColor = 0; + unsigned mMinHairStyle = 0; + unsigned mMaxHairStyle = 0; + unsigned mMinStat = 0; + unsigned mMaxStat = 0; + unsigned mSumStat = 0; + unsigned mMinLook = 0; + unsigned mMaxLook = 0; + std::vector<int> mDefaultItems; +} // namespace + +void CharDB::load() +{ + if (mLoaded) + unload(); + + XML::Document *doc = new XML::Document( + paths.getStringValue("charCreationFile")); + const XmlNodePtr root = doc->rootNode(); + + if (!root || !xmlNameEqual(root, "chars")) + { + logger->log("CharDB: Failed to parse %s.", + paths.getStringValue("charCreationFile").c_str()); + delete doc; + return; + } + + for_each_xml_child_node(node, root) + { + if (xmlNameEqual(node, "haircolor")) + { + loadMinMax(node, &mMinHairColor, &mMaxHairColor); + } + else if (xmlNameEqual(node, "hairstyle")) + { + loadMinMax(node, &mMinHairStyle, &mMaxHairStyle); + } + else if (xmlNameEqual(node, "look")) + { + loadMinMax(node, &mMinLook, &mMaxLook); + } + else if (xmlNameEqual(node, "stat")) + { + loadMinMax(node, &mMinStat, &mMaxStat); + mSumStat = XML::getProperty(node, "sum", 0); + } + else if (xmlNameEqual(node, "item")) + { + const int id = XML::getProperty(node, "id", 0); + if (id > 0) + mDefaultItems.push_back(id); + } + } + + delete doc; + + mLoaded = true; +} + +void CharDB::loadMinMax(const XmlNodePtr node, + unsigned *const min, unsigned *const max) +{ + *min = XML::getProperty(node, "min", 1); + *max = XML::getProperty(node, "max", 10); +} + +void CharDB::unload() +{ + logger->log1("Unloading chars database..."); + + mLoaded = false; +} + +unsigned CharDB::getMinHairColor() +{ + return mMinHairColor; +} + +unsigned CharDB::getMaxHairColor() +{ + return mMaxHairColor; +} + +unsigned CharDB::getMinHairStyle() +{ + return mMinHairStyle; +} + +unsigned CharDB::getMaxHairStyle() +{ + return mMaxHairStyle; +} + +unsigned CharDB::getMinStat() +{ + return mMinStat; +} + +unsigned CharDB::getMaxStat() +{ + return mMaxStat; +} + +unsigned CharDB::getSumStat() +{ + return mSumStat; +} + +unsigned CharDB::getMinLook() +{ + return mMinLook; +} + +unsigned CharDB::getMaxLook() +{ + return mMaxLook; +} + +const std::vector<int> &CharDB::getDefaultItems() +{ + return mDefaultItems; +} diff --git a/src/resources/db/chardb.h b/src/resources/db/chardb.h new file mode 100644 index 000000000..3072d41ff --- /dev/null +++ b/src/resources/db/chardb.h @@ -0,0 +1,68 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 Aethyra Development Team + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_CHARDB_H +#define RESOURCES_CHARDB_H + +#include "utils/xml.h" + +#include <vector> + +/** + * Char information database. + */ +namespace CharDB +{ + /** + * Loads the chars data. + */ + void load(); + + /** + * Clear the chars data + */ + void unload(); + + void loadMinMax(const XmlNodePtr node, + unsigned *const min, unsigned *const max); + + unsigned getMinHairColor() A_WARN_UNUSED; + + unsigned getMaxHairColor() A_WARN_UNUSED; + + unsigned getMinHairStyle() A_WARN_UNUSED; + + unsigned getMaxHairStyle() A_WARN_UNUSED; + + unsigned getMinStat() A_WARN_UNUSED; + + unsigned getMaxStat() A_WARN_UNUSED; + + unsigned getSumStat() A_WARN_UNUSED; + + unsigned getMinLook() A_WARN_UNUSED; + + unsigned getMaxLook() A_WARN_UNUSED; + + const std::vector<int> &getDefaultItems() A_WARN_UNUSED; +} // namespace CharDB + +#endif // RESOURCES_CHARDB_H diff --git a/src/resources/db/colordb.cpp b/src/resources/db/colordb.cpp new file mode 100644 index 000000000..0e81ff1c0 --- /dev/null +++ b/src/resources/db/colordb.cpp @@ -0,0 +1,200 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 Aethyra Development Team + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/colordb.h" + +#include "client.h" +#include "configuration.h" +#include "logger.h" + +#include "utils/xml.h" + +#include "debug.h" + +namespace +{ + int mHairColorsSize = 0; + bool mLoaded = false; + std::string mFail("#ffffff"); + ColorDB::ColorLists mColorLists; +} + +void ColorDB::load() +{ + if (mLoaded) + unload(); + + loadHair(); + if (serverVersion >= 1) + loadColorLists(); + + const ColorListsIterator it = mColorLists.find("hair"); + if (it != mColorLists.end()) + mHairColorsSize = static_cast<int>((*it).second.size()); + else + mHairColorsSize = 0; +} + +void ColorDB::loadHair() +{ + std::map <int, ItemColor> colors; + const ColorListsIterator it = mColorLists.find("hair"); + + if (it != mColorLists.end()) + colors = it->second; + + XML::Document *doc = new XML::Document( + paths.getStringValue("hairColorFile")); + XmlNodePtr root = doc->rootNode(); + bool hairXml = true; + + if (!root || !xmlNameEqual(root, "colors")) + { + logger->log("Trying to fall back on " + + paths.getStringValue("hairColorFile2")); + + hairXml = false; + + delete doc; + doc = new XML::Document(paths.getStringValue("hairColorFile2")); + root = doc->rootNode(); + + if (!root || !xmlNameEqual(root, "colors")) + { + logger->log1("ColorDB: Failed to find any color files."); + colors[0] = ItemColor(0, "", ""); + mLoaded = true; + + delete doc; + + return; + } + } + + for_each_xml_child_node(node, root) + { + if (xmlNameEqual(node, "color")) + { + const int id = XML::getProperty(node, "id", 0); + + if (colors.find(id) != colors.end()) + logger->log("ColorDB: Redefinition of dye ID %d", id); + + colors[id] = ItemColor(id, XML::langProperty(node, "name", ""), + XML::getProperty(node, hairXml ? "value" : "dye", "#FFFFFF")); + } + } + + delete doc; + + mColorLists["hair"] = colors; + mLoaded = true; +} + +void ColorDB::loadColorLists() +{ + XML::Document *doc = new XML::Document( + paths.getStringValue("itemColorsFile")); + const XmlNodePtr root = doc->rootNode(); + if (!root) + { + delete doc; + return; + } + + for_each_xml_child_node(node, root) + { + if (xmlNameEqual(node, "list")) + { + const std::string name = XML::getProperty(node, "name", ""); + if (name.empty()) + continue; + + std::map <int, ItemColor> colors; + const ColorListsIterator it = mColorLists.find(name); + + if (it != mColorLists.end()) + colors = it->second; + + for_each_xml_child_node(colorNode, node) + { + if (xmlNameEqual(colorNode, "color")) + { + ItemColor c(XML::getProperty(colorNode, "id", -1), + XML::langProperty(colorNode, "name", ""), + XML::getProperty(colorNode, "value", "")); + if (c.id > -1) + colors[c.id] = c; + } + } + mColorLists[name] = colors; + } + } + delete doc; +} + +void ColorDB::unload() +{ + logger->log1("Unloading color database..."); + + mColorLists.clear(); + mLoaded = false; +} + +std::string &ColorDB::getHairColorName(const int id) +{ + if (!mLoaded) + load(); + + const ColorListsIterator it = mColorLists.find("hair"); + if (it == mColorLists.end()) + { + logger->log1("ColorDB: Error, hair colors list empty"); + return mFail; + } + + const ColorIterator i = (*it).second.find(id); + + if (i == (*it).second.end()) + { + logger->log("ColorDB: Error, unknown dye ID# %d", id); + return mFail; + } + else + { + return i->second.name; + } +} + +int ColorDB::getHairSize() +{ + return mHairColorsSize; +} + +const std::map <int, ColorDB::ItemColor> + *ColorDB::getColorsList(const std::string &name) +{ + const ColorListsIterator it = mColorLists.find(name); + + if (it != mColorLists.end()) + return &it->second; + return nullptr; +} diff --git a/src/resources/db/colordb.h b/src/resources/db/colordb.h new file mode 100644 index 000000000..3eec3625d --- /dev/null +++ b/src/resources/db/colordb.h @@ -0,0 +1,88 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 Aethyra Development Team + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_COLORDB_H +#define RESOURCES_COLORDB_H + +#include <map> +#include <string> + +#include "localconsts.h" + +/** + * Color information database. + */ +namespace ColorDB +{ + class ItemColor final + { + public: + ItemColor(): + id(0), + name(), + color() + { } + + ItemColor(const int id0, const std::string &name0, + const std::string &color0) : + id(id0), + name(name0), + color(color0) + { + } + + int id; + std::string name; + std::string color; + }; + + /** + * Loads the color data from <code>colors.xml</code>. + */ + void load(); + + /** + * Loads the color data from <code>colors.xml</code>. + */ + void loadHair(); + + void loadColorLists(); + + /** + * Clear the color data + */ + void unload(); + + std::string &getHairColorName(const int id) A_WARN_UNUSED; + + int getHairSize() A_WARN_UNUSED; + + const std::map <int, ItemColor> *getColorsList(const std::string + &name) A_WARN_UNUSED; + + // Color DB + typedef std::map<int, ItemColor> Colors; + typedef Colors::iterator ColorIterator; + typedef std::map <std::string, std::map <int, ItemColor> > ColorLists; + typedef ColorLists::iterator ColorListsIterator; +} // namespace ColorDB + +#endif // RESOURCES_COLORDB_H diff --git a/src/resources/db/deaddb.cpp b/src/resources/db/deaddb.cpp new file mode 100644 index 000000000..fa418ee3e --- /dev/null +++ b/src/resources/db/deaddb.cpp @@ -0,0 +1,81 @@ +/* + * The ManaPlus Client + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/deaddb.h" + +#include "configuration.h" +#include "logger.h" + +#include "utils/translation/podict.h" + +#include "debug.h" + +namespace +{ + bool mLoaded = false; + std::vector<std::string> mMessages; +} // namespace + +void DeadDB::load() +{ + if (mLoaded) + unload(); + + XML::Document *doc = new XML::Document( + paths.getStringValue("deadMessagesFile")); + const XmlNodePtr root = doc->rootNode(); + + if (!root || !xmlNameEqual(root, "messages")) + { + logger->log("DeadDB: Failed to parse %s.", + paths.getStringValue("deadMessagesFile").c_str()); + delete doc; + return; + } + + for_each_xml_child_node(node, root) + { + if (xmlNameEqual(node, "message")) + { + const char *const data = reinterpret_cast<const char*>( + xmlNodeGetContent(node)); + if (!data || !*data) + continue; + mMessages.push_back(data); + } + } + + delete doc; + mLoaded = true; +} + +void DeadDB::unload() +{ + mMessages.clear(); + mLoaded = false; +} + +std::string DeadDB::getRandomString() +{ + const int sz = mMessages.size(); + if (!sz) + return std::string(); + return translator->getStr(mMessages[rand() % sz]); +} diff --git a/src/resources/db/deaddb.h b/src/resources/db/deaddb.h new file mode 100644 index 000000000..a0f6c7b9b --- /dev/null +++ b/src/resources/db/deaddb.h @@ -0,0 +1,44 @@ +/* + * The ManaPlus Client + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_DEADDB_H +#define RESOURCES_DEADDB_H + +#include <string> + +/** + * Char information database. + */ +namespace DeadDB +{ + /** + * Loads the chars data. + */ + void load(); + + /** + * Clear the chars data + */ + void unload(); + + std::string getRandomString(); +} // namespace DeadDB + +#endif // RESOURCES_DEADDB_H diff --git a/src/resources/db/emotedb.cpp b/src/resources/db/emotedb.cpp new file mode 100644 index 000000000..21a3aa0c6 --- /dev/null +++ b/src/resources/db/emotedb.cpp @@ -0,0 +1,257 @@ +/* + * Emote database + * Copyright (C) 2009 Aethyra Development Team + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/emotedb.h" + +#include "animatedsprite.h" +#include "client.h" +#include "logger.h" + +#include "configuration.h" + +#include "debug.h" + +namespace +{ + EmoteInfos mEmoteInfos; + EmoteToEmote mEmotesAlt; + EmoteInfo mUnknown; + bool mLoaded = false; + int mLastEmote = 0; +} + +void EmoteDB::load() +{ + if (mLoaded) + unload(); + + mLastEmote = 0; + + EmoteSprite *const unknownSprite = new EmoteSprite; + unknownSprite->sprite = AnimatedSprite::load( + paths.getStringValue("spriteErrorFile")); + unknownSprite->name = "unknown"; + mUnknown.sprites.push_back(unknownSprite); + + logger->log1("Initializing emote database..."); + + XML::Document doc(paths.getStringValue("emotesFile")); + XmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlNameEqual(rootNode, "emotes")) + { + logger->log("Emote Database: Error while loading %s!", + paths.getStringValue("emotesFile").c_str()); + return; + } + + // iterate <emote>s + for_each_xml_child_node(emoteNode, rootNode) + { + if (!xmlNameEqual(emoteNode, "emote")) + continue; + + const int id = XML::getProperty(emoteNode, "id", -1); + // skip hight images + if (id > 19 || (client->isTmw() && id > 13)) + continue; + + if (id == -1) + { + logger->log("Emote Database: Emote with missing ID in %s!", + paths.getStringValue("emotesFile").c_str()); + continue; + } + + EmoteInfo *const currentInfo = new EmoteInfo; + currentInfo->time = XML::getProperty(emoteNode, "time", 500); + + for_each_xml_child_node(spriteNode, emoteNode) + { + if (!spriteNode->xmlChildrenNode) + continue; + + if (xmlNameEqual(spriteNode, "sprite")) + { + EmoteSprite *const currentSprite = new EmoteSprite; + currentSprite->sprite = AnimatedSprite::load( + paths.getStringValue("sprites").append(std::string( + reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content))), + XML::getProperty(spriteNode, "variant", 0)); + currentSprite->name = XML::langProperty( + spriteNode, "name", ""); + currentInfo->sprites.push_back(currentSprite); + } + else if (xmlNameEqual(spriteNode, "particlefx")) + { + currentInfo->particles.push_back(reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content)); + } + } + mEmoteInfos[id] = currentInfo; + if (id > mLastEmote) + mLastEmote = id; + } + + XML::Document doc2("graphics/sprites/manaplus_emotes.xml"); + rootNode = doc2.rootNode(); + + if (!rootNode || !xmlNameEqual(rootNode, "emotes")) + { + logger->log1("Emote Database: Error while loading" + " manaplus_emotes.xml!"); + return; + } + + // iterate <emote>s + for_each_xml_child_node(emoteNode, rootNode) + { + if (!xmlNameEqual(emoteNode, "emote")) + continue; + + const int id = XML::getProperty(emoteNode, "id", -1); + if (id == -1) + { + logger->log1("Emote Database: Emote with missing ID in " + "manaplus_emotes.xml!"); + continue; + } + const int altId = XML::getProperty(emoteNode, "altid", -1); + + EmoteInfo *const currentInfo = new EmoteInfo; + currentInfo->time = XML::getProperty(emoteNode, "time", 500); + + for_each_xml_child_node(spriteNode, emoteNode) + { + if (!spriteNode->xmlChildrenNode) + continue; + + if (xmlNameEqual(spriteNode, "sprite")) + { + EmoteSprite *const currentSprite = new EmoteSprite; + currentSprite->sprite = AnimatedSprite::load( + paths.getStringValue("sprites").append(std::string( + reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content))), + XML::getProperty(spriteNode, "variant", 0)); + currentSprite->name = XML::langProperty( + spriteNode, "name", ""); + currentInfo->sprites.push_back(currentSprite); + } + else if (xmlNameEqual(spriteNode, "particlefx")) + { + currentInfo->particles.push_back(reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content)); + } + } + mEmoteInfos[id] = currentInfo; + if (altId != -1) + mEmotesAlt[altId] = id; + + if (id > mLastEmote) + mLastEmote = id; + } + + mLoaded = true; +} + +void EmoteDB::unload() +{ + FOR_EACH (EmoteInfos::const_iterator, i, mEmoteInfos) + { + if (i->second) + { + std::list<EmoteSprite*> &sprites = i->second->sprites; + while (!sprites.empty()) + { + delete sprites.front()->sprite; + delete sprites.front(); + sprites.pop_front(); + } + delete i->second; + } + } + + mEmoteInfos.clear(); + + std::list<EmoteSprite*> &sprites = mUnknown.sprites; + while (!sprites.empty()) + { + delete sprites.front()->sprite; + delete sprites.front(); + sprites.pop_front(); + } + + mLoaded = false; +} + +const EmoteInfo *EmoteDB::get(const int id, const bool allowNull) +{ + const EmoteInfos::const_iterator i = mEmoteInfos.find(id); + + if (i == mEmoteInfos.end()) + { + if (allowNull) + return nullptr; + logger->log("EmoteDB: Warning, unknown emote ID %d requested", id); + return &mUnknown; + } + else + { + return i->second; + } +} + +const EmoteInfo *EmoteDB::get2(int id, const bool allowNull) +{ + const EmoteToEmote::const_iterator it = mEmotesAlt.find(id); + if (it != mEmotesAlt.end()) + id = (*it).second; + + const EmoteInfos::const_iterator i = mEmoteInfos.find(id); + + if (i == mEmoteInfos.end()) + { + if (allowNull) + return nullptr; + logger->log("EmoteDB: Warning, unknown emote ID %d requested", id); + return &mUnknown; + } + else + { + return i->second; + } +} + +const EmoteSprite *EmoteDB::getSprite(const int id, const bool allowNull) +{ + const EmoteInfo *const info = get(id, allowNull); + if (!info) + return nullptr; + + return info->sprites.front(); +} + +const int &EmoteDB::getLast() +{ + return mLastEmote; +} diff --git a/src/resources/db/emotedb.h b/src/resources/db/emotedb.h new file mode 100644 index 000000000..b0b232653 --- /dev/null +++ b/src/resources/db/emotedb.h @@ -0,0 +1,87 @@ +/* + * Emote database + * Copyright (C) 2009 Aethyra Development Team + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_EMOTEDB_H +#define RESOURCES_EMOTEDB_H + +#include "utils/stringvector.h" + +#include <list> +#include <map> + +#include "localconsts.h" + +class AnimatedSprite; + +struct EmoteSprite final +{ + EmoteSprite() : + sprite(nullptr), + name() + { } + + A_DELETE_COPY(EmoteSprite) + + const AnimatedSprite *sprite; + std::string name; +}; + +struct EmoteInfo final +{ + EmoteInfo() : + sprites(), + particles(), + time(400) + { } + + A_DELETE_COPY(EmoteInfo) + + std::list<EmoteSprite*> sprites; + StringVect particles; + int time; +}; + +typedef std::map<int, EmoteInfo*> EmoteInfos; +typedef std::map<int, int> EmoteToEmote; + +/** + * Emote information database. + */ +namespace EmoteDB +{ + void load(); + + void unload(); + + const EmoteInfo *get(const int id, + const bool allowNull = false) A_WARN_UNUSED; + + const EmoteInfo *get2(int id, const bool allowNull = false) A_WARN_UNUSED; + + const EmoteSprite *getSprite(const int id, const bool allowNull = false) + A_WARN_UNUSED; + + const int &getLast() A_WARN_UNUSED; + + typedef EmoteInfos::iterator EmoteInfosIterator; +} // namespace EmoteDB + +#endif // RESOURCES_EMOTEDB_H diff --git a/src/resources/db/itemdb.cpp b/src/resources/db/itemdb.cpp new file mode 100644 index 000000000..eeae4cfec --- /dev/null +++ b/src/resources/db/itemdb.cpp @@ -0,0 +1,889 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/itemdb.h" + +#include "client.h" +#include "configuration.h" +#include "logger.h" + +#include "resources/iteminfo.h" + +#include "utils/dtor.h" +#include "utils/gettext.h" + +#include "debug.h" + +namespace +{ + ItemDB::ItemInfos mItemInfos; + ItemDB::NamedItemInfos mNamedItemInfos; + ItemInfo *mUnknown; + bool mLoaded = false; + StringVect mTagNames; + std::map<std::string, int> mTags; +} + +// Forward declarations +static void loadSpriteRef(ItemInfo *const itemInfo, const XmlNodePtr node); +static void loadSoundRef(ItemInfo *const itemInfo, const XmlNodePtr node); +static void loadFloorSprite(SpriteDisplay *const display, + const XmlNodePtr node); +static void loadReplaceSprite(ItemInfo *const itemInfo, + const XmlNodePtr replaceNode); +static void loadOrderSprite(ItemInfo *const itemInfo, const XmlNodePtr node, + const bool drawAfter); +static int parseSpriteName(const std::string &name); +static int parseDirectionName(const std::string &name); + +namespace +{ + struct FieldType + { + const char *name; + const char *description; + const bool sign; + }; + + static const FieldType fields[] = + { + // TRANSLATORS: item info label + { "attack", N_("Attack %s"), true }, + // TRANSLATORS: item info label + { "defense", N_("Defense %s"), true }, + // TRANSLATORS: item info label + { "hp", N_("HP %s"), true }, + // TRANSLATORS: item info label + { "mp", N_("MP %s"), true }, + // TRANSLATORS: item info label + { "level", N_("Level %s"), false } + }; +} // namespace + +static std::vector<ItemDB::Stat> extraStats; + +void ItemDB::setStatsList(const std::vector<ItemDB::Stat> &stats) +{ + extraStats = stats; +} + +static ItemType itemTypeFromString(const std::string &name) +{ + if (name == "generic" || name == "other") + { + return ITEM_UNUSABLE; + } + else if (name == "usable") + { + return ITEM_USABLE; + } + else if (name == "equip-1hand") + { + return ITEM_EQUIPMENT_ONE_HAND_WEAPON; + } + else if (name == "equip-2hand") + { + return ITEM_EQUIPMENT_TWO_HANDS_WEAPON; + } + else if (name == "equip-torso") + { + return ITEM_EQUIPMENT_TORSO; + } + else if (name == "equip-arms") + { + return ITEM_EQUIPMENT_ARMS; + } + else if (name == "equip-head") + { + return ITEM_EQUIPMENT_HEAD; + } + else if (name == "equip-legs") + { + return ITEM_EQUIPMENT_LEGS; + } + else if (name == "equip-shield") + { + return ITEM_EQUIPMENT_SHIELD; + } + else if (name == "equip-ring") + { + return ITEM_EQUIPMENT_RING; + } + else if (name == "equip-charm") + { + return ITEM_EQUIPMENT_CHARM; + } + else if (name == "equip-necklace" || name == "equip-neck") + { + return ITEM_EQUIPMENT_NECKLACE; + } + else if (name == "equip-feet") + { + return ITEM_EQUIPMENT_FEET; + } + else if (name == "equip-ammo") + { + return ITEM_EQUIPMENT_AMMO; + } + else if (name == "racesprite") + { + return ITEM_SPRITE_RACE; + } + else if (name == "hairsprite") + { + return ITEM_SPRITE_HAIR; + } + else + { + logger->log("Unknown item type: " + name); + return ITEM_UNUSABLE; + } +} + +void ItemDB::load() +{ + if (mLoaded) + unload(); + + int tagNum = 0; + logger->log1("Initializing item database..."); + + mTags.clear(); + mTagNames.clear(); + mTagNames.push_back("All"); + mTagNames.push_back("Usable"); + mTagNames.push_back("Unusable"); + mTagNames.push_back("Equipment"); + mTags["All"] = tagNum ++; + mTags["Usable"] = tagNum ++; + mTags["Unusable"] = tagNum ++; + mTags["Equipment"] = tagNum ++; + + mUnknown = new ItemInfo; + // TRANSLATORS: item name + mUnknown->setName(_("Unknown item")); + mUnknown->setDisplay(SpriteDisplay()); + std::string errFile = paths.getStringValue("spriteErrorFile"); + mUnknown->setSprite(errFile, GENDER_MALE, 0); + mUnknown->setSprite(errFile, GENDER_FEMALE, 0); + mUnknown->setSprite(errFile, GENDER_OTHER, 0); + mUnknown->addTag(mTags["All"]); + loadXmlFile(paths.getStringValue("itemsFile"), tagNum); +} + +void ItemDB::loadXmlFile(const std::string &fileName, int &tagNum) +{ + XML::Document doc(fileName); + const XmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlNameEqual(rootNode, "items")) + { + logger->log("ItemDB: Error while loading %s!", fileName.c_str()); + mLoaded = true; + return; + } + + for_each_xml_child_node(node, rootNode) + { + if (xmlNameEqual(node, "include")) + { + const std::string name = XML::getProperty(node, "name", ""); + if (!name.empty()) + loadXmlFile(name, tagNum); + continue; + } + if (!xmlNameEqual(node, "item")) + continue; + + const int id = XML::getProperty(node, "id", 0); + + if (id == 0) + { + logger->log("ItemDB: Invalid or missing item ID in %s!", + fileName.c_str()); + continue; + } + else if (mItemInfos.find(id) != mItemInfos.end()) + { + logger->log("ItemDB: Redefinition of item ID %d", id); + } + + const std::string typeStr = XML::getProperty(node, "type", "other"); + const int weight = XML::getProperty(node, "weight", 0); + const int view = XML::getProperty(node, "view", 0); + + std::string name = XML::langProperty(node, "name", ""); + std::string image = XML::getProperty(node, "image", ""); + std::string floor = XML::getProperty(node, "floor", ""); + std::string description = XML::langProperty(node, "description", ""); + std::string attackAction = XML::getProperty(node, "attack-action", ""); + std::string skyAttackAction = XML::getProperty( + node, "skyattack-action", ""); + std::string waterAttackAction = XML::getProperty( + node, "waterattack-action", ""); + std::string drawBefore = XML::getProperty(node, "drawBefore", ""); + std::string drawAfter = XML::getProperty(node, "drawAfter", ""); + const int pet = XML::getProperty(node, "pet", 0); + const int maxFloorOffset = XML::getIntProperty( + node, "maxFloorOffset", 32, 0, 32); + std::string colors; + if (serverVersion >= 1) + { + colors = XML::getProperty(node, "colors", ""); + + // check for empty hair palete + if (colors.empty() && id <= -1 && id > -100) + colors = "hair"; + } + else + { + if (id <= -1 && id > -100) + colors = "hair"; + else + colors.clear(); + } + + std::string tags[3]; + tags[0] = XML::getProperty(node, "tag", + XML::getProperty(node, "tag1", "")); + tags[1] = XML::getProperty(node, "tag2", ""); + tags[2] = XML::getProperty(node, "tag3", ""); + + const int drawPriority = XML::getProperty(node, "drawPriority", 0); + + const int attackRange = XML::getProperty(node, "attack-range", 0); + std::string missileParticle = XML::getProperty( + node, "missile-particle", ""); + const int hitEffectId = XML::getProperty(node, "hit-effect-id", + paths.getIntValue("hitEffectId")); + const int criticalEffectId = XML::getProperty( + node, "critical-hit-effect-id", + paths.getIntValue("criticalHitEffectId")); + const int missEffectId = XML::getProperty(node, "miss-effect-id", + paths.getIntValue("missEffectId")); + + SpriteDisplay display; + display.image = image; + if (floor != "") + display.floor = floor; + else + display.floor = image; + + ItemInfo *const itemInfo = new ItemInfo; + itemInfo->setId(id); + // TRANSLATORS: item info name + itemInfo->setName(name.empty() ? _("unnamed") : name); + itemInfo->setDescription(description); + itemInfo->setType(itemTypeFromString(typeStr)); + itemInfo->addTag(mTags["All"]); + itemInfo->setPet(pet); + itemInfo->setProtected(XML::getBoolProperty( + node, "sellProtected", false)); + + switch (itemInfo->getType()) + { + case ITEM_USABLE: + itemInfo->addTag(mTags["Usable"]); + break; + case ITEM_UNUSABLE: + itemInfo->addTag(mTags["Unusable"]); + break; + default: + case ITEM_EQUIPMENT_ONE_HAND_WEAPON: + case ITEM_EQUIPMENT_TWO_HANDS_WEAPON: + case ITEM_EQUIPMENT_TORSO: + case ITEM_EQUIPMENT_ARMS: + case ITEM_EQUIPMENT_HEAD: + case ITEM_EQUIPMENT_LEGS: + case ITEM_EQUIPMENT_SHIELD: + case ITEM_EQUIPMENT_RING: + case ITEM_EQUIPMENT_NECKLACE: + case ITEM_EQUIPMENT_FEET: + case ITEM_EQUIPMENT_AMMO: + case ITEM_EQUIPMENT_CHARM: + case ITEM_SPRITE_RACE: + case ITEM_SPRITE_HAIR: + itemInfo->addTag(mTags["Equipment"]); + break; + } + for (int f = 0; f < 3; f++) + { + if (tags[f] != "") + { + if (mTags.find(tags[f]) == mTags.end()) + { + mTagNames.push_back(tags[f]); + mTags[tags[f]] = tagNum ++; + } + itemInfo->addTag(mTags[tags[f]]); + } + } + + itemInfo->setView(view); + itemInfo->setWeight(weight); + itemInfo->setAttackAction(attackAction); + itemInfo->setSkyAttackAction(skyAttackAction); + itemInfo->setWaterAttackAction(waterAttackAction); + itemInfo->setAttackRange(attackRange); + itemInfo->setMissileParticleFile(missileParticle); + itemInfo->setHitEffectId(hitEffectId); + itemInfo->setCriticalHitEffectId(criticalEffectId); + itemInfo->setMissEffectId(missEffectId); + itemInfo->setDrawBefore(-1, parseSpriteName(drawBefore)); + itemInfo->setDrawAfter(-1, parseSpriteName(drawAfter)); + itemInfo->setDrawPriority(-1, drawPriority); + itemInfo->setColorsList(colors); + itemInfo->setMaxFloorOffset(maxFloorOffset); + itemInfo->setPickupCursor(XML::getProperty( + node, "pickupCursor", "pickup")); + + std::string effect; + for (size_t i = 0; i < sizeof(fields) / sizeof(fields[0]); ++ i) + { + std::string value = XML::getProperty(node, fields[i].name, ""); + if (value.empty()) + continue; + if (!effect.empty()) + effect.append(" / "); + if (fields[i].sign && isDigit(value)) + value = "+" + value; + effect.append(strprintf(gettext(fields[i].description), + value.c_str())); + } + FOR_EACH (std::vector<Stat>::const_iterator, it, extraStats) + { + std::string value = XML::getProperty( + node, it->tag.c_str(), ""); + if (value.empty()) + continue; + if (!effect.empty()) + effect.append(" / "); + if (isDigit(value)) + value = "+" + value; + effect.append(strprintf(it->format.c_str(), value.c_str())); + } + std::string temp = XML::langProperty(node, "effect", ""); + if (!effect.empty() && !temp.empty()) + effect.append(" / "); + effect.append(temp); + itemInfo->setEffect(effect); + + for_each_xml_child_node(itemChild, node) + { + if (xmlNameEqual(itemChild, "sprite")) + { + std::string attackParticle = XML::getProperty( + itemChild, "particle-effect", ""); + itemInfo->setParticleEffect(attackParticle); + + loadSpriteRef(itemInfo, itemChild); + } + else if (xmlNameEqual(itemChild, "sound")) + { + loadSoundRef(itemInfo, itemChild); + } + else if (xmlNameEqual(itemChild, "floor")) + { + loadFloorSprite(&display, itemChild); + } + else if (xmlNameEqual(itemChild, "replace")) + { + loadReplaceSprite(itemInfo, itemChild); + } + else if (xmlNameEqual(itemChild, "drawAfter")) + { + loadOrderSprite(itemInfo, itemChild, true); + } + else if (xmlNameEqual(itemChild, "drawBefore")) + { + loadOrderSprite(itemInfo, itemChild, false); + } + } + +/* + logger->log("start dump item: %d", id); + if (itemInfo->isRemoveSprites()) + { + for (int f = 0; f < 10; f ++) + { + logger->log("dir: %d", f); + SpriteToItemMap *const spriteToItems + = itemInfo->getSpriteToItemReplaceMap(f); + if (!spriteToItems) + { + logger->log("null"); + continue; + } + for (SpriteToItemMapCIter itr = spriteToItems->begin(), + itr_end = spriteToItems->end(); itr != itr_end; ++ itr) + { + const int remSprite = itr->first; + const std::map<int, int> &itemReplacer = itr->second; + logger->log("sprite: %d", remSprite); + + for (std::map<int, int>::const_iterator + repIt = itemReplacer.begin(), + repIt_end = itemReplacer.end(); + repIt != repIt_end; ++ repIt) + { + logger->log("from %d to %d", repIt->first, + repIt->second); + } + } + } + } + + logger->log("--------------------------------"); + logger->log("end dump item"); +*/ + + itemInfo->setDisplay(display); + + mItemInfos[id] = itemInfo; + if (!name.empty()) + { + temp = normalize(name); + + const NamedItemInfos::const_iterator + itr = mNamedItemInfos.find(temp); + if (itr == mNamedItemInfos.end()) + { + mNamedItemInfos[temp] = itemInfo; + } + else + { + logger->log("ItemDB: Duplicate name of item found item %d", + id); + } + } + + if (!attackAction.empty()) + { + if (attackRange == 0) + { + logger->log("ItemDB: Missing attack range from weapon %i!", + id); + } + } + +#define CHECK_PARAM(param, error_value) \ + if (param == error_value) \ + logger->log("ItemDB: Missing " #param " attribute for item %i!", \ + id) + + if (id >= 0 && typeStr != "other") + { + CHECK_PARAM(name, ""); + CHECK_PARAM(description, ""); + CHECK_PARAM(image, ""); + } +#undef CHECK_PARAM + } + + mLoaded = true; +} + +const StringVect &ItemDB::getTags() +{ + return mTagNames; +} + +int ItemDB::getTagId(const std::string &tagName) +{ + return mTags[tagName]; +} + +void ItemDB::unload() +{ + logger->log1("Unloading item database..."); + + delete mUnknown; + mUnknown = nullptr; + + delete_all(mItemInfos); + mItemInfos.clear(); + mNamedItemInfos.clear(); + mTags.clear(); + mTagNames.clear(); + mLoaded = false; +} + +bool ItemDB::exists(const int id) +{ + if (!mLoaded) + return false; + + const ItemInfos::const_iterator i = mItemInfos.find(id); + return i != mItemInfos.end(); +} + +const ItemInfo &ItemDB::get(const int id) +{ + if (!mLoaded) + load(); + + const ItemInfos::const_iterator i = mItemInfos.find(id); + + if (i == mItemInfos.end()) + { + logger->log("ItemDB: Warning, unknown item ID# %d", id); + return *mUnknown; + } + + return *(i->second); +} + +const ItemInfo &ItemDB::get(const std::string &name) +{ + if (!mLoaded) + load(); + + const NamedItemInfos::const_iterator i = mNamedItemInfos.find( + normalize(name)); + + if (i == mNamedItemInfos.end()) + { + if (!name.empty()) + { + logger->log("ItemDB: Warning, unknown item name \"%s\"", + name.c_str()); + } + return *mUnknown; + } + + return *(i->second); +} + +const ItemDB::ItemInfos &ItemDB::getItemInfos() +{ + return mItemInfos; +} + +int parseSpriteName(const std::string &name) +{ + int id = -1; + if (name == "shoes" || name == "boot" || name == "boots") + { + id = 1; + } + else if (name == "bottomclothes" || name == "bottom" || name == "pants") + { + id = 2; + } + else if (name == "topclothes" || name == "top" + || name == "torso" || name == "body") + { + id = 3; + } + else if (name == "misc1") + { + id = 4; + } + else if (name == "misc2" || name == "scarf" || name == "scarfs") + { + id = 5; + } + else if (name == "hair") + { + id = 6; + } + else if (name == "hat" || name == "hats") + { + id = 7; + } + else if (name == "wings") + { + id = 8; + } + else if (name == "glove" || name == "gloves") + { + id = 9; + } + else if (name == "weapon" || name == "weapons") + { + id = 10; + } + else if (name == "shield" || name == "shields") + { + id = 11; + } + else if (name == "amulet" || name == "amulets") + { + id = 12; + } + else if (name == "ring" || name == "rings") + { + id = 13; + } + + return id; +} + +int parseDirectionName(const std::string &name) +{ + int id = -1; + if (name == "down") + { + if (serverVersion > 0) + id = DIRECTION_DOWN; + else + id = -2; + } + else if (name == "downleft" || name == "leftdown") + { + id = DIRECTION_DOWNLEFT; + } + else if (name == "left") + { + id = DIRECTION_LEFT; + } + else if (name == "upleft" || name == "leftup") + { + id = DIRECTION_UPLEFT; + } + else if (name == "up") + { + if (serverVersion > 0) + id = DIRECTION_UP; + else + id = -3; + } + else if (name == "upright" || name == "rightup") + { + id = DIRECTION_UPRIGHT; + } + else if (name == "right") + { + id = DIRECTION_RIGHT; + } + else if (name == "downright" || name == "rightdown") + { + id = DIRECTION_DOWNRIGHT; + } + else if (name == "downall") + { + id = -2; + } + else if (name == "upall") + { + id = -3; + } + // hack for died action. + else if (name == "died") + { + id = 9; + } + + return id; +} + +void loadSpriteRef(ItemInfo *const itemInfo, const XmlNodePtr node) +{ + const std::string gender = XML::getProperty(node, "gender", "unisex"); + const std::string filename = reinterpret_cast<const char*>( + node->xmlChildrenNode->content); + + const int race = XML::getProperty(node, "race", 0); + if (gender == "male" || gender == "unisex") + itemInfo->setSprite(filename, GENDER_MALE, race); + if (gender == "female" || gender == "unisex") + itemInfo->setSprite(filename, GENDER_FEMALE, race); + if (gender == "other" || gender == "unisex") + itemInfo->setSprite(filename, GENDER_OTHER, race); +} + +void loadSoundRef(ItemInfo *const itemInfo, const XmlNodePtr node) +{ + const std::string event = XML::getProperty(node, "event", ""); + const std::string filename = reinterpret_cast<const char*>( + node->xmlChildrenNode->content); + const int delay = XML::getProperty(node, "delay", 0); + + if (event == "hit") + { + itemInfo->addSound(SOUND_EVENT_HIT, filename, delay); + } + else if (event == "strike" || event == "miss") + { + itemInfo->addSound(SOUND_EVENT_MISS, filename, delay); + } + else + { + logger->log("ItemDB: Ignoring unknown sound event '%s'", + event.c_str()); + } +} + +void loadFloorSprite(SpriteDisplay *const display, const XmlNodePtr floorNode) +{ + for_each_xml_child_node(spriteNode, floorNode) + { + if (xmlNameEqual(spriteNode, "sprite")) + { + SpriteReference *const currentSprite = new SpriteReference; + currentSprite->sprite = reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content); + currentSprite->variant + = XML::getProperty(spriteNode, "variant", 0); + display->sprites.push_back(currentSprite); + } + else if (xmlNameEqual(spriteNode, "particlefx")) + { + display->particles.push_back(reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content)); + } + } +} + +void loadReplaceSprite(ItemInfo *const itemInfo, const XmlNodePtr replaceNode) +{ + const std::string removeSprite = XML::getProperty( + replaceNode, "sprite", ""); + const int direction = parseDirectionName(XML::getProperty( + replaceNode, "direction", "all")); + + itemInfo->setRemoveSprites(); + + switch (direction) + { + case -1: + { + for (int f = 0; f < 10; f ++) + { + std::map<int, int> *const mapList + = itemInfo->addReplaceSprite( + parseSpriteName(removeSprite), f); + if (!mapList) + continue; + for_each_xml_child_node(itemNode, replaceNode) + { + if (xmlNameEqual(itemNode, "item")) + { + const int from = XML::getProperty(itemNode, "from", 0); + const int to = XML::getProperty(itemNode, "to", 1); + + (*mapList)[from] = to; + } + } + } + break; + } + case -2: + { + itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_DOWN); + itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_DOWNLEFT); + itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_DOWNRIGHT); + + for_each_xml_child_node(itemNode, replaceNode) + { + if (xmlNameEqual(itemNode, "item")) + { + const int from = XML::getProperty(itemNode, "from", 0); + const int to = XML::getProperty(itemNode, "to", 1); + std::map<int, int> *mapList = itemInfo->addReplaceSprite( + parseSpriteName(removeSprite), DIRECTION_DOWN); + if (mapList) + (*mapList)[from] = to; + + mapList = itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_DOWNLEFT); + if (mapList) + (*mapList)[from] = to; + + mapList = itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_DOWNRIGHT); + if (mapList) + (*mapList)[from] = to; + } + } + break; + } + case -3: + { + itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_UP); + itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_UPLEFT); + itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_UPRIGHT); + + for_each_xml_child_node(itemNode, replaceNode) + { + if (xmlNameEqual(itemNode, "item")) + { + const int from = XML::getProperty(itemNode, "from", 0); + const int to = XML::getProperty(itemNode, "to", 1); + std::map<int, int> *mapList = itemInfo->addReplaceSprite( + parseSpriteName(removeSprite), DIRECTION_UP); + if (mapList) + (*mapList)[from] = to; + + mapList = itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_UPLEFT); + if (mapList) + (*mapList)[from] = to; + + mapList = itemInfo->addReplaceSprite(parseSpriteName( + removeSprite), DIRECTION_UPRIGHT); + if (mapList) + (*mapList)[from] = to; + } + } + break; + } + default: + { + std::map<int, int> *const mapList = itemInfo->addReplaceSprite( + parseSpriteName(removeSprite), direction); + if (!mapList) + return; + for_each_xml_child_node(itemNode, replaceNode) + { + if (xmlNameEqual(itemNode, "item")) + { + const int from = XML::getProperty(itemNode, "from", 0); + const int to = XML::getProperty(itemNode, "to", 1); + (*mapList)[from] = to; + } + } + break; + } + } +} + +void loadOrderSprite(ItemInfo *const itemInfo, const XmlNodePtr node, + const bool drawAfter) +{ + const int sprite = parseSpriteName(XML::getProperty(node, "name", "")); + const int priority = XML::getProperty(node, "priority", 0); + + const int direction = parseDirectionName(XML::getProperty( + node, "direction", "all")); + if (drawAfter) + itemInfo->setDrawAfter(direction, sprite); + else + itemInfo->setDrawBefore(direction, sprite); + itemInfo->setDrawPriority(direction, priority); +} diff --git a/src/resources/db/itemdb.h b/src/resources/db/itemdb.h new file mode 100644 index 000000000..1a5a4cce8 --- /dev/null +++ b/src/resources/db/itemdb.h @@ -0,0 +1,75 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_ITEMDB_H +#define RESOURCES_ITEMDB_H + +#include "utils/stringvector.h" + +#include <map> + +#include "localconsts.h" + +class ItemInfo; + +/** + * Item information database. + */ +namespace ItemDB +{ + void load(); + + void unload(); + + void loadXmlFile(const std::string &fileName, int &tagNum); + + const StringVect &getTags(); + + bool exists(const int id) A_WARN_UNUSED; + + const ItemInfo &get(const int id) A_WARN_UNUSED; + const ItemInfo &get(const std::string &name) A_WARN_UNUSED; + + // Items database + typedef std::map<int, ItemInfo*> ItemInfos; + typedef std::map<std::string, ItemInfo*> NamedItemInfos; + + const std::map<int, ItemInfo*> &getItemInfos(); + + int getTagId(const std::string &tagName) A_WARN_UNUSED; + + struct Stat + { + Stat(const std::string &tag0, + const std::string &format0) : + tag(tag0), + format(format0) + {} + + std::string tag; + std::string format; + }; + + void setStatsList(const std::vector<Stat> &stats); +} // namespace ItemDB + +#endif // RESOURCES_ITEMDB_H diff --git a/src/resources/db/mapdb.cpp b/src/resources/db/mapdb.cpp new file mode 100644 index 000000000..13aac3032 --- /dev/null +++ b/src/resources/db/mapdb.cpp @@ -0,0 +1,176 @@ +/* + * Color database + * Copyright (C) 2008 Aethyra Development Team + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/mapdb.h" + +#include "configuration.h" +#include "logger.h" + +#include "debug.h" + +namespace +{ + bool mLoaded = false; + MapDB::Maps mMaps; + MapDB::MapInfos mInfos; + MapDB::Atlases mAtlases; +} + +namespace MapDB +{ + void readMap(XmlNodePtr node); + void readAtlas(XmlNodePtr node); +} + +void MapDB::load() +{ + if (mLoaded) + unload(); + + loadRemap(); + loadInfo(); + mLoaded = true; +} + +void MapDB::loadRemap() +{ + XML::Document *const doc = new XML::Document( + paths.getStringValue("mapsRemapFile")); + + const XmlNodePtr root = doc->rootNode(); + if (!root) + { + delete doc; + return; + } + + for_each_xml_child_node(node, root) + { + if (xmlNameEqual(node, "map")) + { + const std::string name = XML::getProperty(node, "name", ""); + if (name.empty()) + continue; + + const std::string value = XML::getProperty(node, "value", ""); + if (value.empty()) + continue; + + mMaps[name] = value; + } + } + + delete doc; +} + +void MapDB::readMap(XmlNodePtr node) +{ + const std::string map = XML::getProperty(node, "name", ""); + if (map.empty()) + return; + + for_each_xml_child_node(childNode, node) + { + if (xmlNameEqual(childNode, "atlas")) + { + const std::string atlas = XML::getProperty(childNode, "name", ""); + if (atlas.empty()) + continue; + mInfos[map].atlas = atlas; + } + } +} + +void MapDB::readAtlas(XmlNodePtr node) +{ + const std::string atlas = XML::getProperty(node, "name", ""); + if (atlas.empty()) + return; + for_each_xml_child_node(childNode, node) + { + if (xmlNameEqual(childNode, "file")) + { + const std::string file = XML::getProperty(childNode, "name", ""); + if (file.empty()) + continue; + mAtlases[atlas].push_back(file); + } + } + if (atlas != "all") + { + const AtlasCIter &allAtlas = mAtlases.find("all"); + if (allAtlas != mAtlases.end()) + { + FOR_EACH (StringVectCIter, it, (*allAtlas).second) + mAtlases[atlas].push_back(*it); + } + } +} + +void MapDB::loadInfo() +{ + XML::Document *doc = new XML::Document(paths.getStringValue("mapsFile")); + const XmlNodePtr root = doc->rootNode(); + if (!root) + { + delete doc; + return; + } + + for_each_xml_child_node(node, root) + { + if (xmlNameEqual(node, "map")) + readMap(node); + else if (xmlNameEqual(node, "atlas")) + readAtlas(node); + } + delete doc; +} + +void MapDB::unload() +{ + logger->log1("Unloading map database..."); + + mMaps.clear(); + mLoaded = false; +} + +const std::string MapDB::getMapName(const std::string &name) +{ + const MapIterator it = mMaps.find(name); + + if (it != mMaps.end()) + return it->second; + return name; +} + +const MapDB::MapInfo *MapDB::getMapAtlas(const std::string &name) +{ + const MapInfoIter it = mInfos.find(name); + if (it == mInfos.end()) + return nullptr; + MapInfo *const info = &(*it).second; + const AtlasCIter it2 = mAtlases.find(info->atlas); + if (it2 == mAtlases.end()) + return nullptr; + info->files = &((*it2).second); + return info; +} diff --git a/src/resources/db/mapdb.h b/src/resources/db/mapdb.h new file mode 100644 index 000000000..9e0407f66 --- /dev/null +++ b/src/resources/db/mapdb.h @@ -0,0 +1,78 @@ +/* + * Color database + * Copyright (C) 2008 Aethyra Development Team + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_MAPDB_H +#define RESOURCES_MAPDB_H + +#include "utils/stringvector.h" + +#include <map> + +#include "localconsts.h" + +/** + * Color information database. + */ +namespace MapDB +{ + struct MapInfo + { + MapInfo() : + atlas(), + files(nullptr) + { + } + + std::string atlas; + const StringVect *files; + }; + + /** + * Loads the map remap data from <code>maps\remap.xml</code>. + */ + void load(); + + void loadRemap(); + + void loadInfo(); + + /** + * Clear the remap data + */ + void unload(); + + const std::string getMapName(const std::string &name) A_WARN_UNUSED; + + const MapInfo *getMapAtlas(const std::string &name) A_WARN_UNUSED; + + // Maps DB + typedef std::map<std::string, std::string> Maps; + typedef Maps::iterator MapIterator; + // map to infos map + typedef std::map<std::string, MapInfo> MapInfos; + typedef MapInfos::iterator MapInfoIter; + // atlas to files map + typedef std::map<std::string, StringVect> Atlases; + typedef Atlases::iterator AtlasIter; + typedef Atlases::const_iterator AtlasCIter; +} // namespace MapDB + +#endif // RESOURCES_MAPDB_H diff --git a/src/resources/db/monsterdb.cpp b/src/resources/db/monsterdb.cpp new file mode 100644 index 000000000..502c9cc2c --- /dev/null +++ b/src/resources/db/monsterdb.cpp @@ -0,0 +1,273 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/monsterdb.h" + +#include "logger.h" + +#include "resources/beingcommon.h" +#include "resources/beinginfo.h" + +#include "utils/dtor.h" +#include "utils/gettext.h" + +#include "configuration.h" + +#include "debug.h" + +static const unsigned int OLD_TMWATHENA_OFFSET = 1002; + +namespace +{ + BeingInfos mMonsterInfos; + bool mLoaded = false; +} + +void MonsterDB::load() +{ + if (mLoaded) + unload(); + + logger->log1("Initializing monster database..."); + loadXmlFile(paths.getStringValue("monstersFile")); + mLoaded = true; +} + +void MonsterDB::loadXmlFile(const std::string &fileName) +{ + XML::Document doc(fileName); + const XmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlNameEqual(rootNode, "monsters")) + { + logger->log("Monster Database: Error while loading %s!", + paths.getStringValue("monstersFile").c_str()); + mLoaded = true; + return; + } + +#ifdef MANASERV_SUPPORT + const int offset = XML::getProperty(rootNode, "offset", + Net::getNetworkType() != ServerInfo::MANASERV + ? OLD_TMWATHENA_OFFSET : 0); +#else + const int offset = XML::getProperty(rootNode, + "offset", OLD_TMWATHENA_OFFSET); +#endif + + // iterate <monster>s + for_each_xml_child_node(monsterNode, rootNode) + { + if (xmlNameEqual(monsterNode, "include")) + { + const std::string name = XML::getProperty(monsterNode, "name", ""); + if (!name.empty()) + loadXmlFile(name); + continue; + } + if (!xmlNameEqual(monsterNode, "monster")) + continue; + + BeingInfo *const currentInfo = new BeingInfo; + + currentInfo->setWalkMask(Map::BLOCKMASK_WALL + | Map::BLOCKMASK_CHARACTER | Map::BLOCKMASK_MONSTER); + currentInfo->setBlockType(Map::BLOCKTYPE_MONSTER); + + currentInfo->setName(XML::langProperty( + // TRANSLATORS: unknown info name + monsterNode, "name", _("unnamed"))); + + BeingCommon::readBasicAttributes(currentInfo, monsterNode, "attack"); + + currentInfo->setMaxHP(XML::getProperty(monsterNode, "maxHP", 0)); + + currentInfo->setDeadSortOffsetY(XML::getProperty( + monsterNode, "deadSortOffsetY", 31)); + + currentInfo->setColorsList(XML::getProperty(monsterNode, + "colors", "")); + + unsigned char block = 0; + std::string walkStr = XML::getProperty( + monsterNode, "walkType", "walk"); + if (walkStr == "walk") + block = Map::BLOCKMASK_WATER | Map::BLOCKMASK_AIR; + else if (walkStr == "fly") + block = 0; + else if (walkStr == "swim") + block = Map::BLOCKMASK_GROUND | Map::BLOCKMASK_AIR; + else if (walkStr == "walkswim" || walkStr == "swimwalk") + block = Map::BLOCKMASK_AIR; + + currentInfo->setWalkMask(static_cast<unsigned char>( + Map::BLOCKMASK_WALL | block)); + + if (currentInfo->getMaxHP()) + currentInfo->setStaticMaxHP(true); + + SpriteDisplay display; + + // iterate <sprite>s and <sound>s + for_each_xml_child_node(spriteNode, monsterNode) + { + if (xmlNameEqual(spriteNode, "sprite")) + { + if (!spriteNode->xmlChildrenNode) + continue; + + SpriteReference *const currentSprite = new SpriteReference; + currentSprite->sprite = reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content); + + currentSprite->variant = XML::getProperty( + spriteNode, "variant", 0); + display.sprites.push_back(currentSprite); + } + else if (xmlNameEqual(spriteNode, "sound")) + { + if (!spriteNode->xmlChildrenNode) + continue; + + const std::string event = XML::getProperty( + spriteNode, "event", ""); + const int delay = XML::getProperty( + spriteNode, "delay", 0); + const char *filename; + filename = reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content); + + if (event == "hit") + { + currentInfo->addSound(SOUND_EVENT_HIT, filename, delay); + } + else if (event == "miss") + { + currentInfo->addSound(SOUND_EVENT_MISS, filename, delay); + } + else if (event == "hurt") + { + currentInfo->addSound(SOUND_EVENT_HURT, filename, delay); + } + else if (event == "die") + { + currentInfo->addSound(SOUND_EVENT_DIE, filename, delay); + } + else if (event == "move") + { + currentInfo->addSound(SOUND_EVENT_MOVE, filename, delay); + } + else if (event == "sit") + { + currentInfo->addSound(SOUND_EVENT_SIT, filename, delay); + } + else if (event == "sittop") + { + currentInfo->addSound(SOUND_EVENT_SITTOP, filename, delay); + } + else if (event == "spawn") + { + currentInfo->addSound(SOUND_EVENT_SPAWN, filename, delay); + } + else + { + logger->log("MonsterDB: Warning, sound effect %s for " + "unknown event %s of monster %s", + filename, event.c_str(), + currentInfo->getName().c_str()); + } + } + else if (xmlNameEqual(spriteNode, "attack")) + { + const int id = XML::getProperty(spriteNode, "id", 0); + const int effectId = XML::getProperty( + spriteNode, "effect-id", paths.getIntValue("effectId")); + const int hitEffectId = XML::getProperty(spriteNode, + "hit-effect-id", paths.getIntValue("hitEffectId")); + const int criticalHitEffectId = XML::getProperty(spriteNode, + "critical-hit-effect-id", + paths.getIntValue("criticalHitEffectId")); + const int missEffectId = XML::getProperty(spriteNode, + "miss-effect-id", paths.getIntValue("missEffectId")); + + const std::string spriteAction = XML::getProperty( + spriteNode, "action", "attack"); + const std::string skySpriteAction = XML::getProperty( + spriteNode, "skyaction", "skyattack"); + const std::string waterSpriteAction = XML::getProperty( + spriteNode, "wateraction", "waterattack"); + + const std::string missileParticle = XML::getProperty( + spriteNode, "missile-particle", ""); + + currentInfo->addAttack(id, spriteAction, skySpriteAction, + waterSpriteAction, effectId, hitEffectId, + criticalHitEffectId, missEffectId, missileParticle); + } + else if (xmlNameEqual(spriteNode, "particlefx")) + { + if (!spriteNode->xmlChildrenNode) + continue; + + display.particles.push_back(reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content)); + } + } + currentInfo->setDisplay(display); + + mMonsterInfos[XML::getProperty( + monsterNode, "id", 0) + offset] = currentInfo; + } +} + +void MonsterDB::unload() +{ + delete_all(mMonsterInfos); + mMonsterInfos.clear(); + + mLoaded = false; +} + + +BeingInfo *MonsterDB::get(const int id) +{ + BeingInfoIterator i = mMonsterInfos.find(id); + + if (i == mMonsterInfos.end()) + { + i = mMonsterInfos.find(id + OLD_TMWATHENA_OFFSET); + if (i == mMonsterInfos.end()) + { + logger->log("MonsterDB: Warning, unknown monster ID %d requested", + id); + return BeingInfo::unknown; + } + else + { + return i->second; + } + } + else + { + return i->second; + } +} diff --git a/src/resources/db/monsterdb.h b/src/resources/db/monsterdb.h new file mode 100644 index 000000000..426228388 --- /dev/null +++ b/src/resources/db/monsterdb.h @@ -0,0 +1,46 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_MONSTERDB_H +#define RESOURCES_MONSTERDB_H + +#include "localconsts.h" + +#include <string> + +class BeingInfo; + +/** + * Monster information database. + */ +namespace MonsterDB +{ + void load(); + + void unload(); + + void loadXmlFile(const std::string &fileName); + + BeingInfo *get(const int id) A_WARN_UNUSED; +} + +#endif // RESOURCES_MONSTERDB_H diff --git a/src/resources/db/npcdb.cpp b/src/resources/db/npcdb.cpp new file mode 100644 index 000000000..922b2e8ee --- /dev/null +++ b/src/resources/db/npcdb.cpp @@ -0,0 +1,158 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/npcdb.h" + +#include "logger.h" + +#include "resources/beingcommon.h" +#include "resources/beinginfo.h" + +#include "utils/dtor.h" +#include "configuration.h" + +#include "debug.h" + +namespace +{ + BeingInfos mNPCInfos; + bool mLoaded = false; +} + +extern int serverVersion; + +void NPCDB::load() +{ + if (mLoaded) + unload(); + + logger->log1("Initializing NPC database..."); + + loadXmlFile(paths.getStringValue("npcsFile")); + mLoaded = true; +} + +void NPCDB::loadXmlFile(const std::string &fileName) +{ + XML::Document doc(fileName); + const XmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlNameEqual(rootNode, "npcs")) + { + logger->log("NPC Database: Error while loading %s!", + paths.getStringValue("npcsFile").c_str()); + mLoaded = true; + return; + } + + // iterate <npc>s + for_each_xml_child_node(npcNode, rootNode) + { + if (xmlNameEqual(npcNode, "include")) + { + const std::string name = XML::getProperty(npcNode, "name", ""); + if (!name.empty()) + loadXmlFile(name); + continue; + } + + if (!xmlNameEqual(npcNode, "npc")) + continue; + + const int id = XML::getProperty(npcNode, "id", 0); + if (id == 0) + { + logger->log("NPC Database: NPC with missing ID in %s!", + paths.getStringValue("npcsFile").c_str()); + continue; + } + + BeingInfo *const currentInfo = new BeingInfo; + + currentInfo->setTargetSelection(XML::getBoolProperty(npcNode, + "targetSelection", true)); + + BeingCommon::readBasicAttributes(currentInfo, npcNode, "talk"); + + currentInfo->setDeadSortOffsetY(XML::getProperty(npcNode, + "deadSortOffsetY", 31)); + + currentInfo->setAvatarId(static_cast<uint16_t>(XML::getProperty( + npcNode, "avatar", 0))); + + SpriteDisplay display; + for_each_xml_child_node(spriteNode, npcNode) + { + if (!spriteNode->xmlChildrenNode) + continue; + + if (xmlNameEqual(spriteNode, "sprite")) + { + SpriteReference *const currentSprite = new SpriteReference; + currentSprite->sprite = reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content); + currentSprite->variant = + XML::getProperty(spriteNode, "variant", 0); + display.sprites.push_back(currentSprite); + } + else if (xmlNameEqual(spriteNode, "particlefx")) + { + display.particles.push_back(reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content)); + } + } + + currentInfo->setDisplay(display); + mNPCInfos[id] = currentInfo; + } +} + +void NPCDB::unload() +{ + delete_all(mNPCInfos); + mNPCInfos.clear(); + + mLoaded = false; +} + +BeingInfo *NPCDB::get(const int id) +{ + const BeingInfoIterator i = mNPCInfos.find(id); + + if (i == mNPCInfos.end()) + { + logger->log("NPCDB: Warning, unknown NPC ID %d requested", id); + return BeingInfo::unknown; + } + else + { + return i->second; + } +} + +uint16_t NPCDB::getAvatarFor(const int id) +{ + const BeingInfo *const info = get(id); + if (!info) + return 0; + return info->getAvatarId(); +} diff --git a/src/resources/db/npcdb.h b/src/resources/db/npcdb.h new file mode 100644 index 000000000..9614c2052 --- /dev/null +++ b/src/resources/db/npcdb.h @@ -0,0 +1,50 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_NPCDB_H +#define RESOURCES_NPCDB_H + +#include <stdint.h> + +#include <string> + +#include "localconsts.h" + +class BeingInfo; + +/** + * NPC information database. + */ +namespace NPCDB +{ + void load(); + + void unload(); + + BeingInfo *get(const int id) A_WARN_UNUSED; + + uint16_t getAvatarFor(const int id); + + void loadXmlFile(const std::string &fileName); +} // namespace NPCDB + +#endif // RESOURCES_NPCDB_H diff --git a/src/resources/db/palettedb.cpp b/src/resources/db/palettedb.cpp new file mode 100644 index 000000000..91c3b1e34 --- /dev/null +++ b/src/resources/db/palettedb.cpp @@ -0,0 +1,108 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/palettedb.h" + +#include "logger.h" + +#include "resources/dyecolor.h" +#include "resources/resourcemanager.h" + +#include <map> + +#include "debug.h" + +namespace +{ + bool mLoaded = false; + std::map<std::string, DyeColor> mColors; + DyeColor mEmpty(0, 0, 0, 0); +} + +void PaletteDB::load() +{ + if (mLoaded) + unload(); + + loadPalette(); +} + +void PaletteDB::loadPalette() +{ + mLoaded = true; + StringVect lines; + ResourceManager::loadTextFile("palette.gpl", lines); + StringVectCIter it = lines.begin(); + if (it == lines.end()) + { + logger->log("missing GIMP palette file"); + return; + } + if (*it != "GIMP Palette") + { + logger->log("wrong GIMP palette file"); + return; + } + ++ it; + // skip header + while (it != lines.end()) + { + const std::string line = *it; + if (!line.empty() && line[0] == '#') + break; + ++ it; + } + + char name[101]; + + // process colors and ignore commets + while (it != lines.end()) + { + const std::string line = *it; + ++ it; + + if (line.empty() || line[0] == '#') + continue; + + unsigned int r; + unsigned int g; + unsigned int b; + + if (sscanf(line.c_str(), "%10u %10u %10u\t%100s", + &r, &g, &b, name) == 4) + { + mColors[name] = DyeColor(r, g, b); + } + } +} + +void PaletteDB::unload() +{ + mColors.clear(); +} + +const DyeColor &PaletteDB::getColor(const std::string &name) +{ + std::map<std::string, DyeColor>::const_iterator it = mColors.find(name); + if (it != mColors.end()) + return (*it).second; + else + return mEmpty; +} diff --git a/src/resources/db/palettedb.h b/src/resources/db/palettedb.h new file mode 100644 index 000000000..307178693 --- /dev/null +++ b/src/resources/db/palettedb.h @@ -0,0 +1,39 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_PALETTEDB_H +#define RESOURCES_PALETTEDB_H + +#include "localconsts.h" + +#include <string> + +struct DyeColor; + +namespace PaletteDB +{ + void load(); + void unload(); + void loadPalette(); + const DyeColor &getColor(const std::string &name); + +} // namespace PaletteDB + +#endif // RESOURCES_PALETTEDB_H diff --git a/src/resources/db/petdb.cpp b/src/resources/db/petdb.cpp new file mode 100644 index 000000000..169c8ee39 --- /dev/null +++ b/src/resources/db/petdb.cpp @@ -0,0 +1,137 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/petdb.h" + +#include "logger.h" + +#include "resources/beingcommon.h" +#include "resources/beinginfo.h" + +#include "utils/dtor.h" +#include "configuration.h" + +#include "debug.h" + +namespace +{ + BeingInfos mPETInfos; + bool mLoaded = false; +} + +extern int serverVersion; + +void PETDB::load() +{ + if (mLoaded) + unload(); + + logger->log1("Initializing PET database..."); + + XML::Document doc(paths.getStringValue("petsFile")); + const XmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlNameEqual(rootNode, "pets")) + { + logger->log("PET Database: Error while loading %s!", + paths.getStringValue("petsFile").c_str()); + mLoaded = true; + return; + } + + // iterate <pet>s + for_each_xml_child_node(petNode, rootNode) + { + if (!xmlNameEqual(petNode, "pet")) + continue; + + const int id = XML::getProperty(petNode, "id", 0); + if (id == 0) + { + logger->log("PET Database: PET with missing ID in %s!", + paths.getStringValue("petsFile").c_str()); + continue; + } + + BeingInfo *const currentInfo = new BeingInfo; + + currentInfo->setTargetSelection(XML::getBoolProperty(petNode, + "targetSelection", false)); + + BeingCommon::readBasicAttributes(currentInfo, petNode, "talk"); + + currentInfo->setDeadSortOffsetY(XML::getProperty(petNode, + "deadSortOffsetY", 31)); + + SpriteDisplay display; + for_each_xml_child_node(spriteNode, petNode) + { + if (!spriteNode->xmlChildrenNode) + continue; + + if (xmlNameEqual(spriteNode, "sprite")) + { + SpriteReference *const currentSprite = new SpriteReference; + currentSprite->sprite = reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content); + currentSprite->variant = + XML::getProperty(spriteNode, "variant", 0); + display.sprites.push_back(currentSprite); + } + else if (xmlNameEqual(spriteNode, "particlefx")) + { + std::string particlefx = reinterpret_cast<const char*>( + spriteNode->xmlChildrenNode->content); + display.particles.push_back(particlefx); + } + } + + currentInfo->setDisplay(display); + + mPETInfos[id] = currentInfo; + } + + mLoaded = true; +} + +void PETDB::unload() +{ + delete_all(mPETInfos); + mPETInfos.clear(); + + mLoaded = false; +} + +BeingInfo *PETDB::get(const int id) +{ + const BeingInfoIterator i = mPETInfos.find(id); + + if (i == mPETInfos.end()) + { + logger->log("PETDB: Warning, unknown PET ID %d requested", id); + return BeingInfo::unknown; + } + else + { + return i->second; + } +} diff --git a/src/resources/db/petdb.h b/src/resources/db/petdb.h new file mode 100644 index 000000000..d5e4b5613 --- /dev/null +++ b/src/resources/db/petdb.h @@ -0,0 +1,39 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_PETDB_H +#define RESOURCES_PETDB_H + +#include "localconsts.h" + +class BeingInfo; + +namespace PETDB +{ + void load(); + + void unload(); + + BeingInfo *get(const int id) A_WARN_UNUSED; +} + +#endif // RESOURCES_PETDB_H diff --git a/src/resources/db/sounddb.cpp b/src/resources/db/sounddb.cpp new file mode 100644 index 000000000..f1e0ff93c --- /dev/null +++ b/src/resources/db/sounddb.cpp @@ -0,0 +1,79 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "resources/db/sounddb.h" + +#include "configuration.h" +#include "notifications.h" +#include "notifymanager.h" + +#include "utils/xml.h" + +#include "debug.h" + +namespace +{ + std::string mDefault; + std::vector<std::string> mSounds; +} + +void SoundDB::load() +{ + unload(); + + XML::Document *doc = new XML::Document(paths.getStringValue("soundsFile")); + const XmlNodePtr root = doc->rootNode(); + + if (!root || !xmlNameEqual(root, "sounds")) + { + delete doc; + return; + } + + for_each_xml_child_node(node, root) + { + if (xmlNameEqual(node, "sound")) + { + const std::string name = XML::getProperty(node, "name", ""); + const int id = NotifyManager::getIndexBySound(name); + if (id) + { + const std::string value = XML::getProperty(node, "value", ""); + mSounds[id] = value; + } + } + } + + delete doc; +} + +void SoundDB::unload() +{ + mSounds.resize(NotifyManager::TYPE_END); + for (int f = 0; f < NotifyManager::TYPE_END; f ++) + mSounds[f] = ""; +} + +std::string &SoundDB::getSound(const int id) +{ + if (id < 0 || id >= NotifyManager::TYPE_END) + return mDefault; + return mSounds[id]; +} diff --git a/src/resources/db/sounddb.h b/src/resources/db/sounddb.h new file mode 100644 index 000000000..356cd4e13 --- /dev/null +++ b/src/resources/db/sounddb.h @@ -0,0 +1,37 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef RESOURCES_SOUNDDB_H +#define RESOURCES_SOUNDDB_H + +#include <string> + +#include "localconsts.h" + +namespace SoundDB +{ + void load(); + + void unload(); + + std::string &getSound(const int id); +} + +#endif // RESOURCES_SOUNDDB_H |