aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp8
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.h8
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp4
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp28
-rw-r--r--src/server/game/Achievements/CriteriaHandler.h17
-rw-r--r--src/server/game/Entities/Player/Player.cpp48
-rw-r--r--src/server/game/Entities/Player/Player.h5
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp8
-rw-r--r--src/server/game/Quests/QuestDef.h6
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp320
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.h64
11 files changed, 503 insertions, 13 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index 34bef1ea62a..ad4998b9543 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -94,6 +94,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, timer FROM character_queststatus WHERE guid = ? AND status <> 0", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES, "SELECT quest, objective, data FROM character_queststatus_objectives WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA, "SELECT questObjectiveId FROM character_queststatus_objectives_criteria WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS, "SELECT criteriaId, counter, date FROM character_queststatus_objectives_criteria_progress WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
@@ -549,6 +551,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_CHAR_TAXIMASK, "UPDATE characters SET taximask = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS, "DELETE FROM character_queststatus WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES, "DELETE FROM character_queststatus_objectives WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA, "DELETE FROM character_queststatus_objectives_criteria WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS, "DELETE FROM character_queststatus_objectives_criteria_progress WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS_BY_CRITERIA, "DELETE FROM character_queststatus_objectives_criteria_progress WHERE guid = ? AND criteriaId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SOCIAL_BY_GUID, "DELETE FROM character_social WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SOCIAL_BY_FRIEND, "DELETE FROM character_social WHERE friend = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT, "DELETE FROM character_achievement WHERE achievement = ? AND guid = ?", CONNECTION_ASYNC);
@@ -596,11 +601,14 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST, "DELETE FROM character_queststatus WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_CHAR_QUESTSTATUS_OBJECTIVES, "REPLACE INTO character_queststatus_objectives (guid, quest, objective, data) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_BY_QUEST, "DELETE FROM character_queststatus_objectives WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA, "INSERT INTO character_queststatus_objectives_criteria (guid, questObjectiveId) VALUES (?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS, "INSERT INTO character_queststatus_objectives_criteria_progress (guid, criteriaId, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_QUESTSTATUS_REWARDED, "INSERT IGNORE INTO character_queststatus_rewarded (guid, quest, active) VALUES (?, ?, 1)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST, "DELETE FROM character_queststatus_rewarded WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_FACTION_CHANGE, "UPDATE character_queststatus_rewarded SET quest = ? WHERE quest = ? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE, "UPDATE character_queststatus_rewarded SET active = 1 WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST, "UPDATE character_queststatus_rewarded SET active = 0 WHERE quest = ? AND guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_INVALID_QUEST_PROGRESS_CRITERIA, "DELETE FROM character_queststatus_objectives_criteria WHERE questObjectiveId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SKILL_BY_SKILL, "DELETE FROM character_skills WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_SKILLS, "INSERT INTO character_skills (guid, skill, value, max) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_SKILLS, "UPDATE character_skills SET value = ?, max = ? WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h
index c2ea5136261..b2acafc2308 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.h
+++ b/src/server/database/Database/Implementation/CharacterDatabase.h
@@ -71,6 +71,8 @@ enum CharacterDatabaseStatements : uint32
CHAR_SEL_CHARACTER_QUESTSTATUS,
CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES,
+ CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA,
+ CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS,
CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY,
CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY,
CHAR_SEL_CHARACTER_QUESTSTATUS_MONTHLY,
@@ -450,6 +452,9 @@ enum CharacterDatabaseStatements : uint32
CHAR_UPD_CHAR_TAXIMASK,
CHAR_DEL_CHAR_QUESTSTATUS,
CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES,
+ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA,
+ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS,
+ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS_BY_CRITERIA,
CHAR_DEL_CHAR_SOCIAL_BY_GUID,
CHAR_DEL_CHAR_SOCIAL_BY_FRIEND,
CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT,
@@ -497,11 +502,14 @@ enum CharacterDatabaseStatements : uint32
CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST,
CHAR_REP_CHAR_QUESTSTATUS_OBJECTIVES,
CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_BY_QUEST,
+ CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA,
+ CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS,
CHAR_INS_CHAR_QUESTSTATUS_REWARDED,
CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST,
CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_FACTION_CHANGE,
CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE,
CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST,
+ CHAR_DEL_INVALID_QUEST_PROGRESS_CRITERIA,
CHAR_DEL_CHAR_SKILL_BY_SKILL,
CHAR_INS_CHAR_SKILLS,
CHAR_UPD_CHAR_SKILLS,
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index b4d7ad07eb6..6ab15152d75 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -272,7 +272,7 @@ void PlayerAchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, Pre
TC_LOG_ERROR("criteria.achievement", "Non-existing achievement criteria %u data has been removed from the table `character_achievement_progress`.", id);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA);
- stmt->setUInt32(0, uint16(id));
+ stmt->setUInt32(0, id);
CharacterDatabase.Execute(stmt);
continue;
@@ -716,7 +716,7 @@ void GuildAchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, Prep
TC_LOG_ERROR("criteria.achievement", "Non-existing achievement criteria %u data removed from table `guild_achievement_progress`.", id);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD);
- stmt->setUInt32(0, uint16(id));
+ stmt->setUInt32(0, id);
CharacterDatabase.Execute(stmt);
continue;
}
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index cbf296ddb7e..f3bb97ecf4b 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -2227,19 +2227,34 @@ void CriteriaMgr::LoadCriteriaList()
if (scenarioStep->CriteriaTreeID)
scenarioCriteriaTreeIds[scenarioStep->CriteriaTreeID] = scenarioStep;
+ std::unordered_map<uint32 /*criteriaTreeID*/, QuestObjective const*> questObjectiveCriteriaTreeIds;
+ for (std::pair<uint32 /*questID*/, Quest const*> itr : sObjectMgr->GetQuestTemplates())
+ {
+ for (QuestObjective const& objective : itr.second->Objectives)
+ {
+ if (objective.Type != QUEST_OBJECTIVE_CRITERIA_TREE)
+ continue;
+
+ if (objective.ObjectID)
+ questObjectiveCriteriaTreeIds[objective.ObjectID] = &objective;
+ }
+ }
+
// Load criteria tree nodes
for (CriteriaTreeEntry const* tree : sCriteriaTreeStore)
{
// Find linked achievement
AchievementEntry const* achievement = GetEntry(achievementCriteriaTreeIds, tree);
ScenarioStepEntry const* scenarioStep = GetEntry(scenarioCriteriaTreeIds, tree);
- if (!achievement && !scenarioStep)
+ QuestObjective const* questObjective = GetEntry(questObjectiveCriteriaTreeIds, tree);
+ if (!achievement && !scenarioStep && !questObjective)
continue;
CriteriaTree* criteriaTree = new CriteriaTree();
criteriaTree->ID = tree->ID;
criteriaTree->Achievement = achievement;
criteriaTree->ScenarioStep = scenarioStep;
+ criteriaTree->QuestObjective = questObjective;
criteriaTree->Entry = tree;
_criteriaTrees[criteriaTree->Entry->ID] = criteriaTree;
@@ -2274,6 +2289,7 @@ void CriteriaMgr::LoadCriteriaList()
uint32 criterias = 0;
uint32 guildCriterias = 0;
uint32 scenarioCriterias = 0;
+ uint32 questObjectiveCriterias = 0;
for (CriteriaEntry const* criteriaEntry : sCriteriaStore)
{
ASSERT(criteriaEntry->Type < CRITERIA_TYPE_TOTAL, "CRITERIA_TYPE_TOTAL must be greater than or equal to %u but is currently equal to %u",
@@ -2305,6 +2321,8 @@ void CriteriaMgr::LoadCriteriaList()
}
else if (tree->ScenarioStep)
criteria->FlagsCu |= CRITERIA_FLAG_CU_SCENARIO;
+ else if (tree->QuestObjective)
+ criteria->FlagsCu |= CRITERIA_FLAG_CU_QUEST_OBJECTIVE;
}
if (criteria->FlagsCu & (CRITERIA_FLAG_CU_PLAYER | CRITERIA_FLAG_CU_ACCOUNT))
@@ -2325,6 +2343,12 @@ void CriteriaMgr::LoadCriteriaList()
_scenarioCriteriasByType[criteriaEntry->Type].push_back(criteria);
}
+ if (criteria->FlagsCu & CRITERIA_FLAG_CU_QUEST_OBJECTIVE)
+ {
+ ++questObjectiveCriterias;
+ _questObjectiveCriteriasByType[criteriaEntry->Type].push_back(criteria);
+ }
+
if (criteriaEntry->StartTimer)
_criteriasByTimedType[criteriaEntry->StartEvent].push_back(criteria);
}
@@ -2332,7 +2356,7 @@ void CriteriaMgr::LoadCriteriaList()
for (auto& p : _criteriaTrees)
const_cast<CriteriaTree*>(p.second)->Criteria = GetCriteria(p.second->Entry->CriteriaID);
- TC_LOG_INFO("server.loading", ">> Loaded %u criteria, %u guild criteria and %u scenario criteria in %u ms.", criterias, guildCriterias, scenarioCriterias, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u criteria, %u guild criteria, %u scenario criteria and %u quest objective criteria in %u ms.", criterias, guildCriterias, scenarioCriterias, questObjectiveCriterias, GetMSTimeDiffToNow(oldMSTime));
}
void CriteriaMgr::LoadCriteriaData()
diff --git a/src/server/game/Achievements/CriteriaHandler.h b/src/server/game/Achievements/CriteriaHandler.h
index c8b96b144cd..7d14df68be1 100644
--- a/src/server/game/Achievements/CriteriaHandler.h
+++ b/src/server/game/Achievements/CriteriaHandler.h
@@ -34,6 +34,7 @@ struct AchievementEntry;
struct CriteriaEntry;
struct CriteriaTreeEntry;
struct ModifierTreeEntry;
+struct QuestObjective;
struct ScenarioStepEntry;
struct ModifierTreeNode
@@ -44,10 +45,11 @@ struct ModifierTreeNode
enum CriteriaFlagsCu
{
- CRITERIA_FLAG_CU_PLAYER = 0x1,
- CRITERIA_FLAG_CU_ACCOUNT = 0x2,
- CRITERIA_FLAG_CU_GUILD = 0x4,
- CRITERIA_FLAG_CU_SCENARIO = 0x8
+ CRITERIA_FLAG_CU_PLAYER = 0x1,
+ CRITERIA_FLAG_CU_ACCOUNT = 0x2,
+ CRITERIA_FLAG_CU_GUILD = 0x4,
+ CRITERIA_FLAG_CU_SCENARIO = 0x8,
+ CRITERIA_FLAG_CU_QUEST_OBJECTIVE = 0x10
};
struct Criteria
@@ -66,6 +68,7 @@ struct CriteriaTree
CriteriaTreeEntry const* Entry = nullptr;
AchievementEntry const* Achievement = nullptr;
ScenarioStepEntry const* ScenarioStep = nullptr;
+ QuestObjective const* QuestObjective = nullptr;
struct Criteria const* Criteria = nullptr;
std::vector<CriteriaTree const*> Children;
};
@@ -331,6 +334,11 @@ public:
return _scenarioCriteriasByType[type];
}
+ CriteriaList const& GetQuestObjectiveCriteriaByType(CriteriaTypes type) const
+ {
+ return _questObjectiveCriteriasByType[type];
+ }
+
CriteriaTreeList const* GetCriteriaTreesByCriteria(uint32 criteriaId) const
{
auto itr = _criteriaTreeByCriteria.find(criteriaId);
@@ -395,6 +403,7 @@ private:
CriteriaList _criteriasByType[CRITERIA_TYPE_TOTAL];
CriteriaList _guildCriteriasByType[CRITERIA_TYPE_TOTAL];
CriteriaList _scenarioCriteriasByType[CRITERIA_TYPE_TOTAL];
+ CriteriaList _questObjectiveCriteriasByType[CRITERIA_TYPE_TOTAL];
CriteriaList _criteriasByTimedType[CRITERIA_TIMED_TYPE_MAX];
};
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 9f5a82f96ea..e2611e9c9ac 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -89,6 +89,7 @@
#include "PetPackets.h"
#include "QueryHolder.h"
#include "QuestDef.h"
+#include "QuestObjectiveCriteriaMgr.h"
#include "QuestPackets.h"
#include "Realm.h"
#include "ReputationMgr.h"
@@ -346,6 +347,7 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
m_achievementMgr = new PlayerAchievementMgr(this);
m_reputationMgr = new ReputationMgr(this);
+ m_questObjectiveCriteriaMgr = Trinity::make_unique<QuestObjectiveCriteriaMgr>(this);
for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
_CUFProfiles[i] = nullptr;
@@ -14745,6 +14747,11 @@ void Player::AddQuestAndCheckCompletion(Quest const* quest, Object* questGiver)
{
AddQuest(quest, questGiver);
+ for (QuestObjective const& obj : quest->GetObjectives())
+ if (obj.Type == QUEST_OBJECTIVE_CRITERIA_TREE)
+ if (m_questObjectiveCriteriaMgr->HasCompletedObjective(&obj))
+ KillCreditCriteriaTreeObjective(obj);
+
if (CanCompleteQuest(quest->GetQuestId()))
CompleteQuest(quest->GetQuestId());
@@ -14900,9 +14907,22 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
AdjustQuestReqItemCount(quest);
for (QuestObjective const& obj : quest->GetObjectives())
- if (obj.Type == QUEST_OBJECTIVE_MIN_REPUTATION || obj.Type == QUEST_OBJECTIVE_MAX_REPUTATION)
- if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(obj.ObjectID))
- GetReputationMgr().SetVisible(factionEntry);
+ {
+ switch (obj.Type)
+ {
+ case QUEST_OBJECTIVE_MIN_REPUTATION:
+ case QUEST_OBJECTIVE_MAX_REPUTATION:
+ if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(obj.ObjectID))
+ GetReputationMgr().SetVisible(factionEntry);
+ break;
+ case QUEST_OBJECTIVE_CRITERIA_TREE:
+ if (quest->HasFlagEx(QUEST_FLAGS_EX_CLEAR_PROGRESS_OF_CRITERIA_TREE_OBJECTIVES_ON_ACCEPT))
+ m_questObjectiveCriteriaMgr->ResetCriteriaTree(obj.ObjectID);
+ break;
+ default:
+ break;
+ }
+ }
uint32 qtime = 0;
if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
@@ -16563,6 +16583,21 @@ void Player::TalkedToCreature(uint32 entry, ObjectGuid guid)
}
}
+void Player::KillCreditCriteriaTreeObjective(QuestObjective const& questObjective)
+{
+ if (questObjective.Type != QUEST_OBJECTIVE_CRITERIA_TREE)
+ return;
+
+ if (GetQuestStatus(questObjective.QuestID) == QUEST_STATUS_INCOMPLETE)
+ {
+ SetQuestObjectiveData(questObjective, 1);
+ SendQuestUpdateAddCreditSimple(questObjective);
+
+ if (CanCompleteQuest(questObjective.QuestID))
+ CompleteQuest(questObjective.QuestID);
+ }
+}
+
void Player::MoneyChanged(uint64 value)
{
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
@@ -16813,6 +16848,7 @@ bool Player::IsQuestObjectiveComplete(QuestObjective const& objective) const
return false;
break;
case QUEST_OBJECTIVE_AREATRIGGER:
+ case QUEST_OBJECTIVE_CRITERIA_TREE:
if (!GetQuestObjectiveData(quest, objective.StorageIndex))
return false;
break;
@@ -17389,6 +17425,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
// load achievements before anything else to prevent multiple gains for the same achievement/criteria on every loading (as loading does call UpdateCriteria)
m_achievementMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS));
+ m_questObjectiveCriteriaMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA_PROGRESS));
uint64 money = fields[8].GetUInt64();
if (money > MAX_MONEY_AMOUNT)
@@ -18056,6 +18093,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
}
m_achievementMgr->CheckAllAchievementCriteria(this);
+ m_questObjectiveCriteriaMgr->CheckAllQuestObjectiveCriteria(this);
return true;
}
@@ -19966,6 +20004,7 @@ void Player::SaveToDB(bool create /*=false*/)
_SaveSkills(trans);
m_achievementMgr->SaveToDB(trans);
m_reputationMgr->SaveToDB(trans);
+ m_questObjectiveCriteriaMgr->SaveToDB(trans);
_SaveEquipmentSets(trans);
GetSession()->SaveTutorialsData(trans); // changed only while character in game
_SaveInstanceTimeRestrictions(trans);
@@ -23448,6 +23487,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendEquipmentSetList();
m_achievementMgr->SendAllData(this);
+ m_questObjectiveCriteriaMgr->SendAllData(this);
/// SMSG_LOGIN_SETTIMESPEED
static float const TimeSpeed = 0.01666667f;
@@ -25876,11 +25916,13 @@ void Player::RemoveCriteriaTimer(CriteriaTimedTypes type, uint32 entry)
void Player::ResetCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, bool evenIfCriteriaComplete /* = false*/)
{
m_achievementMgr->ResetCriteria(type, miscValue1, miscValue2, evenIfCriteriaComplete);
+ m_questObjectiveCriteriaMgr->ResetCriteria(type, miscValue1, miscValue2, evenIfCriteriaComplete);
}
void Player::UpdateCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit* unit /*= NULL*/)
{
m_achievementMgr->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
+ m_questObjectiveCriteriaMgr->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
// Update only individual achievement criteria here, otherwise we may get multiple updates
// from a single boss kill
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 414515b5e36..4f3f270fdc6 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -77,6 +77,7 @@ class PlayerAI;
class PlayerAchievementMgr;
class PlayerMenu;
class PlayerSocial;
+class QuestObjectiveCriteriaMgr;
class ReputationMgr;
class RestMgr;
class SpellCastTargets;
@@ -785,6 +786,8 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_SPELLS,
PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS,
PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES,
+ PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA,
+ PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA_PROGRESS,
PLAYER_LOGIN_QUERY_LOAD_DAILY_QUEST_STATUS,
PLAYER_LOGIN_QUERY_LOAD_REPUTATION,
PLAYER_LOGIN_QUERY_LOAD_INVENTORY,
@@ -1415,6 +1418,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void KilledPlayerCredit();
void KillCreditGO(uint32 entry, ObjectGuid guid = ObjectGuid::Empty);
void TalkedToCreature(uint32 entry, ObjectGuid guid);
+ void KillCreditCriteriaTreeObjective(QuestObjective const& questObjective);
void MoneyChanged(uint64 value);
void ReputationChanged(FactionEntry const* factionEntry);
void CurrencyChanged(uint32 currencyId, int32 change);
@@ -2659,6 +2663,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
PlayerAchievementMgr* m_achievementMgr;
ReputationMgr* m_reputationMgr;
+ std::unique_ptr<QuestObjectiveCriteriaMgr> m_questObjectiveCriteriaMgr;
uint32 m_ChampioningFaction;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 17ddf3ed8a6..1ee32b74991 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -113,6 +113,14 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA_PROGRESS, stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY);
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_DAILY_QUEST_STATUS, stmt);
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 49bce2fe583..700216ef7e8 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -132,7 +132,7 @@ enum QuestGiverStatus
DIALOG_STATUS_SCRIPTED_NO_STATUS = 0x1000
};
-enum QuestFlags
+enum QuestFlags : uint32
{
QUEST_FLAGS_NONE = 0x00000000,
QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently
@@ -164,7 +164,7 @@ enum QuestFlags
};
// last checked in 19802
-enum QuestFlagsEx
+enum QuestFlagsEx : uint32
{
QUEST_FLAGS_EX_NONE = 0x0000000,
QUEST_FLAGS_EX_KEEP_ADDITIONAL_ITEMS = 0x0000001,
@@ -335,6 +335,8 @@ class TC_GAME_API Quest
bool HasSpecialFlag(uint32 flag) const { return (SpecialFlags & flag) != 0; }
void SetSpecialFlag(uint32 flag) { SpecialFlags |= flag; }
+ bool HasFlagEx(QuestFlagsEx flag) const { return (FlagsEx & uint32(flag)) != 0; }
+
// table data accessors:
uint32 GetQuestId() const { return ID; }
uint32 GetQuestType() const { return Type; }
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
new file mode 100644
index 00000000000..965cbd804d1
--- /dev/null
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "QuestObjectiveCriteriaMgr.h"
+#include "AchievementPackets.h"
+#include "DatabaseEnv.h"
+#include "DB2Structure.h"
+#include "Log.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+
+QuestObjectiveCriteriaMgr::QuestObjectiveCriteriaMgr(Player* owner) : _owner(owner)
+{
+}
+
+QuestObjectiveCriteriaMgr::~QuestObjectiveCriteriaMgr()
+{
+}
+
+void QuestObjectiveCriteriaMgr::CheckAllQuestObjectiveCriteria(Player* referencePlayer)
+{
+ // suppress sending packets
+ for (uint32 i = 0; i < CRITERIA_TYPE_TOTAL; ++i)
+ UpdateCriteria(CriteriaTypes(i), 0, 0, 0, nullptr, referencePlayer);
+}
+
+void QuestObjectiveCriteriaMgr::Reset()
+{
+ for (auto& criteriaProgres : _criteriaProgress)
+ SendCriteriaProgressRemoved(criteriaProgres.first);
+
+ _criteriaProgress.clear();
+
+ DeleteFromDB(_owner->GetGUID());
+
+ // re-fill data
+ CheckAllQuestObjectiveCriteria(_owner);
+}
+
+void QuestObjectiveCriteriaMgr::DeleteFromDB(ObjectGuid const& guid)
+{
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
+ stmt->setUInt64(0, guid.GetCounter());
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS);
+ stmt->setUInt64(0, guid.GetCounter());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void QuestObjectiveCriteriaMgr::LoadFromDB(PreparedQueryResult objectiveResult, PreparedQueryResult criteriaResult)
+{
+ if (objectiveResult)
+ {
+ do
+ {
+ uint32 objectiveId = (*objectiveResult)[0].GetUInt32();
+
+ QuestObjective const* objective = sObjectMgr->GetQuestObjective(objectiveId);
+ if (!objective)
+ continue;
+
+ _completedObjectives.insert(objectiveId);
+
+ } while (objectiveResult->NextRow());
+ }
+
+ if (criteriaResult)
+ {
+ time_t now = time(nullptr);
+ do
+ {
+ Field* fields = criteriaResult->Fetch();
+ uint32 criteriaId = fields[0].GetUInt32();
+ uint64 counter = fields[1].GetUInt64();
+ time_t date = time_t(fields[2].GetUInt32());
+
+ Criteria const* criteria = sCriteriaMgr->GetCriteria(criteriaId);
+ if (!criteria)
+ {
+ // Removing non-existing criteria data for all characters
+ TC_LOG_ERROR("criteria.quest", "Non-existing quest objective criteria %u data has been removed from the table `character_queststatus_objectives_criteria_progress`.", criteriaId);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_QUEST_PROGRESS_CRITERIA);
+ stmt->setUInt32(0, criteriaId);
+ CharacterDatabase.Execute(stmt);
+
+ continue;
+ }
+
+ if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now)
+ continue;
+
+ CriteriaProgress& progress = _criteriaProgress[criteriaId];
+ progress.Counter = counter;
+ progress.Date = date;
+ progress.Changed = false;
+ } while (criteriaResult->NextRow());
+ }
+}
+
+void QuestObjectiveCriteriaMgr::SaveToDB(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ if (!_completedObjectives.empty())
+ {
+ for (uint32 completedObjectiveId : _completedObjectives)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, completedObjectiveId);
+ trans->Append(stmt);
+ }
+ }
+
+ if (!_criteriaProgress.empty())
+ {
+ for (auto& criteriaProgres : _criteriaProgress)
+ {
+ if (!criteriaProgres.second.Changed)
+ continue;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS_BY_CRITERIA);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, criteriaProgres.first);
+ trans->Append(stmt);
+
+ if (criteriaProgres.second.Counter)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, criteriaProgres.first);
+ stmt->setUInt64(2, criteriaProgres.second.Counter);
+ stmt->setUInt32(3, uint32(criteriaProgres.second.Date));
+ trans->Append(stmt);
+ }
+
+ criteriaProgres.second.Changed = false;
+ }
+ }
+}
+
+void QuestObjectiveCriteriaMgr::ResetCriteria(CriteriaTypes type, uint64 miscValue1, uint64 miscValue2, bool evenIfCriteriaComplete)
+{
+ TC_LOG_DEBUG("criteria.quest", "QuestObjectiveCriteriaMgr::ResetCriteria(%u, " UI64FMTD ", " UI64FMTD ")", type, miscValue1, miscValue2);
+
+ // disable for gamemasters with GM-mode enabled
+ if (_owner->IsGameMaster())
+ return;
+
+ CriteriaList const& playerCriteriaList = GetCriteriaByType(type);
+ for (Criteria const* playerCriteria : playerCriteriaList)
+ {
+ if (playerCriteria->Entry->FailEvent != miscValue1 || (playerCriteria->Entry->FailAsset && playerCriteria->Entry->FailAsset != miscValue2))
+ continue;
+
+ std::vector<CriteriaTree const*> const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(playerCriteria->ID);
+ bool allComplete = true;
+ for (CriteriaTree const* tree : *trees)
+ {
+ // don't update already completed criteria if not forced
+ if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete))
+ {
+ allComplete = false;
+ break;
+ }
+ }
+
+ if (allComplete)
+ continue;
+
+ RemoveCriteriaProgress(playerCriteria);
+ }
+}
+
+void QuestObjectiveCriteriaMgr::ResetCriteriaTree(uint32 criteriaTreeId)
+{
+ CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(criteriaTreeId);
+ if (!tree)
+ return;
+
+ CriteriaMgr::WalkCriteriaTree(tree, [this](CriteriaTree const* criteriaTree)
+ {
+ RemoveCriteriaProgress(criteriaTree->Criteria);
+ });
+}
+
+void QuestObjectiveCriteriaMgr::SendAllData(Player const* /*receiver*/) const
+{
+ for (const auto& criteriaProgres : _criteriaProgress)
+ {
+ WorldPackets::Achievement::CriteriaUpdate criteriaUpdate;
+
+ criteriaUpdate.CriteriaID = criteriaProgres.first;
+ criteriaUpdate.Quantity = criteriaProgres.second.Counter;
+ criteriaUpdate.PlayerGUID = _owner->GetGUID();
+ criteriaUpdate.Flags = 0;
+
+ criteriaUpdate.CurrentTime = criteriaProgres.second.Date;
+ criteriaUpdate.CreationTime = 0;
+
+ SendPacket(criteriaUpdate.Write());
+ }
+}
+
+void QuestObjectiveCriteriaMgr::CompletedObjective(QuestObjective const* questObjective, Player* referencePlayer)
+{
+ // disable for gamemasters with GM-mode enabled
+ if (_owner->IsGameMaster())
+ return;
+
+ if (HasCompletedObjective(questObjective))
+ return;
+
+ referencePlayer->KillCreditCriteriaTreeObjective(*questObjective);
+
+ TC_LOG_INFO("criteria.quest", "QuestObjectiveCriteriaMgr::CompletedObjective(%u). %s", questObjective->ID, GetOwnerInfo().c_str());
+
+ _completedObjectives.insert(questObjective->ID);
+}
+
+bool QuestObjectiveCriteriaMgr::HasCompletedObjective(QuestObjective const* questObjective) const
+{
+ return _completedObjectives.find(questObjective->ID) != _completedObjectives.end();
+}
+
+void QuestObjectiveCriteriaMgr::SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const
+{
+ WorldPackets::Achievement::CriteriaUpdate criteriaUpdate;
+
+ criteriaUpdate.CriteriaID = criteria->ID;
+ criteriaUpdate.Quantity = progress->Counter;
+ criteriaUpdate.PlayerGUID = _owner->GetGUID();
+ criteriaUpdate.Flags = 0;
+ if (criteria->Entry->StartTimer)
+ criteriaUpdate.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
+
+ criteriaUpdate.CurrentTime = progress->Date;
+ criteriaUpdate.ElapsedTime = timeElapsed;
+ criteriaUpdate.CreationTime = 0;
+
+ SendPacket(criteriaUpdate.Write());
+}
+
+void QuestObjectiveCriteriaMgr::SendCriteriaProgressRemoved(uint32 criteriaId)
+{
+ WorldPackets::Achievement::CriteriaDeleted criteriaDeleted;
+ criteriaDeleted.CriteriaID = criteriaId;
+ SendPacket(criteriaDeleted.Write());
+}
+
+bool QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const
+{
+ QuestObjective const* objective = tree->QuestObjective;
+ if (!objective)
+ return false;
+
+ if (HasCompletedObjective(objective))
+ {
+ TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: %u Type %s Quest Objective %u) Objective already completed",
+ criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
+ return false;
+ }
+
+ return CriteriaHandler::CanUpdateCriteriaTree(criteria, tree, referencePlayer);
+}
+
+bool QuestObjectiveCriteriaMgr::CanCompleteCriteriaTree(CriteriaTree const* tree)
+{
+ QuestObjective const* objective = tree->QuestObjective;
+ if (!objective)
+ return false;
+
+ return CriteriaHandler::CanCompleteCriteriaTree(tree);
+}
+
+void QuestObjectiveCriteriaMgr::CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer)
+{
+ QuestObjective const* objective = tree->QuestObjective;
+ if (!objective)
+ return;
+
+ CompletedObjective(objective, referencePlayer);
+}
+
+void QuestObjectiveCriteriaMgr::SendPacket(WorldPacket const* data) const
+{
+ _owner->SendDirectMessage(data);
+}
+
+std::string QuestObjectiveCriteriaMgr::GetOwnerInfo() const
+{
+ return Trinity::StringFormat("%s %s", _owner->GetGUID().ToString().c_str(), _owner->GetName().c_str());
+}
+
+CriteriaList const& QuestObjectiveCriteriaMgr::GetCriteriaByType(CriteriaTypes type) const
+{
+ return sCriteriaMgr->GetQuestObjectiveCriteriaByType(type);
+}
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.h b/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
new file mode 100644
index 00000000000..76c6bbb8d1d
--- /dev/null
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QuestObjectiveCriteriaMgr_h__
+#define QuestObjectiveCriteriaMgr_h__
+
+#include "CriteriaHandler.h"
+
+class TC_GAME_API QuestObjectiveCriteriaMgr : public CriteriaHandler
+{
+public:
+ explicit QuestObjectiveCriteriaMgr(Player* owner);
+ ~QuestObjectiveCriteriaMgr();
+
+ void CheckAllQuestObjectiveCriteria(Player* referencePlayer);
+
+ void Reset() override;
+
+ static void DeleteFromDB(ObjectGuid const& guid);
+ void LoadFromDB(PreparedQueryResult objectiveResult, PreparedQueryResult criteriaResult);
+ void SaveToDB(SQLTransaction& trans);
+
+ void ResetCriteria(CriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
+ void ResetCriteriaTree(uint32 criteriaTreeId);
+
+ void SendAllData(Player const* receiver) const override;
+
+ void CompletedObjective(QuestObjective const* questObjective, Player* referencePlayer);
+ bool HasCompletedObjective(QuestObjective const* questObjective) const;
+
+protected:
+ void SendCriteriaUpdate(Criteria const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const override;
+
+ void SendCriteriaProgressRemoved(uint32 criteriaId) override;
+
+ bool CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const override;
+ bool CanCompleteCriteriaTree(CriteriaTree const* tree) override;
+ void CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer) override;
+
+ void SendPacket(WorldPacket const* data) const override;
+
+ std::string GetOwnerInfo() const override;
+ CriteriaList const& GetCriteriaByType(CriteriaTypes type) const override;
+
+private:
+ Player* _owner;
+ std::unordered_set<uint32> _completedObjectives;
+};
+
+#endif