aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
diff options
context:
space:
mode:
authorRoger Stebler <roger.stebler@students.unibe.ch>2017-08-20 17:24:41 +0200
committerShauren <shauren.trinity@gmail.com>2017-08-20 17:24:41 +0200
commit4bc9ed0fdeee0822fb2142c94c8360c1af777f6b (patch)
tree741d5dcb24ed8adbb2631ae8ff61890357f54eed /src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
parent1de03622c5ee61298a7e3da42b22626b8f89f2d4 (diff)
Core/Quests: Implemented criteria tree quest objective type
Closes #20161
Diffstat (limited to 'src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp')
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp320
1 files changed, 320 insertions, 0 deletions
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);
+}