aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.cpp11
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.h4
-rw-r--r--src/server/game/DataStores/DB2LoadInfo.h47
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp78
-rw-r--r--src/server/game/DataStores/DB2Stores.h5
-rw-r--r--src/server/game/DataStores/DB2Structure.h27
-rw-r--r--src/server/game/DataStores/DBCEnums.h18
-rw-r--r--src/server/game/Entities/Player/Player.cpp27
8 files changed, 148 insertions, 69 deletions
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;
}