diff options
-rw-r--r-- | src/being.cpp | 6 | ||||
-rw-r--r-- | src/being.h | 11 | ||||
-rw-r--r-- | src/gui/charcreatedialog.cpp | 43 | ||||
-rw-r--r-- | src/gui/charcreatedialog.h | 2 | ||||
-rw-r--r-- | src/gui/register.cpp | 2 | ||||
-rw-r--r-- | src/net/charhandler.h | 6 | ||||
-rw-r--r-- | src/net/logindata.h | 4 | ||||
-rw-r--r-- | src/net/manaserv/beinghandler.cpp | 10 | ||||
-rw-r--r-- | src/net/manaserv/charhandler.cpp | 4 | ||||
-rw-r--r-- | src/net/tmwa/beinghandler.cpp | 57 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.cpp | 20 | ||||
-rw-r--r-- | src/net/tmwa/charserverhandler.h | 1 | ||||
-rw-r--r-- | src/net/tmwa/gamehandler.cpp | 2 | ||||
-rw-r--r-- | src/net/tmwa/loginhandler.cpp | 4 | ||||
-rw-r--r-- | src/net/tmwa/protocol.h | 20 | ||||
-rw-r--r-- | src/net/tmwa/token.h | 2 | ||||
-rw-r--r-- | src/resources/hairdb.cpp | 8 | ||||
-rw-r--r-- | src/resources/hairdb.h | 2 | ||||
-rw-r--r-- | src/resources/itemdb.cpp | 16 | ||||
-rw-r--r-- | src/resources/iteminfo.cpp | 28 | ||||
-rw-r--r-- | src/resources/iteminfo.h | 7 | ||||
-rw-r--r-- | src/resources/settingsmanager.cpp | 16 |
22 files changed, 164 insertions, 107 deletions
diff --git a/src/being.cpp b/src/being.cpp index ad43ec52..46b499af 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -942,9 +942,9 @@ void Being::showName() { if (config.getBoolValue("showgender")) { - if (getGender() == GENDER_FEMALE) + if (getGender() == Gender::FEMALE) mDisplayName += " \u2640"; - else if (getGender() == GENDER_MALE) + else if (getGender() == Gender::MALE) mDisplayName += " \u2642"; } @@ -1041,7 +1041,7 @@ void Being::setSprite(unsigned int slot, int id, const std::string &color, } else { - std::string filename = itemDb->get(id).getSprite(mGender); + std::string filename = itemDb->get(id).getSprite(mGender, mSubType); AnimatedSprite *equipmentSprite = nullptr; if (!filename.empty()) diff --git a/src/being.h b/src/being.h index 411db3b7..32cfcf99 100644 --- a/src/being.h +++ b/src/being.h @@ -51,11 +51,12 @@ struct Position; class SpeechBubble; class Text; -enum Gender +enum class Gender { - GENDER_MALE = 0, - GENDER_FEMALE = 1, - GENDER_UNSPECIFIED = 2 + MALE = 0, + FEMALE = 1, + UNSPECIFIED = 2, + HIDDEN = 3 }; class Being : public ActorSprite, public EventListener @@ -505,7 +506,7 @@ class Being : public ActorSprite, public EventListener std::vector<int> mSpriteIDs; std::vector<std::string> mSpriteColors; - Gender mGender = GENDER_UNSPECIFIED; + Gender mGender = Gender::UNSPECIFIED; // Character guild information std::map<int, Guild*> mGuilds; diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp index 0d8a928e..fa1144b6 100644 --- a/src/gui/charcreatedialog.cpp +++ b/src/gui/charcreatedialog.cpp @@ -21,18 +21,13 @@ #include "gui/charcreatedialog.h" -#include "game.h" #include "localplayer.h" -#include "main.h" -#include "units.h" #include "gui/charselectdialog.h" -#include "gui/confirmdialog.h" #include "gui/okdialog.h" #include "gui/widgets/button.h" #include "gui/widgets/label.h" -#include "gui/widgets/layout.h" #include "gui/widgets/playerbox.h" #include "gui/widgets/radiobutton.h" #include "gui/widgets/slider.h" @@ -55,7 +50,7 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): mSlot(slot) { mPlayer = new Being(0, ActorSprite::PLAYER, 0, nullptr); - mPlayer->setGender(GENDER_MALE); + mPlayer->setGender(Gender::MALE); const std::vector<int> &items = CharDB::getDefaultItems(); for (size_t i = 0; i < items.size(); ++i) @@ -66,6 +61,7 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): mHairStyleId = rand() * mHairStylesIds.size() / RAND_MAX; mHairColorsIds = hairDB.getHairColorIds( + Net::getCharHandler()->getCharCreateMinHairColorId(), Net::getCharHandler()->getCharCreateMaxHairColorId()); mHairColorId = rand() * mHairColorsIds.size() / RAND_MAX; @@ -137,12 +133,21 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): add(mPlayerBox); add(mNameField); add(mNameLabel); - add(mNextHairColorButton); - add(mPrevHairColorButton); - add(mHairColorLabel); - add(mNextHairStyleButton); - add(mPrevHairStyleButton); - add(mHairStyleLabel); + + if (mHairColorsIds.size() > 1) + { + add(mNextHairColorButton); + add(mPrevHairColorButton); + add(mHairColorLabel); + } + + if (mHairStylesIds.size() > 1) + { + add(mNextHairStyleButton); + add(mPrevHairStyleButton); + add(mHairStyleLabel); + } + add(mAttributesLeft); add(mCreateButton); add(mCancelButton); @@ -226,9 +231,9 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) else if (event.getId() == "gender") { if (mMale->isSelected()) - mPlayer->setGender(GENDER_MALE); + mPlayer->setGender(Gender::MALE); else - mPlayer->setGender(GENDER_FEMALE); + mPlayer->setGender(Gender::FEMALE); } } @@ -366,9 +371,9 @@ void CharCreateDialog::setAttributes(const std::vector<std::string> &labels, center(); } -void CharCreateDialog::setFixedGender(bool fixed, Gender gender) +void CharCreateDialog::setDefaultGender(Gender gender) { - if (gender == GENDER_FEMALE) + if (gender == Gender::FEMALE) { mFemale->setSelected(true); mMale->setSelected(false); @@ -380,12 +385,6 @@ void CharCreateDialog::setFixedGender(bool fixed, Gender gender) } mPlayer->setGender(gender); - - if (fixed) - { - mMale->setEnabled(false); - mFemale->setEnabled(false); - } } void CharCreateDialog::updateHair() diff --git a/src/gui/charcreatedialog.h b/src/gui/charcreatedialog.h index 89706b54..46db6229 100644 --- a/src/gui/charcreatedialog.h +++ b/src/gui/charcreatedialog.h @@ -61,7 +61,7 @@ class CharCreateDialog : public Window, public gcn::ActionListener unsigned available, unsigned min, unsigned max); - void setFixedGender(bool fixed, Gender gender = GENDER_FEMALE); + void setDefaultGender(Gender gender); private: void updateSliders(); diff --git a/src/gui/register.cpp b/src/gui/register.cpp index 0e23777c..d4ebb59c 100644 --- a/src/gui/register.cpp +++ b/src/gui/register.cpp @@ -227,7 +227,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event) mLoginData->password = mPasswordField->getText(); if (mFemaleButton) mLoginData->gender = mFemaleButton->isSelected() ? - GENDER_FEMALE : GENDER_MALE; + Gender::FEMALE : Gender::MALE; if (mEmailField) mLoginData->email = mEmailField->getText(); mLoginData->registerLogin = true; diff --git a/src/net/charhandler.h b/src/net/charhandler.h index ee8f2298..cebf0b93 100644 --- a/src/net/charhandler.h +++ b/src/net/charhandler.h @@ -78,6 +78,12 @@ class CharHandler virtual unsigned int maxSprite() const = 0; /** + * Returns the min permitted hair color Id at character creation time, + * or 0 if there is no minimum. + */ + virtual int getCharCreateMinHairColorId() const { return 0; } + + /** * Returns the max permitted hair color Id at character creation time, * or 0 if no limit should be applied. */ diff --git a/src/net/logindata.h b/src/net/logindata.h index 1e19b541..34b259fb 100644 --- a/src/net/logindata.h +++ b/src/net/logindata.h @@ -40,7 +40,7 @@ public: std::string email; std::string captchaResponse; - Gender gender = GENDER_UNSPECIFIED; + Gender gender = Gender::UNSPECIFIED; bool remember; /**< Whether to store the username. */ bool registerLogin; /**< Whether an account is being registered. */ @@ -64,7 +64,7 @@ public: updateHost.clear(); email.clear(); captchaResponse.clear(); - gender = GENDER_UNSPECIFIED; + gender = Gender::UNSPECIFIED; resetCharacterSlots(); } }; diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index 6193fed1..186239c1 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -115,12 +115,12 @@ void BeingHandler::handleBeingEnterMessage(MessageIn &msg) auto direction = (BeingDirection)msg.readInt8(); Gender gender; int genderAsInt = msg.readInt8(); - if (genderAsInt == ::GENDER_FEMALE) - gender = ::GENDER_FEMALE; - else if (genderAsInt == ::GENDER_MALE) - gender = ::GENDER_MALE; + if (genderAsInt == GENDER_FEMALE) + gender = Gender::FEMALE; + else if (genderAsInt == GENDER_MALE) + gender = Gender::MALE; else - gender = ::GENDER_UNSPECIFIED; + gender = Gender::UNSPECIFIED; Being *being; switch (type) diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp index 61e44506..83919d4e 100644 --- a/src/net/manaserv/charhandler.cpp +++ b/src/net/manaserv/charhandler.cpp @@ -102,8 +102,8 @@ void CharHandler::handleCharacterInfo(MessageIn &msg) CachedCharacterInfo info; info.slot = msg.readInt8(); info.name = msg.readString(); - info.gender = msg.readInt8() == ManaServ::GENDER_MALE ? - ::GENDER_MALE : ::GENDER_FEMALE; + info.gender = msg.readInt8() == ManaServ::GENDER_MALE ? Gender::MALE + : Gender::FEMALE; info.hairStyle = msg.readInt8(); info.hairColor = msg.readInt8(); info.level = msg.readInt16(); diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 50585970..33adb93b 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -242,8 +242,8 @@ void BeingHandler::handleMessage(MessageIn &msg) if (dstBeing->getType() == ActorSprite::PLAYER) { - dstBeing->setGender((gender == 0) - ? GENDER_FEMALE : GENDER_MALE); + 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.getHairColor(hairColor)); @@ -415,53 +415,60 @@ void BeingHandler::handleMessage(MessageIn &msg) break; } - int type = msg.readInt8(); - int id = msg.readInt16(); - int id2 = msg.readInt16(); + const LOOK type = static_cast<LOOK>(msg.readInt8()); + const int id = msg.readInt16(); + const int id2 = msg.readInt16(); switch (type) { - case 1: // eAthena LOOK_HAIR - dstBeing->setSpriteID(SPRITE_HAIR, id *-1); + case LOOK::HAIR: + { + // const int look = id / 256; + const int hair = id % 256; + dstBeing->setSpriteID(SPRITE_HAIR, hair * -1); break; - case 2: // Weapon ID in id, Shield ID in id2 - dstBeing->setSprite(SPRITE_WEAPON, id, "", true); + } + case LOOK::WEAPON: // Weapon ID in id, Shield ID in id2 + dstBeing->setSprite(SPRITE_WEAPON, id, std::string(), true); dstBeing->setSprite(SPRITE_SHIELD, id2); break; - case 3: // Change lower headgear for eAthena, pants for us + case LOOK::HEAD_BOTTOM: // Change lower headgear for eAthena, pants for us dstBeing->setSprite(SPRITE_BOTTOMCLOTHES, id); break; - case 4: // Change upper headgear for eAthena, hat for us + case LOOK::HEAD_TOP: // Change upper headgear for eAthena, hat for us dstBeing->setSprite(SPRITE_HAT, id); break; - case 5: // Change middle headgear for eathena, armor for us + case LOOK::HEAD_MID: // Change middle headgear for eathena, armor for us dstBeing->setSprite(SPRITE_TOPCLOTHES, id); break; - case 6: // eAthena LOOK_HAIR_COLOR + case LOOK::HAIR_COLOR: dstBeing->setSpriteColor(SPRITE_HAIR, hairDB.getHairColor(id)); break; - case 8: // eAthena LOOK_SHIELD + case LOOK::CLOTHES_COLOR: + // ignoring it + break; + case LOOK::SHIELD: dstBeing->setSprite(SPRITE_SHIELD, id); break; - case 9: // eAthena LOOK_SHOES + case LOOK::SHOES: dstBeing->setSprite(SPRITE_SHOE, id); break; - case 10: // LOOK_GLOVES + case LOOK::GLOVES: dstBeing->setSprite(SPRITE_GLOVES, id); break; - case 11: // LOOK_CAPE + case LOOK::CAPE: dstBeing->setSprite(SPRITE_CAPE, id); break; - case 12: + case LOOK::MISC1: dstBeing->setSprite(SPRITE_MISC1, id); break; - case 13: + case LOOK::MISC2: dstBeing->setSprite(SPRITE_MISC2, id); break; default: logger->log("SMSG_BEING_CHANGE_LOOKS2: unsupported type: " - "%d, id: %d", type, id); + "%d, id: %d", static_cast<int>(type), id); break; } } @@ -549,9 +556,8 @@ void BeingHandler::handleMessage(MessageIn &msg) msg.readInt16(); // manner dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 msg.readInt8(); // karma - dstBeing->setGender((msg.readInt8() == 0) - ? GENDER_FEMALE : GENDER_MALE); - + dstBeing->setGender(msg.readInt8() == 0 ? Gender::FEMALE + : Gender::MALE); // Set these after the gender, as the sprites may be gender-specific dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true); dstBeing->setSprite(SPRITE_SHIELD, shield); @@ -629,9 +635,8 @@ void BeingHandler::handleMessage(MessageIn &msg) dstBeing = actorSpriteManager->findBeing(id); if (dstBeing) { - Uint16 x, y; - x = msg.readInt16(); - y = msg.readInt16(); + Uint16 x = msg.readInt16(); + Uint16 y = msg.readInt16(); handlePosMessage(map, dstBeing, x, y); } } diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index 324afd2d..d6b1f5a0 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -229,7 +229,7 @@ void CharServerHandler::readPlayerData(MessageIn &msg, Net::Character *character msg.readInt32(); // option msg.readInt32(); // karma msg.readInt32(); // manner - msg.skip(2); // unknown + msg.readInt16(); // character points left character->data.mAttributes[HP] = msg.readInt16(); character->data.mAttributes[MAX_HP] = msg.readInt16(); @@ -237,8 +237,10 @@ void CharServerHandler::readPlayerData(MessageIn &msg, Net::Character *character character->data.mAttributes[MAX_MP] = msg.readInt16(); msg.readInt16(); // speed - tempPlayer->setSubtype(msg.readInt16()); // class (used for race) - int hairStyle = msg.readInt16(); + const uint16_t race = msg.readInt16(); // class (used for race) + int hairStyle = msg.readInt8(); + msg.readInt8(); // look + tempPlayer->setSubtype(race); Uint16 weapon = msg.readInt16(); tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true); @@ -260,7 +262,8 @@ void CharServerHandler::readPlayerData(MessageIn &msg, Net::Character *character character->data.mStats[i + STRENGTH].base = msg.readInt8(); character->slot = msg.readInt8(); // character slot - msg.readInt8(); // unknown + const uint8_t sex = msg.readInt8(); + tempPlayer->setGender(sex ? Gender::MALE : Gender::FEMALE); } void CharServerHandler::setCharSelectDialog(CharSelectDialog *window) @@ -298,7 +301,7 @@ void CharServerHandler::setCharCreateDialog(CharCreateDialog *window) sumStat = Attributes::getCreationPoints(); mCharCreateDialog->setAttributes(attributes, sumStat, minStat, maxStat); - mCharCreateDialog->setFixedGender(true, token.sex); + mCharCreateDialog->setDefaultGender(token.sex); } void CharServerHandler::requestCharacters() @@ -361,6 +364,11 @@ unsigned int CharServerHandler::maxSprite() const return SPRITE_VECTOREND; } +int CharServerHandler::getCharCreateMinHairColorId() const +{ + return CharDB::getMinHairColor(); +} + int CharServerHandler::getCharCreateMaxHairColorId() const { const int max = CharDB::getMaxHairColor(); @@ -387,7 +395,7 @@ void CharServerHandler::connect() // [Fate] The next word is unused by the old char server, so we squeeze in // mana client version information outMsg.writeInt16(CLIENT_PROTOCOL_VERSION); - outMsg.writeInt8((token.sex == GENDER_MALE) ? 1 : 0); + outMsg.writeInt8(token.sex == Gender::MALE ? 1 : 0); // We get 4 useless bytes before the real answer comes in (what are these?) mNetwork->skip(4); diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h index 1102bb08..c8ba4f6f 100644 --- a/src/net/tmwa/charserverhandler.h +++ b/src/net/tmwa/charserverhandler.h @@ -68,6 +68,7 @@ class CharServerHandler : public MessageHandler, public Net::CharHandler unsigned int maxSprite() const override; + int getCharCreateMinHairColorId() const override; int getCharCreateMaxHairColorId() const override; int getCharCreateMaxHairStyleId() const override; diff --git a/src/net/tmwa/gamehandler.cpp b/src/net/tmwa/gamehandler.cpp index 0f423d8d..6f276e66 100644 --- a/src/net/tmwa/gamehandler.cpp +++ b/src/net/tmwa/gamehandler.cpp @@ -140,7 +140,7 @@ void GameHandler::connect() outMsg.writeInt32(mCharID); outMsg.writeInt32(token.session_ID1); outMsg.writeInt32(token.session_ID2); - outMsg.writeInt8((token.sex == GENDER_MALE) ? 1 : 0); + outMsg.writeInt8(token.sex == Gender::MALE ? 1 : 0); // We get 4 useless bytes before the real answer comes in (what are these?) mNetwork->skip(4); diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp index 725e0e35..1e0c6eda 100644 --- a/src/net/tmwa/loginhandler.cpp +++ b/src/net/tmwa/loginhandler.cpp @@ -126,7 +126,7 @@ void LoginHandler::handleMessage(MessageIn &msg) mToken.account_ID = msg.readInt32(); mToken.session_ID2 = msg.readInt32(); msg.skip(30); // unknown - mToken.sex = msg.readInt8() ? GENDER_MALE : GENDER_FEMALE; + mToken.sex = msg.readInt8() ? Gender::MALE : Gender::FEMALE; for (int i = 0; i < worldCount; i++) { @@ -305,7 +305,7 @@ void LoginHandler::chooseServer(unsigned int server) void LoginHandler::registerAccount(LoginData *loginData) { std::string username = loginData->username; - username.append((loginData->gender == GENDER_FEMALE) ? "_F" : "_M"); + username.append(loginData->gender == Gender::FEMALE ? "_F" : "_M"); sendLoginRegister(username, loginData->password); } diff --git a/src/net/tmwa/protocol.h b/src/net/tmwa/protocol.h index e50948c5..609b18a5 100644 --- a/src/net/tmwa/protocol.h +++ b/src/net/tmwa/protocol.h @@ -22,6 +22,8 @@ #ifndef TA_PROTOCOL_H #define TA_PROTOCOL_H +#include <cstdint> + namespace TmwAthena { enum { @@ -60,6 +62,24 @@ enum SPRITE_VECTOREND }; +enum class LOOK : uint8_t +{ + BASE = 0, + HAIR = 1, + WEAPON = 2, + HEAD_BOTTOM = 3, + HEAD_TOP = 4, + HEAD_MID = 5, + HAIR_COLOR = 6, + CLOTHES_COLOR = 7, + SHIELD = 8, + SHOES = 9, + GLOVES = 10, + CAPE = 11, + MISC1 = 12, + MISC2 = 13, +}; + enum NpcCommand { NPC_REQUEST_LANG = 0, diff --git a/src/net/tmwa/token.h b/src/net/tmwa/token.h index b5e84238..c0a2b3c8 100644 --- a/src/net/tmwa/token.h +++ b/src/net/tmwa/token.h @@ -36,7 +36,7 @@ struct Token account_ID = 0; session_ID1 = 0; session_ID2 = 0; - sex = GENDER_UNSPECIFIED; + sex = Gender::UNSPECIFIED; } }; diff --git a/src/resources/hairdb.cpp b/src/resources/hairdb.cpp index ff301a23..09ac14f4 100644 --- a/src/resources/hairdb.cpp +++ b/src/resources/hairdb.cpp @@ -104,15 +104,15 @@ std::vector<int> HairDB::getHairStyleIds(int maxId) const return hairStylesIds; } -std::vector<int> HairDB::getHairColorIds(int maxId) const +std::vector<int> HairDB::getHairColorIds(int minId, int maxId) const { std::vector<int> hairColorsIds; - for (const auto &hairColor : mHairColors) + for (const auto &[id, _] : mHairColors) { // Don't give ids higher than the requested maximum. - if (maxId > 0 && hairColor.first > maxId) + if ((maxId > 0 && id > maxId) || id < minId) continue; - hairColorsIds.push_back(hairColor.first); + hairColorsIds.push_back(id); } return hairColorsIds; } diff --git a/src/resources/hairdb.h b/src/resources/hairdb.h index b4374985..1f75a33a 100644 --- a/src/resources/hairdb.h +++ b/src/resources/hairdb.h @@ -64,7 +64,7 @@ public: * @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; + std::vector<int> getHairColorIds(int minId, int maxId) const; /** * Add a hair style to the database. diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index b910c639..77fda11b 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -66,8 +66,9 @@ void ItemDB::loadEmptyItemDefinition() mUnknown->mName = _("Unknown item"); mUnknown->mDisplay = SpriteDisplay(); std::string errFile = paths.getStringValue("spriteErrorFile"); - mUnknown->setSprite(errFile, GENDER_MALE); - mUnknown->setSprite(errFile, GENDER_FEMALE); + mUnknown->setSprite(errFile, Gender::MALE, 0); + mUnknown->setSprite(errFile, Gender::FEMALE, 0); + mUnknown->setSprite(errFile, Gender::HIDDEN, 0); mUnknown->setHitEffectId(paths.getIntValue("hitEffectId")); mUnknown->setCriticalHitEffectId(paths.getIntValue("criticalHitEffectId")); } @@ -122,14 +123,13 @@ void ItemDB::loadSpriteRef(ItemInfo *itemInfo, xmlNodePtr node) std::string gender = XML::getProperty(node, "gender", "unisex"); std::string filename = (const char*) node->xmlChildrenNode->content; + const int race = XML::getProperty(node, "race", 0); if (gender == "male" || gender == "unisex") - { - itemInfo->setSprite(filename, GENDER_MALE); - } + itemInfo->setSprite(filename, Gender::MALE, race); if (gender == "female" || gender == "unisex") - { - itemInfo->setSprite(filename, GENDER_FEMALE); - } + itemInfo->setSprite(filename, Gender::FEMALE, race); + if (gender == "hidden" || gender == "other" || gender == "unisex") + itemInfo->setSprite(filename, Gender::HIDDEN, race); } void ItemDB::loadSoundRef(ItemInfo *itemInfo, xmlNodePtr node) diff --git a/src/resources/iteminfo.cpp b/src/resources/iteminfo.cpp index 9e7fd6b7..b3208777 100644 --- a/src/resources/iteminfo.cpp +++ b/src/resources/iteminfo.cpp @@ -24,21 +24,22 @@ #include "resources/itemdb.h" #include "configuration.h" -const std::string &ItemInfo::getSprite(Gender gender) const +const std::string &ItemInfo::getSprite(Gender gender, int race) const { if (mView) { // Forward the request to the item defining how to view this item - return itemDb->get(mView).getSprite(gender); + return itemDb->get(mView).getSprite(gender, race); } - else - { - static const std::string empty; - auto i = - mAnimationFiles.find(gender); - return (i != mAnimationFiles.end()) ? i->second : empty; - } + auto i = mAnimationFiles.find(static_cast<int>(gender) + race * 4); + + // Fall back to ignoring race + if (race != 0 && i == mAnimationFiles.end()) + i = mAnimationFiles.find(static_cast<int>(gender)); + + static const std::string empty; + return i != mAnimationFiles.end() ? i->second : empty; } void ItemInfo::addSound(EquipmentSoundEvent event, const std::string &filename) @@ -49,8 +50,11 @@ void ItemInfo::addSound(EquipmentSoundEvent event, const std::string &filename) const std::string &ItemInfo::getSound(EquipmentSoundEvent event) const { static const std::string empty; - std::map< EquipmentSoundEvent, std::vector<std::string> >::const_iterator i; - i = mSounds.find(event); - + auto i = mSounds.find(event); return i == mSounds.end() ? empty : i->second[rand() % i->second.size()]; } + +void ItemInfo::setSprite(const std::string &animationFile, Gender gender, int race) +{ + mAnimationFiles[static_cast<int>(gender) + race * 4] = animationFile; +} diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index 5763e423..7344d668 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -106,7 +106,7 @@ class ItemInfo int getWeight() const { return mWeight; } - const std::string &getSprite(Gender gender) const; + const std::string &getSprite(Gender gender, int race) const; // Handlers for seting and getting the string used for particles when attacking void setMissileParticleFile(const std::string &s) @@ -145,9 +145,8 @@ class ItemInfo { return mType; } private: - - void setSprite(const std::string &animationFile, Gender gender) - { mAnimationFiles[gender] = animationFile; } + void setSprite(const std::string &animationFile, + Gender gender, int race); void addSound(EquipmentSoundEvent event, const std::string &filename); diff --git a/src/resources/settingsmanager.cpp b/src/resources/settingsmanager.cpp index 28c08617..eceedcf4 100644 --- a/src/resources/settingsmanager.cpp +++ b/src/resources/settingsmanager.cpp @@ -68,7 +68,7 @@ namespace SettingsManager loadFile("npcs.xml"); loadFile("emotes.xml"); loadFile("status-effects.xml"); - loadFile("hair.xml"); + loadFile("itemcolors.xml"); loadFile("units.xml"); } @@ -194,6 +194,20 @@ namespace SettingsManager { hairDB.readHairColorNode(childNode, filename); } + else if (xmlStrEqual(childNode->name, BAD_CAST "list")) + { + // todo: consider if we need a "color DB", but in tmwa clientdata + // I only see hair colors in the itemcolors.xml file. + const std::string name = XML::getProperty(childNode, "name", std::string()); + if (name == "hair") + { + for_each_xml_child_node(hairColorNode, childNode) + { + if (xmlStrEqual(hairColorNode->name, BAD_CAST "color")) + hairDB.readHairColorNode(hairColorNode, filename); + } + } + } else if (xmlStrEqual(childNode->name, BAD_CAST "item")) { itemDb->readItemNode(childNode, filename); |