TrinityCore
Loading...
Searching...
No Matches
QuestObjectiveCriteriaMgr.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
19#include "AchievementPackets.h"
20#include "DatabaseEnv.h"
21#include "DB2Structure.h"
22#include "GameTime.h"
23#include "Group.h"
24#include "Log.h"
25#include "Map.h"
26#include "ObjectMgr.h"
27#include "Player.h"
28#include "WorldSession.h"
29
33
37
39{
40 // suppress sending packets
42 UpdateCriteria(criteriaType, 0, 0, 0, nullptr, referencePlayer);
43}
44
46{
47 for (auto& criteriaProgres : _criteriaProgress)
48 SendCriteriaProgressRemoved(criteriaProgres.first);
49
50 _criteriaProgress.clear();
51
53
54 // re-fill data
56}
57
59{
60 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
61
63 stmt->setUInt64(0, guid.GetCounter());
64 trans->Append(stmt);
65
67 stmt->setUInt64(0, guid.GetCounter());
68 trans->Append(stmt);
69
70 CharacterDatabase.CommitTransaction(trans);
71}
72
74{
75 if (objectiveResult)
76 {
77 do
78 {
79 uint32 objectiveId = (*objectiveResult)[0].GetUInt32();
80
81 QuestObjective const* objective = sObjectMgr->GetQuestObjective(objectiveId);
82 if (!objective)
83 continue;
84
85 _completedObjectives.insert(objectiveId);
86
87 } while (objectiveResult->NextRow());
88 }
89
90 if (criteriaResult)
91 {
92 time_t now = GameTime::GetGameTime();
93 do
94 {
95 Field* fields = criteriaResult->Fetch();
96 uint32 criteriaId = fields[0].GetUInt32();
97 uint64 counter = fields[1].GetUInt64();
98 time_t date = fields[2].GetInt64();
99
100 Criteria const* criteria = sCriteriaMgr->GetCriteria(criteriaId);
101 if (!criteria)
102 {
103 // Removing non-existing criteria data for all characters
104 TC_LOG_ERROR("criteria.quest", "Non-existing quest objective criteria {} data has been removed from the table `character_queststatus_objectives_criteria_progress`.", criteriaId);
105
107 stmt->setUInt32(0, criteriaId);
108 CharacterDatabase.Execute(stmt);
109
110 continue;
111 }
112
113 if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now)
114 continue;
115
116 CriteriaProgress& progress = _criteriaProgress[criteriaId];
117 progress.Counter = counter;
118 progress.Date = date;
119 progress.Changed = false;
120 } while (criteriaResult->NextRow());
121 }
122}
123
125{
127 stmt->setUInt64(0, _owner->GetGUID().GetCounter());
128 trans->Append(stmt);
129
130 if (!_completedObjectives.empty())
131 {
132 for (uint32 completedObjectiveId : _completedObjectives)
133 {
135 stmt->setUInt64(0, _owner->GetGUID().GetCounter());
136 stmt->setUInt32(1, completedObjectiveId);
137 trans->Append(stmt);
138 }
139 }
140
141 if (!_criteriaProgress.empty())
142 {
143 for (auto& criteriaProgres : _criteriaProgress)
144 {
145 if (!criteriaProgres.second.Changed)
146 continue;
147
149 stmt->setUInt64(0, _owner->GetGUID().GetCounter());
150 stmt->setUInt32(1, criteriaProgres.first);
151 trans->Append(stmt);
152
153 if (criteriaProgres.second.Counter)
154 {
156 stmt->setUInt64(0, _owner->GetGUID().GetCounter());
157 stmt->setUInt32(1, criteriaProgres.first);
158 stmt->setUInt64(2, criteriaProgres.second.Counter);
159 stmt->setInt64(3, criteriaProgres.second.Date);
160 trans->Append(stmt);
161 }
162
163 criteriaProgres.second.Changed = false;
164 }
165 }
166}
167
169{
170 _completedObjectives.erase(questObjective->ID);
171
172 CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(questObjective->ObjectID);
173 if (!tree)
174 return;
175
176 CriteriaMgr::WalkCriteriaTree(tree, [this](CriteriaTree const* criteriaTree)
177 {
178 RemoveCriteriaProgress(criteriaTree->Criteria);
179 });
180
181 CriteriaMgr::WalkCriteriaTree(tree, [this](CriteriaTree const* criteriaTree)
182 {
184 UpdateCriteria(criteriaTree->Criteria, 0, 0, 0, nullptr, _owner);
185 });
186}
187
188void QuestObjectiveCriteriaMgr::SendAllData(Player const* /*receiver*/) const
189{
190 for (const auto& criteriaProgres : _criteriaProgress)
191 {
193
194 criteriaUpdate.CriteriaID = criteriaProgres.first;
195 criteriaUpdate.Quantity = criteriaProgres.second.Counter;
196 criteriaUpdate.PlayerGUID = _owner->GetGUID();
197 criteriaUpdate.Flags = 0;
198
199 criteriaUpdate.CurrentTime.SetUtcTimeFromUnixTime(criteriaProgres.second.Date);
200 criteriaUpdate.CurrentTime += _owner->GetSession()->GetTimezoneOffset();
201 criteriaUpdate.CreationTime = 0;
202
203 SendPacket(criteriaUpdate.Write());
204 }
205}
206
207void QuestObjectiveCriteriaMgr::CompletedObjective(QuestObjective const* questObjective, Player* /*referencePlayer*/)
208{
209 if (HasCompletedObjective(questObjective))
210 return;
211
212 _owner->KillCreditCriteriaTreeObjective(*questObjective);
213
214 TC_LOG_INFO("criteria.quest", "QuestObjectiveCriteriaMgr::CompletedObjective({}). {}", questObjective->ID, GetOwnerInfo());
215
216 _completedObjectives.insert(questObjective->ID);
217}
218
220{
221 return _completedObjectives.contains(questObjective->ID);
222}
223
224void QuestObjectiveCriteriaMgr::SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, Seconds timeElapsed, bool timedCompleted) const
225{
227
228 criteriaUpdate.CriteriaID = criteria->ID;
229 criteriaUpdate.Quantity = progress->Counter;
230 criteriaUpdate.PlayerGUID = _owner->GetGUID();
231 criteriaUpdate.Flags = 0;
232 if (criteria->Entry->StartTimer)
233 criteriaUpdate.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
234
235 criteriaUpdate.CurrentTime.SetUtcTimeFromUnixTime(progress->Date);
236 criteriaUpdate.CurrentTime += _owner->GetSession()->GetTimezoneOffset();
237 criteriaUpdate.ElapsedTime = timeElapsed;
238 criteriaUpdate.CreationTime = 0;
239
240 SendPacket(criteriaUpdate.Write());
241}
242
244{
246 criteriaDeleted.CriteriaID = criteriaId;
247 SendPacket(criteriaDeleted.Write());
248}
249
250bool QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const
251{
252 QuestObjective const* objective = tree->QuestObjective;
253 if (!objective)
254 return false;
255
256 if (HasCompletedObjective(objective))
257 {
258 TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: {} Type {} Quest Objective {}) Objective already completed",
259 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
260 return false;
261 }
262
264 {
265 TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: {} Type {} Quest Objective {}) Not on quest",
266 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
267 return false;
268 }
269
270 Quest const* quest = ASSERT_NOTNULL(sObjectMgr->GetQuestTemplate(objective->QuestID));
271 if (_owner->GetGroup() && _owner->GetGroup()->isRaidGroup() && !quest->IsAllowedInRaid(referencePlayer->GetMap()->GetDifficultyID()))
272 {
273 TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: {} Type {} Quest Objective {}) Quest cannot be completed in raid group",
274 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
275 return false;
276 }
277
278 uint16 slot = _owner->FindQuestSlot(objective->QuestID);
279 if (slot >= MAX_QUEST_LOG_SIZE || !_owner->IsQuestObjectiveCompletable(slot, quest, *objective))
280 {
281 TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: {} Type {} Quest Objective {}) Objective not completable",
282 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
283 return false;
284 }
285
286 return CriteriaHandler::CanUpdateCriteriaTree(criteria, tree, referencePlayer);
287}
288
290{
291 QuestObjective const* objective = tree->QuestObjective;
292 if (!objective)
293 return false;
294
296}
297
299{
300 QuestObjective const* objective = tree->QuestObjective;
301 if (!objective)
302 return;
303
304 CriteriaTree const* entireObjectiveTree = sCriteriaMgr->GetCriteriaTree(objective->ObjectID);
305 if (IsCompletedCriteriaTree(entireObjectiveTree))
306 CompletedObjective(objective, referencePlayer);
307}
308
310{
312}
313
315{
316 return Trinity::StringFormat("{} {}", _owner->GetGUID().ToString(), _owner->GetName());
317}
318
320{
321 return sCriteriaMgr->GetQuestObjectiveCriteriaByType(type);
322}
323
325{
326 return _owner->HasAchieved(achievementId);
327}
@ CHAR_DEL_INVALID_QUEST_PROGRESS_CRITERIA
@ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS
@ CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA
@ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA
@ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS_BY_CRITERIA
@ CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS
#define sCriteriaMgr
std::vector< Criteria const * > CriteriaList
CriteriaType
Definition DBCEnums.h:546
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint64_t uint64
Definition Define.h:153
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:82
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_INFO(filterType__, message__,...)
Definition Log.h:184
#define TC_LOG_TRACE(filterType__, message__,...)
Definition Log.h:178
#define sObjectMgr
Definition ObjectMgr.h:1885
#define MAX_QUEST_LOG_SIZE
Definition QuestDef.h:46
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:150
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
virtual bool CanUpdateCriteriaTree(Criteria const *criteria, CriteriaTree const *tree, Player *referencePlayer) const
CriteriaProgressMap _criteriaProgress
void RemoveCriteriaProgress(Criteria const *criteria)
virtual bool CanCompleteCriteriaTree(CriteriaTree const *tree)
bool IsCompletedCriteriaTree(CriteriaTree const *tree)
void UpdateCriteria(CriteriaType type, uint64 miscValue1=0, uint64 miscValue2=0, uint64 miscValue3=0, WorldObject const *ref=nullptr, Player *referencePlayer=nullptr)
static char const * GetCriteriaTypeString(CriteriaType type)
static void WalkCriteriaTree(CriteriaTree const *tree, Func const &func)
static std::span< CriteriaType const > GetRetroactivelyUpdateableCriteriaTypes()
Class used to access individual fields of database query result.
Definition Field.h:94
uint64 GetUInt64() const noexcept
Definition Field.cpp:71
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
int64 GetInt64() const noexcept
Definition Field.cpp:78
bool isRaidGroup() const
Definition Group.cpp:1628
Difficulty GetDifficultyID() const
Definition Map.h:360
LowType GetCounter() const
Definition ObjectGuid.h:336
std::string ToString() const
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6283
uint16 FindQuestSlot(uint32 quest_id) const
Definition Player.cpp:16383
bool HasAchieved(uint32 achievementId) const
Definition Player.cpp:27572
WorldSession * GetSession() const
Definition Player.h:2272
bool IsQuestObjectiveCompletable(uint16 slot, Quest const *quest, QuestObjective const &objective) const
Definition Player.cpp:17133
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition Player.cpp:15962
Group * GetGroup(Optional< uint8 > partyIndex)
Definition Player.h:2796
void KillCreditCriteriaTreeObjective(QuestObjective const &questObjective)
Definition Player.cpp:16713
void setUInt32(uint8 index, uint32 value)
void setInt64(uint8 index, int64 value)
void setUInt64(uint8 index, uint64 value)
void SendCriteriaProgressRemoved(uint32 criteriaId) override
void SaveToDB(CharacterDatabaseTransaction trans)
void SendCriteriaUpdate(Criteria const *entry, CriteriaProgress const *progress, Seconds timeElapsed, bool timedCompleted) const override
bool RequiredAchievementSatisfied(uint32 achievementId) const override
void CheckAllQuestObjectiveCriteria(Player *referencePlayer)
void CompletedCriteriaTree(CriteriaTree const *tree, Player *referencePlayer) override
std::unordered_set< uint32 > _completedObjectives
static void DeleteFromDB(ObjectGuid const &guid)
std::string GetOwnerInfo() const override
void SendAllData(Player const *receiver) const override
void CompletedObjective(QuestObjective const *questObjective, Player *referencePlayer)
void SendPacket(WorldPacket const *data) const override
CriteriaList const & GetCriteriaByType(CriteriaType type, uint32 asset) const override
bool CanUpdateCriteriaTree(Criteria const *criteria, CriteriaTree const *tree, Player *referencePlayer) const override
bool CanCompleteCriteriaTree(CriteriaTree const *tree) override
bool HasCompletedObjective(QuestObjective const *questObjective) const
void ResetCriteriaTree(QuestObjective const *questObjective)
void LoadFromDB(PreparedQueryResult objectiveResult, PreparedQueryResult criteriaResult)
bool IsAllowedInRaid(Difficulty difficulty) const
Definition QuestDef.cpp:618
Map * GetMap() const
Definition Object.h:411
std::string const & GetName() const
Definition Object.h:342
Minutes GetTimezoneOffset() const
void SetUtcTimeFromUnixTime(std::time_t unixTime)
Definition WowTime.cpp:86
time_t GetGameTime()
Definition GameTime.cpp:52
std::string StringFormat(FormatString< Args... > fmt, Args &&... args) noexcept
Default TC string format function.
struct advstd::ranges::Contains contains
::Criteria const * Criteria
::QuestObjective const * QuestObjective
CriteriaEntry const * Entry
uint32 QuestID
Definition QuestDef.h:483