From 1a99d37d059df95f6a144c4f9e9fa85dacefd185 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Sat, 27 Apr 2013 16:43:59 +0200 Subject: Always read the attributes.xml file This way it can also be used when connecting to a tmwAthena server for customizing the min/max of attributes and the amount of starting points. Mantis-issue: 501 Reviewed-by: Ablu --- mana.files | 7 +- src/CMakeLists.txt | 4 +- src/net/manaserv/attributes.cpp | 408 ------------------------------------ src/net/manaserv/attributes.h | 70 ------- src/net/manaserv/charhandler.cpp | 4 +- src/net/manaserv/generalhandler.cpp | 5 +- src/net/manaserv/playerhandler.cpp | 6 +- src/net/tmwa/charserverhandler.cpp | 6 +- src/net/tmwa/generalhandler.cpp | 19 +- src/resources/attributes.cpp | 405 +++++++++++++++++++++++++++++++++++ src/resources/attributes.h | 68 ++++++ 11 files changed, 508 insertions(+), 494 deletions(-) delete mode 100644 src/net/manaserv/attributes.cpp delete mode 100644 src/net/manaserv/attributes.h create mode 100644 src/resources/attributes.cpp create mode 100644 src/resources/attributes.h diff --git a/mana.files b/mana.files index be668387..dbfddc00 100644 --- a/mana.files +++ b/mana.files @@ -18,7 +18,8 @@ data/help/index.txt data/help/support.txt data/help/windows.txt data/icons/CMakeLists.txt -docs/FAQ.txt +data/sfx/CMakeLists.txt +data/sfx/system/CMakeLists.txt docs/HACKING.txt docs/example.mana docs/items.txt @@ -340,8 +341,6 @@ src/net/logindata.h src/net/loginhandler.h src/net/manaserv/adminhandler.cpp src/net/manaserv/adminhandler.h -src/net/manaserv/attributes.cpp -src/net/manaserv/attributes.h src/net/manaserv/beinghandler.cpp src/net/manaserv/beinghandler.h src/net/manaserv/buysellhandler.cpp @@ -468,6 +467,8 @@ src/resources/ambientlayer.cpp src/resources/ambientlayer.h src/resources/animation.cpp src/resources/animation.h +src/resources/attributes.cpp +src/resources/attributes.h src/resources/beinginfo.cpp src/resources/beinginfo.h src/resources/dye.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f7483cfa..32ac5426 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -365,6 +365,8 @@ SET(SRCS resources/ambientlayer.h resources/animation.cpp resources/animation.h + resources/attributes.cpp + resources/attributes.h resources/beinginfo.cpp resources/beinginfo.h resources/dye.cpp @@ -593,8 +595,6 @@ SET(SRCS_TMWA SET(SRCS_MANA net/manaserv/adminhandler.cpp net/manaserv/adminhandler.h - net/manaserv/attributes.cpp - net/manaserv/attributes.h net/manaserv/beinghandler.cpp net/manaserv/beinghandler.h net/manaserv/buysellhandler.cpp diff --git a/src/net/manaserv/attributes.cpp b/src/net/manaserv/attributes.cpp deleted file mode 100644 index e754a6a9..00000000 --- a/src/net/manaserv/attributes.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * The Mana Client - * Copyright (C) 2010-2012 The Mana Developers - * - * This file is part of The Mana 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 . - */ - -#include "net/manaserv/attributes.h" - -#include "log.h" -#include "playerinfo.h" - -#include "gui/statuswindow.h" - -#include "resources/itemdb.h" - -#include "utils/gettext.h" -#include "utils/stringutils.h" -#include "utils/xml.h" - -#include -#include - -#define DEFAULT_ATTRIBUTESDB_FILE "attributes.xml" -#define DEFAULT_POINTS 60 -#define DEFAULT_MIN_PTS 1 -#define DEFAULT_MAX_PTS 20 - -namespace ManaServ { -namespace Attributes { - - typedef struct - { - unsigned int id; - std::string name; - std::string description; - /** Whether the attribute value can be modified by the player */ - bool modifiable; - /**< Attribute scope. */ - std::string scope; - /** The playerInfo core Id the attribute is linked with or -1 if not */ - int playerInfoId; - } Attribute; - - /** Map for attributes. */ - typedef std::map AttributeMap; - static AttributeMap attributes; - - /** tags = effects on attributes. */ - typedef std::map< std::string, std::string > TagMap; - static TagMap tags; - - /** List of modifiable attribute names used at character's creation. */ - static std::vector attributeLabels; - - /** Characters creation points. */ - static unsigned int creationPoints = 0; - static unsigned int attributeMinimum = 0; - static unsigned int attributeMaximum = 0; - - unsigned int getCreationPoints() - { - return creationPoints; - } - - unsigned int getAttributeMinimum() - { - return attributeMinimum; - } - - unsigned int getAttributeMaximum() - { - return attributeMaximum; - } - - std::vector& getLabels() - { - return attributeLabels; - } - - /** - * Fills the list of base attribute labels. - */ - static void fillLabels() - { - // Fill up the modifiable attribute label list. - attributeLabels.clear(); - AttributeMap::const_iterator it, it_end; - for (it = attributes.begin(), it_end = attributes.end(); it != it_end; - it++) - { - if (it->second.modifiable && - (it->second.scope == "character" || it->second.scope == "being")) - attributeLabels.push_back(it->second.name + ":"); - } - } - - /** - * Fills the list of base attribute labels. - */ - static int getPlayerInfoIdFromAttrType(std::string attrType) - { - toLower(attrType); - if (attrType == "level") - return ::LEVEL; - else if (attrType == "hp") - return ::HP; - else if (attrType == "max-hp") - return ::MAX_HP; - else if (attrType == "mp") - return ::MP; - else if (attrType == "max-mp") - return ::MAX_MP; - else if (attrType == "exp") - return ::EXP; - else if (attrType == "exp-needed") - return ::EXP_NEEDED; - else if (attrType == "money") - return ::MONEY; - else if (attrType == "total-weight") - return ::TOTAL_WEIGHT; - else if (attrType == "max-weight") - return ::MAX_WEIGHT; - else if (attrType == "skill-points") - return ::SKILL_POINTS; - else if (attrType == "char-points") - return ::CHAR_POINTS; - else if (attrType == "corr-points") - return ::CORR_POINTS; - else if (attrType == "none") - return -2; // Used to hide the attribute display. - - return -1; // Not linked to a playerinfo stat. - } - - int getPlayerInfoIdFromAttrId(int attrId) - { - AttributeMap::const_iterator it = attributes.find(attrId); - - if (it != attributes.end()) - { - return it->second.playerInfoId; - } - - return -1; - } - - static void loadBuiltins() - { - { - Attribute a; - a.id = 16; - a.name = _("Strength"); - a.description = ""; - a.modifiable = true; - a.scope = "character"; - a.playerInfoId = -1; - - attributes[a.id] = a; - tags.insert(std::make_pair("str", _("Strength %+.1f"))); - } - - { - Attribute a; - a.id = 17; - a.name = _("Agility"); - a.description = ""; - a.modifiable = true; - a.scope = "character"; - a.playerInfoId = -1; - - attributes[a.id] = a; - tags.insert(std::make_pair("agi", _("Agility %+.1f"))); - } - - { - Attribute a; - a.id = 18; - a.name = _("Dexterity"); - a.description = ""; - a.modifiable = true; - a.scope = "character"; - a.playerInfoId = -1; - - attributes[a.id] = a; - tags.insert(std::make_pair("dex", _("Dexterity %+.1f"))); - } - - { - Attribute a; - a.id = 19; - a.name = _("Vitality"); - a.description = ""; - a.modifiable = true; - a.scope = "character"; - a.playerInfoId = -1; - - attributes[a.id] = a; - tags.insert(std::make_pair("vit", _("Vitality %+.1f"))); - } - - { - Attribute a; - a.id = 20; - a.name = _("Intelligence"); - a.description = ""; - a.modifiable = true; - a.scope = "character"; - a.playerInfoId = -1; - - attributes[a.id] = a; - tags.insert(std::make_pair("int", _("Intelligence %+.1f"))); - } - - { - Attribute a; - a.id = 21; - a.name = _("Willpower"); - a.description = ""; - a.modifiable = true; - a.scope = "character"; - a.playerInfoId = -1; - - attributes[a.id] = a; - tags.insert(std::make_pair("wil", _("Willpower %+.1f"))); - } - } - - void load() - { - logger->log("Initializing attributes database..."); - - XML::Document doc(DEFAULT_ATTRIBUTESDB_FILE); - xmlNodePtr rootNode = doc.rootNode(); - - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "attributes")) - { - logger->log("Attributes: Error while loading " - DEFAULT_ATTRIBUTESDB_FILE ". Using Built-ins."); - loadBuiltins(); - fillLabels(); - return; - } - - for_each_xml_child_node(node, rootNode) - { - if (xmlStrEqual(node->name, BAD_CAST "attribute")) - { - int id = XML::getProperty(node, "id", 0); - - if (!id) - { - logger->log("Attributes: Invalid or missing stat ID in " - DEFAULT_ATTRIBUTESDB_FILE "!"); - continue; - } - else if (attributes.find(id) != attributes.end()) - { - logger->log("Attributes: Redefinition of stat ID %d", id); - } - - std::string name = XML::getProperty(node, "name", ""); - - if (name.empty()) - { - logger->log("Attributes: Invalid or missing stat name in " - DEFAULT_ATTRIBUTESDB_FILE "!"); - continue; - } - - // Create the attribute. - Attribute a; - a.id = id; - a.name = name; - a.description = XML::getProperty(node, "desc", ""); - a.modifiable = XML::getBoolProperty(node, "modifiable", false); - a.scope = XML::getProperty(node, "scope", "none"); - a.playerInfoId = getPlayerInfoIdFromAttrType( - XML::getProperty(node, "player-info", "")); - - attributes[id] = a; - - unsigned int count = 0; - for_each_xml_child_node(effectNode, node) - { - if (!xmlStrEqual(effectNode->name, BAD_CAST "modifier")) - continue; - ++count; - std::string tag = XML::getProperty(effectNode, "tag", ""); - if (tag.empty()) - { - if (name.empty()) - { - logger->log("Attribute modifier in attribute %u:%s: " - "Empty name definition " - "on empty tag definition, skipping.", - a.id, a.name.c_str()); - --count; - continue; - } - tag = name.substr(0, name.size() > 3 ? 3 : name.size()); - tag = toLower(tag) + toString(count); - } - - std::string effect = XML::getProperty(effectNode, "effect", ""); - if (effect.empty()) - { - if (name.empty()) - { - logger->log("Attribute modifier in attribute %u:%s: " - "Empty name definition " - "on empty effect definition, skipping.", - a.id, a.name.c_str()); - --count; - continue; - } - else - effect = name + " %+f"; - } - tags.insert(std::make_pair(tag, effect)); - } - logger->log("Found %d tags for attribute %d.", count, id); - - }// End attribute - else if (xmlStrEqual(node->name, BAD_CAST "points")) - { - creationPoints = XML::getProperty(node, "start",DEFAULT_POINTS); - attributeMinimum = XML::getProperty(node, "minimum", - DEFAULT_MIN_PTS); - attributeMaximum = XML::getProperty(node, "maximum", - DEFAULT_MAX_PTS); - logger->log("Loaded points: start: %i, min: %i, max: %i.", - creationPoints, attributeMinimum, attributeMaximum); - } - else - { - continue; - } - } - logger->log("Found %d tags for %d attributes.", int(tags.size()), - int(attributes.size())); - - fillLabels(); - - // Sanity checks on starting points - float modifiableAttributeCount = (float) attributeLabels.size(); - float averageValue = ((float) creationPoints) / modifiableAttributeCount; - if (averageValue > attributeMaximum || averageValue < attributeMinimum - || creationPoints < 1) - { - logger->log("Attributes: Character's point values make " - "the character's creation impossible. " - "Switch back to defaults."); - creationPoints = DEFAULT_POINTS; - attributeMinimum = DEFAULT_MIN_PTS; - attributeMaximum = DEFAULT_MAX_PTS; - } - } - - void unload() - { - attributes.clear(); - } - - void informItemDB() - { - std::list dbStats; - - TagMap::const_iterator it, it_end; - for (it = tags.begin(), it_end = tags.end(); it != it_end; ++it) - dbStats.push_back(ItemStat(it->first, - it->second)); - - setStatsList(dbStats); - } - - void informStatusWindow() - { - AttributeMap::const_iterator it, it_end; - for (it = attributes.begin(), it_end = attributes.end(); it != it_end; - it++) - { - if (it->second.playerInfoId == -1 && - (it->second.scope == "character" || it->second.scope == "being")) - { - statusWindow->addAttribute(it->second.id, - it->second.name, - it->second.modifiable, - it->second.description); - } - } - } - -} // namespace Attributes -} // namespace ManaServ diff --git a/src/net/manaserv/attributes.h b/src/net/manaserv/attributes.h deleted file mode 100644 index e004d16c..00000000 --- a/src/net/manaserv/attributes.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * The Mana Client - * Copyright (C) 2010-2012 The Mana Developers - * - * This file is part of The Mana 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 . - */ - -#ifndef NET_MANASERV_ATTRIBUTES_H -#define NET_MANASERV_ATTRIBUTES_H - -#include -#include - -namespace ManaServ { -namespace Attributes { - - void load(); - - void unload(); - - void informItemDB(); - - void informStatusWindow(); - - /** - * Returns the list of base attribute labels. - */ - std::vector& getLabels(); - - /** - * Give back the corresponding playerinfo Id from the attribute id - * defined in the xml file. - */ - int getPlayerInfoIdFromAttrId(int attrId); - - /** - * Give the attribute points given to a character - * at its creation. - */ - unsigned int getCreationPoints(); - - /** - * Give the minimum attribute point possible - * at character's creation. - */ - unsigned int getAttributeMinimum(); - - /** - * Give the maximum attribute point possible - * at character's creation. - */ - unsigned int getAttributeMaximum(); - -} // namespace Attributes -} // namespace ManaServ - -#endif // NET_MANASERV_ATTRIBUTES_H diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp index e809bfac..ece8e108 100644 --- a/src/net/manaserv/charhandler.cpp +++ b/src/net/manaserv/charhandler.cpp @@ -1,7 +1,7 @@ /* * The Mana Client * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2012 The Mana Developers + * Copyright (C) 2009-2013 The Mana Developers * * This file is part of The Mana Client. * @@ -39,8 +39,8 @@ #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" #include "net/manaserv/manaserv_protocol.h" -#include "net/manaserv/attributes.h" +#include "resources/attributes.h" #include "resources/hairdb.h" #include "utils/dtor.h" diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp index d1fa41fe..c6b2af18 100644 --- a/src/net/manaserv/generalhandler.cpp +++ b/src/net/manaserv/generalhandler.cpp @@ -1,7 +1,7 @@ /* * The Mana Client * Copyright (C) 2009 The Mana World Development Team - * Copyright (C) 2009-2012 The Mana Developers + * Copyright (C) 2009-2013 The Mana Developers * * This file is part of The Mana Client. * @@ -47,9 +47,10 @@ #include "net/manaserv/partyhandler.h" #include "net/manaserv/playerhandler.h" #include "net/manaserv/specialhandler.h" -#include "net/manaserv/attributes.h" #include "net/manaserv/tradehandler.h" +#include "resources/attributes.h" + #include "utils/gettext.h" #include diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp index 484e551a..c1f78f67 100644 --- a/src/net/manaserv/playerhandler.cpp +++ b/src/net/manaserv/playerhandler.cpp @@ -1,7 +1,7 @@ /* * The Mana Client * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2012 The Mana Developers + * Copyright (C) 2009-2013 The Mana Developers * * This file is part of The Mana Client. * @@ -20,7 +20,6 @@ */ #include "net/manaserv/playerhandler.h" -#include "net/manaserv/beinghandler.h" #include "client.h" #include "effectmanager.h" @@ -43,7 +42,8 @@ #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" #include "net/manaserv/manaserv_protocol.h" -#include "net/manaserv/attributes.h" + +#include "resources/attributes.h" /** * Max. distance in tiles we are willing to scroll after a teleport; diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index ce193821..cc242951 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -38,6 +38,7 @@ #include "net/tmwa/network.h" #include "net/tmwa/protocol.h" +#include "resources/attributes.h" #include "resources/hairdb.h" #include "utils/dtor.h" @@ -278,7 +279,10 @@ void CharServerHandler::setCharCreateDialog(CharCreateDialog *window) const Token &token = static_cast(Net::getLoginHandler())->getToken(); - mCharCreateDialog->setAttributes(attributes, 30, 1, 9); + mCharCreateDialog->setAttributes(attributes, + Attributes::getCreationPoints(), + Attributes::getAttributeMinimum(), + Attributes::getAttributeMaximum()); mCharCreateDialog->setFixedGender(true, token.sex); } diff --git a/src/net/tmwa/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp index 6c2bcddb..0ce16691 100644 --- a/src/net/tmwa/generalhandler.cpp +++ b/src/net/tmwa/generalhandler.cpp @@ -1,7 +1,7 @@ /* * The Mana Client * Copyright (C) 2009 The Mana World Development Team - * Copyright (C) 2009-2012 The Mana Developers + * Copyright (C) 2009-2013 The Mana Developers * * This file is part of The Mana Client. * @@ -57,11 +57,11 @@ #include "net/tmwa/gui/guildtab.h" #include "net/tmwa/gui/partytab.h" +#include "resources/attributes.h" #include "resources/itemdb.h" #include "utils/gettext.h" -#include #include extern Net::GeneralHandler *generalHandler; @@ -108,6 +108,7 @@ GeneralHandler::GeneralHandler(): setStatsList(stats); + listen(Event::ClientChannel); listen(Event::GameChannel); } @@ -185,12 +186,17 @@ void GeneralHandler::reload() static_cast(mLoginHandler.get())->clearWorlds(); static_cast(mCharHandler.get())->setCharCreateDialog(0); static_cast(mCharHandler.get())->setCharSelectDialog(0); + + Attributes::unload(); + Attributes::load(); } void GeneralHandler::unload() { if (mNetwork) mNetwork->clearHandlers(); + + Attributes::unload(); } void GeneralHandler::flushNetwork() @@ -220,7 +226,14 @@ void GeneralHandler::clearHandlers() void GeneralHandler::event(Event::Channel channel, const Event &event) { - if (channel == Event::GameChannel) + if (channel == Event::ClientChannel) + { + if (event.getType() == Event::LoadingDatabases) + { + Attributes::load(); + } + } + else if (channel == Event::GameChannel) { if (event.getType() == Event::GuiWindowsLoaded) { diff --git a/src/resources/attributes.cpp b/src/resources/attributes.cpp new file mode 100644 index 00000000..c4c67fba --- /dev/null +++ b/src/resources/attributes.cpp @@ -0,0 +1,405 @@ +/* + * The Mana Client + * Copyright (C) 2010-2013 The Mana Developers + * + * This file is part of The Mana 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 . + */ + +#include "resources/attributes.h" + +#include "log.h" +#include "playerinfo.h" + +#include "gui/statuswindow.h" + +#include "resources/itemdb.h" + +#include "utils/gettext.h" +#include "utils/stringutils.h" +#include "utils/xml.h" + +#include +#include + +#define DEFAULT_ATTRIBUTESDB_FILE "attributes.xml" +#define DEFAULT_POINTS 30 +#define DEFAULT_MIN_PTS 1 +#define DEFAULT_MAX_PTS 9 + +namespace Attributes { + + typedef struct + { + unsigned int id; + std::string name; + std::string description; + /** Whether the attribute value can be modified by the player */ + bool modifiable; + /**< Attribute scope. */ + std::string scope; + /** The playerInfo core Id the attribute is linked with or -1 if not */ + int playerInfoId; + } Attribute; + + /** Map for attributes. */ + typedef std::map AttributeMap; + static AttributeMap attributes; + + /** tags = effects on attributes. */ + typedef std::map< std::string, std::string > TagMap; + static TagMap tags; + + /** List of modifiable attribute names used at character's creation. */ + static std::vector attributeLabels; + + /** Characters creation points. */ + static unsigned int creationPoints = DEFAULT_POINTS; + static unsigned int attributeMinimum = DEFAULT_MIN_PTS; + static unsigned int attributeMaximum = DEFAULT_MAX_PTS; + + unsigned int getCreationPoints() + { + return creationPoints; + } + + unsigned int getAttributeMinimum() + { + return attributeMinimum; + } + + unsigned int getAttributeMaximum() + { + return attributeMaximum; + } + + std::vector& getLabels() + { + return attributeLabels; + } + + /** + * Fills the list of base attribute labels. + */ + static void fillLabels() + { + // Fill up the modifiable attribute label list. + attributeLabels.clear(); + AttributeMap::const_iterator it, it_end; + for (it = attributes.begin(), it_end = attributes.end(); it != it_end; + it++) + { + if (it->second.modifiable && + (it->second.scope == "character" || it->second.scope == "being")) + attributeLabels.push_back(it->second.name + ":"); + } + } + + /** + * Fills the list of base attribute labels. + */ + static int getPlayerInfoIdFromAttrType(std::string attrType) + { + toLower(attrType); + if (attrType == "level") + return ::LEVEL; + else if (attrType == "hp") + return ::HP; + else if (attrType == "max-hp") + return ::MAX_HP; + else if (attrType == "mp") + return ::MP; + else if (attrType == "max-mp") + return ::MAX_MP; + else if (attrType == "exp") + return ::EXP; + else if (attrType == "exp-needed") + return ::EXP_NEEDED; + else if (attrType == "money") + return ::MONEY; + else if (attrType == "total-weight") + return ::TOTAL_WEIGHT; + else if (attrType == "max-weight") + return ::MAX_WEIGHT; + else if (attrType == "skill-points") + return ::SKILL_POINTS; + else if (attrType == "char-points") + return ::CHAR_POINTS; + else if (attrType == "corr-points") + return ::CORR_POINTS; + else if (attrType == "none") + return -2; // Used to hide the attribute display. + + return -1; // Not linked to a playerinfo stat. + } + + int getPlayerInfoIdFromAttrId(int attrId) + { + AttributeMap::const_iterator it = attributes.find(attrId); + + if (it != attributes.end()) + { + return it->second.playerInfoId; + } + + return -1; + } + + static void loadBuiltins() + { + { + Attribute a; + a.id = 16; + a.name = _("Strength"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("str", _("Strength %+.1f"))); + } + + { + Attribute a; + a.id = 17; + a.name = _("Agility"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("agi", _("Agility %+.1f"))); + } + + { + Attribute a; + a.id = 18; + a.name = _("Dexterity"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("dex", _("Dexterity %+.1f"))); + } + + { + Attribute a; + a.id = 19; + a.name = _("Vitality"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("vit", _("Vitality %+.1f"))); + } + + { + Attribute a; + a.id = 20; + a.name = _("Intelligence"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("int", _("Intelligence %+.1f"))); + } + + { + Attribute a; + a.id = 21; + a.name = _("Willpower"); + a.description = ""; + a.modifiable = true; + a.scope = "character"; + a.playerInfoId = -1; + + attributes[a.id] = a; + tags.insert(std::make_pair("wil", _("Willpower %+.1f"))); + } + } + + void load() + { + logger->log("Initializing attributes database..."); + + XML::Document doc(DEFAULT_ATTRIBUTESDB_FILE); + xmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "attributes")) + { + logger->log("Attributes: Error while loading " + DEFAULT_ATTRIBUTESDB_FILE ". Using Built-ins."); + loadBuiltins(); + fillLabels(); + return; + } + + for_each_xml_child_node(node, rootNode) + { + if (xmlStrEqual(node->name, BAD_CAST "attribute")) + { + int id = XML::getProperty(node, "id", 0); + + if (!id) + { + logger->log("Attributes: Invalid or missing stat ID in " + DEFAULT_ATTRIBUTESDB_FILE "!"); + continue; + } + else if (attributes.find(id) != attributes.end()) + { + logger->log("Attributes: Redefinition of stat ID %d", id); + } + + std::string name = XML::getProperty(node, "name", ""); + + if (name.empty()) + { + logger->log("Attributes: Invalid or missing stat name in " + DEFAULT_ATTRIBUTESDB_FILE "!"); + continue; + } + + // Create the attribute. + Attribute a; + a.id = id; + a.name = name; + a.description = XML::getProperty(node, "desc", ""); + a.modifiable = XML::getBoolProperty(node, "modifiable", false); + a.scope = XML::getProperty(node, "scope", "none"); + a.playerInfoId = getPlayerInfoIdFromAttrType( + XML::getProperty(node, "player-info", "")); + + attributes[id] = a; + + unsigned int count = 0; + for_each_xml_child_node(effectNode, node) + { + if (!xmlStrEqual(effectNode->name, BAD_CAST "modifier")) + continue; + ++count; + std::string tag = XML::getProperty(effectNode, "tag", ""); + if (tag.empty()) + { + if (name.empty()) + { + logger->log("Attribute modifier in attribute %u:%s: " + "Empty name definition " + "on empty tag definition, skipping.", + a.id, a.name.c_str()); + --count; + continue; + } + tag = name.substr(0, name.size() > 3 ? 3 : name.size()); + tag = toLower(tag) + toString(count); + } + + std::string effect = XML::getProperty(effectNode, "effect", ""); + if (effect.empty()) + { + if (name.empty()) + { + logger->log("Attribute modifier in attribute %u:%s: " + "Empty name definition " + "on empty effect definition, skipping.", + a.id, a.name.c_str()); + --count; + continue; + } + else + effect = name + " %+f"; + } + tags.insert(std::make_pair(tag, effect)); + } + logger->log("Found %d tags for attribute %d.", count, id); + + }// End attribute + else if (xmlStrEqual(node->name, BAD_CAST "points")) + { + creationPoints = XML::getProperty(node, "start",DEFAULT_POINTS); + attributeMinimum = XML::getProperty(node, "minimum", + DEFAULT_MIN_PTS); + attributeMaximum = XML::getProperty(node, "maximum", + DEFAULT_MAX_PTS); + logger->log("Loaded points: start: %i, min: %i, max: %i.", + creationPoints, attributeMinimum, attributeMaximum); + } + else + { + continue; + } + } + logger->log("Found %d tags for %d attributes.", int(tags.size()), + int(attributes.size())); + + fillLabels(); + + // Sanity checks on starting points + float modifiableAttributeCount = (float) attributeLabels.size(); + float averageValue = ((float) creationPoints) / modifiableAttributeCount; + if (averageValue > attributeMaximum || averageValue < attributeMinimum + || creationPoints < 1) + { + logger->log("Attributes: Character's point values make " + "the character's creation impossible. " + "Switch back to defaults."); + creationPoints = DEFAULT_POINTS; + attributeMinimum = DEFAULT_MIN_PTS; + attributeMaximum = DEFAULT_MAX_PTS; + } + } + + void unload() + { + attributes.clear(); + } + + void informItemDB() + { + std::list dbStats; + + TagMap::const_iterator it, it_end; + for (it = tags.begin(), it_end = tags.end(); it != it_end; ++it) + dbStats.push_back(ItemStat(it->first, it->second)); + + setStatsList(dbStats); + } + + void informStatusWindow() + { + AttributeMap::const_iterator it, it_end; + for (it = attributes.begin(), it_end = attributes.end(); it != it_end; + it++) + { + if (it->second.playerInfoId == -1 && + (it->second.scope == "character" || it->second.scope == "being")) + { + statusWindow->addAttribute(it->second.id, + it->second.name, + it->second.modifiable, + it->second.description); + } + } + } + +} // namespace Attributes diff --git a/src/resources/attributes.h b/src/resources/attributes.h new file mode 100644 index 00000000..7124ba94 --- /dev/null +++ b/src/resources/attributes.h @@ -0,0 +1,68 @@ +/* + * The Mana Client + * Copyright (C) 2010-2013 The Mana Developers + * + * This file is part of The Mana 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 . + */ + +#ifndef RESOURCES_ATTRIBUTES_H +#define RESOURCES_ATTRIBUTES_H + +#include +#include + +namespace Attributes { + + void load(); + + void unload(); + + void informItemDB(); + + void informStatusWindow(); + + /** + * Returns the list of base attribute labels. + */ + std::vector& getLabels(); + + /** + * Give back the corresponding playerinfo Id from the attribute id + * defined in the xml file. + */ + int getPlayerInfoIdFromAttrId(int attrId); + + /** + * Give the attribute points given to a character + * at its creation. + */ + unsigned int getCreationPoints(); + + /** + * Give the minimum attribute point possible + * at character's creation. + */ + unsigned int getAttributeMinimum(); + + /** + * Give the maximum attribute point possible + * at character's creation. + */ + unsigned int getAttributeMaximum(); + +} // namespace Attributes + +#endif // RESOURCES_ATTRIBUTES_H -- cgit v1.2.3-70-g09d2