From 5c7f9d1d216fd1edca231ed274ac3077cb34909f Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Mon, 4 Mar 2024 16:29:14 +0100 Subject: Fixed character display This change fixes hair style to take into account "race", which makes the faces visible again. Hair colors should also be fixed now, with partial support for itemcolors.xml added. The Mana client now also supports per-character gender, and it now hides the hair style and color buttons on character creation, when there are none to choose from. Closes #43 --- src/resources/hairdb.cpp | 8 ++++---- src/resources/hairdb.h | 2 +- src/resources/itemdb.cpp | 16 ++++++++-------- src/resources/iteminfo.cpp | 28 ++++++++++++++++------------ src/resources/iteminfo.h | 7 +++---- src/resources/settingsmanager.cpp | 16 +++++++++++++++- 6 files changed, 47 insertions(+), 30 deletions(-) (limited to 'src/resources') 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 HairDB::getHairStyleIds(int maxId) const return hairStylesIds; } -std::vector HairDB::getHairColorIds(int maxId) const +std::vector HairDB::getHairColorIds(int minId, int maxId) const { std::vector 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 getHairColorIds(int maxId = 0) const; + std::vector 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(gender) + race * 4); + + // Fall back to ignoring race + if (race != 0 && i == mAnimationFiles.end()) + i = mAnimationFiles.find(static_cast(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 >::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(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); -- cgit v1.2.3-70-g09d2