diff options
author | Ovahlord <dreadkiller@gmx.de> | 2024-11-01 08:09:15 +0100 |
---|---|---|
committer | Ovahlord <dreadkiller@gmx.de> | 2024-11-01 16:33:57 +0100 |
commit | 6de12ffcfa30355687f293a051dfae58ceac5cc7 (patch) | |
tree | af38cb407f80fda4b1cdc9a5fd1db53a884c759d /src | |
parent | 5c0fb42c9b34707ff4e671739591b008fb0a07f2 (diff) |
Core/Packets: updated packet structures for 4.4.1
Diffstat (limited to 'src')
73 files changed, 764 insertions, 324 deletions
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index b9576d9ce66..024aa3264f0 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -322,6 +322,8 @@ private: return int64(left->BidAmount) - int64(right->BidAmount); case AuctionHouseSortOrder::Buyout: return int64(left->BuyoutOrUnitPrice) - int64(right->BuyoutOrUnitPrice); + case AuctionHouseSortOrder::TimeRemaining: + return (left->EndTime - right->EndTime).count(); default: break; } diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h index bdaa0516339..f6354060022 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.h +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h @@ -116,11 +116,12 @@ DEFINE_ENUM_FLAG(AuctionHouseFilterMask); enum class AuctionHouseSortOrder : uint8 { - Price = 0, - Name = 1, - Level = 2, - Bid = 3, - Buyout = 4 + Price = 0, + Name = 1, + Level = 2, + Bid = 3, + Buyout = 4, + TimeRemaining = 5 }; enum class AuctionHouseBrowseMode : uint8 diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index bd7795f31cb..734c0caa392 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -1629,7 +1629,7 @@ std::vector<DB2Manager::HotfixOptionalData> const* DB2Manager::GetHotfixOptional uint32 DB2Manager::GetEmptyAnimStateID() const { //return sAnimationDataStore.GetNumRows(); - return 1778; // the Classic client expects the retail storage size so we have to hardcode the value + return 1788; // Yup, again } void DB2Manager::InsertNewHotfix(uint32 tableHash, uint32 recordId) diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 81cba0090b0..55d60d4ec5f 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -1758,7 +1758,7 @@ enum class PlayerInteractionType : int32 PersonalTabardVendor = 65, ForgeMaster = 66, CharacterBanker = 67, - AccountBanker = 68 + AccountBanker = 68, }; enum class PowerTypeFlags : int16 diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 3de50a81f32..2aef082dd71 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -246,7 +246,10 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID) packet.GossipGUID = objectGUID; packet.GossipID = _gossipMenu.GetMenuId(); if (GossipMenuAddon const* addon = sObjectMgr->GetGossipMenuAddon(packet.GossipID)) + { packet.FriendshipFactionID = addon->FriendshipFactionID; + packet.LfgDungeonsID = addon->LfgDungeonsID; + } if (NpcText const* text = sObjectMgr->GetNpcText(titleTextId)) packet.BroadcastTextID = Trinity::Containers::SelectRandomWeightedContainerElement(text->Data, [](NpcTextData const& data) { return data.Probability; })->BroadcastTextID; @@ -284,8 +287,10 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID) text.QuestMaxScalingLevel = quest->GetQuestMaxScalingLevel(); text.QuestFlags[0] = quest->GetFlags(); text.QuestFlags[1] = quest->GetFlagsEx(); + text.QuestFlags[2] = quest->GetFlagsEx2(); text.Repeatable = quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly(); text.Important = quest->IsImportant(); + text.Meta = quest->IsMeta(); text.QuestTitle = quest->GetLogTitle(); LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex(); @@ -411,8 +416,10 @@ void PlayerMenu::SendQuestGiverQuestListMessage(Object* questgiver) text.QuestType = questMenuItem.QuestIcon; text.QuestFlags[0] = quest->GetFlags(); text.QuestFlags[1] = quest->GetFlagsEx(); + text.QuestFlags[2] = quest->GetFlagsEx2(); text.Repeatable = quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly(); text.Important = quest->IsImportant(); + text.Meta = quest->IsMeta(); text.QuestTitle = quest->GetLogTitle(); LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex(); @@ -478,6 +485,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU packet.PortraitGiverMount = quest->GetQuestGiverPortraitMount(); packet.PortraitGiverModelSceneID = quest->GetQuestGiverPortraitModelSceneId(); packet.PortraitTurnIn = quest->GetQuestTurnInPortrait(); + packet.QuestInfoID = quest->GetQuestInfoID(); packet.QuestSessionBonus = 0; //quest->GetQuestSessionBonus(); // this is only sent while quest session is active packet.AutoLaunched = autoLaunched; packet.DisplayPopup = displayPopup; @@ -510,9 +518,9 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU for (uint32 i = 0; i < objs.size(); ++i) { packet.Objectives[i].ID = objs[i].ID; + packet.Objectives[i].Type = objs[i].Type; packet.Objectives[i].ObjectID = objs[i].ObjectID; packet.Objectives[i].Amount = objs[i].Amount; - packet.Objectives[i].Type = objs[i].Type; } _session->SendPacket(packet.Write()); @@ -582,6 +590,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI offer.QuestID = quest->GetQuestId(); offer.AutoLaunched = autoLaunched; offer.SuggestedPartyMembers = quest->GetSuggestedPlayers(); + offer.QuestInfoID = quest->GetQuestInfoID(); for (uint32 i = 0; i < QUEST_EMOTE_COUNT && quest->OfferRewardEmote[i]; ++i) offer.Emotes.emplace_back(quest->OfferRewardEmote[i], quest->OfferRewardEmoteDelay[i]); @@ -656,6 +665,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGU packet.QuestFlags[1] = quest->GetFlagsEx(); packet.QuestFlags[2] = quest->GetFlagsEx2(); packet.SuggestPartyMembers = quest->GetSuggestedPlayers(); + packet.QuestInfoID = quest->GetQuestInfoID(); // incomplete: FD // incomplete quest with item objective but item objective is complete DD diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h index cb303ed329a..12d40c84553 100644 --- a/src/server/game/Entities/Item/Container/Bag.h +++ b/src/server/game/Entities/Item/Container/Bag.h @@ -19,7 +19,7 @@ #define TRINITY_BAG_H // Maximum 36 Slots ((CONTAINER_END - CONTAINER_FIELD_SLOT_1)/2 -#define MAX_BAG_SIZE 36 // 2.0.12 +#define MAX_BAG_SIZE 36 // 4.4.1 #include "Item.h" diff --git a/src/server/game/Entities/Object/Updates/UpdateMask.h b/src/server/game/Entities/Object/Updates/UpdateMask.h index b8262387907..a79b5c038ab 100644 --- a/src/server/game/Entities/Object/Updates/UpdateMask.h +++ b/src/server/game/Entities/Object/Updates/UpdateMask.h @@ -63,7 +63,7 @@ public: constexpr bool operator[](uint32 index) const { - return (_blocks[index / 32] & (1 << (index % 32))) != 0; + return (_blocks[UpdateMaskHelpers::GetBlockIndex(index)] & UpdateMaskHelpers::GetBlockFlag(index)) != 0; } constexpr bool IsAnySet() const diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index a8291c568ed..9a3adbd32d4 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -6100,6 +6100,35 @@ int32 Player::CalculateReputationGain(ReputationSource source, uint32 creatureOr return CalculatePct(rep, percent); } +void Player::SetVisibleForcedReaction(uint32 factionId, ReputationRank rank) +{ + auto itr = std::ranges::find(m_playerData->ForcedReactions, int32(factionId), &UF::ZonePlayerForcedReaction::FactionID); + if (itr == m_playerData->ForcedReactions.end()) + itr = std::ranges::find(m_playerData->ForcedReactions, 0, &UF::ZonePlayerForcedReaction::FactionID); + + if (itr == m_playerData->ForcedReactions.end()) + return; // no more free slots + + auto setter = m_values.ModifyValue(&Player::m_playerData) + .ModifyValue(&UF::PlayerData::ForcedReactions, std::ranges::distance(m_playerData->ForcedReactions.begin(), itr)); + + SetUpdateFieldValue(setter.ModifyValue(&UF::ZonePlayerForcedReaction::FactionID), factionId); + SetUpdateFieldValue(setter.ModifyValue(&UF::ZonePlayerForcedReaction::Reaction), rank); +} + +void Player::RemoveVisibleForcedReaction(uint32 factionId) +{ + auto itr = std::ranges::find(m_playerData->ForcedReactions, int32(factionId), &UF::ZonePlayerForcedReaction::FactionID); + if (itr == m_playerData->ForcedReactions.end()) + return; + + auto setter = m_values.ModifyValue(&Player::m_playerData) + .ModifyValue(&UF::PlayerData::ForcedReactions, std::ranges::distance(m_playerData->ForcedReactions.begin(), itr)); + + SetUpdateFieldValue(setter.ModifyValue(&UF::ZonePlayerForcedReaction::FactionID), 0); + SetUpdateFieldValue(setter.ModifyValue(&UF::ZonePlayerForcedReaction::Reaction), 0); +} + // Calculates how many reputation points player gains in victim's enemy factions void Player::RewardReputation(Unit* victim, float rate) { @@ -12983,6 +13012,7 @@ void Player::SendNewItem(Item* item, uint32 quantity, bool pushed, bool created, packet.QuestLogItemID = item->GetTemplate()->QuestLogItemId; packet.Quantity = quantity; packet.QuantityInInventory = GetItemCount(item->GetEntry()); + packet.BattlePetSpeciesID = item->GetModifier(ITEM_MODIFIER_BATTLE_PET_SPECIES_ID); packet.BattlePetBreedID = item->GetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA) & 0xFFFFFF; packet.BattlePetBreedQuality = (item->GetModifier(ITEM_MODIFIER_BATTLE_PET_BREED_DATA) >> 24) & 0xFF; @@ -15243,20 +15273,28 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object const* questgiver) const case QUEST_STATUS_COMPLETE: if (quest->IsImportant()) result |= quest->HasFlag(QUEST_FLAGS_HIDE_REWARD_POI) ? QuestGiverStatus::ImportantQuestRewardCompleteNoPOI : QuestGiverStatus::ImportantQuestRewardCompletePOI; + else if (quest->IsMeta()) + result |= quest->HasFlag(QUEST_FLAGS_HIDE_REWARD_POI) ? QuestGiverStatus::MetaQuestRewardCompleteNoPOI : QuestGiverStatus::MetaQuestRewardCompletePOI; else if (quest->GetQuestTag() == QuestTagType::CovenantCalling) result |= quest->HasFlag(QUEST_FLAGS_HIDE_REWARD_POI) ? QuestGiverStatus::CovenantCallingRewardCompleteNoPOI : QuestGiverStatus::CovenantCallingRewardCompletePOI; else if (quest->HasFlagEx(QUEST_FLAGS_EX_LEGENDARY)) result |= quest->HasFlag(QUEST_FLAGS_HIDE_REWARD_POI) ? QuestGiverStatus::LegendaryRewardCompleteNoPOI : QuestGiverStatus::LegendaryRewardCompletePOI; + else if (quest->IsDailyOrWeekly()) + result |= quest->HasFlag(QUEST_FLAGS_HIDE_REWARD_POI) ? QuestGiverStatus::RepeatableRewardCompleteNoPOI : QuestGiverStatus::RepeatableRewardCompletePOI; else result |= quest->HasFlag(QUEST_FLAGS_HIDE_REWARD_POI) ? QuestGiverStatus::RewardCompleteNoPOI : QuestGiverStatus::RewardCompletePOI; break; case QUEST_STATUS_INCOMPLETE: if (quest->IsImportant()) result |= QuestGiverStatus::ImportantReward; + else if (quest->IsMeta()) + result |= QuestGiverStatus::MetaReward; else if (quest->GetQuestTag() == QuestTagType::CovenantCalling) result |= QuestGiverStatus::CovenantCallingReward; else if (quest->HasFlagEx(QUEST_FLAGS_EX_LEGENDARY)) result |= QuestGiverStatus::LegendaryReward; + else if (quest->IsDailyOrWeekly()) + result |= QuestGiverStatus::RepeatableReward; else result |= QuestGiverStatus::Reward; break; @@ -15264,12 +15302,17 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object const* questgiver) const break; } - if (quest->IsTurnIn() && CanTakeQuest(quest, false) && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly()) + if (quest->IsTurnIn() && CanTakeQuest(quest, false)) { - if (GetLevel() > (GetQuestLevel(quest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) - result |= QuestGiverStatus::RepeatableTurnin; + if (quest->IsRepeatable()) + { + if (GetLevel() > (GetQuestLevel(quest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) + result |= QuestGiverStatus::RepeatableTurnin; + else + result |= QuestGiverStatus::TrivialRepeatableTurnin; + } else - result |= QuestGiverStatus::TrivialRepeatableTurnin; + result |= quest->HasFlag(QUEST_FLAGS_HIDE_REWARD_POI) ? QuestGiverStatus::RewardCompleteNoPOI : QuestGiverStatus::RewardCompletePOI; } } @@ -15291,12 +15334,14 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object const* questgiver) const bool isTrivial = GetLevel() > (GetQuestLevel(quest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF)); if (quest->IsImportant()) result |= isTrivial ? QuestGiverStatus::TrivialImportantQuest : QuestGiverStatus::ImportantQuest; + else if (quest->IsMeta()) + result |= isTrivial ? QuestGiverStatus::TrivialMetaQuest : QuestGiverStatus::MetaQuest; else if (quest->GetQuestTag() == QuestTagType::CovenantCalling) result |= QuestGiverStatus::CovenantCallingQuest; else if (quest->HasFlagEx(QUEST_FLAGS_EX_LEGENDARY)) result |= isTrivial ? QuestGiverStatus::TrivialLegendaryQuest : QuestGiverStatus::LegendaryQuest; - else if (quest->IsDaily()) - result |= isTrivial ? QuestGiverStatus::TrivialDailyQuest : QuestGiverStatus::DailyQuest; + else if (quest->IsDailyOrWeekly()) + result |= isTrivial ? QuestGiverStatus::TrivialRepeatableQuest : QuestGiverStatus::RepeatableQuest; else result |= isTrivial ? QuestGiverStatus::Trivial : QuestGiverStatus::Quest; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index ebbe8672933..0265e2f79db 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2221,6 +2221,9 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player> int32 CalculateReputationGain(ReputationSource source, uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool noQuestBonus = false); + void SetVisibleForcedReaction(uint32 factionId, ReputationRank rank); + void RemoveVisibleForcedReaction(uint32 factionId); + void UpdateSkillsForLevel(); void ModifySkillBonus(uint32 skillid, int32 val, bool talent); diff --git a/src/server/game/Entities/Unit/enuminfo_UnitDefines.cpp b/src/server/game/Entities/Unit/enuminfo_UnitDefines.cpp index ba419d8a6b2..0c04002403b 100644 --- a/src/server/game/Entities/Unit/enuminfo_UnitDefines.cpp +++ b/src/server/game/Entities/Unit/enuminfo_UnitDefines.cpp @@ -421,7 +421,7 @@ TC_API_EXPORT EnumText EnumUtils<NPCFlags>::ToString(NPCFlags value) case UNIT_NPC_FLAG_NONE: return { "UNIT_NPC_FLAG_NONE", "UNIT_NPC_FLAG_NONE", "" }; case UNIT_NPC_FLAG_GOSSIP: return { "UNIT_NPC_FLAG_GOSSIP", "has gossip menu", "100%" }; case UNIT_NPC_FLAG_QUESTGIVER: return { "UNIT_NPC_FLAG_QUESTGIVER", "is quest giver", "100%" }; - case UNIT_NPC_FLAG_ACCOUNT_BANKER: return { "UNIT_NPC_FLAG_ACCOUNT_BANKER", "UNIT_NPC_FLAG_ACCOUNT_BANKER", "" }; + case UNIT_NPC_FLAG_ACCOUNT_BANKER: return { "UNIT_NPC_FLAG_ACCOUNT_BANKER", "is account banker", "" }; case UNIT_NPC_FLAG_UNK2: return { "UNIT_NPC_FLAG_UNK2", "UNIT_NPC_FLAG_UNK2", "" }; case UNIT_NPC_FLAG_TRAINER: return { "UNIT_NPC_FLAG_TRAINER", "is trainer", "100%" }; case UNIT_NPC_FLAG_TRAINER_CLASS: return { "UNIT_NPC_FLAG_TRAINER_CLASS", "is class trainer", "100%" }; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 3a55a5ae777..e4e06525335 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4303,9 +4303,9 @@ void ObjectMgr::LoadQuests() "RewardFactionID5, RewardFactionValue5, RewardFactionOverride5, RewardFactionCapIn5, RewardFactionFlags, " //93 94 95 96 97 98 99 100 "RewardCurrencyID1, RewardCurrencyQty1, RewardCurrencyID2, RewardCurrencyQty2, RewardCurrencyID3, RewardCurrencyQty3, RewardCurrencyID4, RewardCurrencyQty4, " - //101 102 103 104 105 106 107 108 109 - "AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, TreasurePickerID, Expansion, ManagedWorldStateID, QuestSessionBonus, " - //110 111 112 113 114 115 116 117 118 + //101 102 103 104 105 106 107 108 + "AcceptedSoundKitID, CompleteSoundKitID, AreaGroupID, TimeAllowed, AllowableRaces, Expansion, ManagedWorldStateID, QuestSessionBonus, " + //109 110 111 112 113 114 115 116 117 "LogTitle, LogDescription, QuestDescription, AreaDescription, PortraitGiverText, PortraitGiverName, PortraitTurnInText, PortraitTurnInName, QuestCompletionLog " "FROM quest_template"); if (!result) @@ -4384,7 +4384,10 @@ void ObjectMgr::LoadQuests() { "QuestId, PlayerConditionId, QuestgiverCreatureId, Text, locale", "quest_offer_reward_conditional", "ORDER BY OrderIndex", "conditional reward", &Quest::LoadConditionalConditionalOfferRewardText }, // 0 1 2 3 4 - { "QuestId, PlayerConditionId, QuestgiverCreatureId, Text, locale", "quest_completion_log_conditional", "ORDER BY OrderIndex", "conditional completion log", &Quest::LoadConditionalConditionalQuestCompletionLog } + { "QuestId, PlayerConditionId, QuestgiverCreatureId, Text, locale", "quest_completion_log_conditional", "ORDER BY OrderIndex", "conditional completion log", &Quest::LoadConditionalConditionalQuestCompletionLog }, + + // 0 1 + { "QuestID, TreasurePickerID", "quest_treasure_pickers", "ORDER BY OrderIndex", "treasure pickers", &Quest::LoadTreasurePickers } }; for (QuestLoaderHelper const& loader : QuestLoaderHelpers) @@ -9518,8 +9521,8 @@ void ObjectMgr::LoadGossipMenuAddon() _gossipMenuAddonStore.clear(); - // 0 1 - QueryResult result = WorldDatabase.Query("SELECT MenuID, FriendshipFactionID FROM gossip_menu_addon"); + // 0 1 2 + QueryResult result = WorldDatabase.Query("SELECT MenuID, FriendshipFactionID, LfgDungeonsID FROM gossip_menu_addon"); if (!result) { @@ -9534,20 +9537,30 @@ void ObjectMgr::LoadGossipMenuAddon() uint32 menuID = fields[0].GetUInt32(); GossipMenuAddon& addon = _gossipMenuAddonStore[menuID]; addon.FriendshipFactionID = fields[1].GetInt32(); + addon.LfgDungeonsID = fields[2].GetInt32(); - if (FactionEntry const* faction = sFactionStore.LookupEntry(addon.FriendshipFactionID)) + if (addon.FriendshipFactionID) { - if (!sFriendshipReputationStore.LookupEntry(faction->FriendshipRepID)) + if (FactionEntry const* faction = sFactionStore.LookupEntry(addon.FriendshipFactionID)) + { + if (!sFriendshipReputationStore.LookupEntry(faction->FriendshipRepID)) + { + TC_LOG_ERROR("sql.sql", "Table gossip_menu_addon: ID {} is using FriendshipFactionID {} referencing non-existing FriendshipRepID {}", + menuID, addon.FriendshipFactionID, faction->FriendshipRepID); + addon.FriendshipFactionID = 0; + } + } + else { - TC_LOG_ERROR("sql.sql", "Table gossip_menu_addon: ID {} is using FriendshipFactionID {} referencing non-existing FriendshipRepID {}", - menuID, addon.FriendshipFactionID, faction->FriendshipRepID); + TC_LOG_ERROR("sql.sql", "Table gossip_menu_addon: ID {} is using non-existing FriendshipFactionID {}", menuID, addon.FriendshipFactionID); addon.FriendshipFactionID = 0; } } - else + + if (addon.LfgDungeonsID && sLFGDungeonsStore.LookupEntry(addon.LfgDungeonsID)) { - TC_LOG_ERROR("sql.sql", "Table gossip_menu_addon: ID {} is using non-existing FriendshipFactionID {}", menuID, addon.FriendshipFactionID); - addon.FriendshipFactionID = 0; + TC_LOG_ERROR("sql.sql", "Table gossip_menu_addon: ID {} is using non-existing LfgDungeonsID {}", menuID, addon.LfgDungeonsID); + addon.LfgDungeonsID = 0; } } while (result->NextRow()); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index e972ca59ef1..72e0bfaa332 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -779,6 +779,7 @@ struct GossipMenus struct GossipMenuAddon { int32 FriendshipFactionID; + int32 LfgDungeonsID; }; typedef std::multimap<uint32, GossipMenus> GossipMenusContainer; diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index bd173358fa1..90c895d11a3 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -246,6 +246,9 @@ void Group::LoadGroupFromDB(Field* fields) m_masterLooterGuid = ObjectGuid::Create<HighGuid::Player>(fields[16].GetUInt64()); + // m_pingRestriction = RestrictPingsTo(fields[18].GetInt8()); + m_pingRestriction = RestrictPingsTo::None; + if (m_groupFlags & GROUP_FLAG_LFG) sLFGMgr->_LoadFromDB(fields, GetGUID()); } @@ -870,6 +873,8 @@ void Group::SendUpdateToPlayer(ObjectGuid playerGUID, MemberSlot const* slot) co partyUpdate.SequenceNum = player->NextGroupUpdateSequenceNumber(m_groupCategory); + partyUpdate.PingRestriction = m_pingRestriction; + partyUpdate.MyIndex = -1; uint8 index = 0; for (member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr, ++index) @@ -1901,27 +1906,27 @@ void Group::SetEveryoneIsAssistant(bool apply) SendUpdate(); } -bool Group::IsRestrictPingsToAssistants() const +RestrictPingsTo Group::GetRestrictPings() const { - return (m_groupFlags & GROUP_FLAG_RESTRICT_PINGS) != 0; + return m_pingRestriction; } -void Group::SetRestrictPingsToAssistants(bool restrictPingsToAssistants) +void Group::SetRestrictPingsTo(RestrictPingsTo restrictTo) { - if (restrictPingsToAssistants) - m_groupFlags = GroupFlags(m_groupFlags | GROUP_FLAG_RESTRICT_PINGS); - else - m_groupFlags = GroupFlags(m_groupFlags & ~GROUP_FLAG_RESTRICT_PINGS); + m_pingRestriction = restrictTo; + // Classic only - Disabled + /* if (!isBGGroup() && !isBFGroup()) { - CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_TYPE); + CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_PING_RESTRICTION); - stmt->setUInt16(0, m_groupFlags); + stmt->setInt8(0, int8(m_pingRestriction)); stmt->setUInt32(1, m_dbStoreId); CharacterDatabase.Execute(stmt); } SendUpdate(); + */ } diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 8ba2f36e3c3..773c705a08a 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -103,7 +103,7 @@ enum GroupFlags : uint16 GROUP_FLAG_EVERYONE_ASSISTANT = 0x040, // Script_IsEveryoneAssistant() GROUP_FLAG_GUILD_GROUP = 0x100, GROUP_FLAG_CROSS_FACTION = 0x200, - GROUP_FLAG_RESTRICT_PINGS = 0x400, // C_PartyInfo::Script_GetRestrictPings() + GROUP_FLAG_RESTRICT_PINGS = 0x400, // deprecated GROUP_MASK_BGRAID = GROUP_FLAG_FAKE_RAID | GROUP_FLAG_RAID, }; @@ -191,6 +191,15 @@ enum class PingSubjectType : uint8 Max }; + +enum class RestrictPingsTo : int32 +{ + None = 0, + Lead = 1, + Assist = 2, + TankHealer = 3, +}; + /** request member stats checken **/ /// @todo uninvite people that not accepted invite class TC_GAME_API Group @@ -260,8 +269,8 @@ class TC_GAME_API Group void SetLfgRoles(ObjectGuid guid, uint8 roles); uint8 GetLfgRoles(ObjectGuid guid) const; void SetEveryoneIsAssistant(bool apply); - bool IsRestrictPingsToAssistants() const; - void SetRestrictPingsToAssistants(bool restrictPingsToAssistants); + RestrictPingsTo GetRestrictPings() const; + void SetRestrictPingsTo(RestrictPingsTo restrictTo); // Update void UpdateReadyCheck(uint32 diff); @@ -451,6 +460,8 @@ class TC_GAME_API Group std::array<std::unique_ptr<CountdownInfo>, 3> m_countdowns; + RestrictPingsTo m_pingRestriction; + struct NoopGroupDeleter { void operator()(Group*) const { /*noop - not managed*/ } }; Trinity::unique_trackable_ptr<Group> m_scriptRef; }; diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 28147294e1d..8a5ead4c218 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -2479,7 +2479,6 @@ void Guild::SendEventPresenceChanged(WorldSession* session, bool loggedOn, bool eventPacket.Name = player->GetName(); eventPacket.VirtualRealmAddress = player->m_playerData->VirtualPlayerRealm; eventPacket.LoggedOn = loggedOn; - eventPacket.Mobile = false; if (broadcast) BroadcastPacket(eventPacket.Write()); diff --git a/src/server/game/Handlers/BankHandler.cpp b/src/server/game/Handlers/BankHandler.cpp index f10b2553d19..7e8b49e6ef8 100644 --- a/src/server/game/Handlers/BankHandler.cpp +++ b/src/server/game/Handlers/BankHandler.cpp @@ -15,14 +15,15 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "WorldSession.h" #include "BankPackets.h" -#include "Item.h" +#include "Creature.h" #include "DB2Stores.h" #include "GossipDef.h" +#include "Item.h" #include "Log.h" #include "NPCPackets.h" #include "Player.h" -#include "WorldSession.h" void WorldSession::HandleAutoBankItemOpcode(WorldPackets::Bank::AutoBankItem& packet) { @@ -34,6 +35,9 @@ void WorldSession::HandleAutoBankItemOpcode(WorldPackets::Bank::AutoBankItem& pa return; } + if (packet.BankType != BankType::Character) + return; + Item* item = _player->GetItemByPos(packet.Bag, packet.Slot); if (!item) return; @@ -57,22 +61,43 @@ void WorldSession::HandleAutoBankItemOpcode(WorldPackets::Bank::AutoBankItem& pa _player->BankItem(dest, item, true); } -void WorldSession::HandleBankerActivateOpcode(WorldPackets::NPC::Hello& packet) +void WorldSession::HandleBankerActivateOpcode(WorldPackets::Bank::BankerActivate const& bankerActivate) { - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(packet.Unit, UNIT_NPC_FLAG_BANKER, UNIT_NPC_FLAG_2_NONE); + if (bankerActivate.InteractionType != PlayerInteractionType::Banker) + return; + + Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(bankerActivate.Banker, UNIT_NPC_FLAG_ACCOUNT_BANKER | UNIT_NPC_FLAG_BANKER, UNIT_NPC_FLAG_2_NONE); if (!unit) { - TC_LOG_ERROR("network", "WORLD: HandleBankerActivateOpcode - {} not found or you can not interact with him.", packet.Unit.ToString()); + TC_LOG_ERROR("network", "WORLD: HandleBankerActivateOpcode - {} not found or you can not interact with him.", bankerActivate.Banker); return; } + switch (bankerActivate.InteractionType) + { + case PlayerInteractionType::Banker: + if (!unit->HasNpcFlag(UNIT_NPC_FLAG_ACCOUNT_BANKER) || !unit->HasNpcFlag(UNIT_NPC_FLAG_BANKER)) + return; + break; + case PlayerInteractionType::CharacterBanker: + if (!unit->HasNpcFlag(UNIT_NPC_FLAG_BANKER)) + return; + break; + case PlayerInteractionType::AccountBanker: + if (!unit->HasNpcFlag(UNIT_NPC_FLAG_ACCOUNT_BANKER)) + return; + break; + default: + break; + } + // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // set currentBankerGUID for other bank action - SendShowBank(packet.Unit); + SendShowBank(bankerActivate.Banker, bankerActivate.InteractionType); } void WorldSession::HandleAutoStoreBankItemOpcode(WorldPackets::Bank::AutoStoreBankItem& packet) @@ -149,13 +174,13 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPackets::Bank::BuyBankSlot& pack _player->UpdateCriteria(CriteriaType::BankSlotsPurchased); } -void WorldSession::SendShowBank(ObjectGuid guid) +void WorldSession::SendShowBank(ObjectGuid guid, PlayerInteractionType interactionType) { _player->PlayerTalkClass->GetInteractionData().Reset(); _player->PlayerTalkClass->GetInteractionData().SourceGuid = guid; WorldPackets::NPC::NPCInteractionOpenResult npcInteraction; npcInteraction.Npc = guid; - npcInteraction.InteractionType = PlayerInteractionType::Banker; + npcInteraction.InteractionType = interactionType; npcInteraction.Success = true; SendPacket(npcInteraction.Write()); } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 3603e793405..6f4bf4e2091 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -349,7 +349,7 @@ void WorldSession::HandleCharEnum(CharacterDatabaseQueryHolder const& holder) { charEnum.Characters.emplace_back(result->Fetch()); - WorldPackets::Character::EnumCharactersResult::CharacterInfo& charInfo = charEnum.Characters.back(); + WorldPackets::Character::EnumCharactersResult::CharacterInfoBasic& charInfo = charEnum.Characters.back().Basic; if (std::vector<UF::ChrCustomizationChoice>* customizationsForChar = Trinity::Containers::MapGetValuePtr(customizations, charInfo.Guid.GetCounter())) charInfo.Customizations = std::move(*customizationsForChar); diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 9217e42225b..5f2ab41c856 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -260,6 +260,7 @@ void WorldSession::HandleSuspendTokenResponse(WorldPackets::Movement::SuspendTok packet.MapID = loc.Location.GetMapId(); packet.Loc.Pos = loc.Location; packet.Reason = !_player->IsBeingTeleportedSeamlessly() ? NEW_WORLD_NORMAL : NEW_WORLD_SEAMLESS; + packet.Counter = _player->GetNewWorldCounter(); SendPacket(packet.Write()); if (_player->IsBeingTeleportedSeamlessly()) diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp index 39f9a55f601..49066237cc2 100644 --- a/src/server/game/Handlers/TaxiHandler.cpp +++ b/src/server/game/Handlers/TaxiHandler.cpp @@ -133,7 +133,7 @@ bool WorldSession::SendLearnNewTaxiNode(Creature* unit) if (GetPlayer()->m_taxi.SetTaximaskNode(curloc)) { - SendPacket(WorldPackets::Taxi::NewTaxiPath().Write()); + SendPacket(WorldPackets::Taxi::NewTaxiPath(curloc).Write()); WorldPackets::Taxi::TaxiNodeStatus data; data.Unit = unit->GetGUID(); @@ -149,7 +149,7 @@ bool WorldSession::SendLearnNewTaxiNode(Creature* unit) void WorldSession::SendDiscoverNewTaxiNode(uint32 nodeid) { if (GetPlayer()->m_taxi.SetTaximaskNode(nodeid)) - SendPacket(WorldPackets::Taxi::NewTaxiPath().Write()); + SendPacket(WorldPackets::Taxi::NewTaxiPath(nodeid).Write()); } void WorldSession::HandleActivateTaxiOpcode(WorldPackets::Taxi::ActivateTaxi& activateTaxi) diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 55db20cb361..beddc00ba99 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -118,20 +118,19 @@ Quest::Quest(Field* questRecord) _areaGroupID = questRecord[103].GetUInt32(); _limitTime = questRecord[104].GetInt64(); _allowableRaces.RawValue = questRecord[105].GetUInt64(); - _treasurePickerID = questRecord[106].GetInt32(); - _expansion = questRecord[107].GetInt32(); - _managedWorldStateID = questRecord[108].GetInt32(); - _questSessionBonus = questRecord[109].GetInt32(); - - _logTitle = questRecord[110].GetString(); - _logDescription = questRecord[111].GetString(); - _questDescription = questRecord[112].GetString(); - _areaDescription = questRecord[113].GetString(); - _portraitGiverText = questRecord[114].GetString(); - _portraitGiverName = questRecord[115].GetString(); - _portraitTurnInText = questRecord[116].GetString(); - _portraitTurnInName = questRecord[117].GetString(); - _questCompletionLog = questRecord[118].GetString(); + _expansion = questRecord[106].GetInt32(); + _managedWorldStateID = questRecord[107].GetInt32(); + _questSessionBonus = questRecord[108].GetInt32(); + + _logTitle = questRecord[109].GetString(); + _logDescription = questRecord[110].GetString(); + _questDescription = questRecord[111].GetString(); + _areaDescription = questRecord[112].GetString(); + _portraitGiverText = questRecord[113].GetString(); + _portraitGiverName = questRecord[114].GetString(); + _portraitTurnInText = questRecord[115].GetString(); + _portraitTurnInName = questRecord[116].GetString(); + _questCompletionLog = questRecord[117].GetString(); } Quest::~Quest() @@ -408,6 +407,11 @@ void Quest::LoadConditionalConditionalQuestCompletionLog(Field* fields) ObjectMgr::AddLocaleString(fields[3].GetStringView(), locale, text.Text); } +void Quest::LoadTreasurePickers(Field* fields) +{ + _treasurePickerID.push_back(fields[1].GetInt32()); +} + uint32 Quest::XPValue(Player const* player) const { return XPValue(player ? player->GetLevel() : 0, GetQuestLevelForPlayer(player), _level, _rewardXPDifficulty, _rewardXPMultiplier); @@ -468,6 +472,14 @@ bool Quest::IsImportant() const return false; } +bool Quest::IsMeta() const +{ + if (QuestInfoEntry const* questInfo = sQuestInfoStore.LookupEntry(GetQuestInfoID())) + return (questInfo->Modifiers & 0x800) != 0; + + return false; +} + uint32 Quest::GetQuestLevelForPlayer(Player const* player) const { if (_level != -1) @@ -511,7 +523,7 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player rewards.SpellCompletionID = GetRewSpell(); rewards.SkillLineID = GetRewardSkillId(); rewards.NumSkillUps = GetRewardSkillPoints(); - rewards.TreasurePickerID = GetTreasurePickerId(); + //rewards.TreasurePickerID = GetTreasurePickerId(); for (uint32 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) { @@ -522,8 +534,8 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player for (uint32 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) { - rewards.ItemID[i] = RewardItemId[i]; - rewards.ItemQty[i] = RewardItemCount[i]; + rewards.Items[i].ItemID = RewardItemId[i]; + rewards.Items[i].ItemQty = RewardItemCount[i]; } for (uint32 i = 0; i < QUEST_REWARD_REPUTATIONS_COUNT; ++i) @@ -536,8 +548,8 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) { - rewards.CurrencyID[i] = RewardCurrencyId[i]; - rewards.CurrencyQty[i] = RewardCurrencyCount[i]; + rewards.Currencies[i].CurrencyID = RewardCurrencyId[i]; + rewards.Currencies[i].CurrencyQty = RewardCurrencyCount[i]; } } diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 3b800a679bc..4934b838a97 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -124,39 +124,53 @@ enum QuestStatus : uint8 enum class QuestGiverStatus : uint64 { - None = 0x000000000, - Future = 0x000000002, - Trivial = 0x000000004, - TrivialRepeatableTurnin = 0x000000008, - TrivialDailyQuest = 0x000000010, - Reward = 0x000000020, - JourneyReward = 0x000000040, - CovenantCallingReward = 0x000000080, - RepeatableTurnin = 0x000000100, - DailyQuest = 0x000000200, - Quest = 0x000000400, - RewardCompleteNoPOI = 0x000000800, - RewardCompletePOI = 0x000001000, - LegendaryQuest = 0x000002000, - LegendaryRewardCompleteNoPOI = 0x000004000, - LegendaryRewardCompletePOI = 0x000008000, - JourneyQuest = 0x000010000, - JourneyRewardCompleteNoPOI = 0x000020000, - JourneyRewardCompletePOI = 0x000040000, - CovenantCallingQuest = 0x000080000, - CovenantCallingRewardCompleteNoPOI = 0x000100000, - CovenantCallingRewardCompletePOI = 0x000200000, - TrivialLegendaryQuest = 0x000400000, - FutureLegendaryQuest = 0x000800000, - LegendaryReward = 0x001000000, - ImportantReward = 0x002000000, - ImportantQuest = 0x004000000, - TrivialImportantQuest = 0x008000000, - FutureImportantQuest = 0x010000000, - ImportantQuestRewardCompleteNoPOI = 0x020000000, - ImportantQuestRewardCompletePOI = 0x040000000, - TrivialJourneyQuest = 0x080000000, - FutureJourneyQuest = 0x100000000, + None = 0x000000000000, + Future = 0x000000000002, + FutureJourneyQuest = 0x000000000004, + FutureLegendaryQuest = 0x000000000008, + FutureImportantQuest = 0x000000000010, + TrivialRepeatableTurnin = 0x000000000020, + Trivial = 0x000000000040, + TrivialDailyQuest = 0x000000000080, + TrivialRepeatableQuest = 0x000000000100, + TrivialMetaQuest = 0x000000000200, + TrivialJourneyQuest = 0x000000000400, + TrivialLegendaryQuest = 0x000000000800, + TrivialImportantQuest = 0x000000001000, + Reward = 0x000000002000, + RepeatableReward = 0x000000004000, + MetaReward = 0x000000008000, + JourneyReward = 0x000000010000, + CovenantCallingReward = 0x000000020000, + LegendaryReward = 0x000000040000, + ImportantReward = 0x000000080000, + RepeatableTurnin = 0x000000100000, + QuestAccountCompleted = 0x000000200000, + Quest = 0x000000400000, + DailyQuest = 0x000000800000, + RepeatableQuest = 0x000001000000, + MetaQuest = 0x000002000000, + CovenantCallingQuest = 0x000004000000, + JourneyQuestAccountCompleted = 0x000008000000, + JourneyQuest = 0x000010000000, + LegendaryQuestAccountCompleted = 0x000020000000, + LegendaryQuest = 0x000040000000, + ImportantQuestAccountCompleted = 0x000080000000, + ImportantQuest = 0x000100000000, + RewardCompleteNoPOI = 0x000200000000, + RewardCompletePOI = 0x000400000000, + RepeatableRewardCompleteNoPOI = 0x000800000000, + RepeatableRewardCompletePOI = 0x001000000000, + MetaQuestRewardCompleteNoPOI = 0x002000000000, + MetaQuestRewardCompletePOI = 0x004000000000, + CovenantCallingRewardCompleteNoPOI = 0x008000000000, + CovenantCallingRewardCompletePOI = 0x010000000000, + JourneyRewardCompleteNoPOI = 0x020000000000, + JourneyRewardCompletePOI = 0x040000000000, + LegendaryRewardCompleteNoPOI = 0x080000000000, + LegendaryRewardCompletePOI = 0x100000000000, + ImportantQuestRewardCompleteNoPOI = 0x200000000000, + ImportantQuestRewardCompletePOI = 0x400000000000, }; DEFINE_ENUM_FLAG(QuestGiverStatus); @@ -262,6 +276,8 @@ enum QuestFlagsEx2 : uint32 QUEST_FLAGS_EX2_IGNORE_SOULBOUND_ITEMS = 0x00200000, QUEST_FLAGS_EX2_DONT_DEFER_START_EFFECTS = 0x00400000, QUEST_FLAGS_EX2_HIDE_REQUIRED_ITEMS_PRE_TURN_IN = 0x00800000, + + QUEST_FLAGS_EX2_ABANDON_ON_DISABLE = 0x04000000, }; enum QuestSpecialFlags @@ -360,6 +376,13 @@ enum class QuestCompleteSpellType : uint32 Max }; +enum class QuestRewardContextFlags : int32 +{ + None = 0x0, + FirstCompletionBonus = 0x1, + RepeatCompletionBonus = 0x2 +}; + struct QuestGreeting { uint16 EmoteType; @@ -417,7 +440,7 @@ struct QuestObjective { uint32 ID = 0; uint32 QuestID = 0; - uint8 Type = 0; + int32 Type = 0; int8 StorageIndex = 0; int32 ObjectID = 0; int32 Amount = 0; @@ -530,12 +553,14 @@ class TC_GAME_API Quest void LoadConditionalConditionalRequestItemsText(Field* fields); void LoadConditionalConditionalOfferRewardText(Field* fields); void LoadConditionalConditionalQuestCompletionLog(Field* fields); + void LoadTreasurePickers(Field* fields); uint32 XPValue(Player const* player) const; static uint32 XPValue(uint8 playerLevel, uint32 questLevel, int32 unscaledQuestLevel, uint32 xpDifficulty, float xpMultiplier = 1.0f); uint32 GetMoneyReward(Player const* player) const; Optional<QuestTagType> GetQuestTag() const; bool IsImportant() const; + bool IsMeta() const; uint32 GetQuestLevelForPlayer(Player const* player) const; bool HasFlag(QuestFlags flag) const { return (_flags & uint32(flag)) != 0; } @@ -638,7 +663,7 @@ class TC_GAME_API Quest uint32 GetRewardSkillId() const { return _rewardSkillId; } uint32 GetRewardSkillPoints() const { return _rewardSkillPoints; } uint32 GetRewardReputationMask() const { return _rewardReputationMask; } - int32 GetTreasurePickerId() const { return _treasurePickerID; } + std::vector<int32> const& GetTreasurePickerId() const { return _treasurePickerID; } int32 GetExpansion() const { return _expansion; } int32 GetManagedWorldStateId() const { return _managedWorldStateID; } int32 GetQuestSessionBonus() const { return _questSessionBonus; } @@ -752,7 +777,7 @@ class TC_GAME_API Quest uint32 _areaGroupID = 0; int64 _limitTime = 0; Trinity::RaceMask<uint64> _allowableRaces; - int32 _treasurePickerID = 0; + std::vector<int32> _treasurePickerID; int32 _expansion = 0; int32 _managedWorldStateID = 0; int32 _questSessionBonus = 0; diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp index 770a0dc632f..ed049e73cf6 100644 --- a/src/server/game/Reputation/ReputationMgr.cpp +++ b/src/server/game/Reputation/ReputationMgr.cpp @@ -299,9 +299,15 @@ int32 ReputationMgr::GetRenownMaxLevel(FactionEntry const* renownFactionEntry) c void ReputationMgr::ApplyForceReaction(uint32 faction_id, ReputationRank rank, bool apply) { if (apply) + { _forcedReactions[faction_id] = rank; + _player->SetVisibleForcedReaction(faction_id, rank); + } else + { _forcedReactions.erase(faction_id); + _player->RemoveVisibleForcedReaction(faction_id); + } } ReputationFlags ReputationMgr::GetDefaultStateFlags(FactionEntry const* factionEntry) const @@ -356,9 +362,14 @@ void ReputationMgr::SendInitialReputations() for (FactionStateList::iterator itr = _factions.begin(); itr != _factions.end(); ++itr) { - initFactions.FactionFlags[itr->first] = itr->second.Flags.AsUnderlyingType(); - initFactions.FactionStandings[itr->first] = itr->second.Standing; + WorldPackets::Reputation::FactionData& factionData = initFactions.Factions.emplace_back(); + factionData.FactionID = itr->second.ID; + factionData.Flags = itr->second.Flags.AsUnderlyingType(); + factionData.Standing = itr->second.Standing; /// @todo faction bonus + WorldPackets::Reputation::FactionBonusData& bonus = initFactions.Bonuses.emplace_back(); + bonus.FactionID = itr->second.ID; + bonus.FactionHasBonus = false; itr->second.needSend = false; } diff --git a/src/server/game/Server/Packets/AreaTriggerPackets.cpp b/src/server/game/Server/Packets/AreaTriggerPackets.cpp index ae6dfddb134..c03ddb7d058 100644 --- a/src/server/game/Server/Packets/AreaTriggerPackets.cpp +++ b/src/server/game/Server/Packets/AreaTriggerPackets.cpp @@ -82,6 +82,7 @@ WorldPacket const* WorldPackets::AreaTrigger::AreaTriggerDenied::Write() WorldPacket const* WorldPackets::AreaTrigger::AreaTriggerRePath::Write() { _worldPacket << TriggerGUID; + _worldPacket << Unused_1100; _worldPacket.WriteBit(AreaTriggerSpline.has_value()); _worldPacket.WriteBit(AreaTriggerOrbit.has_value()); diff --git a/src/server/game/Server/Packets/AreaTriggerPackets.h b/src/server/game/Server/Packets/AreaTriggerPackets.h index 2af22e72d2c..1186b772b60 100644 --- a/src/server/game/Server/Packets/AreaTriggerPackets.h +++ b/src/server/game/Server/Packets/AreaTriggerPackets.h @@ -82,6 +82,7 @@ namespace WorldPackets Optional<AreaTriggerOrbitInfo> AreaTriggerOrbit; Optional<AreaTriggerMovementScriptInfo> AreaTriggerMovementScript; ObjectGuid TriggerGUID; + ObjectGuid Unused_1100; }; class AreaTriggerPlaySpellVisual final : public ServerPacket diff --git a/src/server/game/Server/Packets/AuctionHousePackets.cpp b/src/server/game/Server/Packets/AuctionHousePackets.cpp index f8d951c1c3f..1f4913779f1 100644 --- a/src/server/game/Server/Packets/AuctionHousePackets.cpp +++ b/src/server/game/Server/Packets/AuctionHousePackets.cpp @@ -327,7 +327,7 @@ void AuctionSellItem::Read() if (_worldPacket.ReadBit()) TaintedBy.emplace(); - Items.resize(_worldPacket.ReadBits(6)); + Items.resize(_worldPacket.ReadBits(5)); if (TaintedBy) _worldPacket >> *TaintedBy; diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index 5ae68849569..4a948e6ca35 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -327,8 +327,8 @@ void WorldPackets::Auth::AuthContinuedSession::Read() void WorldPackets::Auth::ConnectToFailed::Read() { - _worldPacket >> As<uint32>(Serial); _worldPacket >> Con; + _worldPacket >> As<uint32>(Serial); } bool WorldPackets::Auth::EnterEncryptedMode::InitializeEncryption() diff --git a/src/server/game/Server/Packets/BankPackets.cpp b/src/server/game/Server/Packets/BankPackets.cpp index 0e299e6a5d0..94691712a93 100644 --- a/src/server/game/Server/Packets/BankPackets.cpp +++ b/src/server/game/Server/Packets/BankPackets.cpp @@ -16,10 +16,12 @@ */ #include "BankPackets.h" +#include "DBCEnums.h" void WorldPackets::Bank::AutoBankItem::Read() { _worldPacket >> Inv + >> As<int8>(BankType) >> Bag >> Slot; } @@ -35,3 +37,9 @@ void WorldPackets::Bank::BuyBankSlot::Read() { _worldPacket >> Guid; } + +void WorldPackets::Bank::BankerActivate::Read() +{ + _worldPacket >> Banker; + _worldPacket >> As<int32>(InteractionType); +} diff --git a/src/server/game/Server/Packets/BankPackets.h b/src/server/game/Server/Packets/BankPackets.h index 4277a33a5eb..054bf6d6688 100644 --- a/src/server/game/Server/Packets/BankPackets.h +++ b/src/server/game/Server/Packets/BankPackets.h @@ -22,6 +22,8 @@ #include "ItemPacketsCommon.h" #include "ObjectGuid.h" +enum class PlayerInteractionType : int32; + namespace WorldPackets { namespace Bank @@ -34,6 +36,7 @@ namespace WorldPackets void Read() override; WorldPackets::Item::InvUpdate Inv; + ::BankType BankType = ::BankType::Character; uint8 Bag = 0; uint8 Slot = 0; }; @@ -59,6 +62,17 @@ namespace WorldPackets ObjectGuid Guid; }; + + class BankerActivate final : public ClientPacket + { + public: + explicit BankerActivate(WorldPacket&& packet) : ClientPacket(CMSG_BANKER_ACTIVATE, std::move(packet)) { } + + void Read() override; + + ObjectGuid Banker; + PlayerInteractionType InteractionType = { }; + }; } } #endif // BankPackets_h__ diff --git a/src/server/game/Server/Packets/CalendarPackets.cpp b/src/server/game/Server/Packets/CalendarPackets.cpp index 62eebccf188..ae2ca129f20 100644 --- a/src/server/game/Server/Packets/CalendarPackets.cpp +++ b/src/server/game/Server/Packets/CalendarPackets.cpp @@ -22,7 +22,7 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Calendar::CalendarSendCal data << uint64(eventInfo.EventID); data << uint8(eventInfo.EventType); data << eventInfo.Date; - data << uint32(eventInfo.Flags); + data << uint16(eventInfo.Flags); data << int32(eventInfo.TextureID); data << uint64(eventInfo.EventClubID); data << eventInfo.OwnerGuid; @@ -278,7 +278,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarSendEvent::Write() _worldPacket << uint64(EventID); _worldPacket << uint8(GetEventType); _worldPacket << int32(TextureID); - _worldPacket << uint32(Flags); + _worldPacket << uint16(Flags); _worldPacket << Date; _worldPacket << LockDate; _worldPacket << uint64(EventClubID); @@ -300,7 +300,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarInviteAlert::Write() { _worldPacket << uint64(EventID); _worldPacket << Date; - _worldPacket << uint32(Flags); + _worldPacket << uint16(Flags); _worldPacket << uint8(EventType); _worldPacket << int32(TextureID); _worldPacket << uint64(EventClubID); @@ -313,6 +313,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarInviteAlert::Write() _worldPacket << OwnerGuid; _worldPacket << BitsSize<8>(EventName); + _worldPacket << Bits<1>(Unknown_1100); _worldPacket.FlushBits(); _worldPacket.WriteString(EventName); @@ -376,7 +377,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarEventUpdatedAlert::Write() _worldPacket << OriginalDate; _worldPacket << Date; _worldPacket << LockDate; - _worldPacket << uint32(Flags); + _worldPacket << uint16(Flags); _worldPacket << uint32(TextureID); _worldPacket << uint8(EventType); diff --git a/src/server/game/Server/Packets/CalendarPackets.h b/src/server/game/Server/Packets/CalendarPackets.h index cab6ecec89a..cc789a4022d 100644 --- a/src/server/game/Server/Packets/CalendarPackets.h +++ b/src/server/game/Server/Packets/CalendarPackets.h @@ -103,7 +103,7 @@ namespace WorldPackets uint8 EventType = 0; uint32 TextureID = 0; WowTime Time; - uint32 Flags = 0; + uint16 Flags = 0; }; class CalendarUpdateEvent final : public ClientPacket @@ -185,7 +185,7 @@ namespace WorldPackets std::string EventName; uint8 EventType = 0; WowTime Date; - uint32 Flags = 0; + uint16 Flags = 0; int32 TextureID = 0; uint64 EventClubID = 0; ObjectGuid OwnerGuid; @@ -228,7 +228,7 @@ namespace WorldPackets uint64 EventID = 0; WowTime Date; WowTime LockDate; - uint32 Flags = 0; + uint16 Flags = 0; int32 TextureID = 0; uint8 GetEventType = 0; uint8 EventType = 0; @@ -249,13 +249,14 @@ namespace WorldPackets ObjectGuid InvitedByGuid; uint64 InviteID = 0; uint64 EventID = 0; - uint32 Flags = 0; + uint16 Flags = 0; WowTime Date; int32 TextureID = 0; uint8 Status = 0; uint8 EventType = 0; uint8 ModeratorStatus = 0; std::string EventName; + bool Unknown_1100 = false; }; class CalendarInvite final : public ClientPacket @@ -358,7 +359,7 @@ namespace WorldPackets uint64 EventClubID = 0; uint64 EventID = 0; WowTime Date; - uint32 Flags = 0; + uint16 Flags = 0; WowTime LockDate; WowTime OriginalDate; int32 TextureID = 0; diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp index e7bfac49d1b..c6fbda45636 100644 --- a/src/server/game/Server/Packets/CharacterPackets.cpp +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -79,7 +79,7 @@ EnumCharacters::EnumCharacters(WorldPacket&& packet) : ClientPacket(std::move(pa ASSERT(GetOpcode() == CMSG_ENUM_CHARACTERS || GetOpcode() == CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT); } -EnumCharactersResult::CharacterInfo::CharacterInfo(Field const* fields) +EnumCharactersResult::CharacterInfoBasic::CharacterInfoBasic(Field const* fields) { // 0 1 2 3 4 5 // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.level, " @@ -95,6 +95,7 @@ EnumCharactersResult::CharacterInfo::CharacterInfo(Field const* fields) // "character_declinedname.genitive" Guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()); + VirtualRealmAddress = GetVirtualRealmAddress(); GuildClubMemberID = ::Battlenet::Services::Clubs::CreateClubMemberId(Guid); Name = fields[1].GetString(); RaceID = fields[2].GetUInt8(); @@ -137,7 +138,6 @@ EnumCharactersResult::CharacterInfo::CharacterInfo(Field const* fields) Flags2 = CHAR_CUSTOMIZE_FLAG_RACE; Flags3 = 0; - Flags4 = 0; FirstLogin = (atLoginFlags & AT_LOGIN_FIRST) != 0; // show pet at selection character in character list only for non-ghost character @@ -151,7 +151,6 @@ EnumCharactersResult::CharacterInfo::CharacterInfo(Field const* fields) } } - BoostInProgress = false; ProfessionIds[0] = 0; ProfessionIds[1] = 0; @@ -180,80 +179,115 @@ EnumCharactersResult::CharacterInfo::CharacterInfo(Field const* fields) } } -ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::CharacterInfo::VisualItemInfo const& visualItem) +ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::CharacterInfoBasic::VisualItemInfo const& visualItem) { data << uint32(visualItem.DisplayID); - data << uint32(visualItem.DisplayEnchantID); - data << int32(visualItem.SecondaryItemModifiedAppearanceID); data << uint8(visualItem.InvType); + data << uint32(visualItem.DisplayEnchantID); data << uint8(visualItem.Subclass); + data << int32(visualItem.SecondaryItemModifiedAppearanceID); + data << uint32(visualItem.ItemID); + data << uint32(visualItem.TransmogrifiedItemID); return data; } -ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::CharacterInfo const& charInfo) +ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::CharacterInfoBasic const& charInfo) { - ASSERT(charInfo.MailSenders.size() == charInfo.MailSenderTypes.size()); - data << charInfo.Guid; - data << uint64(charInfo.GuildClubMemberID); + data << uint32(charInfo.VirtualRealmAddress); data << uint8(charInfo.ListPosition); data << uint8(charInfo.RaceID); - data << uint8(charInfo.ClassID); data << uint8(charInfo.SexID); + data << uint8(charInfo.ClassID); + data << int16(charInfo.SpecID); data << uint32(charInfo.Customizations.size()); data << uint8(charInfo.ExperienceLevel); - data << int32(charInfo.ZoneID); data << int32(charInfo.MapID); + data << int32(charInfo.ZoneID); data << charInfo.PreloadPos; + data << uint64(charInfo.GuildClubMemberID); data << charInfo.GuildGUID; data << uint32(charInfo.Flags); data << uint32(charInfo.Flags2); data << uint32(charInfo.Flags3); + data << uint8(charInfo.unkWod61x); + data << uint32(charInfo.PetCreatureDisplayID); data << uint32(charInfo.PetExperienceLevel); data << uint32(charInfo.PetCreatureFamilyID); - data << uint32(charInfo.ProfessionIds[0]); - data << uint32(charInfo.ProfessionIds[1]); - - for (EnumCharactersResult::CharacterInfo::VisualItemInfo const& visualItem : charInfo.VisualItems) + for (EnumCharactersResult::CharacterInfoBasic::VisualItemInfo const& visualItem : charInfo.VisualItems) data << visualItem; - data << charInfo.LastPlayedTime; - data << int16(charInfo.SpecID); data << int32(charInfo.Unknown703); + data << charInfo.LastPlayedTime; data << int32(charInfo.LastLoginVersion); - data << uint32(charInfo.Flags4); - data << uint32(charInfo.MailSenders.size()); - data << uint32(charInfo.MailSenderTypes.size()); - data << uint32(charInfo.OverrideSelectScreenFileDataID); data << charInfo.PersonalTabard; + data << uint32(charInfo.ProfessionIds[0]); + data << uint32(charInfo.ProfessionIds[1]); + + data << int32(charInfo.TimerunningSeasonID); + data << uint32(charInfo.OverrideSelectScreenFileDataID); + for (ChrCustomizationChoice const& customization : charInfo.Customizations) data << customization; - if (!charInfo.MailSenderTypes.empty()) - data.append(charInfo.MailSenderTypes.data(), charInfo.MailSenderTypes.size()); - data << BitsSize<6>(charInfo.Name); data << Bits<1>(charInfo.FirstLogin); - data << Bits<1>(charInfo.BoostInProgress); - data << Bits<5>(charInfo.unkWod61x); - data << Bits<2>(0); // unk - data << Bits<1>(charInfo.RpeResetAvailable); - data << Bits<1>(charInfo.RpeResetQuestClearAvailable); - for (std::string const& str : charInfo.MailSenders) + data.FlushBits(); + + data.WriteString(charInfo.Name); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::CharacterRestrictionAndMailData const& restrictionsAndMails) +{ + ASSERT(restrictionsAndMails.MailSenders.size() == restrictionsAndMails.MailSenderTypes.size()); + + data << Bits<1>(restrictionsAndMails.BoostInProgress); + data << Bits<1>(restrictionsAndMails.RpeResetAvailable); + data << Bits<1>(restrictionsAndMails.RpeResetQuestClearAvailable); + data.FlushBits(); + + data << uint32(restrictionsAndMails.Flags4); + data << uint32(restrictionsAndMails.MailSenders.size()); + data << uint32(restrictionsAndMails.MailSenderTypes.size()); + + if (!restrictionsAndMails.MailSenderTypes.empty()) + data.append(restrictionsAndMails.MailSenderTypes.data(), restrictionsAndMails.MailSenderTypes.size()); + + for (std::string const& str : restrictionsAndMails.MailSenders) data << Bits<6>(str.length() + 1); data.FlushBits(); - for (std::string const& str : charInfo.MailSenders) + for (std::string const& str : restrictionsAndMails.MailSenders) if (!str.empty()) data << str; - data.WriteString(charInfo.Name); + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::CharacterInfo const& charInfo) +{ + data << charInfo.Basic; + data << charInfo.RestrictionsAndMails; + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::RegionwideCharacterListEntry const& charInfo) +{ + data << charInfo.Basic; + data << uint64(charInfo.Money); + data << float(charInfo.CurrentSeasonMythicPlusOverallScore); + data << int32(charInfo.CurrentSeasonBestPvpRating); + data << int8(charInfo.PvpRatingBracket); + data << int16(charInfo.PvpRatingAssociatedSpecID); return data; } @@ -265,6 +299,7 @@ ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::RaceUnlock const& data << Bits<1>(raceUnlock.HasAchievement); data << Bits<1>(raceUnlock.HasHeritageArmor); data << Bits<1>(raceUnlock.IsLocked); + data << Bits<1>(raceUnlock.Unused1027); data.FlushBits(); return data; @@ -286,22 +321,57 @@ ByteBuffer& operator<<(ByteBuffer& data, EnumCharactersResult::RaceLimitDisableI return data; } +ByteBuffer& operator<<(ByteBuffer& data, WarbandGroupMember const& warbandGroupMember) +{ + data << int32(warbandGroupMember.WarbandScenePlacementID); + data << int32(warbandGroupMember.Type); + if (warbandGroupMember.Type == 0) + data << warbandGroupMember.Guid; + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WarbandGroup const& warbandGroup) +{ + data << uint64(warbandGroup.GroupID); + data << uint8(warbandGroup.Unknown_1100); + data << int32(warbandGroup.Flags); + data << uint32(warbandGroup.Members.size()); + + for (WarbandGroupMember const& member : warbandGroup.Members) + data << member; + + return data; +} + +EnumCharactersResult::CharacterInfo::CharacterInfo(Field const* fields) : Basic(fields) +{ +} + +EnumCharactersResult::RegionwideCharacterListEntry::RegionwideCharacterListEntry(Field const* fields) : Basic(fields) +{ +} + WorldPacket const* EnumCharactersResult::Write() { _worldPacket.reserve(9 + Characters.size() * sizeof(CharacterInfo) + RaceUnlockData.size() * sizeof(RaceUnlock)); _worldPacket << Bits<1>(Success); + _worldPacket << Bits<1>(Realmless); _worldPacket << Bits<1>(IsDeletedCharacters); _worldPacket << Bits<1>(IsNewPlayerRestrictionSkipped); _worldPacket << Bits<1>(IsNewPlayerRestricted); _worldPacket << Bits<1>(IsNewPlayer); _worldPacket << Bits<1>(IsTrialAccountRestricted); _worldPacket << OptionalInit(DisabledClassesMask); + _worldPacket << Bits<1>(DontCreateCharacterDisplays); _worldPacket << uint32(Characters.size()); + _worldPacket << uint32(RegionwideCharacters.size()); _worldPacket << int32(MaxCharacterLevel); _worldPacket << uint32(RaceUnlockData.size()); _worldPacket << uint32(UnlockedConditionalAppearances.size()); _worldPacket << uint32(RaceLimitDisables.size()); + _worldPacket << uint32(WarbandGroups.size()); if (DisabledClassesMask) _worldPacket << uint32(*DisabledClassesMask); @@ -312,9 +382,15 @@ WorldPacket const* EnumCharactersResult::Write() for (RaceLimitDisableInfo const& raceLimitDisableInfo : RaceLimitDisables) _worldPacket << raceLimitDisableInfo; + for (WarbandGroup const& warbandGroup : WarbandGroups) + _worldPacket << warbandGroup; + for (CharacterInfo const& charInfo : Characters) _worldPacket << charInfo; + for (RegionwideCharacterListEntry const& charInfo : RegionwideCharacters) + _worldPacket << charInfo; + for (RaceUnlock const& raceUnlock : RaceUnlockData) _worldPacket << raceUnlock; @@ -579,6 +655,7 @@ void AlterApperance::Read() _worldPacket >> NewSex; _worldPacket >> CustomizedRace; _worldPacket >> CustomizedChrModelID; + _worldPacket >> UnalteredVisualRaceID; for (ChrCustomizationChoice& customization : Customizations) _worldPacket >> customization; diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h index 312955cafae..deeb8314e06 100644 --- a/src/server/game/Server/Packets/CharacterPackets.h +++ b/src/server/game/Server/Packets/CharacterPackets.h @@ -114,10 +114,25 @@ namespace WorldPackets int32 BackgroundColor = -1; }; + struct WarbandGroupMember + { + int32 WarbandScenePlacementID = 0; + int32 Type = 0; + ObjectGuid Guid; + }; + + struct WarbandGroup + { + uint64 GroupID = 0; + uint8 Unknown_1100 = 0; + int32 Flags = 0; ///< enum WarbandGroupFlags { Collapsed = 1 } + std::vector<WarbandGroupMember> Members; + }; + class EnumCharactersResult final : public ServerPacket { public: - struct CharacterInfo + struct CharacterInfoBasic { /** * @fn void WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Field* fields); @@ -126,9 +141,10 @@ namespace WorldPackets * * @param fields Field set of CharacterDatabaseStatements::CHAR_SEL_ENUM */ - CharacterInfo(Field const* fields); + CharacterInfoBasic(Field const* fields); ObjectGuid Guid; + uint32 VirtualRealmAddress = 0; uint64 GuildClubMemberID = 0; ///< same as bgs.protocol.club.v1.MemberId.unique_id, guessed basing on SMSG_QUERY_PLAYER_NAME_RESPONSE (that one is known) std::string Name; uint8 ListPosition = 0; ///< Order of the characters in list @@ -144,7 +160,6 @@ namespace WorldPackets uint32 Flags = 0; ///< Character flag @see enum CharacterFlags uint32 Flags2 = 0; ///< Character customization flags @see enum CharacterCustomizeFlags uint32 Flags3 = 0; ///< Character flags 3 @todo research - uint32 Flags4 = 0; bool FirstLogin = false; uint8 unkWod61x = 0; Timestamp<> LastPlayedTime; @@ -152,29 +167,57 @@ namespace WorldPackets uint32 Unknown703 = 0; uint32 LastLoginVersion = 0; uint32 OverrideSelectScreenFileDataID = 0; + int32 TimerunningSeasonID = 0; uint32 PetCreatureDisplayID = 0; uint32 PetExperienceLevel = 0; uint32 PetCreatureFamilyID = 0; - bool BoostInProgress = false; ///< @todo int32 ProfessionIds[2] = { }; ///< @todo struct VisualItemInfo { - uint32 DisplayID = 0; + uint32 DisplayID = 0; uint32 DisplayEnchantID = 0; int32 SecondaryItemModifiedAppearanceID = 0; // also -1 is some special value - uint8 InvType = 0; - uint8 Subclass = 0; + uint8 InvType = 0; + uint8 Subclass = 0; + uint32 ItemID = 0; + uint32 TransmogrifiedItemID = 0; }; - std::array<VisualItemInfo, 34> VisualItems = { }; + std::array<VisualItemInfo, 19> VisualItems = { }; + CustomTabardInfo PersonalTabard; + }; + + struct CharacterRestrictionAndMailData + { + bool BoostInProgress = false; ///< @todo + uint32 Flags4 = 0; std::vector<std::string> MailSenders; std::vector<uint32> MailSenderTypes; bool RpeResetAvailable = false; bool RpeResetQuestClearAvailable = false; - CustomTabardInfo PersonalTabard; + }; + + struct CharacterInfo + { + CharacterInfo(Field const* fields); + + CharacterInfoBasic Basic; + CharacterRestrictionAndMailData RestrictionsAndMails; + }; + + struct RegionwideCharacterListEntry + { + RegionwideCharacterListEntry(Field const* fields); + + CharacterInfoBasic Basic; + uint64 Money = 0; + float CurrentSeasonMythicPlusOverallScore = 0.0f; + uint32 CurrentSeasonBestPvpRating = 0; + int8 PvpRatingBracket = 0; + int16 PvpRatingAssociatedSpecID = 0; }; struct RaceUnlock @@ -184,6 +227,7 @@ namespace WorldPackets bool HasAchievement = false; bool HasHeritageArmor = false; bool IsLocked = false; + bool Unused1027 = false; }; struct UnlockedConditionalAppearance @@ -208,20 +252,24 @@ namespace WorldPackets WorldPacket const* Write() override; - bool Success = false; ///< + bool Success = false; + bool Realmless = false; bool IsDeletedCharacters = false; ///< used for character undelete list bool IsNewPlayerRestrictionSkipped = false; ///< allows client to skip new player restrictions bool IsNewPlayerRestricted = false; ///< forbids using level boost and class trials bool IsNewPlayer = false; ///< forbids hero classes and allied races bool IsTrialAccountRestricted = false; + bool DontCreateCharacterDisplays = false; int32 MaxCharacterLevel = 1; Optional<uint32> DisabledClassesMask; std::vector<CharacterInfo> Characters; ///< all characters on the list - std::vector<RaceUnlock> RaceUnlockData; ///< + std::vector<RegionwideCharacterListEntry> RegionwideCharacters; + std::vector<RaceUnlock> RaceUnlockData; std::vector<UnlockedConditionalAppearance> UnlockedConditionalAppearances; std::vector<RaceLimitDisableInfo> RaceLimitDisables; + std::vector<WarbandGroup> WarbandGroups; }; class CheckCharacterNameAvailabilityResult final : public ServerPacket @@ -641,6 +689,7 @@ namespace WorldPackets Array<ChrCustomizationChoice, 250> Customizations; int32 CustomizedRace = 0; int32 CustomizedChrModelID = 0; + int32 UnalteredVisualRaceID = 0; }; class BarberShopResult final : public ServerPacket diff --git a/src/server/game/Server/Packets/ChatPackets.cpp b/src/server/game/Server/Packets/ChatPackets.cpp index 64fc9765539..75029adc9e5 100644 --- a/src/server/game/Server/Packets/ChatPackets.cpp +++ b/src/server/game/Server/Packets/ChatPackets.cpp @@ -47,7 +47,7 @@ void WorldPackets::Chat::ChatMessageWhisper::Read() _worldPacket >> TargetGUID; _worldPacket >> TargetVirtualRealmAddress; - uint32 targetLen = _worldPacket.ReadBits(6); + uint32 targetLen = _worldPacket.ReadBits(7); uint32 textLen = _worldPacket.ReadBits(11); if (targetLen > 1) @@ -100,8 +100,8 @@ void WorldPackets::Chat::ChatAddonMessageTargeted::Read() _worldPacket >> PlayerGUID; _worldPacket >> PlayerVirtualRealmAddress; - uint32 playerNameLength = _worldPacket.ReadBits(6); - uint32 channelNameLength = _worldPacket.ReadBits(6); + uint32 playerNameLength = _worldPacket.ReadBits(7); + uint32 channelNameLength = _worldPacket.ReadBits(7); if (playerNameLength > 1) { @@ -208,6 +208,7 @@ WorldPacket const* WorldPackets::Chat::Chat::Write() _worldPacket << uint32(TargetVirtualAddress); _worldPacket << uint32(SenderVirtualAddress); _worldPacket << int32(AchievementID); + _worldPacket << uint16(_ChatFlags); _worldPacket << float(DisplayTime); _worldPacket << int32(SpellID); _worldPacket.WriteBits(SenderName.length(), 11); @@ -215,7 +216,6 @@ WorldPacket const* WorldPackets::Chat::Chat::Write() _worldPacket.WriteBits(Prefix.length(), 5); _worldPacket.WriteBits(_Channel.length(), 7); _worldPacket.WriteBits(ChatText.length(), 12); - _worldPacket.WriteBits(_ChatFlags, 15); _worldPacket.WriteBit(HideChatLog); _worldPacket.WriteBit(FakeSenderName); _worldPacket.WriteBit(Unused_801.has_value()); diff --git a/src/server/game/Server/Packets/CombatLogPackets.cpp b/src/server/game/Server/Packets/CombatLogPackets.cpp index 934b4c80000..83fad7d24be 100644 --- a/src/server/game/Server/Packets/CombatLogPackets.cpp +++ b/src/server/game/Server/Packets/CombatLogPackets.cpp @@ -102,7 +102,7 @@ WorldPacket const* SpellExecuteLog::Write() { *this << powerDrainTarget.Victim; *this << uint32(powerDrainTarget.Points); - *this << uint32(powerDrainTarget.PowerType); + *this << int8(powerDrainTarget.PowerType); *this << float(powerDrainTarget.Amplitude); } } diff --git a/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp b/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp index 0ac7591c034..9a2519dc1b4 100644 --- a/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp +++ b/src/server/game/Server/Packets/CombatLogPacketsCommon.cpp @@ -48,13 +48,13 @@ void SpellCastLogData::Initialize(Spell const* spell) bool primaryPowerAdded = false; for (SpellPowerCost const& cost : spell->GetPowerCost()) { - PowerData.emplace_back(int32(cost.Power), unitCaster->GetPower(Powers(cost.Power)), int32(cost.Amount)); + PowerData.emplace_back(int8(cost.Power), unitCaster->GetPower(Powers(cost.Power)), int32(cost.Amount)); if (cost.Power == primaryPowerType) primaryPowerAdded = true; } if (!primaryPowerAdded) - PowerData.emplace(PowerData.begin(), int32(primaryPowerType), unitCaster->GetPower(primaryPowerType), 0); + PowerData.emplace(PowerData.begin(), int8(primaryPowerType), unitCaster->GetPower(primaryPowerType), 0); } } @@ -135,7 +135,7 @@ ByteBuffer& operator<<(ByteBuffer& data, SpellCastLogData const& spellCastLogDat for (SpellLogPowerData const& powerData : spellCastLogData.PowerData) { - data << int32(powerData.PowerType); + data << int8(powerData.PowerType); data << int32(powerData.Amount); data << int32(powerData.Cost); } diff --git a/src/server/game/Server/Packets/CombatLogPacketsCommon.h b/src/server/game/Server/Packets/CombatLogPacketsCommon.h index 8165e7bab35..8589b07d2da 100644 --- a/src/server/game/Server/Packets/CombatLogPacketsCommon.h +++ b/src/server/game/Server/Packets/CombatLogPacketsCommon.h @@ -30,9 +30,9 @@ namespace WorldPackets { struct SpellLogPowerData { - SpellLogPowerData(int32 powerType, int32 amount, int32 cost) : PowerType(powerType), Amount(amount), Cost(cost) { } + SpellLogPowerData(int8 powerType, int32 amount, int32 cost) : PowerType(powerType), Amount(amount), Cost(cost) { } - int32 PowerType = 0; + int8 PowerType = 0; int32 Amount = 0; int32 Cost = 0; }; diff --git a/src/server/game/Server/Packets/CombatPackets.cpp b/src/server/game/Server/Packets/CombatPackets.cpp index 33dd2c9a64a..51de6ecde50 100644 --- a/src/server/game/Server/Packets/CombatPackets.cpp +++ b/src/server/game/Server/Packets/CombatPackets.cpp @@ -107,8 +107,8 @@ WorldPacket const* WorldPackets::Combat::PowerUpdate::Write() _worldPacket << uint32(Powers.size()); for (PowerUpdatePower const& power : Powers) { - _worldPacket << int32(power.Power); _worldPacket << uint8(power.PowerType); + _worldPacket << int32(power.Power); } return &_worldPacket; @@ -116,7 +116,7 @@ WorldPacket const* WorldPackets::Combat::PowerUpdate::Write() WorldPacket const* WorldPackets::Combat::InterruptPowerRegen::Write() { - _worldPacket << int32(PowerType); + _worldPacket << int8(PowerType); return &_worldPacket; } diff --git a/src/server/game/Server/Packets/CombatPackets.h b/src/server/game/Server/Packets/CombatPackets.h index 27dc7ec44ad..42424d8f18b 100644 --- a/src/server/game/Server/Packets/CombatPackets.h +++ b/src/server/game/Server/Packets/CombatPackets.h @@ -163,7 +163,7 @@ namespace WorldPackets class InterruptPowerRegen final : public ServerPacket { public: - explicit InterruptPowerRegen(Powers powerType) : ServerPacket(SMSG_INTERRUPT_POWER_REGEN, 4), PowerType(powerType) { } + explicit InterruptPowerRegen(Powers powerType) : ServerPacket(SMSG_INTERRUPT_POWER_REGEN, 1), PowerType(powerType) { } WorldPacket const* Write() override; diff --git a/src/server/game/Server/Packets/CraftingPacketsCommon.cpp b/src/server/game/Server/Packets/CraftingPacketsCommon.cpp index d5518dda79e..ee03eedbb75 100644 --- a/src/server/game/Server/Packets/CraftingPacketsCommon.cpp +++ b/src/server/game/Server/Packets/CraftingPacketsCommon.cpp @@ -44,6 +44,9 @@ ByteBuffer& operator<<(ByteBuffer& data, CraftingData const& craftingData) data << craftingData.ItemGUID; data << int32(craftingData.Quantity); data << int32(craftingData.EnchantID); + data << int32(craftingData.ConcentrationCurrencyID); + data << int32(craftingData.ConcentrationSpent); + data << int32(craftingData.IngenuityRefund); for (SpellReducedReagent const& spellReducedReagent : craftingData.ResourcesReturned) data << spellReducedReagent; @@ -52,6 +55,8 @@ ByteBuffer& operator<<(ByteBuffer& data, CraftingData const& craftingData) data << Bits<1>(craftingData.field_29); data << Bits<1>(craftingData.field_2A); data << Bits<1>(craftingData.BonusCraft); + data << Bits<1>(craftingData.HasIngenuityProc); + data << Bits<1>(craftingData.ApplyConcentration); data.FlushBits(); data << craftingData.OldItem; diff --git a/src/server/game/Server/Packets/CraftingPacketsCommon.h b/src/server/game/Server/Packets/CraftingPacketsCommon.h index 9426662d460..2182a28627b 100644 --- a/src/server/game/Server/Packets/CraftingPacketsCommon.h +++ b/src/server/game/Server/Packets/CraftingPacketsCommon.h @@ -52,6 +52,11 @@ struct CraftingData Item::ItemInstance OldItem; Item::ItemInstance NewItem; int32 EnchantID = 0; + int32 ConcentrationCurrencyID = 0; + int32 ConcentrationSpent = 0; + int32 IngenuityRefund = 0; + bool HasIngenuityProc = false; + bool ApplyConcentration = false; }; ByteBuffer& operator<<(ByteBuffer& data, SpellReducedReagent const& spellReducedReagent); diff --git a/src/server/game/Server/Packets/EquipmentSetPackets.cpp b/src/server/game/Server/Packets/EquipmentSetPackets.cpp index 7d7fa640b9a..f8423393343 100644 --- a/src/server/game/Server/Packets/EquipmentSetPackets.cpp +++ b/src/server/game/Server/Packets/EquipmentSetPackets.cpp @@ -19,9 +19,9 @@ WorldPacket const* WorldPackets::EquipmentSet::EquipmentSetID::Write() { - _worldPacket << uint64(GUID); _worldPacket << int32(Type); _worldPacket << uint32(SetID); + _worldPacket << uint64(GUID); return &_worldPacket; } @@ -119,8 +119,8 @@ void WorldPackets::EquipmentSet::UseEquipmentSet::Read() WorldPacket const* WorldPackets::EquipmentSet::UseEquipmentSetResult::Write() { + _worldPacket << int32(Reason); _worldPacket << uint64(GUID); - _worldPacket << uint8(Reason); return &_worldPacket; } diff --git a/src/server/game/Server/Packets/EquipmentSetPackets.h b/src/server/game/Server/Packets/EquipmentSetPackets.h index a36c95829e0..ed4165b4236 100644 --- a/src/server/game/Server/Packets/EquipmentSetPackets.h +++ b/src/server/game/Server/Packets/EquipmentSetPackets.h @@ -94,7 +94,7 @@ namespace WorldPackets WorldPacket const* Write() override; uint64 GUID = 0; ///< Set Identifier - uint8 Reason = 0; + int32 Reason = 0; }; } } diff --git a/src/server/game/Server/Packets/GuildPackets.cpp b/src/server/game/Server/Packets/GuildPackets.cpp index c8166747dbe..f6c75915527 100644 --- a/src/server/game/Server/Packets/GuildPackets.cpp +++ b/src/server/game/Server/Packets/GuildPackets.cpp @@ -99,6 +99,17 @@ WorldPacket const* WorldPackets::Guild::GuildCommandResult::Write() return &_worldPacket; } +void WorldPackets::Guild::AcceptGuildInvite::Read() +{ + _worldPacket >> GuildGuid; +} + +void WorldPackets::Guild::GuildDeclineInvitation::Read() +{ + _worldPacket >> GuildGuid; + _worldPacket >> Bits<1>(IsAuto); +} + void WorldPackets::Guild::DeclineGuildInvites::Read() { Allow = _worldPacket.ReadBit(); @@ -204,7 +215,6 @@ WorldPacket const* WorldPackets::Guild::GuildEventPresenceChange::Write() _worldPacket.WriteBits(Name.length(), 6); _worldPacket.WriteBit(LoggedOn); - _worldPacket.WriteBit(Mobile); _worldPacket.FlushBits(); _worldPacket.WriteString(Name); diff --git a/src/server/game/Server/Packets/GuildPackets.h b/src/server/game/Server/Packets/GuildPackets.h index 035c9304bd2..2ca2fdbc202 100644 --- a/src/server/game/Server/Packets/GuildPackets.h +++ b/src/server/game/Server/Packets/GuildPackets.h @@ -163,7 +163,9 @@ namespace WorldPackets public: AcceptGuildInvite(WorldPacket&& packet) : ClientPacket(CMSG_ACCEPT_GUILD_INVITE, std::move(packet)) { } - void Read() override { } + void Read() override; + + ObjectGuid GuildGuid; }; class GuildDeclineInvitation final : public ClientPacket @@ -171,7 +173,10 @@ namespace WorldPackets public: GuildDeclineInvitation(WorldPacket&& packet) : ClientPacket(CMSG_GUILD_DECLINE_INVITATION, std::move(packet)) { } - void Read() override { } + void Read() override; + + ObjectGuid GuildGuid; + bool IsAuto = false; }; class DeclineGuildInvites final : public ClientPacket @@ -240,7 +245,6 @@ namespace WorldPackets ObjectGuid Guid; uint32 VirtualRealmAddress = 0; std::string Name; - bool Mobile = false; bool LoggedOn = false; }; diff --git a/src/server/game/Server/Packets/InstancePackets.cpp b/src/server/game/Server/Packets/InstancePackets.cpp index 41e73128573..86caa86b6ee 100644 --- a/src/server/game/Server/Packets/InstancePackets.cpp +++ b/src/server/game/Server/Packets/InstancePackets.cpp @@ -108,9 +108,11 @@ WorldPacket const* WorldPackets::Instance::PendingRaidLock::Write() WorldPacket const* WorldPackets::Instance::RaidInstanceMessage::Write() { - _worldPacket << uint8(Type); + _worldPacket << int32(Type); _worldPacket << uint32(MapID); _worldPacket << uint32(DifficultyID); + _worldPacket << int32(TimeLeft); + _worldPacket << BitsSize<8>(WarningMessage); _worldPacket << Bits<1>(Locked); _worldPacket << Bits<1>(Extended); _worldPacket.FlushBits(); diff --git a/src/server/game/Server/Packets/InstancePackets.h b/src/server/game/Server/Packets/InstancePackets.h index 86f6838946f..ab980ca148f 100644 --- a/src/server/game/Server/Packets/InstancePackets.h +++ b/src/server/game/Server/Packets/InstancePackets.h @@ -157,9 +157,11 @@ namespace WorldPackets WorldPacket const* Write() override; - uint8 Type = 0; + int32 Type = 0; uint32 MapID = 0; uint32 DifficultyID = 0; + int32 TimeLeft = 0; + std::string_view WarningMessage; // GlobalStrings tag bool Locked = false; bool Extended = false; }; diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp index fd07ebf5a0c..58cdac4959f 100644 --- a/src/server/game/Server/Packets/ItemPackets.cpp +++ b/src/server/game/Server/Packets/ItemPackets.cpp @@ -257,7 +257,7 @@ WorldPacket const* WorldPackets::Item::ItemPushResult::Write() _worldPacket << int32(DungeonEncounterID); _worldPacket << int32(BattlePetSpeciesID); _worldPacket << int32(BattlePetBreedID); - _worldPacket << uint32(BattlePetBreedQuality); + _worldPacket << uint8(BattlePetBreedQuality); _worldPacket << int32(BattlePetLevel); _worldPacket << ItemGUID; diff --git a/src/server/game/Server/Packets/ItemPackets.h b/src/server/game/Server/Packets/ItemPackets.h index 093db816652..040b6746ed6 100644 --- a/src/server/game/Server/Packets/ItemPackets.h +++ b/src/server/game/Server/Packets/ItemPackets.h @@ -349,7 +349,7 @@ namespace WorldPackets int32 DungeonEncounterID = 0; int32 BattlePetSpeciesID = 0; int32 BattlePetBreedID = 0; - uint32 BattlePetBreedQuality = 0; + uint8 BattlePetBreedQuality = 0; int32 BattlePetLevel = 0; ObjectGuid ItemGUID; bool Pushed = false; diff --git a/src/server/game/Server/Packets/ItemPacketsCommon.cpp b/src/server/game/Server/Packets/ItemPacketsCommon.cpp index 63843747a63..961b387f8fd 100644 --- a/src/server/game/Server/Packets/ItemPacketsCommon.cpp +++ b/src/server/game/Server/Packets/ItemPacketsCommon.cpp @@ -160,16 +160,16 @@ ByteBuffer& operator>>(ByteBuffer& data, ItemBonuses& itemBonusInstanceData) ByteBuffer& operator<<(ByteBuffer& data, ItemMod const& itemMod) { - data << int32(itemMod.Value); data << uint8(itemMod.Type); + data << int32(itemMod.Value); return data; } ByteBuffer& operator>>(ByteBuffer& data, ItemMod& itemMod) { - data >> itemMod.Value; data >> As<uint8>(itemMod.Type); + data >> itemMod.Value; return data; } diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index 3105c46b6f9..ef05b6ebe08 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -681,6 +681,7 @@ WorldPacket const* WorldPackets::Movement::NewWorld::Write() _worldPacket << Loc; _worldPacket << uint32(Reason); _worldPacket << MovementOffset; + _worldPacket << int32(Counter); return &_worldPacket; } diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h index 51a0c4c002a..1ed4e1d70d5 100644 --- a/src/server/game/Server/Packets/MovementPackets.h +++ b/src/server/game/Server/Packets/MovementPackets.h @@ -270,6 +270,7 @@ namespace WorldPackets uint32 Reason = 0; TeleportLocation Loc; TaggedPosition<Position::XYZ> MovementOffset; // Adjusts all pending movement events by this offset + int32 Counter = 0; }; class WorldPortResponse final : public ClientPacket diff --git a/src/server/game/Server/Packets/NPCPackets.cpp b/src/server/game/Server/Packets/NPCPackets.cpp index ca1213cadd2..390fd319753 100644 --- a/src/server/game/Server/Packets/NPCPackets.cpp +++ b/src/server/game/Server/Packets/NPCPackets.cpp @@ -24,6 +24,7 @@ ByteBuffer& operator<<(ByteBuffer& data, TreasureItem const& treasureItem) data << Bits<1>(treasureItem.Type); data << int32(treasureItem.ID); data << int32(treasureItem.Quantity); + data << int8(treasureItem.ItemContext); return data; } @@ -51,6 +52,7 @@ ByteBuffer& operator<<(ByteBuffer& data, ClientGossipOptions const& gossipOption data << Bits<2>(gossipOption.Status); data << OptionalInit(gossipOption.SpellID); data << OptionalInit(gossipOption.OverrideIconID); + data << Bits<8>(gossipOption.FailureDescription.length() + 1); data.FlushBits(); data << gossipOption.Treasure; @@ -64,6 +66,9 @@ ByteBuffer& operator<<(ByteBuffer& data, ClientGossipOptions const& gossipOption if (gossipOption.OverrideIconID) data << int32(*gossipOption.OverrideIconID); + if (!gossipOption.FailureDescription.empty()) + data << gossipOption.FailureDescription; + return data; } @@ -74,11 +79,15 @@ ByteBuffer& operator<<(ByteBuffer& data, ClientGossipText const& gossipText) data << int32(gossipText.QuestType); data << int32(gossipText.QuestLevel); data << int32(gossipText.QuestMaxScalingLevel); + data << int32(gossipText.Unused1102); data << int32(gossipText.QuestFlags[0]); data << int32(gossipText.QuestFlags[1]); + data << int32(gossipText.QuestFlags[2]); data << Bits<1>(gossipText.Repeatable); + data << Bits<1>(gossipText.ResetByScheduler); data << Bits<1>(gossipText.Important); + data << Bits<1>(gossipText.Meta); data << BitsSize<9>(gossipText.QuestTitle); data.FlushBits(); @@ -106,6 +115,7 @@ WorldPacket const* GossipMessage::Write() { _worldPacket << GossipGUID; _worldPacket << int32(GossipID); + _worldPacket << int32(LfgDungeonsID); _worldPacket << int32(FriendshipFactionID); _worldPacket << uint32(GossipOptions.size()); _worldPacket << uint32(GossipText.size()); diff --git a/src/server/game/Server/Packets/NPCPackets.h b/src/server/game/Server/Packets/NPCPackets.h index 8b398f72f87..526f1c1432c 100644 --- a/src/server/game/Server/Packets/NPCPackets.h +++ b/src/server/game/Server/Packets/NPCPackets.h @@ -34,7 +34,6 @@ namespace WorldPackets { namespace NPC { - // CMSG_BANKER_ACTIVATE // CMSG_BINDER_ACTIVATE // CMSG_BINDER_CONFIRM // CMSG_GOSSIP_HELLO @@ -68,6 +67,7 @@ namespace WorldPackets GossipOptionRewardType Type = GossipOptionRewardType(0); int32 ID = 0; int32 Quantity = 0; + int8 ItemContext = 0; }; struct TreasureLootList @@ -90,6 +90,7 @@ namespace WorldPackets TreasureLootList Treasure; Optional<int32> SpellID; Optional<int32> OverrideIconID; + std::string FailureDescription; }; struct ClientGossipText @@ -97,12 +98,15 @@ namespace WorldPackets int32 QuestID = 0; int32 ContentTuningID = 0; int32 QuestType = 0; + int32 Unused1102 = 0; int32 QuestLevel = 0; int32 QuestMaxScalingLevel = 0; bool Repeatable = false; + bool ResetByScheduler = false; bool Important = false; + bool Meta = false; std::string QuestTitle; - std::array<int32, 2> QuestFlags = { }; + std::array<int32, 3> QuestFlags = { }; }; ByteBuffer& operator<<(ByteBuffer& data, ClientGossipText const& gossipText); @@ -121,6 +125,7 @@ namespace WorldPackets Optional<int32> TextID; // in classic variants this still holds npc_text id Optional<int32> BroadcastTextID; int32 GossipID = 0; + int32 LfgDungeonsID = 0; }; class GossipSelectOption final : public ClientPacket diff --git a/src/server/game/Server/Packets/PartyPackets.cpp b/src/server/game/Server/Packets/PartyPackets.cpp index 7a015e4bdae..25393445918 100644 --- a/src/server/game/Server/Packets/PartyPackets.cpp +++ b/src/server/game/Server/Packets/PartyPackets.cpp @@ -507,6 +507,7 @@ WorldPacket const* WorldPackets::Party::PartyUpdate::Write() _worldPacket << uint32(SequenceNum); _worldPacket << LeaderGUID; _worldPacket << uint8(LeaderFactionGroup); + _worldPacket << int32(PingRestriction); _worldPacket << uint32(PlayerList.size()); _worldPacket.WriteBit(LfgInfos.has_value()); _worldPacket.WriteBit(LootSettings.has_value()); diff --git a/src/server/game/Server/Packets/PartyPackets.h b/src/server/game/Server/Packets/PartyPackets.h index f450f25ee90..986fcbde694 100644 --- a/src/server/game/Server/Packets/PartyPackets.h +++ b/src/server/game/Server/Packets/PartyPackets.h @@ -560,6 +560,8 @@ namespace WorldPackets int32 MyIndex = 0; int32 SequenceNum = 0; + RestrictPingsTo PingRestriction = RestrictPingsTo::None; + std::vector<PartyPlayerInfo> PlayerList; Optional<PartyLFGInfo> LfgInfos; diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp index fd124ea5095..afd92df1306 100644 --- a/src/server/game/Server/Packets/QueryPackets.cpp +++ b/src/server/game/Server/Packets/QueryPackets.cpp @@ -153,21 +153,6 @@ void QueryPlayerNames::Read() _worldPacket >> player; } -ByteBuffer& operator<<(ByteBuffer& data, PlayerGuidLookupHint const& lookupHint) -{ - data.WriteBit(lookupHint.VirtualRealmAddress.has_value()); - data.WriteBit(lookupHint.NativeRealmAddress.has_value()); - data.FlushBits(); - - if (lookupHint.VirtualRealmAddress) - data << uint32(*lookupHint.VirtualRealmAddress); - - if (lookupHint.NativeRealmAddress) - data << uint32(*lookupHint.NativeRealmAddress); - - return data; -} - bool PlayerGuidLookupData::Initialize(ObjectGuid const& guid, Player const* player /*= nullptr*/) { CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByGuid(guid); @@ -185,6 +170,7 @@ bool PlayerGuidLookupData::Initialize(ObjectGuid const& guid, Player const* play Sex = player->GetNativeGender(); ClassID = player->GetClass(); Level = player->GetLevel(); + TimerunningSeasonID = 0; // player->m_activePlayerData->TimerunningSeasonID; if (UF::DeclinedNames const* names = player->GetDeclinedNames()) DeclinedNames = *names; @@ -232,6 +218,7 @@ ByteBuffer& operator<<(ByteBuffer& data, PlayerGuidLookupData const& lookupData) data << uint8(lookupData.ClassID); data << uint8(lookupData.Level); data << uint8(lookupData.Unused915); + data << int32(lookupData.TimerunningSeasonID); data.WriteString(lookupData.Name); return data; @@ -391,9 +378,9 @@ WorldPacket const* CorpseLocation::Write() _worldPacket << Player; _worldPacket << ActualMapID; - _worldPacket << Position; _worldPacket << MapID; _worldPacket << Transport; + _worldPacket << Position; return &_worldPacket; } diff --git a/src/server/game/Server/Packets/QueryPackets.h b/src/server/game/Server/Packets/QueryPackets.h index ea286d6ea9b..726791ebdf8 100644 --- a/src/server/game/Server/Packets/QueryPackets.h +++ b/src/server/game/Server/Packets/QueryPackets.h @@ -101,12 +101,6 @@ namespace WorldPackets uint32 CreatureID = 0; }; - struct PlayerGuidLookupHint - { - Optional<uint32> VirtualRealmAddress; ///< current realm (?) (identifier made from the Index, BattleGroup and Region) - Optional<uint32> NativeRealmAddress; ///< original realm (?) (identifier made from the Index, BattleGroup and Region) - }; - class QueryPlayerNames final : public ClientPacket { public: @@ -133,6 +127,7 @@ namespace WorldPackets uint8 ClassID = CLASS_NONE; uint8 Level = 0; uint8 Unused915 = 0; + int32 TimerunningSeasonID = 0; DeclinedName DeclinedNames; }; @@ -443,7 +438,6 @@ namespace WorldPackets WorldPackets::Auth::VirtualRealmNameInfo NameInfo; }; - ByteBuffer& operator<<(ByteBuffer& data, PlayerGuidLookupHint const& lookupHint); ByteBuffer& operator<<(ByteBuffer& data, PlayerGuidLookupData const& lookupData); } } diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp index c000257862c..1b5878981cb 100644 --- a/src/server/game/Server/Packets/QuestPackets.cpp +++ b/src/server/game/Server/Packets/QuestPackets.cpp @@ -185,12 +185,19 @@ WorldPacket const* QueryQuestInfoResponse::Write() _worldPacket << uint32(Info.Objectives.size()); _worldPacket << uint64(Info.AllowableRaces.RawValue); - _worldPacket << int32(Info.TreasurePickerID); + _worldPacket << uint32(Info.TreasurePickerID.size()); + _worldPacket << uint32(Info.TreasurePickerID2.size()); _worldPacket << int32(Info.Expansion); _worldPacket << int32(Info.ManagedWorldStateID); _worldPacket << int32(Info.QuestSessionBonus); _worldPacket << int32(Info.QuestGiverCreatureID); + if (!Info.TreasurePickerID.empty()) + _worldPacket.append(Info.TreasurePickerID.data(), Info.TreasurePickerID.size()); + + if (!Info.TreasurePickerID2.empty()) + _worldPacket.append(Info.TreasurePickerID2.data(), Info.TreasurePickerID2.size()); + _worldPacket << BitsSize<9>(Info.LogTitle); _worldPacket << BitsSize<12>(Info.LogDescription); _worldPacket << BitsSize<12>(Info.QuestDescription); @@ -206,7 +213,7 @@ WorldPacket const* QueryQuestInfoResponse::Write() for (QuestObjective const& questObjective : Info.Objectives) { _worldPacket << uint32(questObjective.ID); - _worldPacket << uint8(questObjective.Type); + _worldPacket << int32(questObjective.Type); _worldPacket << int8(questObjective.StorageIndex); _worldPacket << int32(questObjective.ObjectID); _worldPacket << int32(questObjective.Amount); @@ -267,6 +274,14 @@ WorldPacket const* QuestUpdateAddPvPCredit::Write() return &_worldPacket; } +ByteBuffer& operator<<(ByteBuffer& data, QuestRewardItem const& questRewardItem) +{ + data << int32(questRewardItem.ItemID); + data << int32(questRewardItem.ItemQty); + + return data; +} + ByteBuffer& operator<<(ByteBuffer& data, QuestChoiceItem const& questChoiceItem) { data << Bits<2>(questChoiceItem.LootItemType); @@ -286,17 +301,25 @@ ByteBuffer& operator>>(ByteBuffer& data, QuestChoiceItem& questChoiceItem) return data; } +ByteBuffer& operator<<(ByteBuffer& data, QuestRewardCurrency const& questRewardCurrency) +{ + data << int32(questRewardCurrency.CurrencyID); + data << int32(questRewardCurrency.CurrencyQty); + data << int32(questRewardCurrency.BonusQty); + + return data; +} + ByteBuffer& operator<<(ByteBuffer& data, QuestRewards const& questRewards) { - data << int32(questRewards.ChoiceItemCount); - data << int32(questRewards.ItemCount); + for (QuestRewardItem const& item : questRewards.Items) + data << item; - for (uint32 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) - { - data << int32(questRewards.ItemID[i]); - data << int32(questRewards.ItemQty[i]); - } + for (QuestRewardCurrency const& currency : questRewards.Currencies) + data << currency; + data << int32(questRewards.ChoiceItemCount); + data << int32(questRewards.ItemCount); data << int32(questRewards.Money); data << int32(questRewards.XP); data << int64(questRewards.ArtifactXP); @@ -316,16 +339,11 @@ ByteBuffer& operator<<(ByteBuffer& data, QuestRewards const& questRewards) data.append(questRewards.SpellCompletionDisplayID.data(), questRewards.SpellCompletionDisplayID.size()); data << int32(questRewards.SpellCompletionID); - - for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - { - data << int32(questRewards.CurrencyID[i]); - data << int32(questRewards.CurrencyQty[i]); - } - data << int32(questRewards.SkillLineID); data << int32(questRewards.NumSkillUps); - data << int32(questRewards.TreasurePickerID); + data << uint32(questRewards.TreasurePickerID.size()); + if (!questRewards.TreasurePickerID.empty()) + data.append(questRewards.TreasurePickerID.data(), questRewards.TreasurePickerID.size()); for (QuestChoiceItem const& choiceItem : questRewards.ChoiceItems) data << choiceItem; @@ -338,14 +356,16 @@ ByteBuffer& operator<<(ByteBuffer& data, QuestRewards const& questRewards) ByteBuffer& operator<<(ByteBuffer& data, QuestGiverOfferReward const& offer) { + data << offer.Rewards; // QuestRewards + data << int32(offer.Emotes.size()); data << offer.QuestGiverGUID; - data << int32(offer.QuestGiverCreatureID); - data << int32(offer.QuestID); data << int32(offer.QuestFlags[0]); // Flags data << int32(offer.QuestFlags[1]); // FlagsEx data << int32(offer.QuestFlags[2]); // FlagsEx2 + data << int32(offer.QuestGiverCreatureID); + data << int32(offer.QuestID); data << int32(offer.SuggestedPartyMembers); - data << int32(offer.Emotes.size()); + data << int32(offer.QuestInfoID); for (QuestDescEmote const& emote : offer.Emotes) { data << int32(emote.Type); @@ -354,10 +374,9 @@ ByteBuffer& operator<<(ByteBuffer& data, QuestGiverOfferReward const& offer) data << Bits<1>(offer.AutoLaunched); data << Bits<1>(false); // Unused + data << Bits<1>(offer.ResetByScheduler); data.FlushBits(); - data << offer.Rewards; // QuestRewards - return data; } @@ -447,6 +466,7 @@ WorldPacket const* QuestGiverQuestDetails::Write() _worldPacket << uint32(DescEmotes.size()); _worldPacket << uint32(Objectives.size()); _worldPacket << int32(QuestStartItemID); + _worldPacket << int32(QuestInfoID); _worldPacket << int32(QuestSessionBonus); _worldPacket << int32(QuestGiverCreatureID); _worldPacket << uint32(ConditionalDescriptionText.size()); @@ -463,9 +483,9 @@ WorldPacket const* QuestGiverQuestDetails::Write() for (QuestObjectiveSimple const& obj : Objectives) { _worldPacket << int32(obj.ID); + _worldPacket << int32(obj.Type); _worldPacket << int32(obj.ObjectID); _worldPacket << int32(obj.Amount); - _worldPacket << uint8(obj.Type); } _worldPacket << BitsSize<9>(QuestTitle); @@ -498,19 +518,20 @@ WorldPacket const* QuestGiverQuestDetails::Write() WorldPacket const* QuestGiverRequestItems::Write() { + _worldPacket << int32(Collect.size()); + _worldPacket << int32(Currency.size()); _worldPacket << QuestGiverGUID; + _worldPacket << uint32(QuestFlags[0]); + _worldPacket << uint32(QuestFlags[1]); + _worldPacket << uint32(QuestFlags[2]); + _worldPacket << int32(StatusFlags); _worldPacket << int32(QuestGiverCreatureID); _worldPacket << int32(QuestID); _worldPacket << int32(CompEmoteDelay); _worldPacket << int32(CompEmoteType); - _worldPacket << uint32(QuestFlags[0]); - _worldPacket << uint32(QuestFlags[1]); - _worldPacket << uint32(QuestFlags[2]); _worldPacket << int32(SuggestPartyMembers); _worldPacket << int32(MoneyToGet); - _worldPacket << int32(Collect.size()); - _worldPacket << int32(Currency.size()); - _worldPacket << int32(StatusFlags); + _worldPacket << int32(QuestInfoID); for (QuestObjectiveCollect const& obj : Collect) { @@ -526,6 +547,7 @@ WorldPacket const* QuestGiverRequestItems::Write() } _worldPacket << Bits<1>(AutoLaunched); + _worldPacket << Bits<1>(ResetByScheduler); _worldPacket.FlushBits(); _worldPacket << int32(QuestGiverCreatureID); diff --git a/src/server/game/Server/Packets/QuestPackets.h b/src/server/game/Server/Packets/QuestPackets.h index f90977ef07a..3c956bc1d4e 100644 --- a/src/server/game/Server/Packets/QuestPackets.h +++ b/src/server/game/Server/Packets/QuestPackets.h @@ -188,7 +188,8 @@ namespace WorldPackets int32 CompleteSoundKitID = 0; int32 AreaGroupID = 0; int64 TimeAllowed = 0; - int32 TreasurePickerID = 0; + std::span<int32 const> TreasurePickerID; + std::span<int32 const> TreasurePickerID2; // unknown purpose, used only sometimes and only if TreasurePickerID is empty int32 Expansion = 0; int32 ManagedWorldStateID = 0; int32 QuestSessionBonus = 0; @@ -258,6 +259,13 @@ namespace WorldPackets uint16 Count = 0; }; + struct QuestRewardItem + { + int32 ItemID = 0; + int32 ItemQty = 0; + }; + + struct QuestChoiceItem { ::LootItemType LootItemType = ::LootItemType::Item; @@ -265,6 +273,13 @@ namespace WorldPackets int32 Quantity = 0; }; + struct QuestRewardCurrency + { + int32 CurrencyID = 0; + int32 CurrencyQty = 0; + int32 BonusQty = 0; + }; + struct QuestRewards { int32 ChoiceItemCount = 0; @@ -280,16 +295,14 @@ namespace WorldPackets int32 SpellCompletionID = 0; int32 SkillLineID = 0; int32 NumSkillUps = 0; - int32 TreasurePickerID = 0; + std::span<int32 const> TreasurePickerID; std::array<QuestChoiceItem, QUEST_REWARD_CHOICES_COUNT> ChoiceItems = { }; - std::array<int32, QUEST_REWARD_ITEM_COUNT> ItemID = { }; - std::array<int32, QUEST_REWARD_ITEM_COUNT> ItemQty = { }; + std::array<QuestRewardItem, QUEST_REWARD_ITEM_COUNT> Items = { }; std::array<int32, QUEST_REWARD_REPUTATIONS_COUNT> FactionID = { }; std::array<int32, QUEST_REWARD_REPUTATIONS_COUNT> FactionValue = { }; std::array<int32, QUEST_REWARD_REPUTATIONS_COUNT> FactionOverride = { }; std::array<int32, QUEST_REWARD_REPUTATIONS_COUNT> FactionCapIn = { }; - std::array<int32, QUEST_REWARD_CURRENCY_COUNT> CurrencyID = { }; - std::array<int32, QUEST_REWARD_CURRENCY_COUNT> CurrencyQty = { }; + std::array<QuestRewardCurrency, QUEST_REWARD_CURRENCY_COUNT> Currencies = { }; bool IsBoostSpell = false; }; @@ -306,10 +319,12 @@ namespace WorldPackets int32 QuestGiverCreatureID = 0; int32 QuestID = 0; bool AutoLaunched = false; + bool ResetByScheduler = false; int32 SuggestedPartyMembers = 0; QuestRewards Rewards; std::vector<QuestDescEmote> Emotes; std::array<int32, 3> QuestFlags = { }; + int32 QuestInfoID = 0; }; class QuestGiverOfferRewardMessage final : public ServerPacket @@ -391,9 +406,9 @@ namespace WorldPackets struct QuestObjectiveSimple { int32 ID = 0; + int32 Type = 0; int32 ObjectID = 0; int32 Amount = 0; - uint8 Type = 0; }; class QuestGiverQuestDetails final : public ServerPacket @@ -418,6 +433,7 @@ namespace WorldPackets int32 PortraitGiverMount = 0; int32 PortraitGiverModelSceneID = 0; int32 QuestStartItemID = 0; + int32 QuestInfoID = 0; int32 QuestSessionBonus = 0; int32 QuestGiverCreatureID = 0; std::string PortraitGiverText; @@ -461,11 +477,13 @@ namespace WorldPackets int32 CompEmoteDelay = 0; int32 CompEmoteType = 0; bool AutoLaunched = false; + bool ResetByScheduler = false; int32 SuggestPartyMembers = 0; int32 MoneyToGet = 0; std::vector<QuestObjectiveCollect> Collect; std::vector<QuestCurrency> Currency; int32 StatusFlags = 0; + int32 QuestInfoID = 0; uint32 QuestFlags[3] = { }; std::string QuestTitle; std::string CompletionText; diff --git a/src/server/game/Server/Packets/ReputationPackets.cpp b/src/server/game/Server/Packets/ReputationPackets.cpp index 9f77a774f73..0f867067736 100644 --- a/src/server/game/Server/Packets/ReputationPackets.cpp +++ b/src/server/game/Server/Packets/ReputationPackets.cpp @@ -18,18 +18,37 @@ #include "ReputationPackets.h" #include "PacketUtilities.h" +namespace WorldPackets::Reputation +{ +ByteBuffer& operator<<(ByteBuffer& data, FactionData const& factionData) +{ + data << int32(factionData.FactionID); + data << uint16(factionData.Flags); + data << int32(factionData.Standing); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, FactionBonusData const& factionBonusData) +{ + data << int32(factionBonusData.FactionID); + data << Bits<1>(factionBonusData.FactionHasBonus); + data.FlushBits(); + + return data; +} +} + WorldPacket const* WorldPackets::Reputation::InitializeFactions::Write() { - for (uint16 i = 0; i < FactionCount; ++i) - { - _worldPacket << uint16(FactionFlags[i]); - _worldPacket << int32(FactionStandings[i]); - } + _worldPacket << uint32(Factions.size()); + _worldPacket << uint32(Bonuses.size()); - for (uint16 i = 0; i < FactionCount; ++i) - _worldPacket.WriteBit(FactionHasBonus[i]); + for (FactionData const& faction : Factions) + _worldPacket << faction; - _worldPacket.FlushBits(); + for (FactionBonusData const& bonus : Bonuses) + _worldPacket << bonus; return &_worldPacket; } diff --git a/src/server/game/Server/Packets/ReputationPackets.h b/src/server/game/Server/Packets/ReputationPackets.h index 2acaa859ed6..30199fdd246 100644 --- a/src/server/game/Server/Packets/ReputationPackets.h +++ b/src/server/game/Server/Packets/ReputationPackets.h @@ -25,18 +25,28 @@ namespace WorldPackets { namespace Reputation { - static constexpr uint16 FactionCount = 1000; + struct FactionData + { + int32 FactionID = 0; + uint16 Flags = 0; + int32 Standing = 0; + }; + + struct FactionBonusData + { + int32 FactionID = 0; + bool FactionHasBonus = false; + }; class InitializeFactions final : public ServerPacket { public: - InitializeFactions() : ServerPacket(SMSG_INITIALIZE_FACTIONS, FactionCount * (4 + 2) + FactionCount / 8) { } + InitializeFactions() : ServerPacket(SMSG_INITIALIZE_FACTIONS, 0x1000) { } WorldPacket const* Write() override; - std::array<int32, FactionCount> FactionStandings = { }; - std::array<bool, FactionCount> FactionHasBonus = { }; ///< @todo: implement faction bonus - std::array<uint16, FactionCount> FactionFlags = { }; ///< @see enum FactionFlags + std::vector<FactionData> Factions; + std::vector<FactionBonusData> Bonuses; }; struct FactionStandingData diff --git a/src/server/game/Server/Packets/ScenePackets.cpp b/src/server/game/Server/Packets/ScenePackets.cpp index f474b11c2b7..5ee41987e85 100644 --- a/src/server/game/Server/Packets/ScenePackets.cpp +++ b/src/server/game/Server/Packets/ScenePackets.cpp @@ -26,6 +26,7 @@ WorldPacket const* WorldPackets::Scenes::PlayScene::Write() _worldPacket << int32(SceneScriptPackageID); _worldPacket << TransportGUID; _worldPacket << Location; + _worldPacket << int32(MovieID); _worldPacket << Bits<1>(Encrypted); _worldPacket.FlushBits(); diff --git a/src/server/game/Server/Packets/ScenePackets.h b/src/server/game/Server/Packets/ScenePackets.h index ce63a086e38..56d60a1f776 100644 --- a/src/server/game/Server/Packets/ScenePackets.h +++ b/src/server/game/Server/Packets/ScenePackets.h @@ -37,6 +37,7 @@ namespace WorldPackets uint32 PlaybackFlags = 0; uint32 SceneInstanceID = 0; int32 SceneScriptPackageID = 0; + int32 MovieID = 0; ObjectGuid TransportGUID; TaggedPosition<Position::XYZO> Location; bool Encrypted = false; diff --git a/src/server/game/Server/Packets/SocialPackets.cpp b/src/server/game/Server/Packets/SocialPackets.cpp index 7e7d7e188e5..839a9ea91f0 100644 --- a/src/server/game/Server/Packets/SocialPackets.cpp +++ b/src/server/game/Server/Packets/SocialPackets.cpp @@ -50,7 +50,6 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Social::ContactInfo const data << uint32(contact.Level); data << uint32(contact.ClassID); data.WriteBits(contact.Notes.length(), 10); - data.WriteBit(contact.Mobile); data.FlushBits(); data.WriteString(contact.Notes); @@ -93,7 +92,6 @@ WorldPacket const* WorldPackets::Social::FriendStatus::Write() _worldPacket << uint32(Level); _worldPacket << uint32(ClassID); _worldPacket.WriteBits(Notes.length(), 10); - _worldPacket.WriteBit(Mobile); _worldPacket.FlushBits(); _worldPacket.WriteString(Notes); diff --git a/src/server/game/Server/Packets/SocialPackets.h b/src/server/game/Server/Packets/SocialPackets.h index 3007cb3800b..9ee43e163b1 100644 --- a/src/server/game/Server/Packets/SocialPackets.h +++ b/src/server/game/Server/Packets/SocialPackets.h @@ -53,7 +53,6 @@ namespace WorldPackets uint32 AreaID = 0; uint32 Level = 0; uint32 ClassID = CLASS_NONE; - bool Mobile = false; }; class ContactList final : public ServerPacket @@ -85,7 +84,6 @@ namespace WorldPackets uint32 Level = 0; uint32 AreaID = 0; uint8 FriendResult = 0; ///< @see enum FriendsResult - bool Mobile = false; }; struct QualifiedGUID diff --git a/src/server/game/Server/Packets/SpellPackets.cpp b/src/server/game/Server/Packets/SpellPackets.cpp index ccb284edfe5..3f142ed0671 100644 --- a/src/server/game/Server/Packets/SpellPackets.cpp +++ b/src/server/game/Server/Packets/SpellPackets.cpp @@ -220,6 +220,7 @@ ByteBuffer& operator>>(ByteBuffer& buffer, SpellCastRequest& request) request.OptionalCurrencies.resize(buffer.read<uint32>()); request.OptionalReagents.resize(buffer.read<uint32>()); request.RemovedModifications.resize(buffer.read<uint32>()); + buffer >> request.CraftingFlags; for (SpellExtraCurrencyCost& optionalCurrency : request.OptionalCurrencies) buffer >> optionalCurrency; @@ -328,8 +329,8 @@ ByteBuffer& operator<<(ByteBuffer& data, SpellMissStatus const& spellMissStatus) ByteBuffer& operator<<(ByteBuffer& data, SpellPowerData const& spellPowerData) { - data << int32(spellPowerData.Cost); data << int8(spellPowerData.Type); + data << int32(spellPowerData.Cost); return data; } @@ -742,6 +743,7 @@ WorldPacket const* PlayOrphanSpellVisual::Write() _worldPacket << SourceRotation; _worldPacket << TargetLocation; _worldPacket << Target; + _worldPacket << TargetTransport; _worldPacket << int32(SpellVisualID); _worldPacket << float(TravelSpeed); _worldPacket << float(LaunchDelay); diff --git a/src/server/game/Server/Packets/SpellPackets.h b/src/server/game/Server/Packets/SpellPackets.h index dd60478e9b6..cd8523c34df 100644 --- a/src/server/game/Server/Packets/SpellPackets.h +++ b/src/server/game/Server/Packets/SpellPackets.h @@ -241,6 +241,7 @@ namespace WorldPackets Array<SpellCraftingReagent, 6> RemovedModifications; Array<SpellExtraCurrencyCost, 5 /*MAX_ITEM_EXT_COST_CURRENCIES*/> OptionalCurrencies; Optional<uint64> CraftingOrderID; + uint8 CraftingFlags = 0; // 1 = ApplyConcentration ObjectGuid CraftingNPC; int32 Misc[2] = { }; }; @@ -695,6 +696,7 @@ namespace WorldPackets WorldPacket const* Write() override; ObjectGuid Target; // Exclusive with TargetLocation + ObjectGuid TargetTransport; TaggedPosition<Position::XYZ> SourceLocation; int32 SpellVisualID = 0; bool SpeedAsTime = false; diff --git a/src/server/game/Server/Packets/SystemPackets.cpp b/src/server/game/Server/Packets/SystemPackets.cpp index c336555ea28..c14bc777465 100644 --- a/src/server/game/Server/Packets/SystemPackets.cpp +++ b/src/server/game/Server/Packets/SystemPackets.cpp @@ -82,6 +82,8 @@ WorldPacket const* FeatureSystemStatus::Write() _worldPacket << int32(ActiveSeason); _worldPacket << uint32(GameRuleValues.size()); + _worldPacket << int32(ActiveTimerunningSeasonID); + _worldPacket << int32(RemainingTimerunningSeasonSeconds); _worldPacket << int16(MaxPlayerNameQueriesPerPacket); _worldPacket << int16(PlayerNameQueryTelemetryInterval); @@ -126,7 +128,7 @@ WorldPacket const* FeatureSystemStatus::Write() _worldPacket << Bits<1>(QuestSessionEnabled); _worldPacket << Bits<1>(IsMuted); _worldPacket << Bits<1>(ClubFinderEnabled); - _worldPacket << Bits<1>(IsCommunityFinderEnabled); + _worldPacket << Bits<1>(CommunityFinderEnabled); _worldPacket << Bits<1>(Unknown901CheckoutRelated); _worldPacket << Bits<1>(TextToSpeechFeatureEnabled); @@ -134,22 +136,25 @@ WorldPacket const* FeatureSystemStatus::Write() _worldPacket << Bits<1>(ChatDisabledByPlayer); _worldPacket << Bits<1>(LFGListCustomRequiresAuthenticator); _worldPacket << Bits<1>(AddonsDisabled); + _worldPacket << Bits<1>(TimerunningEnabled); _worldPacket << Bits<1>(WarGamesEnabled); - _worldPacket << Bits<1>(Unk440_1); // unk, unused 4.4.0 - _worldPacket << Bits<1>(false); // unk, unused 4.4.0 _worldPacket << Bits<1>(ContentTrackingEnabled); - _worldPacket << Bits<1>(IsSellAllJunkEnabled); + _worldPacket << Bits<1>(IsGroupFinderEnabled); _worldPacket << Bits<1>(IsLFDEnabled); _worldPacket << Bits<1>(IsLFREnabled); _worldPacket << Bits<1>(IsPremadeGroupEnabled); _worldPacket << Bits<1>(CanShowSetRoleButton); - _worldPacket << Bits<1>(PetHappinessEnabled); - _worldPacket << Bits<1>(CanEditGuildEvent); + _worldPacket << Bits<1>(false); // unused 10.2.7 + _worldPacket << Bits<1>(GuildEventsEditsEnabled); + _worldPacket << Bits<1>(GuildTradeSkillsEnabled); + + _worldPacket << BitsSize<7>(Unknown1027); + _worldPacket << Bits<1>(BNSendWhisperUseV2Services); - _worldPacket.WriteBit(IsGuildTradeSkillsEnabled); - _worldPacket << BitsSize<7>(Field_16F); + _worldPacket << Bits<1>(BNSendGameDataUseV2Services); + _worldPacket << Bits<1>(IsAccountCurrencyTransferEnabled); _worldPacket.FlushBits(); @@ -186,16 +191,10 @@ WorldPacket const* FeatureSystemStatus::Write() _worldPacket << int32(SessionAlert->DisplayTime); } - if (Unk440_1) - { - _worldPacket << uint32(Unk440_2.size()); - _worldPacket.append(Unk440_2.data(), Unk440_2.size()); - } - - _worldPacket.WriteString(Field_16F); + _worldPacket.WriteString(Unknown1027); { - _worldPacket.WriteBit(Squelch.IsSquelched); + _worldPacket << Bits<1>(Squelch.IsSquelched); _worldPacket << Squelch.BnetAccountGuid; _worldPacket << Squelch.GuildGuid; } @@ -222,29 +221,30 @@ WorldPacket const* FeatureSystemStatusGlueScreen::Write() _worldPacket << Bits<1>(IsBoostEnabled); _worldPacket << Bits<1>(TrialBoostEnabled); _worldPacket << Bits<1>(TokenBalanceEnabled); + _worldPacket << Bits<1>(PaidCharacterTransfersBetweenBnetAccountsEnabled); _worldPacket << Bits<1>(LiveRegionCharacterListEnabled); _worldPacket << Bits<1>(LiveRegionCharacterCopyEnabled); - _worldPacket << Bits<1>(LiveRegionAccountCopyEnabled); + _worldPacket << Bits<1>(LiveRegionAccountCopyEnabled); _worldPacket << Bits<1>(LiveRegionKeyBindingsCopyEnabled); _worldPacket << Bits<1>(Unknown901CheckoutRelated); _worldPacket << Bits<1>(false); // unused, 10.0.2 _worldPacket << OptionalInit(EuropaTicketSystemStatus); _worldPacket << Bits<1>(IsNameReservationEnabled); _worldPacket << OptionalInit(LaunchETA); - _worldPacket << Bits<1>(false); // unused, 4.4.0 - _worldPacket << Bits<1>(false); // unused, 4.4.0 + _worldPacket << Bits<1>(TimerunningEnabled); - _worldPacket << Bits<1>(false); // unused, 4.4.0 - _worldPacket << Bits<1>(IsSoMNotificationEnabled); _worldPacket << Bits<1>(AddonsDisabled); _worldPacket << Bits<1>(Unused1000); _worldPacket << Bits<1>(AccountSaveDataExportEnabled); _worldPacket << Bits<1>(AccountLockedByExport); - _worldPacket << OptionalInit(RealmHiddenAlert); - if (RealmHiddenAlert) - _worldPacket << Bits<11>(RealmHiddenAlert->length() + 1); + _worldPacket << Bits<11>(RealmHiddenAlert.length() + 1); + + _worldPacket << Bits<1>(BNSendWhisperUseV2Services); + + _worldPacket << Bits<1>(BNSendGameDataUseV2Services); + _worldPacket << Bits<1>(CharacterSelectListModeRealmless); _worldPacket.FlushBits(); @@ -263,18 +263,20 @@ WorldPacket const* FeatureSystemStatusGlueScreen::Write() _worldPacket << int32(MaximumExpansionLevel); _worldPacket << int32(ActiveSeason); _worldPacket << uint32(GameRuleValues.size()); + _worldPacket << int32(ActiveTimerunningSeasonID); + _worldPacket << int32(RemainingTimerunningSeasonSeconds); _worldPacket << int16(MaxPlayerNameQueriesPerPacket); _worldPacket << int16(PlayerNameQueryTelemetryInterval); _worldPacket << PlayerNameQueryInterval; _worldPacket << uint32(DebugTimeEvents.size()); _worldPacket << int32(Unused1007); - _worldPacket << int32(EventRealmQueues); + _worldPacket << uint32(EventRealmQueues); if (LaunchETA) _worldPacket << int32(*LaunchETA); - if (RealmHiddenAlert && !RealmHiddenAlert->empty()) - _worldPacket.WriteString(*RealmHiddenAlert); + if (!RealmHiddenAlert.empty()) + _worldPacket << RealmHiddenAlert; if (!LiveRegionCharacterCopySourceRegions.empty()) _worldPacket.append(LiveRegionCharacterCopySourceRegions.data(), LiveRegionCharacterCopySourceRegions.size()); diff --git a/src/server/game/Server/Packets/SystemPackets.h b/src/server/game/Server/Packets/SystemPackets.h index 4ffd3ebd806..8c1ff5f18e5 100644 --- a/src/server/game/Server/Packets/SystemPackets.h +++ b/src/server/game/Server/Packets/SystemPackets.h @@ -106,7 +106,7 @@ namespace WorldPackets uint32 Unknown1007 = 0; }; - struct AddonChatThrottleInfo + struct AddonChatThrottleParams { int32 MaxTries = 0; int32 TriesRestoredPerSecond = 0; @@ -158,33 +158,36 @@ namespace WorldPackets bool QuestSessionEnabled = false; bool IsMuted = false; bool ClubFinderEnabled = false; - bool IsCommunityFinderEnabled = false; + bool CommunityFinderEnabled = false; bool Unknown901CheckoutRelated = false; bool TextToSpeechFeatureEnabled = false; bool ChatDisabledByDefault = false; bool ChatDisabledByPlayer = false; bool LFGListCustomRequiresAuthenticator = false; bool AddonsDisabled = false; + bool TimerunningEnabled = false; bool WarGamesEnabled = false; // classic only - bool Unk440_1 = false; // classic only bool ContentTrackingEnabled = false; bool IsSellAllJunkEnabled = false; - bool IsGroupFinderEnabled = false; // classic only - bool IsLFDEnabled = false; // classic only - bool IsLFREnabled = false; // classic only - bool IsPremadeGroupEnabled = false; // classic only - bool CanShowSetRoleButton = false; // classic only - bool PetHappinessEnabled = false; // classic only - bool CanEditGuildEvent = false; // classic only - bool IsGuildTradeSkillsEnabled = false; // classic only + bool IsGroupFinderEnabled = true; // classic only + bool IsLFDEnabled = true; // classic only + bool IsLFREnabled = true; // classic only + bool IsPremadeGroupEnabled = true; // classic only + bool CanShowSetRoleButton = true; + bool GuildEventsEditsEnabled = true; + bool GuildTradeSkillsEnabled = true; + bool BNSendWhisperUseV2Services = true; ///< BNSendWhisper will send to v2.WhisperService instead of v1.NotificationService + bool BNSendGameDataUseV2Services = true; ///< BNSendGameData will send to v2.NotificationService instead of v1.NotificationService + bool IsAccountCurrencyTransferEnabled = false; SocialQueueConfig QuickJoinConfig; SquelchInfo Squelch; RafSystemFeatureInfo RAFSystem; - AddonChatThrottleInfo AddonChatThrottle; std::vector<GameRuleValuePair> GameRuleValues; - std::vector<uint8> Unk440_2; - std::string Field_16F = ""; + int32 ActiveTimerunningSeasonID = 0; + int32 RemainingTimerunningSeasonSeconds = 0; + std::string Unknown1027; // related to movement lua functions used by keybinds + AddonChatThrottleParams AddonChatThrottle; }; struct DebugTimeEventInfo @@ -213,17 +216,21 @@ namespace WorldPackets bool IsBoostEnabled = false; // classic only bool TrialBoostEnabled = false; // NYI bool TokenBalanceEnabled = false; // NYI + bool PaidCharacterTransfersBetweenBnetAccountsEnabled = false; bool LiveRegionCharacterListEnabled = false; // NYI bool LiveRegionCharacterCopyEnabled = false; // NYI bool LiveRegionAccountCopyEnabled = false; // NYI bool LiveRegionKeyBindingsCopyEnabled = false; bool Unknown901CheckoutRelated = false; // NYI + bool IsNameReservationEnabled = false; // classic only + bool TimerunningEnabled = false; // NYI bool AddonsDisabled = false; - bool IsSoMNotificationEnabled = false; // NYI bool Unused1000 = false; bool AccountSaveDataExportEnabled = false; bool AccountLockedByExport = false; - bool IsNameReservationEnabled = false; // NYI classic only + bool BNSendWhisperUseV2Services = true; ///< BNSendWhisper will send to v2.WhisperService instead of v1.NotificationService + bool BNSendGameDataUseV2Services = true; ///< BNSendGameData will send to v2.NotificationService instead of v1.NotificationService + bool CharacterSelectListModeRealmless = false; Optional<EuropaTicketConfig> EuropaTicketSystemStatus; std::vector<int32> LiveRegionCharacterCopySourceRegions; uint32 TokenPollTimeSeconds = 0; // NYI @@ -237,6 +244,8 @@ namespace WorldPackets uint32 KioskSessionMinutes = 0; int32 ActiveSeason = 0; // Currently active Classic season std::vector<GameRuleValuePair> GameRuleValues; + int32 ActiveTimerunningSeasonID = 0; + int32 RemainingTimerunningSeasonSeconds = 0; int16 MaxPlayerNameQueriesPerPacket = 50; int16 PlayerNameQueryTelemetryInterval = 600; Duration<Seconds, uint32> PlayerNameQueryInterval = 10s; @@ -244,7 +253,7 @@ namespace WorldPackets std::vector<DebugTimeEventInfo> DebugTimeEvents; int32 Unused1007 = 0; uint32 EventRealmQueues = 0; - Optional<std::string> RealmHiddenAlert; + std::string RealmHiddenAlert; }; class SetTimeZoneInformation final : public ServerPacket diff --git a/src/server/game/Server/Packets/TaxiPackets.cpp b/src/server/game/Server/Packets/TaxiPackets.cpp index 3fe652aa590..f11519b5c9c 100644 --- a/src/server/game/Server/Packets/TaxiPackets.cpp +++ b/src/server/game/Server/Packets/TaxiPackets.cpp @@ -69,6 +69,13 @@ void WorldPackets::Taxi::ActivateTaxi::Read() _worldPacket >> FlyingMountID; } +WorldPacket const* WorldPackets::Taxi::NewTaxiPath::Write() +{ + _worldPacket << int32(TaxiNodesID); + + return &_worldPacket; +} + WorldPacket const* WorldPackets::Taxi::ActivateTaxiReply::Write() { _worldPacket.WriteBits(Reply, 4); diff --git a/src/server/game/Server/Packets/TaxiPackets.h b/src/server/game/Server/Packets/TaxiPackets.h index ddeb7920d3d..0f80a7b2020 100644 --- a/src/server/game/Server/Packets/TaxiPackets.h +++ b/src/server/game/Server/Packets/TaxiPackets.h @@ -102,9 +102,11 @@ namespace WorldPackets class NewTaxiPath final : public ServerPacket { public: - NewTaxiPath() : ServerPacket(SMSG_NEW_TAXI_PATH, 0) { } + explicit NewTaxiPath(int32 taxiNodesId) : ServerPacket(SMSG_NEW_TAXI_PATH, 4), TaxiNodesID(taxiNodesId) { } - WorldPacket const* Write() override { return &_worldPacket; } + WorldPacket const* Write() override; + + int32 TaxiNodesID = 0; }; class ActivateTaxiReply final : public ServerPacket diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 315c44bfcea..5b5a72e7df0 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -66,6 +66,7 @@ struct Petition; struct Position; enum class AuctionCommand : int8; enum class AuctionResult : int8; +enum class PlayerInteractionType : int32; enum InventoryResult : uint8; enum class StableResult : uint8; enum class TabardVendorType : int32; @@ -134,6 +135,7 @@ namespace WorldPackets { class AutoBankItem; class AutoStoreBankItem; + class BankerActivate; class BuyBankSlot; } @@ -786,13 +788,15 @@ enum AccountDataType PER_CHARACTER_CLICK_BINDINGS_CACHE = 12, GLOBAL_EDIT_MODE_CACHE = 13, PER_CHARACTER_EDIT_MODE_CACHE = 14, + GLOBAL_FRONTEND_CHAT_SETTINGS = 15, + GLOBAL_CHARACTER_LIST_ORDER = 16 }; -#define NUM_ACCOUNT_DATA_TYPES 15 +#define NUM_ACCOUNT_DATA_TYPES 17 -#define ALL_ACCOUNT_DATA_CACHE_MASK 0x7FFF -#define GLOBAL_CACHE_MASK 0x2515 -#define PER_CHARACTER_CACHE_MASK 0x5AEA +#define ALL_ACCOUNT_DATA_CACHE_MASK 0x0001FFFFu +#define GLOBAL_CACHE_MASK 0x0001A515u +#define PER_CHARACTER_CACHE_MASK 0x00005AEAu struct AccountData { @@ -983,7 +987,7 @@ class TC_GAME_API WorldSession void SendTrainerList(Creature* npc, uint32 trainerId); void SendListInventory(ObjectGuid guid); - void SendShowBank(ObjectGuid guid); + void SendShowBank(ObjectGuid guid, PlayerInteractionType interactionType); bool CanOpenMailBox(ObjectGuid guid); void SendShowMailBox(ObjectGuid guid); void SendTabardVendorActivate(ObjectGuid guid, TabardVendorType type); @@ -1327,7 +1331,7 @@ class TC_GAME_API WorldSession void HandleTaxiRequestEarlyLanding(WorldPackets::Taxi::TaxiRequestEarlyLanding& taxiRequestEarlyLanding); void HandleTabardVendorActivateOpcode(WorldPackets::NPC::TabardVendorActivate const& tabardVendorActivate); - void HandleBankerActivateOpcode(WorldPackets::NPC::Hello& packet); + void HandleBankerActivateOpcode(WorldPackets::Bank::BankerActivate const& bankerActivate); void HandleTrainerListOpcode(WorldPackets::NPC::Hello& packet); void HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpell& packet); void HandlePetitionShowList(WorldPackets::Petition::PetitionShowList& packet); diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 8f0e6bde021..7a7fe2122d3 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1388,7 +1388,7 @@ public: static bool HandleBankCommand(ChatHandler* handler) { - handler->GetSession()->SendShowBank(handler->GetSession()->GetPlayer()->GetGUID()); + handler->GetSession()->SendShowBank(handler->GetSession()->GetPlayer()->GetGUID(), PlayerInteractionType::Banker); return true; } |