diff options
author | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2012-01-18 19:20:34 +0100 |
---|---|---|
committer | Yohann Ferreira <yohann_dot_ferreira_at_orange_dot_efer> | 2012-02-02 15:31:41 +0100 |
commit | f5de9ae444f1bca1f6ba6969214e9a8cacb15f68 (patch) | |
tree | f9b9c699c52d279cdc4d93b09f48dd3b24403f5b /src | |
parent | 7cc504d993fa948ae2e10848993f4552b2d6daaa (diff) | |
download | mana-f5de9ae444f1bca1f6ba6969214e9a8cacb15f68.tar.gz mana-f5de9ae444f1bca1f6ba6969214e9a8cacb15f68.tar.bz2 mana-f5de9ae444f1bca1f6ba6969214e9a8cacb15f68.tar.xz mana-f5de9ae444f1bca1f6ba6969214e9a8cacb15f68.zip |
Fix to the hair colors and styles handling.
- I made the charCreatedialog handle a possible
max permitted color Id and a minimum hair style id for tA.
- Added a foundation to later load the styles and colors from
the same file, to handle the Mana-issue #224 for manaserv.
- Support for non-contiguous hair color and style ids
has also been added.
- I also replaced the < and > arrow signs with images.
Reviewed-by: Ben Longbons, Thorbjørn Lindeijer
Diffstat (limited to 'src')
-rw-r--r-- | src/being.cpp | 15 | ||||
-rw-r--r-- | src/being.h | 10 | ||||
-rw-r--r-- | src/client.cpp | 8 | ||||
-rw-r--r-- | src/gui/charcreatedialog.cpp | 73 | ||||
-rw-r--r-- | src/gui/charcreatedialog.h | 16 | ||||
-rw-r--r-- | src/net/charhandler.h | 12 | ||||
-rw-r--r-- | src/net/manaserv/beinghandler.cpp | 6 | ||||
-rw-r--r-- | src/net/manaserv/charhandler.cpp | 2 | ||||
-rw-r--r-- | src/net/manaserv/charhandler.h | 8 | ||||
-rw-r--r-- | src/net/tmwa/beinghandler.cpp | 9 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.cpp | 3 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.h | 10 | ||||
-rw-r--r-- | src/resources/hairdb.cpp | 146 | ||||
-rw-r--r-- | src/resources/hairdb.h | 66 | ||||
-rw-r--r-- | src/resources/itemdb.cpp | 11 |
15 files changed, 269 insertions, 126 deletions
diff --git a/src/being.cpp b/src/being.cpp index b77dfd7d..62081bb4 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -66,8 +66,6 @@ #include <cassert> #include <cmath> -int Being::mNumberOfHairstyles = 1; - Being::Being(int id, Type type, int subtype, Map *map): ActorSprite(id), mInfo(BeingInfo::Unknown), @@ -1122,19 +1120,6 @@ int Being::getNumberOfLayers() const return CompoundSprite::getNumberOfLayers(); } -void Being::load() -{ - // Hairstyles are encoded as negative numbers. Count how far negative - // we can go. - int hairstyles = 1; - - while (itemDb->get(-hairstyles).getSprite(GENDER_MALE) != - paths.getStringValue("spriteErrorFile")) - hairstyles++; - - mNumberOfHairstyles = hairstyles; -} - void Being::updateName() { if (mShowName) diff --git a/src/being.h b/src/being.h index 8d2ae1b0..6464090c 100644 --- a/src/being.h +++ b/src/being.h @@ -269,12 +269,6 @@ class Being : public ActorSprite, public EventListener void setSpriteColor(unsigned int slot, const std::string &color = ""); /** - * Get the number of hairstyles implemented - */ - static int getNumOfHairstyles() - { return mNumberOfHairstyles; } - - /** * Get the number of layers used to draw the being */ int getNumberOfLayers() const; @@ -400,8 +394,6 @@ class Being : public ActorSprite, public EventListener */ const Path &getPath() const { return mPath; } - static void load(); - void flashName(int time); int getDamageTaken() const @@ -500,8 +492,6 @@ class Being : public ActorSprite, public EventListener /** Engine-related infos about weapon. */ const ItemInfo *mEquippedWeapon; - static int mNumberOfHairstyles; /** Number of hair styles in use */ - Path mPath; std::string mSpeech; Text *mText; diff --git a/src/client.cpp b/src/client.cpp index 1fa36d48..d50257f2 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -119,7 +119,8 @@ KeyboardConfig keyboard; UserPalette *userPalette; Graphics *graphics; -ItemDB *itemDb; +ItemDB *itemDb; /**< Items info database */ +HairDB hairDB; /**< Hair styles and colors info database */ Sound sound; @@ -452,7 +453,7 @@ Client::~Client() SDL_RemoveTimer(mSecondsCounterId); // Unload XML databases - HairDB::unload(); + hairDB.unload(); EmoteDB::unload(); delete itemDb; MonsterDB::unload(); @@ -761,7 +762,7 @@ int Client::exec() Event::trigger(Event::ClientChannel, Event::LoadingDatabases); // Load XML databases - HairDB::load(); + hairDB.load(); switch (Net::getNetworkType()) { case ServerInfo::TMWATHENA: @@ -786,7 +787,6 @@ int Client::exec() STATE_CHOOSE_SERVER); break; } - Being::load(); // Hairstyles MonsterDB::load(); SpecialDB::load(); NPCDB::load(); diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp index 99a8800a..84bce434 100644 --- a/src/gui/charcreatedialog.cpp +++ b/src/gui/charcreatedialog.cpp @@ -57,23 +57,30 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): mPlayer = new Being(0, ActorSprite::PLAYER, 0, NULL); mPlayer->setGender(GENDER_MALE); - int numberOfHairColors = HairDB::size(); + mHairStylesIds = hairDB.getHairStyleIds( + Net::getCharHandler()->getCharCreateMaxHairStyleId()); + mHairStyleId = rand() * mHairStylesIds.size() / RAND_MAX; + + mHairColorsIds = hairDB.getHairColorIds( + Net::getCharHandler()->getCharCreateMaxHairColorId()); + mHairColorId = rand() * mHairColorsIds.size() / RAND_MAX; - mHairStyle = rand() % mPlayer->getNumOfHairstyles(); - mHairColor = rand() % numberOfHairColors; updateHair(); mNameField = new TextField(""); mNameLabel = new Label(_("Name:")); - // TRANSLATORS: This is an arrow symbol used to denote 'next'. - // You may change this symbol if your language uses another. - mNextHairColorButton = new Button(_(">"), "nextcolor", this); - // TRANSLATORS: This is an arrow symbol used to denote 'previous'. - // You may change this symbol if your language uses another. - mPrevHairColorButton = new Button(_("<"), "prevcolor", this); + + mNextHairColorButton = new Button("", "nextcolor", this); + mPrevHairColorButton = new Button("", "prevcolor", this); + mPrevHairColorButton->setButtonIcon("tab_arrows_left.png"); + mNextHairColorButton->setButtonIcon("tab_arrows_right.png"); + mHairColorLabel = new Label(_("Hair color:")); - mNextHairStyleButton = new Button(_(">"), "nextstyle", this); - mPrevHairStyleButton = new Button(_("<"), "prevstyle", this); + mNextHairStyleButton = new Button("", "nextstyle", this); + mPrevHairStyleButton = new Button("", "prevstyle", this); + mPrevHairStyleButton->setButtonIcon("tab_arrows_left.png"); + mNextHairStyleButton->setButtonIcon("tab_arrows_right.png"); + mHairStyleLabel = new Label(_("Hair style:")); mCreateButton = new Button(_("Create"), "create", this); mCancelButton = new Button(_("Cancel"), "cancel", this); @@ -173,10 +180,14 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) if (Net::getNetworkType() == ServerInfo::MANASERV) ++characterSlot; + // Should avoid the most common crash case + int hairStyle = mHairStylesIds.empty() ? + 0 : mHairStylesIds.at(mHairStyleId); + int hairColor = mHairColorsIds.empty() ? + 0 : mHairColorsIds.at(mHairColorId); Net::getCharHandler()->newCharacter(getName(), characterSlot, mFemale->isSelected(), - mHairStyle, - mHairColor, atts); + hairStyle, hairColor, atts); } else { @@ -189,22 +200,22 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) scheduleDelete(); else if (event.getId() == "nextcolor") { - mHairColor++; + ++mHairColorId; updateHair(); } else if (event.getId() == "prevcolor") { - mHairColor--; + --mHairColorId; updateHair(); } else if (event.getId() == "nextstyle") { - mHairStyle++; + ++mHairStyleId; updateHair(); } else if (event.getId() == "prevstyle") { - mHairStyle--; + --mHairStyleId; updateHair(); } else if (event.getId() == "statslider") @@ -214,13 +225,9 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) else if (event.getId() == "gender") { if (mMale->isSelected()) - { mPlayer->setGender(GENDER_MALE); - } else - { mPlayer->setGender(GENDER_FEMALE); - } } } @@ -359,14 +366,24 @@ void CharCreateDialog::setFixedGender(bool fixed, Gender gender) void CharCreateDialog::updateHair() { - mHairStyle %= Being::getNumOfHairstyles(); - if (mHairStyle < 0) - mHairStyle += Being::getNumOfHairstyles(); + if (mHairColorId < 0) + mHairColorId = mHairColorsIds.size() - 1; + + if (mHairColorId > (int)mHairColorsIds.size() - 1) + mHairColorId = 0; + + if (mHairStyleId < 0) + mHairStyleId = mHairStylesIds.size() - 1; + + if (mHairStyleId > (int)mHairStylesIds.size() - 1) + mHairStyleId = 0; - mHairColor %= HairDB::size(); - if (mHairColor < 0) - mHairColor += HairDB::size(); + // Should avoid the most common crash case + int hairStyle = mHairStylesIds.empty() ? + 0 : mHairStylesIds.at(mHairStyleId); + int hairColor = mHairColorsIds.empty() ? + 0 : mHairColorsIds.at(mHairColorId); mPlayer->setSprite(Net::getCharHandler()->hairSprite(), - mHairStyle * -1, HairDB::get(mHairColor)); + hairStyle * -1, hairDB.getHairColor(hairColor)); } diff --git a/src/gui/charcreatedialog.h b/src/gui/charcreatedialog.h index 42a57ab5..7548bbff 100644 --- a/src/gui/charcreatedialog.h +++ b/src/gui/charcreatedialog.h @@ -34,6 +34,7 @@ #include <string> #include <vector> +class Button; class LocalPlayer; class PlayerBox; @@ -83,11 +84,11 @@ class CharCreateDialog : public Window, public gcn::ActionListener gcn::TextField *mNameField; gcn::Label *mNameLabel; - gcn::Button *mNextHairColorButton; - gcn::Button *mPrevHairColorButton; + Button *mNextHairColorButton; + Button *mPrevHairColorButton; gcn::Label *mHairColorLabel; - gcn::Button *mNextHairStyleButton; - gcn::Button *mPrevHairStyleButton; + Button *mNextHairStyleButton; + Button *mPrevHairStyleButton; gcn::Label *mHairStyleLabel; gcn::RadioButton *mMale; @@ -107,8 +108,11 @@ class CharCreateDialog : public Window, public gcn::ActionListener Being *mPlayer; PlayerBox *mPlayerBox; - int mHairStyle; - int mHairColor; + // A vector containing the available hair color or style ids + std::vector<int> mHairColorsIds; + std::vector<int> mHairStylesIds; + int mHairStyleId; + int mHairColorId; int mSlot; }; diff --git a/src/net/charhandler.h b/src/net/charhandler.h index 60c332f9..1835ceb9 100644 --- a/src/net/charhandler.h +++ b/src/net/charhandler.h @@ -83,6 +83,18 @@ class CharHandler virtual unsigned int maxSprite() const = 0; + /** + * Returns the max permitted hair color Id at character creation time, + * or 0 if no limit should be applied. + */ + virtual int getCharCreateMaxHairColorId() const = 0; + + /** + * Returns the max permitted hair style Id at character creation time, + * or 0 if no limit should be applied. + */ + virtual int getCharCreateMaxHairStyleId() const = 0; + protected: CharHandler(): mSelectedCharacter(0), diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index be4daa49..fb3a3644 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -144,7 +144,8 @@ void BeingHandler::handleBeingEnterMessage(Net::MessageIn &msg) being->setName(name); } int hs = msg.readInt8(), hc = msg.readInt8(); - being->setSprite(SPRITE_LAYER_HAIR, hs * -1, HairDB::get(hc)); + being->setSprite(SPRITE_LAYER_HAIR, hs * -1, + hairDB.getHairColor(hc)); being->setGender(msg.readInt8() == ManaServ::GENDER_MALE ? ::GENDER_MALE : ::GENDER_FEMALE); handleLooks(being, msg); @@ -334,7 +335,8 @@ void BeingHandler::handleBeingLooksChangeMessage(Net::MessageIn &msg) { int style = msg.readInt16(); int color = msg.readInt16(); - being->setSprite(SPRITE_LAYER_HAIR, style * -1, HairDB::get(color)); + being->setSprite(SPRITE_LAYER_HAIR, style * -1, + hairDB.getHairColor(color)); } } diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp index 4c4c9475..c05e9320 100644 --- a/src/net/manaserv/charhandler.cpp +++ b/src/net/manaserv/charhandler.cpp @@ -392,7 +392,7 @@ void CharHandler::updateCharacters() player->setName(info.name); player->setGender(info.gender); player->setSprite(SPRITE_LAYER_HAIR, info.hairStyle * -1, - HairDB::get(info.hairColor)); + hairDB.getHairColor(info.hairColor)); character->data.mAttributes[LEVEL] = info.level; character->data.mAttributes[CHAR_POINTS] = info.characterPoints; character->data.mAttributes[CORR_POINTS] = info.correctionPoints; diff --git a/src/net/manaserv/charhandler.h b/src/net/manaserv/charhandler.h index fef9627b..e3098c09 100644 --- a/src/net/manaserv/charhandler.h +++ b/src/net/manaserv/charhandler.h @@ -73,6 +73,14 @@ class CharHandler : public MessageHandler, public Net::CharHandler unsigned int maxSprite() const; + // No limitation on Manaserv + int getCharCreateMaxHairColorId() const + { return 0; } + + // No limitation on Manaserv + int getCharCreateMaxHairStyleId() const + { return 0; } + void clear(); private: diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index bcfb335f..c94e08df 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -245,7 +245,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) dstBeing->setGender((gender == 0) ? GENDER_FEMALE : GENDER_MALE); // Set these after the gender, as the sprites may be gender-specific - dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, HairDB::get(hairColor)); + dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, + hairDB.getHairColor(hairColor)); dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, headBottom); dstBeing->setSprite(SPRITE_TOPCLOTHES, headMid); dstBeing->setSprite(SPRITE_HAT, headTop); @@ -486,7 +487,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) dstBeing->setSprite(SPRITE_TOPCLOTHES, id); break; case 6: // eAthena LOOK_HAIR_COLOR - dstBeing->setSpriteColor(SPRITE_HAIR, HairDB::get(id)); + dstBeing->setSpriteColor(SPRITE_HAIR, + hairDB.getHairColor(id)); break; case 8: // eAthena LOOK_SHIELD dstBeing->setSprite(SPRITE_SHIELD, id); @@ -613,7 +615,8 @@ void BeingHandler::handleMessage(Net::MessageIn &msg) //dstBeing->setSprite(SPRITE_CAPE, cape); //dstBeing->setSprite(SPRITE_MISC1, misc1); //dstBeing->setSprite(SPRITE_MISC2, misc2); - dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, HairDB::get(hairColor)); + dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, + hairDB.getHairColor(hairColor)); if (msg.getId() == SMSG_PLAYER_MOVE) { diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index d794f2cf..8834798f 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -240,7 +240,8 @@ void CharServerHandler::readPlayerData(Net::MessageIn &msg, Net::Character *char tempPlayer->setSprite(SPRITE_SHIELD, msg.readInt16()); tempPlayer->setSprite(SPRITE_HAT, msg.readInt16()); // head option top tempPlayer->setSprite(SPRITE_TOPCLOTHES, msg.readInt16()); // head option mid - tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, HairDB::get(msg.readInt16())); + tempPlayer->setSprite(SPRITE_HAIR, hairStyle * -1, + hairDB.getHairColor(msg.readInt16())); tempPlayer->setSprite(SPRITE_MISC2, msg.readInt16()); tempPlayer->setName(msg.readString(24)); diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h index 7a7b6a67..31b2ba8e 100644 --- a/src/net/tmwa/charserverhandler.h +++ b/src/net/tmwa/charserverhandler.h @@ -69,6 +69,16 @@ class CharServerHandler : public MessageHandler, public Net::CharHandler unsigned int maxSprite() const; + // Must be < 12 at character creation time, but can be higher + // after that. + int getCharCreateMaxHairColorId() const + { return 11; } + + // Must be < 20 at character creation time, but can be higher + // after that. + int getCharCreateMaxHairStyleId() const + { return 19; } + void connect(); private: diff --git a/src/resources/hairdb.cpp b/src/resources/hairdb.cpp index abf64bd5..26ad966e 100644 --- a/src/resources/hairdb.cpp +++ b/src/resources/hairdb.cpp @@ -1,5 +1,5 @@ /* - * Color database + * Hair database * Copyright (C) 2008 Aethyra Development Team * Copyright (C) 2009-2012 The Mana Developers * @@ -25,58 +25,51 @@ #include "utils/xml.h" -#include <libxml/tree.h> +#include <assert.h> -namespace -{ - HairDB::Colors mColors; - bool mLoaded = false; - std::string mFail = "#ffffff"; -} +#define COLOR_WHITE "#ffffff" +#define HAIR_XML_FILE "hair.xml" void HairDB::load() { if (mLoaded) unload(); + // Default entry + mHairColors[0] = COLOR_WHITE; + XML::Document *doc = new XML::Document(HAIR_XML_FILE); xmlNodePtr root = doc->rootNode(); - bool hairXml = true; - if (!root || !xmlStrEqual(root->name, BAD_CAST "colors")) + if (!root || (!xmlStrEqual(root->name, BAD_CAST "colors") + && !xmlStrEqual(root->name, BAD_CAST "hair"))) { - logger->log("Trying to fall back on " COLORS_XML_FILE); - - hairXml = false; - + logger->log("HairDb: Failed to find any old <colors> or new " + "<hair> nodes."); delete doc; - doc = new XML::Document(COLORS_XML_FILE); - root = doc->rootNode(); - - if (!root || !xmlStrEqual(root->name, BAD_CAST "colors")) - { - logger->log("ColorDB: Failed to find any color files."); - mColors[0] = mFail; - mLoaded = true; - - delete doc; + mLoaded = true; + return; + } - return; - } + // Old colors.xml file style. The hair style will be declared + // in the items.xml file. + if (xmlStrEqual(root->name, BAD_CAST "colors")) + { + loadHairColorsNode(root); } - for_each_xml_child_node(node, root) + else if (xmlStrEqual(root->name, BAD_CAST "hair")) { - if (xmlStrEqual(node->name, BAD_CAST "color")) + // Loading new format: hair styles + colors. + for_each_xml_child_node(node, root) { - int id = XML::getProperty(node, "id", 0); - - if (mColors.find(id) != mColors.end()) + if (xmlStrEqual(node->name, BAD_CAST "styles")) { - logger->log("ColorDB: Redefinition of dye ID %d", id); + loadHairStylesNode(root); + } + else if (xmlStrEqual(node->name, BAD_CAST "colors")) + { + loadHairColorsNode(node); } - - mColors[id] = hairXml ? XML::getProperty(node, "value", "#FFFFFF") : - XML::getProperty(node, "dye", "#FFFFFF"); } } @@ -87,31 +80,88 @@ void HairDB::load() void HairDB::unload() { - logger->log("Unloading color database..."); + if (!mLoaded) + return; + + logger->log("Unloading hair style and color database..."); + + mHairColors.clear(); + mHairStyles.clear(); - mColors.clear(); mLoaded = false; } -std::string &HairDB::get(int id) +void HairDB::loadHairColorsNode(xmlNodePtr colorsNode) +{ + for_each_xml_child_node(node, colorsNode) + { + if (xmlStrEqual(node->name, BAD_CAST "color")) + { + int id = XML::getProperty(node, "id", 0); + + if (mHairColors.find(id) != mHairColors.end()) + logger->log("HairDb: Redefinition of color Id %d", id); + + mHairColors[id] = XML::getProperty(node, "value", COLOR_WHITE); + } + } +} + +void HairDB::loadHairStylesNode(xmlNodePtr stylesNode) +{ + // TODO: Add support of the races.xml file. +} + +void HairDB::addHairStyle(int id) +{ + // TODO: Adapt the sprite handling with hair styles separated from items. + // And remove that hack for negative ids. + if (id < 0) + id = -id; + + if (mHairStyles.find(id) != mHairStyles.end()) + logger->log("Warning: Redefinition of hairstyle id %i:", id); + + mHairStyles.insert(id); +} + +const std::string &HairDB::getHairColor(int id) { if (!mLoaded) load(); - ColorIterator i = mColors.find(id); + ColorConstIterator it = mHairColors.find(id); + if (it != mHairColors.end()) + return it->second; - if (i == mColors.end()) - { - logger->log("ColorDB: Error, unknown dye Id# %d", id); - return mFail; - } - else + logger->log("HairDb: Error, unknown color Id# %d", id); + return mHairColors[0]; +} + +std::vector<int> HairDB::getHairStyleIds(int maxId) const +{ + std::vector<int> hairStylesIds; + for (HairStylesConstIterator it = mHairStyles.begin(), + it_end = mHairStyles.end(); it != it_end; ++it) { - return i->second; + // Don't give ids higher than the requested maximum. + if (maxId > 0 && (*it) > maxId) + continue; + hairStylesIds.push_back(*it); } + return hairStylesIds; } -int HairDB::size() +std::vector<int> HairDB::getHairColorIds(int maxId) const { - return mColors.size(); + std::vector<int> hairColorsIds; + for (ColorConstIterator it = mHairColors.begin(), + it_end = mHairColors.end(); it != it_end; ++it) + { + // Don't give ids higher than the requested maximum. + if (maxId > 0 && it->first > maxId) + continue; + hairColorsIds.push_back(it->first); + } + return hairColorsIds; } diff --git a/src/resources/hairdb.h b/src/resources/hairdb.h index c29dbb83..700bd8b7 100644 --- a/src/resources/hairdb.h +++ b/src/resources/hairdb.h @@ -1,5 +1,5 @@ /* - * Color database + * Hair database * Copyright (C) 2008 Aethyra Development Team * Copyright (C) 2009-2012 The Mana Developers * @@ -22,16 +22,26 @@ #ifndef HAIR_MANAGER_H #define HAIR_MANAGER_H +#include "iteminfo.h" + #include <map> #include <string> /** * Hair information database. */ -namespace HairDB +class HairDB { + public: + HairDB(): + mLoaded(false) + {} + + ~HairDB() + { unload(); } + /** - * Loads the color data from <code>colors.xml</code>. + * Loads the color data from <code>hair.xml</code>. */ void load(); @@ -40,13 +50,55 @@ namespace HairDB */ void unload(); - std::string &get(int id); + const std::string &getHairColor(int id); + + /** + * Returns the available hair style ids + * @param maxId the max permited id. If not 0, the hairDb won't + * return ids > to the parameter. + */ + std::vector<int> getHairStyleIds(int maxId = 0) const; + + /** + * Returns the available hair color ids + * @param maxId the max permited id. If not 0, the hairDb won't + * return ids > to the parameter. + */ + std::vector<int> getHairColorIds(int maxId = 0) const; + + /** + * Add a hair style to the database. + * @see ItemDB for the itemInfo. + */ + void addHairStyle(int id); + + private: + /** + * Load the hair colors, contained in a <colors> node. + */ + void loadHairColorsNode(xmlNodePtr colorsNode); - int size(); + /** + * Load the hair styles, contained in a <styles> node. + * Used only by Manaserv. TMW-Athena is considering hairstyles as items. + * @see ItemDB + */ + void loadHairStylesNode(xmlNodePtr stylesNode); - // Hair Color DB + // Hair colors Db typedef std::map<int, std::string> Colors; typedef Colors::iterator ColorIterator; -} + typedef Colors::const_iterator ColorConstIterator; + Colors mHairColors; + + typedef std::set<int> HairStyles; + typedef HairStyles::iterator HairStylesIterator; + typedef HairStyles::const_iterator HairStylesConstIterator; + HairStyles mHairStyles; + + bool mLoaded; +}; + +extern HairDB hairDB; #endif diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index 977fd56f..95fdae2f 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -25,7 +25,7 @@ #include "net/net.h" -#include "resources/iteminfo.h" +#include "resources/hairdb.h" #include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -382,6 +382,10 @@ void TaItemDB::load() checkItemInfo(itemInfo); addItem(itemInfo); + + // Insert hairstyle id while letting the info as an item. + if (itemInfo->mType == ITEM_SPRITE_HAIR) + hairDB.addHairStyle(itemInfo->mId); } checkHairWeaponsRacesSpecialIds(); @@ -528,6 +532,11 @@ void ManaServItemDB::load() (const char*)effectChild->xmlChildrenNode->content); } } + + // FIXME: Load hair styles through the races.xml file + if (itemInfo->mType == ITEM_SPRITE_HAIR) + hairDB.addHairStyle(itemInfo->mId); + // Set Item Type based on subnodes info // TODO: Improve it once the itemTypes are loaded through xml itemInfo->mType = ITEM_UNUSABLE; |