diff options
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 74 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureData.h | 5 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/GossipDef.cpp | 163 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/GossipDef.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 48 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObjectData.h | 4 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 44 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 49 | ||||
-rw-r--r-- | src/server/game/Handlers/QueryHandler.cpp | 186 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.cpp | 163 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.h | 6 | ||||
-rw-r--r-- | src/server/game/Server/Packets/QueryPackets.cpp | 69 | ||||
-rw-r--r-- | src/server/game/Server/Packets/QueryPackets.h | 33 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 6 | ||||
-rw-r--r-- | src/server/game/World/World.h | 1 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_go.cpp | 8 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_reload.cpp | 3 | ||||
-rw-r--r-- | src/server/worldserver/worldserver.conf.dist | 11 |
18 files changed, 492 insertions, 383 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 8f63d58da85..563f57220a4 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -41,6 +41,7 @@ #include "PhasingHandler.h" #include "Player.h" #include "PoolMgr.h" +#include "QueryPackets.h" #include "QuestDef.h" #include "ScriptedGossip.h" #include "SpellAuraEffects.h" @@ -140,6 +141,79 @@ CreatureModel const* CreatureTemplate::GetFirstVisibleModel() const return &CreatureModel::DefaultVisibleModel; } +void CreatureTemplate::InitializeQueryData() +{ + WorldPacket queryTemp; + for (uint8 loc = LOCALE_enUS; loc < TOTAL_LOCALES; ++loc) + { + queryTemp = BuildQueryData(static_cast<LocaleConstant>(loc)); + QueryData[loc] = queryTemp; + } +} + +WorldPacket CreatureTemplate::BuildQueryData(LocaleConstant loc) const +{ + WorldPackets::Query::QueryCreatureResponse queryTemp; + + queryTemp.CreatureID = Entry; + + queryTemp.Allow = true; + + WorldPackets::Query::CreatureStats& stats = queryTemp.Stats; + + stats.Leader = RacialLeader; + + stats.Name[0] = Name; + stats.NameAlt[0] = FemaleName; + + stats.Flags[0] = type_flags; + stats.Flags[1] = type_flags2; + + stats.CreatureType = type; + stats.CreatureFamily = family; + stats.Classification = rank; + + for (uint32 i = 0; i < MAX_KILL_CREDIT; ++i) + stats.ProxyCreatureID[i] = KillCredit[i]; + + std::transform(Models.begin(), Models.end(), std::back_inserter(stats.Display.CreatureDisplay), + [&stats](CreatureModel const& model) -> WorldPackets::Query::CreatureXDisplay + { + stats.Display.TotalProbability += model.Probability; + return { model.CreatureDisplayID, model.DisplayScale, model.Probability }; + }); + + stats.HpMulti = ModHealth; + stats.EnergyMulti = ModMana; + + stats.CreatureMovementInfoID = movementId; + stats.RequiredExpansion = RequiredExpansion; + stats.HealthScalingExpansion = HealthScalingExpansion; + stats.VignetteID = VignetteID; + stats.Class = unit_class; + stats.FadeRegionRadius = FadeRegionRadius; + stats.WidgetSetID = WidgetSetID; + stats.WidgetSetUnitConditionID = WidgetSetUnitConditionID; + + stats.Title = SubName; + stats.TitleAlt = TitleAlt; + stats.CursorName = IconName; + + if (std::vector<uint32> const* items = sObjectMgr->GetCreatureQuestItemList(Entry)) + stats.QuestItems.insert(stats.QuestItems.begin(), items->begin(), items->end()); + + if (loc != LOCALE_enUS) + if (CreatureLocale const* creatureLocale = sObjectMgr->GetCreatureLocale(Entry)) + { + ObjectMgr::GetLocaleString(creatureLocale->Name, loc, stats.Name[0]); + ObjectMgr::GetLocaleString(creatureLocale->NameAlt, loc, stats.NameAlt[0]); + ObjectMgr::GetLocaleString(creatureLocale->Title, loc, stats.Title); + ObjectMgr::GetLocaleString(creatureLocale->TitleAlt, loc, stats.TitleAlt); + } + + return *queryTemp.Write(); +} + bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { if (Unit* victim = ObjectAccessor::GetUnit(m_owner, m_victim)) diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index bea8ce9fb62..d5f3479f82d 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -22,6 +22,7 @@ #include "Optional.h" #include "SharedDefines.h" #include "UnitDefines.h" +#include "WorldPacket.h" #include <string> #include <unordered_map> #include <vector> @@ -387,6 +388,7 @@ struct TC_GAME_API CreatureTemplate uint32 MechanicImmuneMask; uint32 flags_extra; uint32 ScriptID; + WorldPacket QueryData[TOTAL_LOCALES]; CreatureModel const* GetModelByIdx(uint32 idx) const; CreatureModel const* GetRandomValidModel() const; CreatureModel const* GetFirstValidModel() const; @@ -421,6 +423,9 @@ struct TC_GAME_API CreatureTemplate return canTameExotic || !IsExotic(); } + void InitializeQueryData(); + WorldPacket BuildQueryData(LocaleConstant loc) const; + static int32 DifficultyIDToDifficultyEntryIndex(uint32 difficulty) { switch (difficulty) diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 95b0e042046..743c27d5076 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -256,7 +256,7 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID) ObjectMgr::GetLocaleString(localeData->LogTitle, localeConstant, text.QuestTitle); if (questLevelInTitle) - AddQuestLevelToTitle(text.QuestTitle, quest->GetQuestLevel()); + Quest::AddQuestLevelToTitle(text.QuestTitle, quest->GetQuestLevel()); ++count; } @@ -382,7 +382,7 @@ void PlayerMenu::SendQuestGiverQuestListMessage(Object* questgiver) ObjectMgr::GetLocaleString(questTemplateLocale->LogTitle, localeConstant, title); if (questLevelInTitle) - AddQuestLevelToTitle(title, quest->GetQuestLevel()); + Quest::AddQuestLevelToTitle(title, quest->GetQuestLevel()); bool repeatable = false; // NYI @@ -433,7 +433,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU } if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) - AddQuestLevelToTitle(packet.QuestTitle, quest->GetQuestLevel()); + Quest::AddQuestLevelToTitle(packet.QuestTitle, quest->GetQuestLevel()); packet.QuestGiverGUID = npcGUID; packet.InformUnit = _session->GetPlayer()->GetDivider(); @@ -476,147 +476,14 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const { - WorldPackets::Quest::QueryQuestInfoResponse packet; - - packet.Allow = true; - packet.QuestID = quest->GetQuestId(); - - packet.Info.LogTitle = quest->GetLogTitle(); - packet.Info.LogDescription = quest->GetLogDescription(); - packet.Info.QuestDescription = quest->GetQuestDescription(); - packet.Info.AreaDescription = quest->GetAreaDescription(); - packet.Info.QuestCompletionLog = quest->GetQuestCompletionLog(); - packet.Info.PortraitGiverText = quest->GetPortraitGiverText(); - packet.Info.PortraitGiverName = quest->GetPortraitGiverName(); - packet.Info.PortraitTurnInText = quest->GetPortraitTurnInText(); - packet.Info.PortraitTurnInName = quest->GetPortraitTurnInName(); - - LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex(); - if (localeConstant != LOCALE_enUS) - { - if (QuestTemplateLocale const* questTemplateLocale = sObjectMgr->GetQuestLocale(quest->GetQuestId())) - { - ObjectMgr::GetLocaleString(questTemplateLocale->LogTitle, localeConstant, packet.Info.LogTitle); - ObjectMgr::GetLocaleString(questTemplateLocale->LogDescription, localeConstant, packet.Info.LogDescription); - ObjectMgr::GetLocaleString(questTemplateLocale->QuestDescription, localeConstant, packet.Info.QuestDescription); - ObjectMgr::GetLocaleString(questTemplateLocale->AreaDescription, localeConstant, packet.Info.AreaDescription); - ObjectMgr::GetLocaleString(questTemplateLocale->QuestCompletionLog, localeConstant, packet.Info.QuestCompletionLog); - ObjectMgr::GetLocaleString(questTemplateLocale->PortraitGiverText, localeConstant, packet.Info.PortraitGiverText); - ObjectMgr::GetLocaleString(questTemplateLocale->PortraitGiverName, localeConstant, packet.Info.PortraitGiverName); - ObjectMgr::GetLocaleString(questTemplateLocale->PortraitTurnInText, localeConstant, packet.Info.PortraitTurnInText); - ObjectMgr::GetLocaleString(questTemplateLocale->PortraitTurnInName, localeConstant, packet.Info.PortraitTurnInName); - } - } - - if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) - AddQuestLevelToTitle(packet.Info.LogTitle, quest->GetQuestLevel()); - - packet.Info.QuestID = quest->GetQuestId(); - packet.Info.QuestType = quest->GetQuestType(); - packet.Info.QuestLevel = quest->GetQuestLevel(); - packet.Info.QuestScalingFactionGroup = quest->GetQuestScalingFactionGroup(); - packet.Info.QuestMaxScalingLevel = quest->GetQuestMaxScalingLevel(); - packet.Info.QuestPackageID = quest->GetQuestPackageID(); - packet.Info.QuestMinLevel = quest->GetMinLevel(); - packet.Info.QuestSortID = quest->GetZoneOrSort(); - packet.Info.QuestInfoID = quest->GetQuestInfoID(); - packet.Info.SuggestedGroupNum = quest->GetSuggestedPlayers(); - packet.Info.RewardNextQuest = quest->GetNextQuestInChain(); - packet.Info.RewardXPDifficulty = quest->GetXPDifficulty(); - packet.Info.RewardXPMultiplier = quest->GetXPMultiplier(); - - if (!quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) - packet.Info.RewardMoney = quest->RewardMoney < 0 ? quest->RewardMoney : _session->GetPlayer()->GetQuestMoneyReward(quest); - - packet.Info.RewardMoneyDifficulty = quest->GetRewMoneyDifficulty(); - packet.Info.RewardMoneyMultiplier = quest->GetMoneyMultiplier(); - packet.Info.RewardBonusMoney = quest->GetRewMoneyMaxLevel(); - for (uint8 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i) - packet.Info.RewardDisplaySpell[i] = quest->RewardDisplaySpell[i]; - - packet.Info.RewardSpell = quest->GetRewSpell(); - - packet.Info.RewardHonor = quest->GetRewHonor(); - packet.Info.RewardKillHonor = quest->GetRewKillHonor(); - - packet.Info.RewardArtifactXPDifficulty = quest->GetArtifactXPDifficulty(); - packet.Info.RewardArtifactXPMultiplier = quest->GetArtifactXPMultiplier(); - packet.Info.RewardArtifactCategoryID = quest->GetArtifactCategoryId(); - - packet.Info.StartItem = quest->GetSrcItemId(); - packet.Info.Flags = quest->GetFlags(); - packet.Info.FlagsEx = quest->GetFlagsEx(); - packet.Info.FlagsEx2 = quest->GetFlagsEx2(); - packet.Info.RewardTitle = quest->GetRewTitle(); - packet.Info.RewardArenaPoints = quest->GetRewArenaPoints(); - packet.Info.RewardSkillLineID = quest->GetRewardSkillId(); - packet.Info.RewardNumSkillUps = quest->GetRewardSkillPoints(); - packet.Info.RewardFactionFlags = quest->GetRewardReputationMask(); - packet.Info.PortraitGiver = quest->GetQuestGiverPortrait(); - packet.Info.PortraitGiverMount = quest->GetQuestGiverPortraitMount(); - packet.Info.PortraitTurnIn = quest->GetQuestTurnInPortrait(); - - for (uint8 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i) - { - packet.Info.ItemDrop[i] = quest->ItemDrop[i]; - packet.Info.ItemDropQuantity[i] = quest->ItemDropQuantity[i]; - } - - if (!quest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) - { - for (uint8 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) - { - packet.Info.RewardItems[i] = quest->RewardItemId[i]; - packet.Info.RewardAmount[i] = quest->RewardItemCount[i]; - } - for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - { - packet.Info.UnfilteredChoiceItems[i].ItemID = quest->RewardChoiceItemId[i]; - packet.Info.UnfilteredChoiceItems[i].Quantity = quest->RewardChoiceItemCount[i]; - } - } - - for (uint8 i = 0; i < QUEST_REWARD_REPUTATIONS_COUNT; ++i) - { - packet.Info.RewardFactionID[i] = quest->RewardFactionId[i]; - packet.Info.RewardFactionValue[i] = quest->RewardFactionValue[i]; - packet.Info.RewardFactionOverride[i] = quest->RewardFactionOverride[i]; - packet.Info.RewardFactionCapIn[i] = quest->RewardFactionCapIn[i]; - } - - packet.Info.POIContinent = quest->GetPOIContinent(); - packet.Info.POIx = quest->GetPOIx(); - packet.Info.POIy = quest->GetPOIy(); - packet.Info.POIPriority = quest->GetPOIPriority(); - - packet.Info.AllowableRaces = quest->GetAllowableRaces(); - packet.Info.TreasurePickerID = quest->GetTreasurePickerId(); - packet.Info.Expansion = quest->GetExpansion(); - - for (QuestObjective const& questObjective : quest->GetObjectives()) - { - packet.Info.Objectives.push_back(questObjective); - - if (localeConstant != LOCALE_enUS) - { - if (QuestObjectivesLocale const* questObjectivesLocale = sObjectMgr->GetQuestObjectivesLocale(questObjective.ID)) - ObjectMgr::GetLocaleString(questObjectivesLocale->Description, localeConstant, packet.Info.Objectives.back().Description); - } - } - - for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES)) + _session->SendPacket(&quest->QueryData[static_cast<uint32>(_session->GetSessionDbLocaleIndex())]); + else { - packet.Info.RewardCurrencyID[i] = quest->RewardCurrencyId[i]; - packet.Info.RewardCurrencyQty[i] = quest->RewardCurrencyCount[i]; + WorldPacket queryPacket = quest->BuildQueryData(_session->GetSessionDbLocaleIndex()); + _session->SendPacket(&queryPacket); } - packet.Info.AcceptedSoundKitID = quest->GetSoundAccept(); - packet.Info.CompleteSoundKitID = quest->GetSoundTurnIn(); - packet.Info.AreaGroupID = quest->GetAreaGroupID(); - packet.Info.TimeAllowed = quest->GetLimitTime(); - - _session->SendPacket(packet.Write()); - TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", quest->GetQuestId()); } @@ -648,7 +515,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI } if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) - AddQuestLevelToTitle(packet.QuestTitle, quest->GetQuestLevel()); + Quest::AddQuestLevelToTitle(packet.QuestTitle, quest->GetQuestLevel()); WorldPackets::Quest::QuestGiverOfferReward& offer = packet.QuestData; @@ -705,7 +572,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGU } if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) - AddQuestLevelToTitle(packet.QuestTitle, quest->GetQuestLevel()); + Quest::AddQuestLevelToTitle(packet.QuestTitle, quest->GetQuestLevel()); packet.QuestGiverGUID = npcGUID; @@ -758,13 +625,3 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGU _session->SendPacket(packet.Write()); TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPC=%s, questid=%u", npcGUID.ToString().c_str(), quest->GetQuestId()); } - -void PlayerMenu::AddQuestLevelToTitle(std::string &title, int32 level) -{ - // Adds the quest level to the front of the quest title - // example: [13] Westfall Stew - - std::stringstream questTitlePretty; - questTitlePretty << "[" << level << "] " << title; - title = questTitlePretty.str(); -} diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h index 259e30160fa..bd0faf257a5 100644 --- a/src/server/game/Entities/Creature/GossipDef.h +++ b/src/server/game/Entities/Creature/GossipDef.h @@ -287,8 +287,6 @@ class TC_GAME_API PlayerMenu void SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUID, bool autoLaunched) const; void SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGUID, bool canComplete, bool autoLaunched) const; - static void AddQuestLevelToTitle(std::string &title, int32 level); - private: GossipMenu _gossipMenu; QuestMenu _questMenu; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index bda1e0bae21..1d294a1528c 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -37,12 +37,60 @@ #include "OutdoorPvPMgr.h" #include "PhasingHandler.h" #include "PoolMgr.h" +#include "QueryPackets.h" #include "ScriptMgr.h" #include "SpellMgr.h" #include "Transport.h" #include "World.h" #include <G3D/Quat.h> +void GameObjectTemplate::InitializeQueryData() +{ + WorldPacket queryTemp; + for (uint8 loc = LOCALE_enUS; loc < TOTAL_LOCALES; ++loc) + { + queryTemp = BuildQueryData(static_cast<LocaleConstant>(loc)); + QueryData[loc] = queryTemp; + } +} + +WorldPacket GameObjectTemplate::BuildQueryData(LocaleConstant loc) const +{ + WorldPackets::Query::QueryGameObjectResponse queryTemp; + + queryTemp.GameObjectID = entry; + + queryTemp.Allow = true; + WorldPackets::Query::GameObjectStats& stats = queryTemp.Stats; + + stats.Type = type; + stats.DisplayID = displayId; + + stats.Name[0] = name; + stats.IconName = IconName; + stats.CastBarCaption = castBarCaption; + stats.UnkString = unk1; + + if (loc != LOCALE_enUS) + if (GameObjectLocale const* gameObjectLocale = sObjectMgr->GetGameObjectLocale(entry)) + { + ObjectMgr::GetLocaleString(gameObjectLocale->Name, loc, stats.Name[0]); + ObjectMgr::GetLocaleString(gameObjectLocale->CastBarCaption, loc, stats.CastBarCaption); + ObjectMgr::GetLocaleString(gameObjectLocale->Unk1, loc, stats.UnkString); + } + + stats.Size = size; + + if (std::vector<uint32> const* items = sObjectMgr->GetGameObjectQuestItemList(entry)) + for (int32 item : *items) + stats.QuestItems.push_back(item); + + memcpy(stats.Data, raw.data, MAX_GAMEOBJECT_DATA * sizeof(int32)); + stats.RequiredLevel = RequiredLevel; + + return *queryTemp.Write(); +} + bool QuaternionData::isUnit() const { return fabs(x * x + y * y + z * z + w * w - 1.0f) < 1e-5; diff --git a/src/server/game/Entities/GameObject/GameObjectData.h b/src/server/game/Entities/GameObject/GameObjectData.h index 6c1252e4c1d..7f8c6e8b977 100644 --- a/src/server/game/Entities/GameObject/GameObjectData.h +++ b/src/server/game/Entities/GameObject/GameObjectData.h @@ -713,6 +713,7 @@ struct GameObjectTemplate std::string AIName; uint32 ScriptId; + WorldPacket QueryData[TOTAL_LOCALES]; // helpers bool IsDespawnAtAction() const @@ -914,6 +915,9 @@ struct GameObjectTemplate default: return false; } } + + void InitializeQueryData(); + WorldPacket BuildQueryData(LocaleConstant loc) const; }; // From `gameobject_template_addon` diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 54beee16659..320d9d70f9e 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -41,6 +41,7 @@ #include "PhasingHandler.h" #include "Player.h" #include "PoolMgr.h" +#include "QueryPackets.h" #include "QuestDef.h" #include "Random.h" #include "ReputationMgr.h" @@ -7681,7 +7682,7 @@ void ObjectMgr::LoadQuestPOI() // 0 1 2 3 QueryResult points = WorldDatabase.Query("SELECT QuestID, Idx1, X, Y FROM quest_poi_points ORDER BY QuestID DESC, Idx1, Idx2"); - std::vector<std::vector<std::vector<QuestPOIPoint>>> POIs; + std::vector<std::vector<std::vector<QuestPOIBlobPoint>>> POIs; if (points) { @@ -7702,7 +7703,7 @@ void ObjectMgr::LoadQuestPOI() if (int32(POIs[QuestID].size()) <= Idx1 + 1) POIs[QuestID].resize(Idx1 + 10); - QuestPOIPoint point(X, Y); + QuestPOIBlobPoint point(X, Y); POIs[QuestID][Idx1].push_back(point); } while (points->NextRow()); } @@ -7729,11 +7730,12 @@ void ObjectMgr::LoadQuestPOI() if (!sObjectMgr->GetQuestTemplate(questID)) TC_LOG_ERROR("sql.sql", "`quest_poi` quest id (%u) Idx1 (%u) does not exist in `quest_template`", questID, idx1); - QuestPOI POI(blobIndex, objectiveIndex, questObjectiveID, questObjectID, mapID, uiMapID, priority, flags, worldEffectID, playerConditionID, spawnTrackingID, alwaysAllowMergingBlobs); if (questID < int32(POIs.size()) && idx1 < int32(POIs[questID].size())) { - POI.points = POIs[questID][idx1]; - _questPOIStore[questID].push_back(POI); + QuestPOIData& poiData = _questPOIStore[questID]; + poiData.QuestID = questID; + poiData.QuestPOIBlobDataStats.emplace_back(blobIndex, objectiveIndex, questObjectiveID, questObjectID, mapID, uiMapID, priority, flags, + worldEffectID, playerConditionID, spawnTrackingID, std::move(POIs[questID][idx1]), alwaysAllowMergingBlobs); } else TC_LOG_ERROR("sql.sql", "Table quest_poi references unknown quest points for quest %i POI id %i", questID, blobIndex); @@ -10024,6 +10026,38 @@ void ObjectMgr::LoadCreatureQuestItems() TC_LOG_INFO("server.loading", ">> Loaded %u creature quest items in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } +void ObjectMgr::InitializeQueriesData(QueryDataGroup mask) +{ + // cache disabled + if (!sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES)) + return; + + // Initialize Query data for creatures + if (mask & QUERY_DATA_CREATURES) + for (auto& creaturePair : _creatureTemplateStore) + creaturePair.second.InitializeQueryData(); + + // Initialize Query Data for gameobjects + if (mask & QUERY_DATA_GAMEOBJECTS) + for (auto& gameobjectPair : _gameObjectTemplateStore) + gameobjectPair.second.InitializeQueryData(); + + // Initialize Query Data for quests + if (mask & QUERY_DATA_QUESTS) + for (auto& questPair : _questTemplates) + questPair.second->InitializeQueryData(); + + // Initialize Quest POI data + if (mask & QUERY_DATA_POIS) + for (auto& poiPair : _questPOIStore) + poiPair.second.InitializeQueryData(); +} + +void QuestPOIData::InitializeQueryData() +{ + QueryDataBuffer << *this; +} + void ObjectMgr::LoadSceneTemplates() { uint32 oldMSTime = getMSTime(); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index ef20c9ffd24..229f92497eb 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -696,16 +696,16 @@ typedef std::multimap<uint32, GossipMenuItems> GossipMenuItemsContainer; typedef std::pair<GossipMenuItemsContainer::const_iterator, GossipMenuItemsContainer::const_iterator> GossipMenuItemsMapBounds; typedef std::pair<GossipMenuItemsContainer::iterator, GossipMenuItemsContainer::iterator> GossipMenuItemsMapBoundsNonConst; -struct QuestPOIPoint +struct QuestPOIBlobPoint { int32 X; int32 Y; - QuestPOIPoint() : X(0), Y(0) { } - QuestPOIPoint(int32 _X, int32 _Y) : X(_X), Y(_Y) { } + QuestPOIBlobPoint() : X(0), Y(0) { } + QuestPOIBlobPoint(int32 _X, int32 _Y) : X(_X), Y(_Y) { } }; -struct QuestPOI +struct QuestPOIBlobData { int32 BlobIndex; int32 ObjectiveIndex; @@ -718,17 +718,29 @@ struct QuestPOI int32 WorldEffectID; int32 PlayerConditionID; int32 SpawnTrackingID; - std::vector<QuestPOIPoint> points; + std::vector<QuestPOIBlobPoint> QuestPOIBlobPointStats; bool AlwaysAllowMergingBlobs; - QuestPOI() : BlobIndex(0), ObjectiveIndex(0), QuestObjectiveID(0), QuestObjectID(0), MapID(0), UiMapID(0), Priority(0), Flags(0), WorldEffectID(0), PlayerConditionID(0), SpawnTrackingID(0), AlwaysAllowMergingBlobs(false){ } - QuestPOI(int32 blobIndex, int32 objectiveIndex, int32 questObjectiveID, int32 questObjectID, int32 mapID, int32 uiMapID, int32 priority, int32 flags, int32 worldEffectID, int32 playerConditionID, int32 spawnTrackingID, bool alwaysAllowMergingBlobs) : - BlobIndex(blobIndex), ObjectiveIndex(objectiveIndex), QuestObjectiveID(questObjectiveID), QuestObjectID(questObjectID), MapID(mapID), UiMapID(uiMapID), - Priority(priority), Flags(flags), WorldEffectID(worldEffectID), PlayerConditionID(playerConditionID), SpawnTrackingID(spawnTrackingID), AlwaysAllowMergingBlobs(alwaysAllowMergingBlobs) { } + QuestPOIBlobData() : BlobIndex(0), ObjectiveIndex(0), QuestObjectiveID(0), QuestObjectID(0), MapID(0), UiMapID(0), Priority(0), Flags(0), WorldEffectID(0), + PlayerConditionID(0), SpawnTrackingID(0), AlwaysAllowMergingBlobs(false) { } + QuestPOIBlobData(int32 blobIndex, int32 objectiveIndex, int32 questObjectiveID, int32 questObjectID, int32 mapID, int32 uiMapID, int32 priority, + int32 flags, int32 worldEffectID, int32 playerConditionID, int32 spawnTrackingID, std::vector<QuestPOIBlobPoint> questPOIBlobPointStats, + bool alwaysAllowMergingBlobs) : BlobIndex(blobIndex), ObjectiveIndex(objectiveIndex), QuestObjectiveID(questObjectiveID), + QuestObjectID(questObjectID), MapID(mapID), UiMapID(uiMapID), Priority(priority), Flags(flags), WorldEffectID(worldEffectID), + PlayerConditionID(playerConditionID), SpawnTrackingID(spawnTrackingID), QuestPOIBlobPointStats(std::move(questPOIBlobPointStats)), + AlwaysAllowMergingBlobs(alwaysAllowMergingBlobs) { } }; -typedef std::vector<QuestPOI> QuestPOIVector; -typedef std::unordered_map<uint32, QuestPOIVector> QuestPOIContainer; +struct QuestPOIData +{ + int32 QuestID = 0; + std::vector<QuestPOIBlobData> QuestPOIBlobDataStats; + + void InitializeQueryData(); + ByteBuffer QueryDataBuffer; +}; + +typedef std::unordered_map<uint32, QuestPOIData> QuestPOIContainer; typedef std::array<std::unordered_map<uint32, QuestGreeting>, 2> QuestGreetingContainer; typedef std::array<std::unordered_map<uint32, QuestGreetingLocale>, 2> QuestGreetingLocaleContainer; @@ -922,6 +934,17 @@ struct RaceUnlockRequirement uint32 AchievementId; }; +enum QueryDataGroup +{ + QUERY_DATA_CREATURES = 0x01, + QUERY_DATA_GAMEOBJECTS = 0x02, + QUERY_DATA_ITEMS = 0x04, + QUERY_DATA_QUESTS = 0x08, + QUERY_DATA_POIS = 0x10, + + QUERY_DATA_ALL = 0xFF +}; + class PlayerDumpReader; class TC_GAME_API ObjectMgr @@ -1101,7 +1124,7 @@ class TC_GAME_API ObjectMgr return nullptr; } - QuestPOIVector const* GetQuestPOIVector(int32 QuestID) + QuestPOIData const* GetQuestPOIData(int32 QuestID) { QuestPOIContainer::const_iterator itr = _questPOIStore.find(QuestID); if (itr != _questPOIStore.end()) @@ -1257,6 +1280,8 @@ class TC_GAME_API ObjectMgr void LoadPlayerChoices(); void LoadPlayerChoicesLocale(); + void InitializeQueriesData(QueryDataGroup mask); + std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint8 level); uint32 GetXPForLevel(uint8 level) const; diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index d9af761eb22..19aa93b27ea 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -68,112 +68,52 @@ void WorldSession::SendQueryTimeResponse() /// Only _static_ data is sent in this packet !!! void WorldSession::HandleCreatureQuery(WorldPackets::Query::QueryCreature& packet) { - WorldPackets::Query::QueryCreatureResponse response; - - CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(packet.CreatureID); - - response.CreatureID = packet.CreatureID; - - if (creatureInfo) + if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(packet.CreatureID)) { - response.Allow = true; - - WorldPackets::Query::CreatureStats& stats = response.Stats; - - stats.Leader = creatureInfo->RacialLeader; - - stats.Name[0] = creatureInfo->Name; - stats.NameAlt[0] = creatureInfo->FemaleName; - - stats.Flags[0] = creatureInfo->type_flags; - stats.Flags[1] = creatureInfo->type_flags2; - - stats.CreatureType = creatureInfo->type; - stats.CreatureFamily = creatureInfo->family; - stats.Classification = creatureInfo->rank; - - for (uint32 i = 0; i < MAX_KILL_CREDIT; ++i) - stats.ProxyCreatureID[i] = creatureInfo->KillCredit[i]; - - std::transform(creatureInfo->Models.begin(), creatureInfo->Models.end(), std::back_inserter(stats.Display.CreatureDisplay), - [&stats](CreatureModel const& model) -> WorldPackets::Query::CreatureXDisplay + TC_LOG_DEBUG("network", "WORLD: CMSG_QUERY_CREATURE '%s' - Entry: %u.", ci->Name.c_str(), packet.CreatureID); + if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES)) + SendPacket(&ci->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]); + else { - stats.Display.TotalProbability += model.Probability; - return { model.CreatureDisplayID, model.DisplayScale, model.Probability }; - }); - - stats.HpMulti = creatureInfo->ModHealth; - stats.EnergyMulti = creatureInfo->ModMana; - - stats.CreatureMovementInfoID = creatureInfo->movementId; - stats.RequiredExpansion = creatureInfo->RequiredExpansion; - stats.HealthScalingExpansion = creatureInfo->HealthScalingExpansion; - stats.VignetteID = creatureInfo->VignetteID; - stats.Class = creatureInfo->unit_class; - stats.FadeRegionRadius = creatureInfo->FadeRegionRadius; - stats.WidgetSetID = creatureInfo->WidgetSetID; - stats.WidgetSetUnitConditionID = creatureInfo->WidgetSetUnitConditionID; - - stats.Title = creatureInfo->SubName; - stats.TitleAlt = creatureInfo->TitleAlt; - stats.CursorName = creatureInfo->IconName; - - if (std::vector<uint32> const* items = sObjectMgr->GetCreatureQuestItemList(packet.CreatureID)) - stats.QuestItems.insert(stats.QuestItems.begin(), items->begin(), items->end()); - - LocaleConstant localeConstant = GetSessionDbLocaleIndex(); - if (localeConstant != LOCALE_enUS) - if (CreatureLocale const* creatureLocale = sObjectMgr->GetCreatureLocale(packet.CreatureID)) - { - ObjectMgr::GetLocaleString(creatureLocale->Name, localeConstant, stats.Name[0]); - ObjectMgr::GetLocaleString(creatureLocale->NameAlt, localeConstant, stats.NameAlt[0]); - ObjectMgr::GetLocaleString(creatureLocale->Title, localeConstant, stats.Title); - ObjectMgr::GetLocaleString(creatureLocale->TitleAlt, localeConstant, stats.TitleAlt); - } + WorldPacket response = ci->BuildQueryData(GetSessionDbLocaleIndex()); + SendPacket(&response); + } + TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUERY_CREATURE_RESPONSE"); } + else + { + TC_LOG_DEBUG("network", "WORLD: CMSG_QUERY_CREATURE - NO CREATURE INFO! (ENTRY: %u)", packet.CreatureID); - SendPacket(response.Write()); + WorldPackets::Query::QueryCreatureResponse response; + response.CreatureID = packet.CreatureID; + SendPacket(response.Write()); + TC_LOG_DEBUG("network", "WORLD: Sent SMSG_QUERY_CREATURE_RESPONSE"); + } } /// Only _static_ data is sent in this packet !!! void WorldSession::HandleGameObjectQueryOpcode(WorldPackets::Query::QueryGameObject& packet) { - WorldPackets::Query::QueryGameObjectResponse response; - response.GameObjectID = packet.GameObjectID; - - if (GameObjectTemplate const* gameObjectInfo = sObjectMgr->GetGameObjectTemplate(packet.GameObjectID)) + if (GameObjectTemplate const* info = sObjectMgr->GetGameObjectTemplate(packet.GameObjectID)) { - response.Allow = true; - WorldPackets::Query::GameObjectStats& stats = response.Stats; - - stats.Type = gameObjectInfo->type; - stats.DisplayID = gameObjectInfo->displayId; - - stats.Name[0] = gameObjectInfo->name; - stats.IconName = gameObjectInfo->IconName; - stats.CastBarCaption = gameObjectInfo->castBarCaption; - stats.UnkString = gameObjectInfo->unk1; - - LocaleConstant localeConstant = GetSessionDbLocaleIndex(); - if (localeConstant != LOCALE_enUS) - if (GameObjectLocale const* gameObjectLocale = sObjectMgr->GetGameObjectLocale(packet.GameObjectID)) - { - ObjectMgr::GetLocaleString(gameObjectLocale->Name, localeConstant, stats.Name[0]); - ObjectMgr::GetLocaleString(gameObjectLocale->CastBarCaption, localeConstant, stats.CastBarCaption); - ObjectMgr::GetLocaleString(gameObjectLocale->Unk1, localeConstant, stats.UnkString); - } - - stats.Size = gameObjectInfo->size; - - if (std::vector<uint32> const* items = sObjectMgr->GetGameObjectQuestItemList(packet.GameObjectID)) - for (int32 item : *items) - stats.QuestItems.push_back(item); - - memcpy(stats.Data, gameObjectInfo->raw.data, MAX_GAMEOBJECT_DATA * sizeof(int32)); - stats.RequiredLevel = gameObjectInfo->RequiredLevel; + if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES)) + SendPacket(&info->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]); + else + { + WorldPacket response = info->BuildQueryData(GetSessionDbLocaleIndex()); + SendPacket(&response); + } + TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); } + else + { + TC_LOG_DEBUG("network", "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (ENTRY: %u)", packet.GameObjectID); - SendPacket(response.Write()); + WorldPackets::Query::QueryGameObjectResponse response; + response.GameObjectID = packet.GameObjectID; + SendPacket(response.Write()); + TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE"); + } } void WorldSession::HandleQueryCorpseLocation(WorldPackets::Query::QueryCorpseLocationFromClient& queryCorpseLocation) @@ -344,60 +284,10 @@ void WorldSession::HandleQuestPOIQuery(WorldPackets::Query::QuestPOIQuery& quest WorldPackets::Query::QuestPOIQueryResponse response; - for (auto itr = questIds.begin(); itr != questIds.end(); ++itr) - { - int32 QuestID = *itr; - - bool questOk = false; - - uint16 questSlot = _player->FindQuestSlot(uint32(QuestID)); - - if (questSlot != MAX_QUEST_LOG_SIZE) - questOk = _player->GetQuestSlotQuestId(questSlot) == uint32(QuestID); - - if (questOk) - { - QuestPOIVector const* poiData = sObjectMgr->GetQuestPOIVector(QuestID); - if (poiData) - { - WorldPackets::Query::QuestPOIData questPOIData; - - questPOIData.QuestID = QuestID; - - for (auto data = poiData->begin(); data != poiData->end(); ++data) - { - WorldPackets::Query::QuestPOIBlobData questPOIBlobData; - - questPOIBlobData.BlobIndex = data->BlobIndex; - questPOIBlobData.ObjectiveIndex = data->ObjectiveIndex; - questPOIBlobData.QuestObjectiveID = data->QuestObjectiveID; - questPOIBlobData.QuestObjectID = data->QuestObjectID; - questPOIBlobData.MapID = data->MapID; - questPOIBlobData.UiMapID = data->UiMapID; - questPOIBlobData.Priority = data->Priority; - questPOIBlobData.Flags = data->Flags; - questPOIBlobData.WorldEffectID = data->WorldEffectID; - questPOIBlobData.PlayerConditionID = data->PlayerConditionID; - questPOIBlobData.SpawnTrackingID = data->SpawnTrackingID; - questPOIBlobData.AlwaysAllowMergingBlobs = data->AlwaysAllowMergingBlobs; - - for (QuestPOIPoint const& point : data->points) - { - WorldPackets::Query::QuestPOIBlobPoint questPOIBlobPoint; - - questPOIBlobPoint.X = point.X; - questPOIBlobPoint.Y = point.Y; - - questPOIBlobData.QuestPOIBlobPointStats.push_back(questPOIBlobPoint); - } - - questPOIData.QuestPOIBlobDataStats.push_back(questPOIBlobData); - } - - response.QuestPOIDataStats.push_back(questPOIData); - } - } - } + for (uint32 questId : questIds) + if (_player->FindQuestSlot(questId) != MAX_QUEST_LOG_SIZE) + if (QuestPOIData const* poiData = sObjectMgr->GetQuestPOIData(questId)) + response.QuestPOIDataStats.push_back(poiData); SendPacket(response.Write()); } diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 91c6516e2e9..bca194591fe 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -419,3 +419,166 @@ bool Quest::CanIncreaseRewardedQuestCounters() const // This affects counters and client requests for completed quests. return (!IsDFQuest() && !IsDaily() && (!IsRepeatable() || IsWeekly() || IsMonthly() || IsSeasonal())); } + +void Quest::InitializeQueryData() +{ + WorldPacket queryTemp; + for (uint8 loc = LOCALE_enUS; loc < TOTAL_LOCALES; ++loc) + { + queryTemp = BuildQueryData(static_cast<LocaleConstant>(loc)); + QueryData[loc] = queryTemp; + } +} + +WorldPacket Quest::BuildQueryData(LocaleConstant loc) const +{ + WorldPackets::Quest::QueryQuestInfoResponse response; + + response.Allow = true; + response.QuestID = GetQuestId(); + + response.Info.LogTitle = GetLogTitle(); + response.Info.LogDescription = GetLogDescription(); + response.Info.QuestDescription = GetQuestDescription(); + response.Info.AreaDescription = GetAreaDescription(); + response.Info.QuestCompletionLog = GetQuestCompletionLog(); + response.Info.PortraitGiverText = GetPortraitGiverText(); + response.Info.PortraitGiverName = GetPortraitGiverName(); + response.Info.PortraitTurnInText = GetPortraitTurnInText(); + response.Info.PortraitTurnInName = GetPortraitTurnInName(); + + if (loc != LOCALE_enUS) + { + if (QuestTemplateLocale const* questTemplateLocale = sObjectMgr->GetQuestLocale(GetQuestId())) + { + ObjectMgr::GetLocaleString(questTemplateLocale->LogTitle, loc, response.Info.LogTitle); + ObjectMgr::GetLocaleString(questTemplateLocale->LogDescription, loc, response.Info.LogDescription); + ObjectMgr::GetLocaleString(questTemplateLocale->QuestDescription, loc, response.Info.QuestDescription); + ObjectMgr::GetLocaleString(questTemplateLocale->AreaDescription, loc, response.Info.AreaDescription); + ObjectMgr::GetLocaleString(questTemplateLocale->QuestCompletionLog, loc, response.Info.QuestCompletionLog); + ObjectMgr::GetLocaleString(questTemplateLocale->PortraitGiverText, loc, response.Info.PortraitGiverText); + ObjectMgr::GetLocaleString(questTemplateLocale->PortraitGiverName, loc, response.Info.PortraitGiverName); + ObjectMgr::GetLocaleString(questTemplateLocale->PortraitTurnInText, loc, response.Info.PortraitTurnInText); + ObjectMgr::GetLocaleString(questTemplateLocale->PortraitTurnInName, loc, response.Info.PortraitTurnInName); + } + } + + if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS)) + AddQuestLevelToTitle(response.Info.LogTitle, GetQuestLevel()); + + response.Info.QuestID = GetQuestId(); + response.Info.QuestType = GetQuestType(); + response.Info.QuestLevel = GetQuestLevel(); + response.Info.QuestScalingFactionGroup = GetQuestScalingFactionGroup(); + response.Info.QuestMaxScalingLevel = GetQuestMaxScalingLevel(); + response.Info.QuestPackageID = GetQuestPackageID(); + response.Info.QuestMinLevel = GetMinLevel(); + response.Info.QuestSortID = GetZoneOrSort(); + response.Info.QuestInfoID = GetQuestInfoID(); + response.Info.SuggestedGroupNum = GetSuggestedPlayers(); + response.Info.RewardNextQuest = GetNextQuestInChain(); + response.Info.RewardXPDifficulty = GetXPDifficulty(); + response.Info.RewardXPMultiplier = GetXPMultiplier(); + + if (!HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) + response.Info.RewardMoney = RewardMoney; + + response.Info.RewardMoneyDifficulty = GetRewMoneyDifficulty(); + response.Info.RewardMoneyMultiplier = GetMoneyMultiplier(); + response.Info.RewardBonusMoney = GetRewMoneyMaxLevel(); + for (uint8 i = 0; i < QUEST_REWARD_DISPLAY_SPELL_COUNT; ++i) + response.Info.RewardDisplaySpell[i] = RewardDisplaySpell[i]; + + response.Info.RewardSpell = GetRewSpell(); + + response.Info.RewardHonor = GetRewHonor(); + response.Info.RewardKillHonor = GetRewKillHonor(); + + response.Info.RewardArtifactXPDifficulty = GetArtifactXPDifficulty(); + response.Info.RewardArtifactXPMultiplier = GetArtifactXPMultiplier(); + response.Info.RewardArtifactCategoryID = GetArtifactCategoryId(); + + response.Info.StartItem = GetSrcItemId(); + response.Info.Flags = GetFlags(); + response.Info.FlagsEx = GetFlagsEx(); + response.Info.FlagsEx2 = GetFlagsEx2(); + response.Info.RewardTitle = GetRewTitle(); + response.Info.RewardArenaPoints = GetRewArenaPoints(); + response.Info.RewardSkillLineID = GetRewardSkillId(); + response.Info.RewardNumSkillUps = GetRewardSkillPoints(); + response.Info.RewardFactionFlags = GetRewardReputationMask(); + response.Info.PortraitGiver = GetQuestGiverPortrait(); + response.Info.PortraitGiverMount = GetQuestGiverPortraitMount(); + response.Info.PortraitTurnIn = GetQuestTurnInPortrait(); + + for (uint8 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i) + { + response.Info.ItemDrop[i] = ItemDrop[i]; + response.Info.ItemDropQuantity[i] = ItemDropQuantity[i]; + } + + if (!HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) + { + for (uint8 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i) + { + response.Info.RewardItems[i] = RewardItemId[i]; + response.Info.RewardAmount[i] = RewardItemCount[i]; + } + for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) + { + response.Info.UnfilteredChoiceItems[i].ItemID = RewardChoiceItemId[i]; + response.Info.UnfilteredChoiceItems[i].Quantity = RewardChoiceItemCount[i]; + } + } + + for (uint8 i = 0; i < QUEST_REWARD_REPUTATIONS_COUNT; ++i) + { + response.Info.RewardFactionID[i] = RewardFactionId[i]; + response.Info.RewardFactionValue[i] = RewardFactionValue[i]; + response.Info.RewardFactionOverride[i] = RewardFactionOverride[i]; + response.Info.RewardFactionCapIn[i] = RewardFactionCapIn[i]; + } + + response.Info.POIContinent = GetPOIContinent(); + response.Info.POIx = GetPOIx(); + response.Info.POIy = GetPOIy(); + response.Info.POIPriority = GetPOIPriority(); + + response.Info.AllowableRaces = GetAllowableRaces(); + response.Info.TreasurePickerID = GetTreasurePickerId(); + response.Info.Expansion = GetExpansion(); + + for (QuestObjective const& questObjective : GetObjectives()) + { + response.Info.Objectives.push_back(questObjective); + + if (loc != LOCALE_enUS) + { + if (QuestObjectivesLocale const* questObjectivesLocale = sObjectMgr->GetQuestObjectivesLocale(questObjective.ID)) + ObjectMgr::GetLocaleString(questObjectivesLocale->Description, loc, response.Info.Objectives.back().Description); + } + } + + for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + { + response.Info.RewardCurrencyID[i] = RewardCurrencyId[i]; + response.Info.RewardCurrencyQty[i] = RewardCurrencyCount[i]; + } + + response.Info.AcceptedSoundKitID = GetSoundAccept(); + response.Info.CompleteSoundKitID = GetSoundTurnIn(); + response.Info.AreaGroupID = GetAreaGroupID(); + response.Info.TimeAllowed = GetLimitTime(); + + return *response.Write(); +} + +void Quest::AddQuestLevelToTitle(std::string& title, int32 level) +{ + // Adds the quest level to the front of the quest title + // example: [13] Westfall Stew + + std::stringstream questTitlePretty; + questTitlePretty << "[" << level << "] " << title; + title = questTitlePretty.str(); +} diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 6e6b90bdbd9..e4eb5eadc15 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -23,6 +23,7 @@ #include "DBCEnums.h" #include "DatabaseEnvFwd.h" #include "SharedDefines.h" +#include "WorldPacket.h" #include <vector> class Player; @@ -463,12 +464,17 @@ class TC_GAME_API Quest void SetEventIdForQuest(uint16 eventId) { _eventIdForQuest = eventId; } uint16 GetEventIdForQuest() const { return _eventIdForQuest; } + static void AddQuestLevelToTitle(std::string& title, int32 level); + void InitializeQueryData(); + WorldPacket BuildQueryData(LocaleConstant loc) const; + void BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const; typedef std::vector<int32> PrevQuests; PrevQuests prevQuests; typedef std::vector<uint32> PrevChainQuests; PrevChainQuests prevChainQuests; + WorldPacket QueryData[TOTAL_LOCALES]; private: uint32 _rewChoiceItemsCount; diff --git a/src/server/game/Server/Packets/QueryPackets.cpp b/src/server/game/Server/Packets/QueryPackets.cpp index 6433b62d2ea..20e7be03d42 100644 --- a/src/server/game/Server/Packets/QueryPackets.cpp +++ b/src/server/game/Server/Packets/QueryPackets.cpp @@ -351,41 +351,52 @@ void WorldPackets::Query::QuestPOIQuery::Read() _worldPacket >> MissingQuestPOIs[i]; } +ByteBuffer& operator<<(ByteBuffer& data, QuestPOIData const& questPOIData) +{ + data << int32(questPOIData.QuestID); + data << int32(questPOIData.QuestPOIBlobDataStats.size()); + + for (QuestPOIBlobData const& questPOIBlobData : questPOIData.QuestPOIBlobDataStats) + { + data << int32(questPOIBlobData.BlobIndex); + data << int32(questPOIBlobData.ObjectiveIndex); + data << int32(questPOIBlobData.QuestObjectiveID); + data << int32(questPOIBlobData.QuestObjectID); + data << int32(questPOIBlobData.MapID); + data << int32(questPOIBlobData.UiMapID); + data << int32(questPOIBlobData.Priority); + data << int32(questPOIBlobData.Flags); + data << int32(questPOIBlobData.WorldEffectID); + data << int32(questPOIBlobData.PlayerConditionID); + data << int32(questPOIBlobData.SpawnTrackingID); + data << int32(questPOIBlobData.QuestPOIBlobPointStats.size()); + + for (QuestPOIBlobPoint const& questPOIBlobPoint : questPOIBlobData.QuestPOIBlobPointStats) + { + data << int32(questPOIBlobPoint.X); + data << int32(questPOIBlobPoint.Y); + } + + data.WriteBit(questPOIBlobData.AlwaysAllowMergingBlobs); + data.FlushBits(); + } + + return data; +} + WorldPacket const* WorldPackets::Query::QuestPOIQueryResponse::Write() { _worldPacket << int32(QuestPOIDataStats.size()); _worldPacket << int32(QuestPOIDataStats.size()); - for (QuestPOIData const& questPOIData : QuestPOIDataStats) - { - _worldPacket << int32(questPOIData.QuestID); - - _worldPacket << int32(questPOIData.QuestPOIBlobDataStats.size()); + bool useCache = sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES); - for (QuestPOIBlobData const& questPOIBlobData : questPOIData.QuestPOIBlobDataStats) - { - _worldPacket << int32(questPOIBlobData.BlobIndex); - _worldPacket << int32(questPOIBlobData.ObjectiveIndex); - _worldPacket << int32(questPOIBlobData.QuestObjectiveID); - _worldPacket << int32(questPOIBlobData.QuestObjectID); - _worldPacket << int32(questPOIBlobData.MapID); - _worldPacket << int32(questPOIBlobData.UiMapID); - _worldPacket << int32(questPOIBlobData.Priority); - _worldPacket << int32(questPOIBlobData.Flags); - _worldPacket << int32(questPOIBlobData.WorldEffectID); - _worldPacket << int32(questPOIBlobData.PlayerConditionID); - _worldPacket << int32(questPOIBlobData.SpawnTrackingID); - _worldPacket << int32(questPOIBlobData.QuestPOIBlobPointStats.size()); - - for (QuestPOIBlobPoint const& questPOIBlobPoint : questPOIBlobData.QuestPOIBlobPointStats) - { - _worldPacket << int32(questPOIBlobPoint.X); - _worldPacket << int32(questPOIBlobPoint.Y); - } - - _worldPacket.WriteBit(questPOIBlobData.AlwaysAllowMergingBlobs); - _worldPacket.FlushBits(); - } + for (QuestPOIData const* questPOIData : QuestPOIDataStats) + { + if (useCache) + _worldPacket.append(questPOIData->QueryDataBuffer); + else + _worldPacket << *questPOIData; } return &_worldPacket; diff --git a/src/server/game/Server/Packets/QueryPackets.h b/src/server/game/Server/Packets/QueryPackets.h index 4331df38c85..c1c138ce0b4 100644 --- a/src/server/game/Server/Packets/QueryPackets.h +++ b/src/server/game/Server/Packets/QueryPackets.h @@ -30,6 +30,7 @@ #include <array> class Player; +struct QuestPOIData; namespace WorldPackets { @@ -319,35 +320,6 @@ namespace WorldPackets std::array<int32, 100> MissingQuestPOIs; }; - struct QuestPOIBlobPoint - { - int32 X = 0; - int32 Y = 0; - }; - - struct QuestPOIBlobData - { - int32 BlobIndex = 0; - int32 ObjectiveIndex = 0; - int32 QuestObjectiveID = 0; - int32 QuestObjectID = 0; - int32 MapID = 0; - int32 UiMapID = 0; - int32 Priority = 0; - int32 Flags = 0; - int32 WorldEffectID = 0; - int32 PlayerConditionID = 0; - int32 SpawnTrackingID = 0; - std::vector<QuestPOIBlobPoint> QuestPOIBlobPointStats; - bool AlwaysAllowMergingBlobs = false; - }; - - struct QuestPOIData - { - int32 QuestID = 0; - std::vector<QuestPOIBlobData> QuestPOIBlobDataStats; - }; - class QuestPOIQueryResponse final : public ServerPacket { public: @@ -355,7 +327,7 @@ namespace WorldPackets WorldPacket const* Write() override; - std::vector<QuestPOIData> QuestPOIDataStats; + std::vector<QuestPOIData const*> QuestPOIDataStats; }; class QueryQuestCompletionNPCs final : public ClientPacket @@ -463,5 +435,6 @@ namespace WorldPackets ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupHint const& lookupHint); ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Query::PlayerGuidLookupData const& lookupData); +ByteBuffer& operator<<(ByteBuffer& data, QuestPOIData const& questPOIData); #endif // QueryPackets_h__ diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index a39c259ec5d..3c29091457c 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1489,6 +1489,9 @@ void World::LoadConfigSettings(bool reload) // Allow 5-man parties to use raid warnings m_bool_configs[CONFIG_CHAT_PARTY_RAID_WARNINGS] = sConfigMgr->GetBoolDefault("PartyRaidWarnings", false); + // Allow to cache data queries + m_bool_configs[CONFIG_CACHE_DATA_QUERIES] = sConfigMgr->GetBoolDefault("CacheDataQueries", true); + // Check Invalid Position m_bool_configs[CONFIG_CREATURE_CHECK_INVALID_POSITION] = sConfigMgr->GetBoolDefault("Creature.CheckInvalidPosition", false); m_bool_configs[CONFIG_GAME_OBJECT_CHECK_INVALID_POSITION] = sConfigMgr->GetBoolDefault("GameObject.CheckInvalidPosition", false); @@ -2071,6 +2074,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Calendar data..."); sCalendarMgr->LoadFromDB(); + TC_LOG_INFO("server.loading", "Initialize query data..."); + sObjectMgr->InitializeQueriesData(QUERY_DATA_ALL); + ///- Initialize game time and timers TC_LOG_INFO("server.loading", "Initialize game time and timers"); m_gameTime = time(NULL); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index fe8255ddd33..eac00f7a2ba 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -191,6 +191,7 @@ enum WorldBoolConfigs CONFIG_HOTSWAP_INSTALL_ENABLED, CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED, CONFIG_PREVENT_RENAME_CUSTOMIZATION, + CONFIG_CACHE_DATA_QUERIES, CONFIG_CREATURE_CHECK_INVALID_POSITION, CONFIG_GAME_OBJECT_CHECK_INVALID_POSITION, BOOL_CONFIG_VALUE_COUNT diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 7c14054fbd9..b062139ce70 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -336,14 +336,14 @@ public: float x, y, z; uint32 mapId; - if (QuestPOIVector const* poiData = sObjectMgr->GetQuestPOIVector(questID)) + if (QuestPOIData const* poiData = sObjectMgr->GetQuestPOIData(questID)) { - auto data = poiData->front(); + auto data = poiData->QuestPOIBlobDataStats.front(); mapId = data.MapID; - x = data.points.front().X; - y = data.points.front().Y; + x = data.QuestPOIBlobPointStats.front().X; + y = data.QuestPOIBlobPointStats.front().Y; } else { diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index ea969f1366f..a8a7ae7de89 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -456,6 +456,7 @@ public: sObjectMgr->CheckCreatureTemplate(cInfo); } + sObjectMgr->InitializeQueriesData(QUERY_DATA_CREATURES); handler->SendGlobalGMSysMessage("Creature template reloaded."); return true; } @@ -538,6 +539,7 @@ public: { TC_LOG_INFO("misc", "Re-Loading Quest Templates..."); sObjectMgr->LoadQuests(); + sObjectMgr->InitializeQueriesData(QUERY_DATA_QUESTS); handler->SendGlobalGMSysMessage("DB table `quest_template` (quest definitions) reloaded."); /// dependent also from `gameobject` but this table not reloaded anyway @@ -721,6 +723,7 @@ public: { TC_LOG_INFO("misc", "Re-Loading Quest POI ..." ); sObjectMgr->LoadQuestPOI(); + sObjectMgr->InitializeQueriesData(QUERY_DATA_POIS); handler->SendGlobalGMSysMessage("DB Table `quest_poi` and `quest_poi_points` reloaded."); return true; } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 65c386abd66..3b959d62cca 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1247,6 +1247,17 @@ Account.PasswordChangeSecurity = 0 BirthdayTime = 1222964635 # +# CacheDataQueries +# Description: Server caches data queries at startup. +# Can be disabled if not enough memory is available. +# Default: 1 - (Enabled) +# 0 - (Disabled) +# +# + + CacheDataQueries = 1 + +# # FeatureSystem.BpayStore.Enabled # Description: Not yet implemented # Default: 0 - (Disabled) |