TrinityCore
Loading...
Searching...
No Matches
QuestMgr.cpp
Go to the documentation of this file.
1/*
2* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3*
4* This program is free software; you can redistribute it and/or modify it
5* under the terms of the GNU General Public License as published by the
6* Free Software Foundation; either version 2 of the License, or (at your
7* option) any later version.
8*
9* This program is distributed in the hope that it will be useful, but WITHOUT
10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12* more details.
13*
14* You should have received a copy of the GNU General Public License along
15* with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include "QuestMgr.h"
19#include "DB2Stores.h"
20#include "MapUtils.h"
21#include "ObjectMgr.h"
22#include "Player.h"
23#include <algorithm>
24
25namespace
26{
27std::unordered_map<uint32, std::vector<QuestLineXQuestEntry const*>> QuestsByQuestLine;
28
29struct QuestLineData
30{
31 QuestLineXQuestEntry const* QuestLineQuest = nullptr;
32 std::vector<CampaignEntry const*>* Campaigns = nullptr;
33};
34std::map<uint32, std::vector<CampaignEntry const*>> CampaignsByQuestLine;
35std::unordered_map<uint32, std::vector<QuestLineData>> QuestLineDataByQuest;
36
37struct CampaignQuestLine
38{
39 uint32 CampaignId = 0;
40 uint32 QuestLineId = 0;
41
42 friend std::strong_ordering operator<=>(CampaignQuestLine const& left, CampaignQuestLine const& right) = default;
43};
44std::vector<CampaignQuestLine> CampaignQuestLines;
45
46struct CampaignQuestLinesSentinel
47{
48 std::vector<CampaignQuestLine>::const_iterator End;
49 uint32 CampaignId;
50
51 friend bool operator==(std::vector<CampaignQuestLine>::const_iterator const& itr, CampaignQuestLinesSentinel const& end)
52 {
53 return itr == end.End || itr->CampaignId != end.CampaignId;
54 }
55};
56
57Trinity::IteratorPair<std::vector<CampaignQuestLine>::iterator, CampaignQuestLinesSentinel> GetQuestLinesForCampaign(uint32 campaignId)
58{
60 std::ranges::lower_bound(CampaignQuestLines, campaignId, std::ranges::less(), &CampaignQuestLine::CampaignId),
61 CampaignQuestLinesSentinel{ .End = CampaignQuestLines.end(), .CampaignId = campaignId });
62}
63}
64
66{
67 for (CampaignXQuestLineEntry const* campaignQuestLine : sCampaignXQuestLineStore)
68 {
69 if (CampaignEntry const* campaign = sCampaignStore.LookupEntry(campaignQuestLine->CampaignID))
70 {
71 CampaignsByQuestLine[campaignQuestLine->QuestLineID].push_back(campaign);
72 CampaignQuestLines.push_back({ .CampaignId = campaignQuestLine->CampaignID, .QuestLineId = campaignQuestLine->QuestLineID });
73 }
74 }
75
76 for (QuestLineXQuestEntry const* questLineQuest : sQuestLineXQuestStore)
77 {
78 QuestsByQuestLine[questLineQuest->QuestLineID].push_back(questLineQuest);
79
80 QuestLineData& questLineData = QuestLineDataByQuest[questLineQuest->QuestID].emplace_back();
81 questLineData.QuestLineQuest = questLineQuest;
82 questLineData.Campaigns = Trinity::Containers::MapGetValuePtr(CampaignsByQuestLine, questLineQuest->QuestLineID);
83 }
84
85 std::ranges::sort(CampaignQuestLines);
86
87 for (auto& [_, questLineQuests] : QuestsByQuestLine)
88 std::ranges::sort(questLineQuests, std::ranges::less(), &QuestLineXQuestEntry::OrderIndex);
89}
90
91std::span<QuestLineXQuestEntry const* const> QuestMgr::GetQuestsForQuestLine(uint32 questLineId)
92{
93 std::span<QuestLineXQuestEntry const* const> result;
94 if (auto itr = QuestsByQuestLine.find(questLineId); itr != QuestsByQuestLine.end())
95 result = itr->second;
96
97 return result;
98}
99
101{
102 for (QuestLineXQuestEntry const* questLineQuest : GetQuestsForQuestLine(questLineId))
103 if (Quest const* quest = sObjectMgr->GetQuestTemplate(questLineQuest->QuestID))
104 if (player->CanTakeQuest(quest, false))
105 return true;
106
107 return false;
108}
109
111{
112 for (QuestLineXQuestEntry const* questLineQuest : GetQuestsForQuestLine(questLineId))
113 if (player->IsActiveQuest(questLineQuest->QuestID))
114 return true;
115
116 return false;
117}
118
120{
121 for (QuestLineXQuestEntry const* questLineQuest : GetQuestsForQuestLine(questLineId))
122 {
123 if (questLineQuest->HasFlag(QuestLineXQuestFlags::IgnoreForCompletion))
124 continue;
125
126 if (!player->IsQuestCompletedBitSet(questLineQuest->QuestID))
127 return false;
128 }
129
130 return true;
131}
132
134{
135 QuestLineStats stats;
136 for (QuestLineXQuestEntry const* questLineQuest : GetQuestsForQuestLine(questLineId))
137 {
138 if (questLineQuest->HasFlag(QuestLineXQuestFlags::IgnoreForCompletion))
139 continue;
140
141 stats.Completed += player->IsQuestCompletedBitSet(questLineQuest->QuestID) ? 1 : 0;
142 ++stats.Total;
143 }
144
145 return stats;
146}
147
149{
150 std::span<QuestLineXQuestEntry const* const> questLineQuests = GetQuestsForQuestLine(questLineId);
151 std::vector<uint32> questIds(questLineQuests.size());
152 std::ranges::transform(questLineQuests, questIds.begin(), &QuestLineXQuestEntry::QuestID);
153 player->SkipQuests(questIds);
154}
155
157{
158 auto questLines = GetQuestLinesForCampaign(campaignId);
159 if (questLines.begin() == questLines.end())
160 return false;
161
162 for (CampaignQuestLine const& campaignQuestLine : questLines)
163 if (!IsQuestLineCompletedByPlayer(campaignQuestLine.QuestLineId, player))
164 return false;
165
166 // all questlines completed
167 return true;
168}
169
171{
172 auto itr = QuestLineDataByQuest.find(questId);
173 if (itr == QuestLineDataByQuest.end())
174 return false;
175
176 for (QuestLineData const& questLineData : itr->second)
177 {
178 if (!questLineData.Campaigns)
179 continue;
180
181 for (CampaignEntry const* campaign : *questLineData.Campaigns)
182 {
183 if (campaign->HasFlag(CampaignFlags::DontUseJourneyQuestBang))
184 continue;
185
186 if (!ConditionMgr::IsPlayerMeetingCondition(player, campaign->Prerequisite))
187 continue;
188
189 if (!ConditionMgr::IsPlayerMeetingCondition(player, campaign->Stalled))
190 continue;
191
192 if (campaign->Completed && ConditionMgr::IsPlayerMeetingCondition(player, campaign->Completed))
193 continue;
194
195 if (!ConditionMgr::IsPlayerMeetingCondition(player, campaign->OnlyStallIf))
196 continue;
197
198 return true;
199 }
200 }
201
202 return false;
203}
204
206{
207 std::vector<uint32> questIds;
208
209 for (CampaignQuestLine const& campaignQuestLine : GetQuestLinesForCampaign(campaignId))
210 {
211 std::ptrdiff_t oldSize = std::ssize(questIds);
212 std::span<QuestLineXQuestEntry const* const> questLineQuests = GetQuestsForQuestLine(campaignQuestLine.QuestLineId);
213 questIds.resize(oldSize + questLineQuests.size());
214 std::ranges::transform(questLineQuests, questIds.begin() + oldSize, &QuestLineXQuestEntry::QuestID);
215 }
216
217 player->SkipQuests(questIds);
218}
DB2Storage< CampaignEntry > sCampaignStore("Campaign.db2", &CampaignLoadInfo::Instance)
DB2Storage< CampaignXQuestLineEntry > sCampaignXQuestLineStore("CampaignXQuestLine.db2", &CampaignXQuestLineLoadInfo::Instance)
DB2Storage< QuestLineXQuestEntry > sQuestLineXQuestStore("QuestLineXQuest.db2", &QuestLineXQuestLoadInfo::Instance)
uint32_t uint32
Definition Define.h:154
#define sObjectMgr
Definition ObjectMgr.h:1885
std::strong_ordering operator<=>(WowTime const &left, WowTime const &right)
Definition WowTime.cpp:142
static bool IsPlayerMeetingCondition(Player const *player, uint32 conditionId)
bool IsQuestCompletedBitSet(uint32 questId) const
Definition Player.cpp:16517
void SkipQuests(std::span< uint32 const > questIds)
Definition Player.cpp:16269
bool IsActiveQuest(uint32 quest_id) const
Definition Player.cpp:14477
bool CanTakeQuest(Quest const *quest, bool msg) const
Definition Player.cpp:14522
Utility class to enable range for loop syntax for multimap.equal_range uses.
TC_GAME_API bool IsQuestLineQuestActiveForPlayer(uint32 questLineId, Player const *player)
Definition QuestMgr.cpp:110
TC_GAME_API void SkipCampaignForPlayer(uint32 campaignId, Player *player)
Definition QuestMgr.cpp:205
TC_GAME_API bool IsQuestLineCompletedByPlayer(uint32 questLineId, Player const *player)
Definition QuestMgr.cpp:119
TC_GAME_API bool IsCampaignCompletedByPlayer(uint32 campaignId, Player const *player)
Definition QuestMgr.cpp:156
TC_GAME_API bool IsQuestLineQuestAvailableForPlayer(uint32 questLineId, Player const *player)
Definition QuestMgr.cpp:100
TC_GAME_API bool IsCampaignQuestStatusVisibleForPlayer(uint32 questId, Player const *player)
Definition QuestMgr.cpp:170
TC_GAME_API QuestLineStats GetQuestLineStatsForPlayer(uint32 questLineId, Player const *player)
Definition QuestMgr.cpp:133
void Load()
Definition QuestMgr.cpp:65
TC_GAME_API void SkipQuestLineForPlayer(uint32 questLineId, Player *player)
Definition QuestMgr.cpp:148
TC_GAME_API std::span< QuestLineXQuestEntry const *const > GetQuestsForQuestLine(uint32 questLineId)
Definition QuestMgr.cpp:91
constexpr IteratorPair< iterator, end_iterator > MakeIteratorPair(iterator first, end_iterator second)
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
bool operator==(unique_trackable_ptr< T1 > const &left, unique_trackable_ptr< T2 > const &right)