diff options
-rw-r--r-- | sql/updates/hotfixes/master/2017_08_23_00_hotfixes.sql | 37 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.cpp | 11 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.h | 4 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2LoadInfo.h | 47 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 78 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 5 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 27 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 18 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 27 |
9 files changed, 185 insertions, 69 deletions
diff --git a/sql/updates/hotfixes/master/2017_08_23_00_hotfixes.sql b/sql/updates/hotfixes/master/2017_08_23_00_hotfixes.sql new file mode 100644 index 00000000000..ee74fde154f --- /dev/null +++ b/sql/updates/hotfixes/master/2017_08_23_00_hotfixes.sql @@ -0,0 +1,37 @@ +-- +-- Table structure for table `character_facial_hair_styles` +-- +DROP TABLE IF EXISTS `character_facial_hair_styles`; +CREATE TABLE `character_facial_hair_styles` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `Geoset1` int(10) unsigned NOT NULL DEFAULT '0', + `Geoset2` int(10) unsigned NOT NULL DEFAULT '0', + `Geoset3` int(10) unsigned NOT NULL DEFAULT '0', + `Geoset4` int(10) unsigned NOT NULL DEFAULT '0', + `Geoset5` int(10) unsigned NOT NULL DEFAULT '0', + `RaceID` tinyint(3) unsigned NOT NULL DEFAULT '0', + `SexID` tinyint(3) unsigned NOT NULL DEFAULT '0', + `VariationID` tinyint(3) unsigned NOT NULL DEFAULT '0', + `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Table structure for table `char_base_section` +-- +DROP TABLE IF EXISTS `char_base_section`; +CREATE TABLE `char_base_section` ( + `ID` int(10) unsigned NOT NULL DEFAULT '0', + `Variation` tinyint(3) unsigned NOT NULL DEFAULT '0', + `ResolutionVariation` tinyint(3) unsigned NOT NULL DEFAULT '0', + `Resolution` tinyint(3) unsigned NOT NULL DEFAULT '0', + `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +ALTER TABLE `char_sections` + CHANGE `Race` `RaceID` tinyint(3) unsigned NOT NULL DEFAULT '0', + CHANGE `Gender` `SexID` tinyint(3) unsigned NOT NULL DEFAULT '0', + CHANGE `GenType` `BaseSection` tinyint(3) unsigned NOT NULL DEFAULT '0', + CHANGE `Type` `VariationIndex` tinyint(3) unsigned NOT NULL DEFAULT '0', + CHANGE `Color` `ColorIndex` tinyint(3) unsigned NOT NULL DEFAULT '0'; diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp index 126c4e8452b..2e7674fcc47 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp @@ -136,9 +136,16 @@ void HotfixDatabaseConnection::DoPrepareStatements() "EmoteDelay3, UnkEmoteID, Language, Type, SoundID1, SoundID2, PlayerConditionID FROM broadcast_text ORDER BY ID DESC", CONNECTION_SYNCH); PREPARE_LOCALE_STMT(HOTFIX_SEL_BROADCAST_TEXT, "SELECT ID, MaleText_lang, FemaleText_lang FROM broadcast_text_locale WHERE locale = ?", CONNECTION_SYNCH); + // CharacterFacialHairStyles.db2 + PrepareStatement(HOTFIX_SEL_CHARACTER_FACIAL_HAIR_STYLES, "SELECT ID, Geoset1, Geoset2, Geoset3, Geoset4, Geoset5, RaceID, SexID, VariationID" + " FROM character_facial_hair_styles ORDER BY ID DESC", CONNECTION_SYNCH); + + // CharBaseSection.db2 + PrepareStatement(HOTFIX_SEL_CHAR_BASE_SECTION, "SELECT ID, Variation, ResolutionVariation, Resolution FROM char_base_section ORDER BY ID DESC", CONNECTION_SYNCH); + // CharSections.db2 - PrepareStatement(HOTFIX_SEL_CHAR_SECTIONS, "SELECT ID, TextureFileDataID1, TextureFileDataID2, TextureFileDataID3, Flags, Race, Gender, GenType, " - "Type, Color FROM char_sections ORDER BY ID DESC", CONNECTION_SYNCH); + PrepareStatement(HOTFIX_SEL_CHAR_SECTIONS, "SELECT ID, TextureFileDataID1, TextureFileDataID2, TextureFileDataID3, Flags, RaceID, SexID, " + "BaseSection, VariationIndex, ColorIndex FROM char_sections ORDER BY ID DESC", CONNECTION_SYNCH); // CharStartOutfit.db2 PrepareStatement(HOTFIX_SEL_CHAR_START_OUTFIT, "SELECT ID, ItemID1, ItemID2, ItemID3, ItemID4, ItemID5, ItemID6, ItemID7, ItemID8, ItemID9, " diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h index b5e9f980268..5d2b1f77765 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.h +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -91,6 +91,10 @@ enum HotfixDatabaseStatements : uint32 HOTFIX_SEL_BROADCAST_TEXT, HOTFIX_SEL_BROADCAST_TEXT_LOCALE, + HOTFIX_SEL_CHARACTER_FACIAL_HAIR_STYLES, + + HOTFIX_SEL_CHAR_BASE_SECTION, + HOTFIX_SEL_CHAR_SECTIONS, HOTFIX_SEL_CHAR_START_OUTFIT, diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h index 7522e8e9295..c5f09946ce3 100644 --- a/src/server/game/DataStores/DB2LoadInfo.h +++ b/src/server/game/DataStores/DB2LoadInfo.h @@ -554,6 +554,43 @@ struct BroadcastTextLoadInfo } }; +struct CharacterFacialHairStylesLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { false, FT_INT, "Geoset1" }, + { false, FT_INT, "Geoset2" }, + { false, FT_INT, "Geoset3" }, + { false, FT_INT, "Geoset4" }, + { false, FT_INT, "Geoset5" }, + { false, FT_BYTE, "RaceID" }, + { false, FT_BYTE, "SexID" }, + { false, FT_BYTE, "VariationID" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharacterFacialHairStylesMeta::Instance(), HOTFIX_SEL_CHARACTER_FACIAL_HAIR_STYLES); + return &loadInfo; + } +}; + +struct CharBaseSectionLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { false, FT_BYTE, "Variation" }, + { false, FT_BYTE, "ResolutionVariation" }, + { false, FT_BYTE, "Resolution" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharBaseSectionMeta::Instance(), HOTFIX_SEL_CHAR_BASE_SECTION); + return &loadInfo; + } +}; + struct CharSectionsLoadInfo { static DB2LoadInfo const* Instance() @@ -565,11 +602,11 @@ struct CharSectionsLoadInfo { false, FT_INT, "TextureFileDataID2" }, { false, FT_INT, "TextureFileDataID3" }, { false, FT_SHORT, "Flags" }, - { false, FT_BYTE, "Race" }, - { false, FT_BYTE, "Gender" }, - { false, FT_BYTE, "GenType" }, - { false, FT_BYTE, "Type" }, - { false, FT_BYTE, "Color" }, + { false, FT_BYTE, "RaceID" }, + { false, FT_BYTE, "SexID" }, + { false, FT_BYTE, "BaseSection" }, + { false, FT_BYTE, "VariationIndex" }, + { false, FT_BYTE, "ColorIndex" }, }; static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, CharSectionsMeta::Instance(), HOTFIX_SEL_CHAR_SECTIONS); return &loadInfo; diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 51da5cc828a..e7bcd266a65 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -25,6 +25,7 @@ #include "ObjectDefines.h" #include "Regex.h" #include "Timer.h" +#include "Util.h" #include <array> #include <sstream> #include <cctype> @@ -59,6 +60,8 @@ DB2Storage<BattlePetSpeciesEntry> sBattlePetSpeciesStore("BattlePe DB2Storage<BattlePetSpeciesStateEntry> sBattlePetSpeciesStateStore("BattlePetSpeciesState.db2", BattlePetSpeciesStateLoadInfo::Instance()); DB2Storage<BattlemasterListEntry> sBattlemasterListStore("BattlemasterList.db2", BattlemasterListLoadInfo::Instance()); DB2Storage<BroadcastTextEntry> sBroadcastTextStore("BroadcastText.db2", BroadcastTextLoadInfo::Instance()); +DB2Storage<CharacterFacialHairStylesEntry> sCharacterFacialHairStylesStore("CharacterFacialHairStyles.db2", CharacterFacialHairStylesLoadInfo::Instance()); +DB2Storage<CharBaseSectionEntry> sCharBaseSectionStore("CharBaseSection.db2", CharBaseSectionLoadInfo::Instance()); DB2Storage<CharSectionsEntry> sCharSectionsStore("CharSections.db2", CharSectionsLoadInfo::Instance()); DB2Storage<CharStartOutfitEntry> sCharStartOutfitStore("CharStartOutfit.db2", CharStartOutfitLoadInfo::Instance()); DB2Storage<CharTitlesEntry> sCharTitlesStore("CharTitles.db2", CharTitlesLoadInfo::Instance()); @@ -263,7 +266,6 @@ typedef std::unordered_map<uint32 /*areaGroupId*/, std::vector<uint32/*areaId*/> typedef std::unordered_map<uint32, std::vector<ArtifactPowerEntry const*>> ArtifactPowersContainer; typedef std::unordered_map<uint32, std::unordered_set<uint32>> ArtifactPowerLinksContainer; typedef std::unordered_map<std::pair<uint32, uint8>, ArtifactPowerRankEntry const*> ArtifactPowerRanksContainer; -typedef std::unordered_multimap<uint32, CharSectionsEntry const*> CharSectionsContainer; typedef std::unordered_map<uint32, CharStartOutfitEntry const*> CharStartOutfitContainer; typedef ChrSpecializationEntry const* ChrSpecializationByIndexContainer[MAX_CLASSES + 1][MAX_SPECIALIZATIONS]; typedef std::unordered_map<uint32, ChrSpecializationEntry const*> ChrSpecialzationByClassContainer; @@ -310,7 +312,8 @@ namespace ArtifactPowersContainer _artifactPowers; ArtifactPowerLinksContainer _artifactPowerLinks; ArtifactPowerRanksContainer _artifactPowerRanks; - CharSectionsContainer _charSections; + std::set<std::tuple<uint8, uint8, uint32>> _characterFacialHairStyles; + std::multimap<std::tuple<uint8, uint8, CharBaseSectionVariation>, CharSectionsEntry const*> _charSections; CharStartOutfitContainer _charStartOutfits; uint32 _powersByClass[MAX_CLASSES][MAX_POWERS]; ChrSpecializationByIndexContainer _chrSpecializationsByIndex; @@ -459,6 +462,8 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) LOAD_DB2(sBattlePetSpeciesStateStore); LOAD_DB2(sBattlemasterListStore); LOAD_DB2(sBroadcastTextStore); + LOAD_DB2(sCharacterFacialHairStylesStore); + LOAD_DB2(sCharBaseSectionStore); LOAD_DB2(sCharSectionsStore); LOAD_DB2(sCharStartOutfitStore); LOAD_DB2(sCharTitlesStore); @@ -669,44 +674,28 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale) ASSERT(BATTLE_PET_SPECIES_MAX_ID >= sBattlePetSpeciesStore.GetNumRows(), "BATTLE_PET_SPECIES_MAX_ID (%d) must be equal to or greater than %u", BATTLE_PET_SPECIES_MAX_ID, sBattlePetSpeciesStore.GetNumRows()); - std::unordered_map<uint32, std::set<std::pair<uint8, uint8>>> addedSections; - for (CharSectionsEntry const* charSection : sCharSectionsStore) + for (CharacterFacialHairStylesEntry const* characterFacialStyle : sCharacterFacialHairStylesStore) + _characterFacialHairStyles.emplace(characterFacialStyle->RaceID, characterFacialStyle->SexID, characterFacialStyle->VariationID); + + std::array<CharBaseSectionVariation, SECTION_TYPE_MAX> sectionToBase = { {} }; + for (CharBaseSectionEntry const* charBaseSection : sCharBaseSectionStore) { - if (!charSection->Race || !((1 << (charSection->Race - 1)) & RACEMASK_ALL_PLAYABLE)) //ignore Nonplayable races - continue; + ASSERT(charBaseSection->ResolutionVariation < SECTION_TYPE_MAX, + "SECTION_TYPE_MAX (%d) must be equal to or greater than %u", uint32(SECTION_TYPE_MAX), uint32(charBaseSection->ResolutionVariation + 1)); + ASSERT(charBaseSection->Variation < AsUnderlyingType(CharBaseSectionVariation::Count), + "CharBaseSectionVariation::Count %u must be equal to or greater than %u", uint32(CharBaseSectionVariation::Count), uint32(charBaseSection->Variation + 1)); - // Not all sections are used for low-res models but we need to get all sections for validation since its viewer dependent - uint8 baseSection = charSection->GenType; - switch (baseSection) - { - case SECTION_TYPE_SKIN_LOW_RES: - case SECTION_TYPE_FACE_LOW_RES: - case SECTION_TYPE_FACIAL_HAIR_LOW_RES: - case SECTION_TYPE_HAIR_LOW_RES: - case SECTION_TYPE_UNDERWEAR_LOW_RES: - baseSection = baseSection + SECTION_TYPE_SKIN; - break; - case SECTION_TYPE_SKIN: - case SECTION_TYPE_FACE: - case SECTION_TYPE_FACIAL_HAIR: - case SECTION_TYPE_HAIR: - case SECTION_TYPE_UNDERWEAR: - break; - case SECTION_TYPE_CUSTOM_DISPLAY_1_LOW_RES: - case SECTION_TYPE_CUSTOM_DISPLAY_2_LOW_RES: - case SECTION_TYPE_CUSTOM_DISPLAY_3_LOW_RES: - ++baseSection; - break; - case SECTION_TYPE_CUSTOM_DISPLAY_1: - case SECTION_TYPE_CUSTOM_DISPLAY_2: - case SECTION_TYPE_CUSTOM_DISPLAY_3: - break; - default: - break; - } + sectionToBase[charBaseSection->ResolutionVariation] = static_cast<CharBaseSectionVariation>(charBaseSection->Variation); + } - uint32 sectionKey = baseSection | (charSection->Gender << 8) | (charSection->Race << 16); - std::pair<uint8, uint8> sectionCombination{ charSection->Type, charSection->Color }; + std::map<std::tuple<uint8, uint8, CharBaseSectionVariation>, std::set<std::pair<uint8, uint8>>> addedSections; + for (CharSectionsEntry const* charSection : sCharSectionsStore) + { + ASSERT(charSection->BaseSection < SECTION_TYPE_MAX, + "SECTION_TYPE_MAX (%d) must be equal to or greater than %u", uint32(SECTION_TYPE_MAX), uint32(charSection->BaseSection + 1)); + + std::tuple<uint8, uint8, CharBaseSectionVariation> sectionKey{ charSection->RaceID, charSection->SexID, sectionToBase[charSection->BaseSection] }; + std::pair<uint8, uint8> sectionCombination{ charSection->VariationIndex, charSection->ColorIndex }; if (addedSections[sectionKey].count(sectionCombination)) continue; @@ -1180,16 +1169,21 @@ char const* DB2Manager::GetBroadcastTextValue(BroadcastTextEntry const* broadcas return broadcastText->MaleText->Str[DEFAULT_LOCALE]; } -bool DB2Manager::HasCharSections(uint8 race, CharSectionType genType, uint8 gender) const +bool DB2Manager::HasCharacterFacialHairStyle(uint8 race, uint8 gender, uint8 variationId) const +{ + return _characterFacialHairStyles.find(std::make_tuple(race, gender, variationId)) != _characterFacialHairStyles.end(); +} + +bool DB2Manager::HasCharSections(uint8 race, uint8 gender, CharBaseSectionVariation variation) const { - auto range = Trinity::Containers::MapEqualRange(_charSections, uint32(genType) | uint32(gender << 8) | uint32(race << 16)); + auto range = Trinity::Containers::MapEqualRange(_charSections, std::make_tuple(race, gender, variation)); return range.begin() != range.end(); } -CharSectionsEntry const* DB2Manager::GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color) const +CharSectionsEntry const* DB2Manager::GetCharSectionEntry(uint8 race, uint8 gender, CharBaseSectionVariation variation, uint8 variationIndex, uint8 colorIndex) const { - for (auto const& section : Trinity::Containers::MapEqualRange(_charSections, uint32(genType) | uint32(gender << 8) | uint32(race << 16))) - if (section.second->Type == type && section.second->Color == color) + for (auto const& section : Trinity::Containers::MapEqualRange(_charSections, std::make_tuple(race, gender, variation))) + if (section.second->VariationIndex == variationIndex && section.second->ColorIndex == colorIndex) return section.second; return nullptr; diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 1ff3dd9afbe..0b52feacb77 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -253,8 +253,9 @@ public: std::unordered_set<uint32> const* GetArtifactPowerLinks(uint32 artifactPowerId) const; ArtifactPowerRankEntry const* GetArtifactPowerRank(uint32 artifactPowerId, uint8 rank) const; static char const* GetBroadcastTextValue(BroadcastTextEntry const* broadcastText, LocaleConstant locale = DEFAULT_LOCALE, uint8 gender = GENDER_MALE, bool forceGender = false); - bool HasCharSections(uint8 race, CharSectionType genType, uint8 gender) const; - CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color) const; + bool HasCharacterFacialHairStyle(uint8 race, uint8 gender, uint8 variationId) const; + bool HasCharSections(uint8 race, uint8 gender, CharBaseSectionVariation variation) const; + CharSectionsEntry const* GetCharSectionEntry(uint8 race, uint8 gender, CharBaseSectionVariation variation, uint8 variationIndex, uint8 color) const; CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender) const; static char const* GetClassName(uint8 class_, LocaleConstant locale = DEFAULT_LOCALE); uint32 GetPowerIndexByClass(uint32 powerType, uint32 classId) const; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index ebd3b27c852..14d9465e7ba 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -326,16 +326,33 @@ struct BroadcastTextEntry uint32 PlayerConditionID; }; +struct CharacterFacialHairStylesEntry +{ + uint32 ID; + uint32 Geoset[5]; + uint8 RaceID; + uint8 SexID; + uint8 VariationID; +}; + +struct CharBaseSectionEntry +{ + uint32 ID; + uint8 Variation; + uint8 ResolutionVariation; + uint8 Resolution; +}; + struct CharSectionsEntry { uint32 ID; uint32 TextureFileDataID[3]; uint16 Flags; - uint8 Race; - uint8 Gender; - uint8 GenType; - uint8 Type; - uint8 Color; + uint8 RaceID; + uint8 SexID; + uint8 BaseSection; + uint8 VariationIndex; + uint8 ColorIndex; }; #define MAX_OUTFIT_ITEMS 24 diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 636808dee1b..aa7a208e9e7 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -505,6 +505,20 @@ enum CriteriaTreeOperator : uint8 CRITERIA_TREE_OPERATOR_SUM_CHILDREN_WEIGHT = 9 }; +enum class CharBaseSectionVariation : uint8 +{ + Skin = 0, + Face = 1, + FacialHair = 2, + Hair = 3, + Underwear = 4, + CustomDisplay1 = 5, + CustomDisplay2 = 6, + CustomDisplay3 = 7, + + Count +}; + enum CharSectionFlags { SECTION_FLAG_PLAYER = 0x01, @@ -529,7 +543,9 @@ enum CharSectionType SECTION_TYPE_CUSTOM_DISPLAY_2_LOW_RES = 12, SECTION_TYPE_CUSTOM_DISPLAY_2 = 13, SECTION_TYPE_CUSTOM_DISPLAY_3_LOW_RES = 14, - SECTION_TYPE_CUSTOM_DISPLAY_3 = 15 + SECTION_TYPE_CUSTOM_DISPLAY_3 = 15, + + SECTION_TYPE_MAX }; enum Curves diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1aac9204843..a50d8798568 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -27606,35 +27606,38 @@ bool IsSectionFlagValid(CharSectionsEntry const* entry, uint8 class_, bool creat return ComponentFlagsMatch(entry, GetSelectionFromContext(2, class_)); } -bool IsSectionValid(uint8 race, uint8 class_, CharSectionType genType, uint8 gender, uint8 type, uint8 color, bool create) +bool IsSectionValid(uint8 race, uint8 class_, uint8 gender, CharBaseSectionVariation variation, uint8 variationIndex, uint8 colorIndex, bool create) { - CharSectionsEntry const* section = sDB2Manager.GetCharSectionEntry(race, genType, gender, type, color); + CharSectionsEntry const* section = sDB2Manager.GetCharSectionEntry(race, gender, variation, variationIndex, colorIndex); if (section) return IsSectionFlagValid(section, class_, create); - if (!sDB2Manager.HasCharSections(race, genType, gender)) - return type == 0; - return false; } bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHairID, uint8 skinColor, std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> const& customDisplay, bool create /*= false*/) { - if (!IsSectionValid(race, class_, SECTION_TYPE_SKIN, gender, 0, skinColor, create)) + if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::Skin, 0, skinColor, create)) return false; - if (!IsSectionValid(race, class_, SECTION_TYPE_FACE, gender, faceID, skinColor, create)) + if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::Face, faceID, skinColor, create)) return false; - if (!IsSectionValid(race, class_, SECTION_TYPE_HAIR, gender, hairID, hairColor, create)) + if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::Hair, hairID, hairColor, create)) return false; - if (!IsSectionValid(race, class_, SECTION_TYPE_FACIAL_HAIR, gender, facialHairID, hairColor, create)) + if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::FacialHair, facialHairID, hairColor, create)) + if (sDB2Manager.HasCharSections(race, gender, CharBaseSectionVariation::FacialHair) || !sDB2Manager.HasCharacterFacialHairStyle(race, gender, facialHairID)) + return false; + + if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::CustomDisplay1, customDisplay[0], 0, create)) return false; - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - if (!IsSectionValid(race, class_, CharSectionType(SECTION_TYPE_CUSTOM_DISPLAY_1 + i * 2), gender, customDisplay[i], 0, create)) - return false; + if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::CustomDisplay2, customDisplay[1], 0, create)) + return false; + + if (!IsSectionValid(race, class_, gender, CharBaseSectionVariation::CustomDisplay3, customDisplay[2], 0, create)) + return false; return true; } |