aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp74
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h5
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp163
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp48
-rw-r--r--src/server/game/Entities/GameObject/GameObjectData.h4
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp44
-rw-r--r--src/server/game/Globals/ObjectMgr.h49
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp186
-rw-r--r--src/server/game/Quests/QuestDef.cpp163
-rw-r--r--src/server/game/Quests/QuestDef.h6
-rw-r--r--src/server/game/Server/Packets/QueryPackets.cpp69
-rw-r--r--src/server/game/Server/Packets/QueryPackets.h33
-rw-r--r--src/server/game/World/World.cpp6
-rw-r--r--src/server/game/World/World.h1
-rw-r--r--src/server/scripts/Commands/cs_go.cpp8
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp3
-rw-r--r--src/server/worldserver/worldserver.conf.dist11
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)