diff options
author | Shauren <shauren.trinity@gmail.com> | 2020-12-01 21:08:06 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2020-12-08 18:16:47 +0100 |
commit | b82a3a557a7bf13d48342ea189325550059b622d (patch) | |
tree | 014fd20fae16fab1da1f056850348282b0e5e331 /src/server/game/Handlers/CharacterHandler.cpp | |
parent | 426cb31676338cf6e5411d38f645f98a7e6ccb91 (diff) |
Core/DataStores: Updated db2 structures to 9.0.2
* Includes support for new character customization
Diffstat (limited to 'src/server/game/Handlers/CharacterHandler.cpp')
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 364 |
1 files changed, 208 insertions, 156 deletions
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 49283ac0c26..9b4b8f41f97 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -31,6 +31,7 @@ #include "Chat.h" #include "ClientConfigPackets.h" #include "Common.h" +#include "Containers.h" #include "DatabaseEnv.h" #include "DB2Stores.h" #include "EquipmentSetPackets.h" @@ -88,6 +89,10 @@ bool LoginQueryHolder::Initialize() stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_FROM, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_CUSTOMIZATIONS); + stmt->setUInt64(0, lowGuid); + res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUSTOMIZATIONS, stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER); stmt->setUInt64(0, lowGuid); res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GROUP, stmt); @@ -307,16 +312,78 @@ bool LoginQueryHolder::Initialize() return res; } -void WorldSession::HandleCharEnum(PreparedQueryResult result) +class EnumCharactersQueryHolder : public CharacterDatabaseQueryHolder +{ +public: + enum + { + CHARACTERS, + CUSTOMIZATIONS, + + MAX + }; + + EnumCharactersQueryHolder() + { + SetSize(MAX); + } + + bool Initialize(uint32 accountId, bool withDeclinedNames, bool isDeletedCharacters) + { + _isDeletedCharacters = isDeletedCharacters; + + constexpr CharacterDatabaseStatements statements[2][3] = + { + { CHAR_SEL_ENUM, CHAR_SEL_ENUM_DECLINED_NAME, CHAR_SEL_ENUM_CUSTOMIZATIONS }, + { CHAR_SEL_UNDELETE_ENUM, CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME, CHAR_SEL_UNDELETE_ENUM_CUSTOMIZATIONS } + }; + + bool result = true; + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(statements[isDeletedCharacters ? 1 : 0][withDeclinedNames ? 1 : 0]); + stmt->setUInt8(0, PET_SAVE_AS_CURRENT); + stmt->setUInt32(1, accountId); + result &= SetPreparedQuery(CHARACTERS, stmt); + + stmt = CharacterDatabase.GetPreparedStatement(statements[isDeletedCharacters ? 1 : 0][2]); + stmt->setUInt32(0, accountId); + result &= SetPreparedQuery(CUSTOMIZATIONS, stmt); + + return result; + } + + bool IsDeletedCharacters() const { return _isDeletedCharacters; } + +private: + bool _isDeletedCharacters = false; +}; + +void WorldSession::HandleCharEnum(CharacterDatabaseQueryHolder* holder) { WorldPackets::Character::EnumCharactersResult charEnum; charEnum.Success = true; - charEnum.IsDeletedCharacters = false; + charEnum.IsDeletedCharacters = static_cast<EnumCharactersQueryHolder*>(holder)->IsDeletedCharacters(); charEnum.DisabledClassesMask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK); - _legitCharacters.clear(); + if (!charEnum.IsDeletedCharacters) + _legitCharacters.clear(); - if (result) + std::unordered_map<ObjectGuid::LowType, std::vector<UF::ChrCustomizationChoice>> customizations; + if (PreparedQueryResult customizationsResult = holder->GetPreparedResult(EnumCharactersQueryHolder::CUSTOMIZATIONS)) + { + do + { + Field* fields = customizationsResult->Fetch(); + std::vector<UF::ChrCustomizationChoice>& customizationsForCharacter = customizations[fields[0].GetUInt64()]; + + customizationsForCharacter.emplace_back(); + UF::ChrCustomizationChoice& choice = customizationsForCharacter.back(); + choice.ChrCustomizationOptionID = fields[1].GetUInt32(); + choice.ChrCustomizationChoiceID = fields[2].GetUInt32(); + + } while (customizationsResult->NextRow()); + } + + if (PreparedQueryResult result = holder->GetPreparedResult(EnumCharactersQueryHolder::CHARACTERS)) { do { @@ -324,32 +391,33 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result) WorldPackets::Character::EnumCharactersResult::CharacterInfo& charInfo = charEnum.Characters.back(); + if (std::vector<UF::ChrCustomizationChoice>* customizationsForChar = Trinity::Containers::MapGetValuePtr(customizations, charInfo.Guid.GetCounter())) + charInfo.Customizations = std::move(*customizationsForChar); + TC_LOG_INFO("network", "Loading char guid %s from account %u.", charInfo.Guid.ToString().c_str(), GetAccountId()); - if (!Player::ValidateAppearance(charInfo.RaceID, charInfo.ClassID, charInfo.SexID, charInfo.HairStyle, charInfo.HairColor, charInfo.FaceID, charInfo.FacialHair, charInfo.SkinID, charInfo.CustomDisplay)) + if (!charEnum.IsDeletedCharacters) { - TC_LOG_ERROR("entities.player.loading", "Player %s has wrong Appearance values (Hair/Skin/Color), forcing recustomize", charInfo.Guid.ToString().c_str()); + if (!ValidateAppearance(Races(charInfo.RaceID), Classes(charInfo.ClassID), Gender(charInfo.SexID), MakeChrCustomizationChoiceRange(charInfo.Customizations))) + { + TC_LOG_ERROR("entities.player.loading", "Player %s has wrong Appearance values (Hair/Skin/Color), forcing recustomize", charInfo.Guid.ToString().c_str()); - // Make sure customization always works properly - send all zeroes instead - charInfo.SkinID = 0; - charInfo.FaceID = 0; - charInfo.HairStyle = 0; - charInfo.HairColor = 0; - charInfo.FacialHair = 0; + charInfo.Customizations.clear(); - if (!(charInfo.Flags2 == CHAR_CUSTOMIZE_FLAG_CUSTOMIZE)) - { - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); - stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE)); - stmt->setUInt64(1, charInfo.Guid.GetCounter()); - CharacterDatabase.Execute(stmt); - charInfo.Flags2 = CHAR_CUSTOMIZE_FLAG_CUSTOMIZE; + if (!(charInfo.Flags2 == CHAR_CUSTOMIZE_FLAG_CUSTOMIZE)) + { + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); + stmt->setUInt16(0, uint16(AT_LOGIN_CUSTOMIZE)); + stmt->setUInt64(1, charInfo.Guid.GetCounter()); + CharacterDatabase.Execute(stmt); + charInfo.Flags2 = CHAR_CUSTOMIZE_FLAG_CUSTOMIZE; + } } - } - // Do not allow locked characters to login - if (!(charInfo.Flags & (CHARACTER_FLAG_LOCKED_FOR_TRANSFER | CHARACTER_FLAG_LOCKED_BY_BILLING))) - _legitCharacters.insert(charInfo.Guid); + // Do not allow locked characters to login + if (!(charInfo.Flags & (CHARACTER_FLAG_LOCKED_FOR_TRANSFER | CHARACTER_FLAG_LOCKED_BY_BILLING))) + _legitCharacters.insert(charInfo.Guid); + } if (!sCharacterCache->HasCharacterCacheEntry(charInfo.Guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. sCharacterCache->AddCharacterCacheEntry(charInfo.Guid, GetAccountId(), charInfo.Name, charInfo.SexID, charInfo.RaceID, charInfo.ClassID, charInfo.ExperienceLevel, false); @@ -370,6 +438,8 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result) } SendPacket(charEnum.Write()); + + delete holder; } void WorldSession::HandleCharEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/) @@ -379,58 +449,123 @@ void WorldSession::HandleCharEnumOpcode(WorldPackets::Character::EnumCharacters& CharacterDatabase.Execute(stmt); /// get all the data necessary for loading all characters (along with their pets) on the account + EnumCharactersQueryHolder* holder = new EnumCharactersQueryHolder(); + if (!holder->Initialize(GetAccountId(), sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED), false)) + { + HandleCharEnum(holder); + return; + } - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED)) - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM_DECLINED_NAME); - else - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ENUM); + _charEnumCallback = CharacterDatabase.DelayQueryHolder(holder); +} - stmt->setUInt8(0, PET_SAVE_AS_CURRENT); - stmt->setUInt32(1, GetAccountId()); +void WorldSession::HandleCharUndeleteEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/) +{ + /// get all the data necessary for loading all undeleted characters (along with their pets) on the account + EnumCharactersQueryHolder* holder = new EnumCharactersQueryHolder(); + if (!holder->Initialize(GetAccountId(), sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED), true)) + { + HandleCharEnum(holder); + return; + } - _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharEnum, this, std::placeholders::_1))); + _charEnumCallback = CharacterDatabase.DelayQueryHolder(holder); } -void WorldSession::HandleCharUndeleteEnum(PreparedQueryResult result) +bool WorldSession::MeetsChrCustomizationReq(ChrCustomizationReqEntry const* req, Classes playerClass, + bool checkRequiredDependentChoices, Trinity::IteratorPair<UF::ChrCustomizationChoice const*> selectedChoices) const { - WorldPackets::Character::EnumCharactersResult charEnum; - charEnum.Success = true; - charEnum.IsDeletedCharacters = true; - charEnum.DisabledClassesMask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK); + if (!req->GetFlags().HasFlag(ChrCustomizationReqFlag::HasRequirements)) + return true; - if (result) + if (req->ClassMask && !(req->ClassMask & (1 << (playerClass - 1)))) + return false; + + if (req->AchievementID /*&& !HasAchieved(req->AchievementID)*/) + return false; + + if (req->ItemModifiedAppearanceID && !GetCollectionMgr()->HasItemAppearance(req->ItemModifiedAppearanceID).first) + return false; + + if (checkRequiredDependentChoices) { - do + if (std::unordered_map<uint32, std::vector<uint32>> const* requiredChoices = sDB2Manager.GetRequiredCustomizationChoices(req->ID)) { - Field* fields = result->Fetch(); - WorldPackets::Character::EnumCharactersResult::CharacterInfo charInfo(fields); - - TC_LOG_INFO("network", "Loading undeleted char guid %s from account %u.", charInfo.Guid.ToString().c_str(), GetAccountId()); + for (std::pair<uint32 const /*chrCustomizationOptionId*/, std::vector<uint32>> const& requiredChoicesForOption : *requiredChoices) + { + bool hasRequiredChoiceForOption = false; + for (uint32 requiredChoice : requiredChoicesForOption.second) + { + auto choiceItr = std::find_if(selectedChoices.begin(), selectedChoices.end(), [requiredChoice](UF::ChrCustomizationChoice const& choice) + { + return choice.ChrCustomizationChoiceID == requiredChoice; + }); - if (!sCharacterCache->HasCharacterCacheEntry(charInfo.Guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. - sCharacterCache->AddCharacterCacheEntry(charInfo.Guid, GetAccountId(), charInfo.Name, charInfo.SexID, charInfo.RaceID, charInfo.ClassID, charInfo.ExperienceLevel, true); + if (choiceItr != selectedChoices.end()) + { + hasRequiredChoiceForOption = true; + break; + } + } - charEnum.Characters.emplace_back(charInfo); + if (!hasRequiredChoiceForOption) + return false; + } } - while (result->NextRow()); } - SendPacket(charEnum.Write()); + return true; } -void WorldSession::HandleCharUndeleteEnumOpcode(WorldPackets::Character::EnumCharacters& /*enumCharacters*/) +bool WorldSession::ValidateAppearance(Races race, Classes playerClass, Gender gender, Trinity::IteratorPair<UF::ChrCustomizationChoice const*> customizations) { - /// get all the data necessary for loading all undeleted characters (along with their pets) on the account - CharacterDatabasePreparedStatement* stmt = nullptr; - if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED)) - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME); - else - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_UNDELETE_ENUM); + std::vector<ChrCustomizationOptionEntry const*> const* options = sDB2Manager.GetCustomiztionOptions(race, gender); + if (!options) + return false; + + uint32 previousOption = 0; + + for (UF::ChrCustomizationChoice playerChoice : customizations) + { + // check uniqueness of options + if (playerChoice.ChrCustomizationOptionID == previousOption) + return false; + + previousOption = playerChoice.ChrCustomizationOptionID; + + // check if we can use this option + auto customizationOptionDataItr = std::find_if(options->begin(), options->end(), [&](ChrCustomizationOptionEntry const* option) + { + return option->ID == playerChoice.ChrCustomizationOptionID; + }); - stmt->setUInt8(0, PET_SAVE_AS_CURRENT); - stmt->setUInt32(1, GetAccountId()); + // option not found for race/gender combination + if (customizationOptionDataItr == options->end()) + return false; - _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharUndeleteEnum, this, std::placeholders::_1))); + if (ChrCustomizationReqEntry const* req = sChrCustomizationReqStore.LookupEntry((*customizationOptionDataItr)->ChrCustomizationReqID)) + if (!MeetsChrCustomizationReq(req, playerClass, false, customizations)) + return false; + + std::vector<ChrCustomizationChoiceEntry const*> const* choicesForOption = sDB2Manager.GetCustomiztionChoices(playerChoice.ChrCustomizationOptionID); + if (!choicesForOption) + return false; + + auto customizationChoiceDataItr = std::find_if(choicesForOption->begin(), choicesForOption->end(), [&](ChrCustomizationChoiceEntry const* choice) + { + return choice->ID == playerChoice.ChrCustomizationChoiceID; + }); + + // choice not found for option + if (customizationChoiceDataItr == choicesForOption->end()) + return false; + + if (ChrCustomizationReqEntry const* req = sChrCustomizationReqStore.LookupEntry((*customizationChoiceDataItr)->ChrCustomizationReqID)) + if (!MeetsChrCustomizationReq(req, playerClass, true, customizations)) + return false; + } + + return true; } void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharacter& charCreate) @@ -673,19 +808,6 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact if (checkDemonHunterReqs) { - uint8 accClass = field[2].GetUInt8(); - if (accClass == CLASS_DEMON_HUNTER) - { - if (freeDemonHunterSlots > 0) - --freeDemonHunterSlots; - - if (freeDemonHunterSlots == 0) - { - SendCharCreate(CHAR_CREATE_FAILED); - return; - } - } - if (!hasDemonHunterReqLevel) { uint8 accLevel = field[0].GetUInt8(); @@ -746,7 +868,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact { TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Create Character: %s %s", GetAccountId(), GetRemoteAddress().c_str(), newChar->GetName().c_str(), newChar->GetGUID().ToString().c_str()); sScriptMgr->OnPlayerCreate(newChar.get()); - sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->m_playerData->NativeSex, newChar->getRace(), newChar->getClass(), newChar->getLevel(), false); + sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->GetNativeSex(), newChar->getRace(), newChar->getClass(), newChar->getLevel(), false); SendCharCreate(CHAR_CREATE_SUCCESS, newChar->GetGUID()); } @@ -763,7 +885,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPackets::Character::CreateCharact CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CREATE_INFO); stmt->setUInt32(0, GetAccountId()); - stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEMON_HUNTER) ? 12 : 1); + stmt->setUInt32(1, (skipCinematics == 1 || createInfo->Class == CLASS_DEMON_HUNTER) ? 1200 : 1); // 200 (max chars per realm) + 1000 (max deleted chars per realm) queryCallback.WithPreparedCallback(std::move(finalizeCharacterCreation)).SetNextQuery(CharacterDatabase.AsyncQuery(stmt)); })); } @@ -1532,41 +1654,7 @@ void WorldSession::HandleSetPlayerDeclinedNames(WorldPackets::Character::SetPlay void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance& packet) { - BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(packet.NewHairStyle); - if (!bs_hair || bs_hair->Type != 0 || bs_hair->Race != _player->getRace() || bs_hair->Sex != _player->m_playerData->NativeSex) - return; - - BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(packet.NewFacialHair); - if (!bs_facialHair || bs_facialHair->Type != 2 || bs_facialHair->Race != _player->getRace() || bs_facialHair->Sex != _player->m_playerData->NativeSex) - return; - - BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(packet.NewSkinColor); - if (bs_skinColor && (bs_skinColor->Type != 3 || bs_skinColor->Race != _player->getRace() || bs_skinColor->Sex != _player->m_playerData->NativeSex)) - return; - - BarberShopStyleEntry const* bs_face = sBarberShopStyleStore.LookupEntry(packet.NewFace); - if (bs_face && (bs_face->Type != 4 || bs_face->Race != _player->getRace() || bs_face->Sex != _player->m_playerData->NativeSex)) - return; - - std::array<BarberShopStyleEntry const*, PLAYER_CUSTOM_DISPLAY_SIZE> customDisplayEntries; - std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> customDisplay; - for (std::size_t i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - { - BarberShopStyleEntry const* bs_customDisplay = sBarberShopStyleStore.LookupEntry(packet.NewCustomDisplay[i]); - if (bs_customDisplay && (bs_customDisplay->Type != 5 + i || bs_customDisplay->Race != _player->getRace() || bs_customDisplay->Sex != _player->m_playerData->NativeSex)) - return; - - customDisplayEntries[i] = bs_customDisplay; - customDisplay[i] = bs_customDisplay ? bs_customDisplay->Data : 0; - } - - if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->m_playerData->NativeSex, - bs_hair->Data, - packet.NewHairColor, - bs_face ? bs_face->Data : _player->m_playerData->FaceID, - bs_facialHair->Data, - bs_skinColor ? bs_skinColor->Data : _player->m_playerData->SkinID, - customDisplay)) + if (!ValidateAppearance(Races(_player->getRace()), Classes(_player->getClass()), Gender(packet.NewSex), MakeChrCustomizationChoiceRange(packet.Customizations))) return; GameObject* go = _player->FindNearestGameObjectOfType(GAMEOBJECT_TYPE_BARBER_CHAIR, 5.0f); @@ -1582,12 +1670,12 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance return; } - uint32 cost = _player->GetBarberShopCost(bs_hair, packet.NewHairColor, bs_facialHair, bs_skinColor, bs_face, customDisplayEntries); + int64 cost = _player->GetBarberShopCost(MakeChrCustomizationChoiceRange(packet.Customizations)); // 0 - ok // 1, 3 - not enough money // 2 - you have to sit on barber chair - if (!_player->HasEnoughMoney((uint64)cost)) + if (!_player->HasEnoughMoney(cost)) { SendPacket(WorldPackets::Character::BarberShopResult(WorldPackets::Character::BarberShopResult::ResultEnum::NoMoney).Write()); return; @@ -1595,23 +1683,17 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance SendPacket(WorldPackets::Character::BarberShopResult(WorldPackets::Character::BarberShopResult::ResultEnum::Success).Write()); - _player->ModifyMoney(-int64(cost)); // it isn't free + _player->ModifyMoney(-cost); // it isn't free _player->UpdateCriteria(CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost); - _player->SetHairStyleId(bs_hair->Data); - _player->SetHairColorId(packet.NewHairColor); - _player->SetFacialHairStyleId(bs_facialHair->Data); - if (bs_skinColor) - _player->SetSkinId(bs_skinColor->Data); - if (bs_face) - _player->SetFaceId(bs_face->Data); - - for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i) - _player->SetCustomDisplayOption(i, customDisplay[i]); + _player->SetNativeSex(packet.NewSex); + _player->SetCustomizations(Trinity::Containers::MakeIteratorPair(packet.Customizations.begin(), packet.Customizations.end())); _player->UpdateCriteria(CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); _player->SetStandState(UNIT_STAND_STATE_STAND); + + sCharacterCache->UpdateCharacterGender(_player->GetGUID(), packet.NewSex); } void WorldSession::HandleCharCustomizeOpcode(WorldPackets::Character::CharCustomize& packet) @@ -1642,13 +1724,12 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<WorldPackets::Cha Field* fields = result->Fetch(); std::string oldName = fields[0].GetString(); - uint8 plrRace = fields[1].GetUInt8(); - uint8 plrClass = fields[2].GetUInt8(); - uint8 plrGender = fields[3].GetUInt8(); + Races plrRace = Races(fields[1].GetUInt8()); + Classes plrClass = Classes(fields[2].GetUInt8()); + Gender plrGender = Gender(fields[3].GetUInt8()); uint16 atLoginFlags = fields[4].GetUInt16(); - if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo->HairStyleID, customizeInfo->HairColorID, customizeInfo->FaceID, - customizeInfo->FacialHairStyleID, customizeInfo->SkinID, customizeInfo->CustomDisplay)) + if (!ValidateAppearance(plrRace, plrClass, plrGender, MakeChrCustomizationChoiceRange(customizeInfo->Customizations))) { SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo.get()); return; @@ -1708,22 +1789,7 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<WorldPackets::Cha ObjectGuid::LowType lowGuid = customizeInfo->CharGUID.GetCounter(); /// Customize - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE); - - stmt->setUInt8(0, customizeInfo->SexID); - stmt->setUInt8(1, customizeInfo->SkinID); - stmt->setUInt8(2, customizeInfo->FaceID); - stmt->setUInt8(3, customizeInfo->HairStyleID); - stmt->setUInt8(4, customizeInfo->HairColorID); - stmt->setUInt8(5, customizeInfo->FacialHairStyleID); - stmt->setUInt8(6, customizeInfo->CustomDisplay[0]); - stmt->setUInt8(7, customizeInfo->CustomDisplay[1]); - stmt->setUInt8(8, customizeInfo->CustomDisplay[2]); - stmt->setUInt64(9, lowGuid); - - trans->Append(stmt); - } + Player::SaveCustomizations(trans, lowGuid, MakeChrCustomizationChoiceRange(customizeInfo->Customizations)); /// Name Change and update atLogin flags { @@ -1823,7 +1889,7 @@ void WorldSession::HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipm if (!illusion->ItemVisual || !(illusion->Flags & ENCHANTMENT_COLLECTABLE)) return false; - if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(illusion->TransmogPlayerConditionID)) + if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(illusion->TransmogUseConditionID)) if (!sConditionMgr->IsPlayerMeetingCondition(_player, condition)) return false; @@ -2055,21 +2121,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPa } // Customize - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GENDER_AND_APPEARANCE); - stmt->setUInt8(0, factionChangeInfo->SexID); - stmt->setUInt8(1, factionChangeInfo->SkinID); - stmt->setUInt8(2, factionChangeInfo->FaceID); - stmt->setUInt8(3, factionChangeInfo->HairStyleID); - stmt->setUInt8(4, factionChangeInfo->HairColorID); - stmt->setUInt8(5, factionChangeInfo->FacialHairStyleID); - stmt->setUInt8(6, factionChangeInfo->CustomDisplay[0]); - stmt->setUInt8(7, factionChangeInfo->CustomDisplay[1]); - stmt->setUInt8(8, factionChangeInfo->CustomDisplay[2]); - stmt->setUInt64(9, lowGuid); - - trans->Append(stmt); - } + Player::SaveCustomizations(trans, lowGuid, MakeChrCustomizationChoiceRange(factionChangeInfo->Customizations)); // Race Change { |