aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMeji <alvaro.megias@outlook.com>2024-08-30 18:11:07 +0200
committerGitHub <noreply@github.com>2024-08-30 18:11:07 +0200
commitefa76de54011d40d69412d2af23cb071ed352688 (patch)
tree8a02bf7b0aec70912f33ffd1b380c11adea0854e /src
parentf213a580540bfc1ec3a7263782aa64d317afc4ce (diff)
Core/PacketIO: Implemented UIMap questlines (#30030)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp9
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp106
-rw-r--r--src/server/game/Globals/ObjectMgr.h11
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp35
-rw-r--r--src/server/game/Server/Packets/QuestPackets.cpp20
-rw-r--r--src/server/game/Server/Packets/QuestPackets.h22
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp4
-rw-r--r--src/server/game/Server/WorldSession.h2
-rw-r--r--src/server/game/World/World.cpp7
9 files changed, 208 insertions, 8 deletions
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index f3552765c43..22e4fd2496d 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -1467,8 +1467,13 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul
}
}
- for (QuestLineXQuestEntry const* questLineQuest : sQuestLineXQuestStore)
- _questsByQuestLine[questLineQuest->QuestLineID].push_back(questLineQuest);
+ {
+ for (QuestLineXQuestEntry const* questLineQuest : sQuestLineXQuestStore)
+ _questsByQuestLine[questLineQuest->QuestLineID].push_back(questLineQuest);
+
+ for (auto& [questLineId, questLineQuests] : _questsByQuestLine)
+ std::ranges::sort(questLineQuests, std::ranges::less(), &QuestLineXQuestEntry::OrderIndex);
+ }
for (QuestPackageItemEntry const* questPackageItem : sQuestPackageItemStore)
{
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index a684806b88c..fca4e4ff71b 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -3518,7 +3518,7 @@ void ObjectMgr::LoadVehicleAccessories()
if (!result)
{
- TC_LOG_INFO("server.loading", ">> Loaded 0 Vehicle Accessories in {} ms", GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded 0 vehicle accessories. DB table `vehicle_accessory` is empty.");
return;
}
@@ -11060,8 +11060,6 @@ void ObjectMgr::LoadSceneTemplates()
return;
}
- uint32 count = 0;
-
do
{
Field* fields = templates->Fetch();
@@ -11076,7 +11074,7 @@ void ObjectMgr::LoadSceneTemplates()
} while (templates->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded {} scene templates in {} ms.", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded {} scene templates in {} ms.", _sceneTemplateStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadPlayerChoices()
@@ -11544,6 +11542,106 @@ void ObjectMgr::LoadPlayerChoicesLocale()
}
}
+void ObjectMgr::LoadUiMapQuestLines()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // need for reload case
+ _uiMapQuestLinesStore.clear();
+
+ // 0 1
+ QueryResult result = WorldDatabase.Query("SELECT UiMapId, QuestLineId FROM ui_map_quest_line");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 questlines for UIMaps. DB table `ui_map_quest_line` is empty!");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 uiMapId = fields[0].GetUInt32();
+ uint32 questLineId = fields[1].GetUInt32();
+
+ if (!sUiMapStore.HasRecord(uiMapId))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `ui_map_quest_line` references non-existing UIMap {}, skipped", uiMapId);
+ continue;
+ }
+
+ if (!sDB2Manager.GetQuestsForQuestLine(questLineId))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `ui_map_quest_line` references empty or non-existing questline {}, skipped", questLineId);
+ continue;
+ }
+
+ _uiMapQuestLinesStore[uiMapId].push_back(questLineId);
+ ++count;
+
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded {} UiMap questlines definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+std::vector<uint32> const* ObjectMgr::GetUiMapQuestLinesList(uint32 uiMapId) const
+{
+ return Trinity::Containers::MapGetValuePtr(_uiMapQuestLinesStore, uiMapId);
+}
+
+void ObjectMgr::LoadUiMapQuests()
+{
+ uint32 oldMSTime = getMSTime();
+
+ // need for reload case
+ _uiMapQuestsStore.clear();
+
+ // 0 1
+ QueryResult result = WorldDatabase.Query("SELECT UiMapId, QuestId FROM ui_map_quest");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 quests for UIMaps. DB table `ui_map_quest` is empty!");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 uiMapId = fields[0].GetUInt32();
+ uint32 questId = fields[1].GetUInt32();
+
+ if (!sUiMapStore.HasRecord(uiMapId))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `ui_map_quest` references non-existing UIMap {}, skipped", uiMapId);
+ continue;
+ }
+
+ if (!GetQuestTemplate(questId))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `ui_map_quest` references non-existing quest {}, skipped", questId);
+ continue;
+ }
+
+ _uiMapQuestsStore[uiMapId].push_back(questId);
+ ++count;
+
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded {} UiMap quests definitions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+std::vector<uint32> const* ObjectMgr::GetUiMapQuestsList(uint32 uiMapId) const
+{
+ return Trinity::Containers::MapGetValuePtr(_uiMapQuestsStore, uiMapId);
+}
+
void ObjectMgr::LoadJumpChargeParams()
{
uint32 oldMSTime = getMSTime();
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 9a0423daa8c..32318209a39 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -530,6 +530,8 @@ typedef std::unordered_map<uint32, QuestObjectivesLocale> QuestObjectivesLocaleC
typedef std::unordered_map<uint32, QuestOfferRewardLocale> QuestOfferRewardLocaleContainer;
typedef std::unordered_map<uint32, QuestRequestItemsLocale> QuestRequestItemsLocaleContainer;
typedef std::unordered_map<uint32, PageTextLocale> PageTextLocaleContainer;
+typedef std::unordered_map<uint32, std::vector<uint32>> UiMapQuestLinesMap;
+typedef std::unordered_map<uint32, std::vector<uint32>> UiMapQuestsMap;
typedef std::unordered_map<uint32, VehicleSeatAddon> VehicleSeatAddonContainer;
struct GossipMenuItemsLocale
@@ -1283,6 +1285,9 @@ class TC_GAME_API ObjectMgr
QuestPOIData const* GetQuestPOIData(int32 questId);
+ std::vector<uint32> const* GetUiMapQuestLinesList(uint32 uiMapId) const;
+ std::vector<uint32> const* GetUiMapQuestsList(uint32 uiMapId) const;
+
VehicleTemplate const* GetVehicleTemplate(Vehicle* veh) const;
VehicleAccessoryList const* GetVehicleAccessoryList(Vehicle* veh) const;
@@ -1420,6 +1425,9 @@ class TC_GAME_API ObjectMgr
void LoadPlayerChoices();
void LoadPlayerChoicesLocale();
+ void LoadUiMapQuestLines();
+ void LoadUiMapQuests();
+
void LoadJumpChargeParams();
void LoadPhaseNames();
@@ -1957,6 +1965,9 @@ class TC_GAME_API ObjectMgr
SceneTemplateContainer _sceneTemplateStore;
+ UiMapQuestLinesMap _uiMapQuestLinesStore;
+ UiMapQuestsMap _uiMapQuestsStore;
+
std::unordered_map<int32, JumpChargeParams> _jumpChargeParams;
PhaseNameContainer _phaseNameStore;
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 9a95bd79374..b6636b1e246 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -826,3 +826,38 @@ void WorldSession::HandlePlayerChoiceResponse(WorldPackets::Quest::ChoiceRespons
_player->GetReputationMgr().ModifyReputation(sFactionStore.AssertEntry(faction.Id), faction.Quantity);
}
}
+
+void WorldSession::HandleUiMapQuestLinesRequest(WorldPackets::Quest::UiMapQuestLinesRequest& uiMapQuestLinesRequest)
+{
+ UiMapEntry const* uiMap = sUiMapStore.LookupEntry(uiMapQuestLinesRequest.UiMapID);
+ if (!uiMap)
+ return;
+
+ WorldPackets::Quest::UiMapQuestLinesResponse response;
+ response.UiMapID = uiMap->ID;
+
+ if (std::vector<uint32> const* questLines = sObjectMgr->GetUiMapQuestLinesList(uiMap->ID))
+ {
+ for (uint32 questLineId : *questLines)
+ {
+ std::vector<QuestLineXQuestEntry const*> const* questLineQuests = sDB2Manager.GetQuestsForQuestLine(questLineId);
+ if (!questLineQuests)
+ continue;
+
+ for (QuestLineXQuestEntry const* questLineQuest : *questLineQuests)
+ if (Quest const* quest = sObjectMgr->GetQuestTemplate(questLineQuest->QuestID))
+ if (_player->CanTakeQuest(quest, false))
+ response.QuestLineXQuestIDs.push_back(questLineQuest->ID);
+ }
+ }
+
+ if (std::vector<uint32> const* quests = sObjectMgr->GetUiMapQuestsList(uiMap->ID))
+ {
+ for (uint32 questId : *quests)
+ if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
+ if (_player->CanTakeQuest(quest, false))
+ response.QuestIDs.push_back(questId);
+ }
+
+ SendPacket(response.Write());
+}
diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp
index 3b63196b7d1..6c8b9517a78 100644
--- a/src/server/game/Server/Packets/QuestPackets.cpp
+++ b/src/server/game/Server/Packets/QuestPackets.cpp
@@ -858,4 +858,24 @@ void ChoiceResponse::Read()
_worldPacket >> ResponseIdentifier;
IsReroll = _worldPacket.ReadBit();
}
+
+WorldPacket const* UiMapQuestLinesResponse::Write()
+{
+ _worldPacket << int32(UiMapID);
+ _worldPacket << uint32(QuestLineXQuestIDs.size());
+ _worldPacket << uint32(QuestIDs.size());
+
+ for (uint32 const& questLineQuestID : QuestLineXQuestIDs)
+ _worldPacket << uint32(questLineQuestID);
+
+ for (uint32 const& questID : QuestIDs)
+ _worldPacket << uint32(questID);
+
+ return &_worldPacket;
+}
+
+void UiMapQuestLinesRequest::Read()
+{
+ _worldPacket >> UiMapID;
+}
}
diff --git a/src/server/game/Server/Packets/QuestPackets.h b/src/server/game/Server/Packets/QuestPackets.h
index 2e295a44b9b..2fb56be4c3f 100644
--- a/src/server/game/Server/Packets/QuestPackets.h
+++ b/src/server/game/Server/Packets/QuestPackets.h
@@ -788,6 +788,28 @@ namespace WorldPackets
int32 ResponseIdentifier = 0;
bool IsReroll = false;
};
+
+ class UiMapQuestLinesResponse final : public ServerPacket
+ {
+ public:
+ UiMapQuestLinesResponse() : ServerPacket(SMSG_UI_MAP_QUEST_LINES_RESPONSE, 4) { }
+
+ WorldPacket const* Write() override;
+
+ int32 UiMapID = 0;
+ std::vector<uint32> QuestLineXQuestIDs;
+ std::vector<uint32> QuestIDs;
+ };
+
+ class UiMapQuestLinesRequest final : public ClientPacket
+ {
+ public:
+ UiMapQuestLinesRequest(WorldPacket&& packet) : ClientPacket(CMSG_UI_MAP_QUEST_LINES_REQUEST, std::move(packet)) { }
+
+ void Read() override;
+
+ int32 UiMapID = 0;
+ };
}
}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 82e261ff5bf..29bc0765015 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -981,7 +981,7 @@ void OpcodeTable::InitializeClientOpcodes()
DEFINE_HANDLER(CMSG_TRANSMOGRIFY_ITEMS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTransmogrifyItems);
DEFINE_HANDLER(CMSG_TURN_IN_PETITION, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTurnInPetition);
DEFINE_HANDLER(CMSG_TUTORIAL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleTutorialFlag);
- DEFINE_HANDLER(CMSG_UI_MAP_QUEST_LINES_REQUEST, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_UI_MAP_QUEST_LINES_REQUEST, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleUiMapQuestLinesRequest);
DEFINE_HANDLER(CMSG_UNACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode);
DEFINE_HANDLER(CMSG_UNDELETE_CHARACTER, STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleCharUndeleteOpcode);
DEFINE_HANDLER(CMSG_UNLEARN_SKILL, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleUnlearnSkillOpcode);
@@ -2161,7 +2161,7 @@ void OpcodeTable::InitializeServerOpcodes()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_MOVIE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TURN_IN_PETITION_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TUTORIAL_FLAGS, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_UI_MAP_QUEST_LINES_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_UI_MAP_QUEST_LINES_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UNDELETE_CHARACTER_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UNDELETE_COOLDOWN_STATUS_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UNLEARNED_SPELLS, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 1b61d60b027..1c3052a3f8a 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -674,6 +674,7 @@ namespace WorldPackets
class PushQuestToParty;
class RequestWorldQuestUpdate;
class ChoiceResponse;
+ class UiMapQuestLinesRequest;
}
namespace RaF
@@ -1566,6 +1567,7 @@ class TC_GAME_API WorldSession
void HandleQuestPushResult(WorldPackets::Quest::QuestPushResult& packet);
void HandleRequestWorldQuestUpdate(WorldPackets::Quest::RequestWorldQuestUpdate& packet);
void HandlePlayerChoiceResponse(WorldPackets::Quest::ChoiceResponse& choiceResponse);
+ void HandleUiMapQuestLinesRequest(WorldPackets::Quest::UiMapQuestLinesRequest& uiMapQuestLinesRequest);
void HandleChatMessageOpcode(WorldPackets::Chat::ChatMessage& chatMessage);
void HandleChatMessageWhisperOpcode(WorldPackets::Chat::ChatMessageWhisper& chatMessageWhisper);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 5321f6c476b..2ec553204c7 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2197,6 +2197,13 @@ bool World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Player Choices Locales...");
sObjectMgr->LoadPlayerChoicesLocale();
}
+
+ TC_LOG_INFO("server.loading", "Loading UIMap questlines...");
+ sObjectMgr->LoadUiMapQuestLines();
+
+ TC_LOG_INFO("server.loading", "Loading UIMap quests...");
+ sObjectMgr->LoadUiMapQuests();
+
TC_LOG_INFO("server.loading", "Loading Jump Charge Params...");
sObjectMgr->LoadJumpChargeParams();