aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Handlers/CharacterHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Handlers/CharacterHandler.cpp')
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp197
1 files changed, 115 insertions, 82 deletions
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index f7f198809aa..abac1b283fb 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -191,6 +191,10 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_EQUIPMENT_SETS, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFITS);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_TRANSMOG_OUTFITS, stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUF_PROFILES);
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_CUF_PROFILES, stmt);
@@ -199,10 +203,6 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_BG_DATA, stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GLYPHS);
- stmt->setUInt64(0, lowGuid);
- res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_GLYPHS, stmt);
-
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_TALENTS);
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_TALENTS, stmt);
@@ -267,6 +267,8 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
WorldPackets::Character::EnumCharactersResult charEnum;
charEnum.Success = true;
charEnum.IsDeletedCharacters = false;
+ charEnum.IsDemonHunterCreationAllowed = true;
+ charEnum.DisabledClassesMask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
_legitCharacters.clear();
@@ -279,7 +281,7 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
TC_LOG_INFO("network", "Loading char guid %s from account %u.", charInfo.Guid.ToString().c_str(), GetAccountId());
- if (!Player::ValidateAppearance(charInfo.Race, charInfo.Class, charInfo.Sex, charInfo.HairStyle, charInfo.HairColor, charInfo.Face, charInfo.FacialHair, charInfo.Skin))
+ if (!Player::ValidateAppearance(charInfo.Race, charInfo.Class, charInfo.Sex, charInfo.HairStyle, charInfo.HairColor, charInfo.Face, charInfo.FacialHair, charInfo.Skin, charInfo.CustomDisplay))
{
TC_LOG_ERROR("entities.player.loading", "Player %s has wrong Appearance values (Hair/Skin/Color), forcing recustomize", charInfo.Guid.ToString().c_str());
@@ -300,6 +302,11 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result)
if (!sWorld->HasCharacterInfo(charInfo.Guid)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet.
sWorld->AddCharacterInfo(charInfo.Guid, GetAccountId(), charInfo.Name, charInfo.Sex, charInfo.Race, charInfo.Class, charInfo.Level, false);
+ if (charInfo.Class == CLASS_DEMON_HUNTER)
+ charEnum.HasDemonHunterOnRealm = true;
+ if (charInfo.Level >= 70)
+ charEnum.HasLevel70OnRealm = true;
+
charEnum.Characters.emplace_back(charInfo);
}
while (result->NextRow());
@@ -333,6 +340,7 @@ void WorldSession::HandleCharUndeleteEnum(PreparedQueryResult result)
WorldPackets::Character::EnumCharactersResult charEnum;
charEnum.Success = true;
charEnum.IsDeletedCharacters = true;
+ charEnum.DisabledClassesMask = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK);
if (result)
{
@@ -1253,22 +1261,6 @@ void WorldSession::HandleRequestForcedReactionsOpcode(WorldPackets::Reputation::
_player->GetReputationMgr().SendForceReactions();
}
-void WorldSession::HandleShowingHelmOpcode(WorldPackets::Character::ShowingHelm& packet)
-{
- if (packet.ShowHelm)
- _player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM);
- else
- _player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM);
-}
-
-void WorldSession::HandleShowingCloakOpcode(WorldPackets::Character::ShowingCloak& packet)
-{
- if (packet.ShowCloak)
- _player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK);
- else
- _player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_CLOAK);
-}
-
void WorldSession::HandleCharRenameOpcode(WorldPackets::Character::CharacterRenameRequest& request)
{
if (!IsLegitCharacterForAccount(request.RenameInfo->Guid))
@@ -1437,12 +1429,25 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance
if (bs_face && (bs_face->Type != 4 || bs_face->Race != _player->getRace() || bs_face->Sex != _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)))
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->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)))
+ return;
+
+ customDisplayEntries[i] = bs_customDisplay;
+ customDisplay[i] = bs_customDisplay->Data;
+ }
+
if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER),
bs_hair->Data,
packet.NewHairColor,
bs_face ? bs_face->Data : _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID),
bs_facialHair->Data,
- bs_skinColor ? bs_skinColor->Data : _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID)))
+ bs_skinColor ? bs_skinColor->Data : _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID),
+ customDisplay))
return;
GameObject* go = _player->FindNearestGameObjectOfType(GAMEOBJECT_TYPE_BARBER_CHAIR, 5.0f);
@@ -1458,7 +1463,7 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance
return;
}
- uint32 cost = _player->GetBarberShopCost(bs_hair, packet.NewHairColor, bs_facialHair, bs_skinColor, bs_face);
+ uint32 cost = _player->GetBarberShopCost(bs_hair, packet.NewHairColor, bs_facialHair, bs_skinColor, bs_face, customDisplayEntries);
// 0 - ok
// 1, 3 - not enough money
@@ -1487,28 +1492,6 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance
_player->SetStandState(UNIT_STAND_STATE_STAND);
}
-void WorldSession::HandleRemoveGlyph(WorldPacket& recvData)
-{
- uint32 slot;
- recvData >> slot;
-
- if (slot >= MAX_GLYPH_SLOT_INDEX)
- {
- TC_LOG_DEBUG("network", "Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot);
- return;
- }
-
- if (uint32 glyph = _player->GetGlyph(_player->GetActiveTalentGroup(), slot))
- {
- if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
- {
- _player->RemoveAurasDueToSpell(gp->SpellID);
- _player->SetGlyph(slot, 0);
- _player->SendTalentsInfoData();
- }
- }
-}
-
void WorldSession::HandleCharCustomizeOpcode(WorldPackets::Character::CharCustomize& packet)
{
if (!IsLegitCharacterForAccount(packet.CustomizeInfo->CharGUID))
@@ -1544,7 +1527,8 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World
uint8 plrGender = fields[3].GetUInt8();
uint16 atLoginFlags = fields[4].GetUInt16();
- if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo->HairStyleID, customizeInfo->HairColorID, customizeInfo->FaceID, customizeInfo->FacialHairStyleID, customizeInfo->SkinID, true))
+ if (!Player::ValidateAppearance(plrRace, plrClass, plrGender, customizeInfo->HairStyleID, customizeInfo->HairColorID, customizeInfo->FaceID,
+ customizeInfo->FacialHairStyleID, customizeInfo->SkinID, customizeInfo->CustomDisplay))
{
SendCharCustomize(CHAR_CREATE_ERROR, customizeInfo);
return;
@@ -1606,7 +1590,10 @@ void WorldSession::HandleCharCustomizeCallback(PreparedQueryResult result, World
stmt->setUInt8(3, customizeInfo->HairStyleID);
stmt->setUInt8(4, customizeInfo->HairColorID);
stmt->setUInt8(5, customizeInfo->FacialHairStyleID);
- stmt->setUInt64(6, lowGuid);
+ 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);
}
@@ -1641,29 +1628,86 @@ void WorldSession::HandleEquipmentSetSave(WorldPackets::EquipmentSet::SaveEquipm
if (saveEquipmentSet.Set.SetID >= MAX_EQUIPMENT_SET_INDEX) // client set slots amount
return;
+ if (saveEquipmentSet.Set.Type > EquipmentSetInfo::TRANSMOG)
+ return;
+
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
{
if (!(saveEquipmentSet.Set.IgnoreMask & (1 << i)))
{
- ObjectGuid const& itemGuid = saveEquipmentSet.Set.Pieces[i];
+ if (saveEquipmentSet.Set.Type == EquipmentSetInfo::EQUIPMENT)
+ {
+ saveEquipmentSet.Set.Appearances[i] = 0;
- Item* item = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
+ ObjectGuid const& itemGuid = saveEquipmentSet.Set.Pieces[i];
- /// cheating check 1 (item equipped but sent empty guid)
- if (!item && !itemGuid.IsEmpty())
- return;
+ Item* item = _player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- /// cheating check 2 (sent guid does not match equipped item)
- if (item && item->GetGUID() != itemGuid)
- return;
+ /// cheating check 1 (item equipped but sent empty guid)
+ if (!item && !itemGuid.IsEmpty())
+ return;
+
+ /// cheating check 2 (sent guid does not match equipped item)
+ if (item && item->GetGUID() != itemGuid)
+ return;
+ }
+ else
+ {
+ saveEquipmentSet.Set.Pieces[i].Clear();
+ if (saveEquipmentSet.Set.Appearances[i])
+ {
+ if (!sItemModifiedAppearanceStore.LookupEntry(saveEquipmentSet.Set.Appearances[i]))
+ return;
+
+ bool hasAppearance, isTemporary;
+ std::tie(hasAppearance, isTemporary) = GetCollectionMgr()->HasItemAppearance(saveEquipmentSet.Set.Appearances[i]);
+ if (!hasAppearance)
+ return;
+ }
+ }
}
else
+ {
saveEquipmentSet.Set.Pieces[i].Clear();
+ saveEquipmentSet.Set.Appearances[i] = 0;
+ }
}
saveEquipmentSet.Set.IgnoreMask &= 0x7FFFF; /// clear invalid bits (i > EQUIPMENT_SLOT_END)
+ if (saveEquipmentSet.Set.Type == EquipmentSetInfo::EQUIPMENT)
+ {
+ saveEquipmentSet.Set.Enchants[0] = 0;
+ saveEquipmentSet.Set.Enchants[1] = 0;
+ }
+ else
+ {
+ auto validateIllusion = [this](uint32 enchantId) -> bool
+ {
+ SpellItemEnchantmentEntry const* illusion = sSpellItemEnchantmentStore.LookupEntry(enchantId);
+ if (!illusion)
+ return false;
+
+ if (!illusion->ItemVisual || !(illusion->Flags & ENCHANTMENT_COLLECTABLE))
+ return false;
+
+ if (PlayerConditionEntry const* condition = sPlayerConditionStore.LookupEntry(illusion->PlayerConditionID))
+ if (!sConditionMgr->IsPlayerMeetingCondition(_player, condition))
+ return false;
+
+ if (illusion->ScalingClassRestricted > 0 && uint8(illusion->ScalingClassRestricted) != _player->getClass())
+ return false;
+
+ return true;
+ };
+
+ if (saveEquipmentSet.Set.Enchants[0] && !validateIllusion(saveEquipmentSet.Set.Enchants[0]))
+ return;
- _player->SetEquipmentSet(std::move(saveEquipmentSet.Set));
+ if (saveEquipmentSet.Set.Enchants[1] && !validateIllusion(saveEquipmentSet.Set.Enchants[1]))
+ return;
+ }
+
+ _player->SetEquipmentSet(saveEquipmentSet.Set);
}
void WorldSession::HandleDeleteEquipmentSet(WorldPackets::EquipmentSet::DeleteEquipmentSet& deleteEquipmentSet)
@@ -1866,29 +1910,17 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
// Customize
{
- if (!factionChangeInfo->SkinID)
- factionChangeInfo->SkinID = fields[2].GetUInt8();
-
- if (!factionChangeInfo->FaceID)
- factionChangeInfo->FaceID = fields[3].GetUInt8();
-
- if (!factionChangeInfo->HairStyleID)
- factionChangeInfo->HairStyleID = fields[4].GetUInt8();
-
- if (!factionChangeInfo->HairColorID)
- factionChangeInfo->HairColorID = fields[5].GetUInt8();
-
- if (!factionChangeInfo->FacialHairStyleID)
- factionChangeInfo->FacialHairStyleID = fields[6].GetUInt8();
-
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->setUInt64(6, lowGuid);
+ 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);
}
@@ -2544,12 +2576,13 @@ void WorldSession::SendCharFactionChange(ResponseCodes result, WorldPackets::Cha
packet.Display = boost::in_place();
packet.Display->Name = factionChangeInfo->Name;
packet.Display->SexID = factionChangeInfo->SexID;
- packet.Display->SkinID = *factionChangeInfo->SkinID;
- packet.Display->HairColorID = *factionChangeInfo->HairColorID;
- packet.Display->HairStyleID = *factionChangeInfo->HairStyleID;
- packet.Display->FacialHairStyleID = *factionChangeInfo->FacialHairStyleID;
- packet.Display->FaceID = *factionChangeInfo->FaceID;
+ packet.Display->SkinID = factionChangeInfo->SkinID;
+ packet.Display->HairColorID = factionChangeInfo->HairColorID;
+ packet.Display->HairStyleID = factionChangeInfo->HairStyleID;
+ packet.Display->FacialHairStyleID = factionChangeInfo->FacialHairStyleID;
+ packet.Display->FaceID = factionChangeInfo->FaceID;
packet.Display->RaceID = factionChangeInfo->RaceID;
+ packet.Display->CustomDisplay = factionChangeInfo->CustomDisplay;
}
SendPacket(packet.Write());