TrinityCore
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
31{
32}
33
35{
36}
37
39{
40 // suppress sending packets
41 for (uint32 i = 0; i < uint32(CriteriaType::Count); ++i)
42 UpdateCriteria(CriteriaType(i), 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 CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(criteriaTreeId);
171 if (!tree)
172 return;
173
174 CriteriaMgr::WalkCriteriaTree(tree, [this](CriteriaTree const* criteriaTree)
175 {
176 RemoveCriteriaProgress(criteriaTree->Criteria);
177 });
178}
179
180void QuestObjectiveCriteriaMgr::SendAllData(Player const* /*receiver*/) const
181{
182 for (const auto& criteriaProgres : _criteriaProgress)
183 {
185
186 criteriaUpdate.CriteriaID = criteriaProgres.first;
187 criteriaUpdate.Quantity = criteriaProgres.second.Counter;
188 criteriaUpdate.PlayerGUID = _owner->GetGUID();
189 criteriaUpdate.Flags = 0;
190
191 criteriaUpdate.CurrentTime.SetUtcTimeFromUnixTime(criteriaProgres.second.Date);
192 criteriaUpdate.CurrentTime += _owner->GetSession()->GetTimezoneOffset();
193 criteriaUpdate.CreationTime = 0;
194
195 SendPacket(criteriaUpdate.Write());
196 }
197}
198
199void QuestObjectiveCriteriaMgr::CompletedObjective(QuestObjective const* questObjective, Player* /*referencePlayer*/)
200{
201 if (HasCompletedObjective(questObjective))
202 return;
203
204 _owner->KillCreditCriteriaTreeObjective(*questObjective);
205
206 TC_LOG_INFO("criteria.quest", "QuestObjectiveCriteriaMgr::CompletedObjective({}). {}", questObjective->ID, GetOwnerInfo());
207
208 _completedObjectives.insert(questObjective->ID);
209}
210
212{
213 return _completedObjectives.find(questObjective->ID) != _completedObjectives.end();
214}
215
216void QuestObjectiveCriteriaMgr::SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, Seconds timeElapsed, bool timedCompleted) const
217{
219
220 criteriaUpdate.CriteriaID = criteria->ID;
221 criteriaUpdate.Quantity = progress->Counter;
222 criteriaUpdate.PlayerGUID = _owner->GetGUID();
223 criteriaUpdate.Flags = 0;
224 if (criteria->Entry->StartTimer)
225 criteriaUpdate.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
226
227 criteriaUpdate.CurrentTime.SetUtcTimeFromUnixTime(progress->Date);
228 criteriaUpdate.CurrentTime += _owner->GetSession()->GetTimezoneOffset();
229 criteriaUpdate.ElapsedTime = timeElapsed;
230 criteriaUpdate.CreationTime = 0;
231
232 SendPacket(criteriaUpdate.Write());
233}
234
236{
238 criteriaDeleted.CriteriaID = criteriaId;
239 SendPacket(criteriaDeleted.Write());
240}
241
242bool QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const
243{
244 QuestObjective const* objective = tree->QuestObjective;
245 if (!objective)
246 return false;
247
248 if (HasCompletedObjective(objective))
249 {
250 TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: {} Type {} Quest Objective {}) Objective already completed",
251 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
252 return false;
253 }
254
256 {
257 TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: {} Type {} Quest Objective {}) Not on quest",
258 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
259 return false;
260 }
261
262 Quest const* quest = ASSERT_NOTNULL(sObjectMgr->GetQuestTemplate(objective->QuestID));
263 if (_owner->GetGroup() && _owner->GetGroup()->isRaidGroup() && !quest->IsAllowedInRaid(referencePlayer->GetMap()->GetDifficultyID()))
264 {
265 TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: {} Type {} Quest Objective {}) Quest cannot be completed in raid group",
266 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
267 return false;
268 }
269
270 uint16 slot = _owner->FindQuestSlot(objective->QuestID);
271 if (slot >= MAX_QUEST_LOG_SIZE || !_owner->IsQuestObjectiveCompletable(slot, quest, *objective))
272 {
273 TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: {} Type {} Quest Objective {}) Objective not completable",
274 criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
275 return false;
276 }
277
278 return CriteriaHandler::CanUpdateCriteriaTree(criteria, tree, referencePlayer);
279}
280
282{
283 QuestObjective const* objective = tree->QuestObjective;
284 if (!objective)
285 return false;
286
288}
289
291{
292 QuestObjective const* objective = tree->QuestObjective;
293 if (!objective)
294 return;
295
296 CompletedObjective(objective, referencePlayer);
297}
298
300{
302}
303
305{
306 return Trinity::StringFormat("{} {}", _owner->GetGUID().ToString(), _owner->GetName());
307}
308
310{
311 return sCriteriaMgr->GetQuestObjectiveCriteriaByType(type);
312}
313
315{
316 return _owner->HasAchieved(achievementId);
317}
@ 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:503
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
std::shared_ptr< PreparedResultSet > PreparedQueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint64_t uint64
Definition: Define.h:141
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:32
#define ASSERT_NOTNULL(pointer)
Definition: Errors.h:84
#define TC_LOG_TRACE(filterType__,...)
Definition: Log.h:153
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
#define sObjectMgr
Definition: ObjectMgr.h:1946
#define MAX_QUEST_LOG_SIZE
Definition: QuestDef.h:44
@ QUEST_STATUS_INCOMPLETE
Definition: QuestDef.h:145
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)
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)
Class used to access individual fields of database query result.
Definition: Field.h:90
int64 GetInt64() const
Definition: Field.cpp:86
uint64 GetUInt64() const
Definition: Field.cpp:78
uint32 GetUInt32() const
Definition: Field.cpp:62
bool isRaidGroup() const
Definition: Group.cpp:1638
Difficulty GetDifficultyID() const
Definition: Map.h:324
LowType GetCounter() const
Definition: ObjectGuid.h:293
std::string ToString() const
Definition: ObjectGuid.cpp:554
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
uint16 FindQuestSlot(uint32 quest_id) const
Definition: Player.cpp:16432
bool HasAchieved(uint32 achievementId) const
Definition: Player.cpp:26751
WorldSession * GetSession() const
Definition: Player.h:2101
bool IsQuestObjectiveCompletable(uint16 slot, Quest const *quest, QuestObjective const &objective) const
Definition: Player.cpp:17032
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition: Player.cpp:16050
Group * GetGroup(Optional< uint8 > partyIndex)
Definition: Player.h:2606
void KillCreditCriteriaTreeObjective(QuestObjective const &questObjective)
Definition: Player.cpp:16714
void setInt64(const uint8 index, const int64 value)
void setUInt32(const uint8 index, const uint32 value)
void setUInt64(const uint8 index, const 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(uint32 criteriaTreeId)
void LoadFromDB(PreparedQueryResult objectiveResult, PreparedQueryResult criteriaResult)
bool IsAllowedInRaid(Difficulty difficulty) const
Definition: QuestDef.cpp:569
Map * GetMap() const
Definition: Object.h:624
std::string const & GetName() const
Definition: Object.h:555
Minutes GetTimezoneOffset() const
void SetUtcTimeFromUnixTime(std::time_t unixTime)
Definition: WowTime.cpp:86
time_t GetGameTime()
Definition: GameTime.cpp:44
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38
std::time_t Date
::Criteria const * Criteria
::QuestObjective const * QuestObjective
CriteriaEntry const * Entry
uint32 QuestID
Definition: QuestDef.h:446