aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Achievements/CriteriaHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Achievements/CriteriaHandler.cpp')
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp183
1 files changed, 89 insertions, 94 deletions
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index 2f10bc605fd..9abf7721db4 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -859,75 +859,94 @@ void CriteriaHandler::UpdateCriteria(CriteriaType type, uint64 miscValue1 /*= 0*
}
}
-void CriteriaHandler::UpdateTimedCriteria(uint32 timeDiff)
+void CriteriaHandler::UpdateTimedCriteria(Milliseconds timeDiff)
{
- if (!_timeCriteriaTrees.empty())
+ for (auto itr = _startedCriteria.begin(); itr != _startedCriteria.end();)
{
- for (auto itr = _timeCriteriaTrees.begin(); itr != _timeCriteriaTrees.end();)
+ // Time is up, remove timer and reset progress
+ if (itr->second <= timeDiff)
{
- // Time is up, remove timer and reset progress
- if (itr->second <= timeDiff)
- {
- CriteriaTree const* criteriaTree = sCriteriaMgr->GetCriteriaTree(itr->first);
- if (criteriaTree->Criteria)
- RemoveCriteriaProgress(criteriaTree->Criteria);
+ RemoveCriteriaProgress(sCriteriaMgr->GetCriteria(itr->first));
- itr = _timeCriteriaTrees.erase(itr);
- }
- else
- {
- itr->second -= timeDiff;
- ++itr;
- }
+ itr = _startedCriteria.erase(itr);
+ }
+ else
+ {
+ itr->second -= timeDiff;
+ ++itr;
}
}
}
-void CriteriaHandler::StartCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry, uint32 timeLost /* = 0 */)
+void CriteriaHandler::StartCriteria(CriteriaStartEvent startEvent, uint32 entry, Milliseconds timeLost /*= Milliseconds::zero()*/)
{
- CriteriaList const& criteriaList = sCriteriaMgr->GetTimedCriteriaByType(startEvent);
- for (Criteria const* criteria : criteriaList)
+ CriteriaList const* criteriaList = sCriteriaMgr->GetCriteriaByStartEvent(startEvent, entry);
+ if (!criteriaList)
+ return;
+
+ for (Criteria const* criteria : *criteriaList)
{
- if (criteria->Entry->StartAsset != int32(entry))
+ Milliseconds timeLimit = Milliseconds::max(); // this value is for criteria that have a start event requirement but no time limit
+ if (criteria->Entry->StartTimer)
+ timeLimit = Seconds(criteria->Entry->StartTimer);
+
+ timeLimit -= timeLost;
+
+ if (timeLimit <= Milliseconds::zero())
continue;
CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
- bool canStart = false;
- for (CriteriaTree const* tree : *trees)
+ bool canStart = std::any_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
{
- if ((_timeCriteriaTrees.find(tree->ID) == _timeCriteriaTrees.end() || criteria->Entry->GetFlags().HasFlag(CriteriaFlags::ResetOnStart)) && !IsCompletedCriteriaTree(tree))
- {
- // Start the timer
- if (criteria->Entry->StartTimer * uint32(IN_MILLISECONDS) > timeLost)
- {
- _timeCriteriaTrees[tree->ID] = criteria->Entry->StartTimer * IN_MILLISECONDS - timeLost;
- canStart = true;
- }
- }
- }
+ return !IsCompletedCriteriaTree(tree);
+ });
if (!canStart)
continue;
+ auto [itr, isNew] = _startedCriteria.try_emplace(criteria->ID, timeLimit);
+ if (!isNew)
+ {
+ if (!criteria->Entry->GetFlags().HasFlag(CriteriaFlags::ResetOnStart))
+ continue;
+
+ itr->second = timeLimit;
+ }
+
// and at client too
SetCriteriaProgress(criteria, 0, nullptr, PROGRESS_SET);
}
}
-void CriteriaHandler::RemoveCriteriaTimer(CriteriaStartEvent startEvent, uint32 entry)
+void CriteriaHandler::FailCriteria(CriteriaFailEvent failEvent, uint32 asset)
{
- CriteriaList const& criteriaList = sCriteriaMgr->GetTimedCriteriaByType(startEvent);
- for (Criteria const* criteria : criteriaList)
+ CriteriaList const* criteriaList = sCriteriaMgr->GetCriteriaByFailEvent(failEvent, asset);
+ if (!criteriaList)
+ return;
+
+ for (Criteria const* criteria : *criteriaList)
{
- if (criteria->Entry->StartAsset != int32(entry))
- continue;
+ _startedCriteria.erase(criteria->ID);
CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
- // Remove the timer from all trees
- for (CriteriaTree const* tree : *trees)
- _timeCriteriaTrees.erase(tree->ID);
+ bool allTreesFullyComplete = std::all_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
+ {
+ CriteriaTree const* root = tree;
+ if (CriteriaTree const* parent = sCriteriaMgr->GetCriteriaTree(root->Entry->Parent))
+ {
+ do
+ {
+ root = parent;
+ parent = sCriteriaMgr->GetCriteriaTree(root->Entry->Parent);
+ } while (parent);
+ }
+
+ return IsCompletedCriteriaTree(root);
+ });
+
+ if (allTreesFullyComplete)
+ continue;
- // remove progress
RemoveCriteriaProgress(criteria);
}
}
@@ -943,29 +962,6 @@ CriteriaProgress* CriteriaHandler::GetCriteriaProgress(Criteria const* entry)
void CriteriaHandler::SetCriteriaProgress(Criteria const* criteria, uint64 changeValue, Player* referencePlayer, ProgressType progressType)
{
- // Don't allow to cheat - doing timed criteria without timer active
- CriteriaTreeList const* trees = nullptr;
- if (criteria->Entry->StartTimer)
- {
- trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
- if (!trees)
- return;
-
- bool hasTreeForTimed = false;
- for (CriteriaTree const* tree : *trees)
- {
- auto timedIter = _timeCriteriaTrees.find(tree->ID);
- if (timedIter != _timeCriteriaTrees.end())
- {
- hasTreeForTimed = true;
- break;
- }
- }
-
- if (!hasTreeForTimed)
- return;
- }
-
TC_LOG_DEBUG("criteria", "CriteriaHandler::SetCriteriaProgress({}, {}) for {}", criteria->ID, changeValue, GetOwnerInfo());
CriteriaProgress* progress = GetCriteriaProgress(criteria);
@@ -1014,20 +1010,22 @@ void CriteriaHandler::SetCriteriaProgress(Criteria const* criteria, uint64 chang
if (criteria->Entry->StartTimer)
{
- ASSERT(trees);
-
- for (CriteriaTree const* tree : *trees)
+ auto startedItr = _startedCriteria.find(criteria->ID);
+ if (startedItr != _startedCriteria.end())
{
- auto timedIter = _timeCriteriaTrees.find(tree->ID);
- if (timedIter != _timeCriteriaTrees.end())
+ // Client expects this in packet
+ timeElapsed = duration_cast<Seconds>(Seconds(criteria->Entry->StartTimer) - startedItr->second);
+
+ // Remove the timer, we wont need it anymore
+ CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
+
+ bool allTreesCompleted = std::all_of(trees->begin(), trees->end(), [&](CriteriaTree const* tree)
{
- // Client expects this in packet
- timeElapsed = Seconds(criteria->Entry->StartTimer - (timedIter->second / IN_MILLISECONDS));
+ return IsCompletedCriteriaTree(tree);
+ });
- // Remove the timer, we wont need it anymore
- if (IsCompletedCriteriaTree(tree))
- _timeCriteriaTrees.erase(timedIter);
- }
+ if (allTreesCompleted)
+ _startedCriteria.erase(startedItr);
}
}
@@ -1045,7 +1043,8 @@ void CriteriaHandler::RemoveCriteriaProgress(Criteria const* criteria)
SendCriteriaProgressRemoved(criteria->ID);
- _criteriaProgress.erase(criteriaProgress);
+ criteriaProgress->second.Counter = 0;
+ criteriaProgress->second.Changed = true;
}
bool CriteriaHandler::IsCompletedCriteriaTree(CriteriaTree const* tree)
@@ -1322,24 +1321,10 @@ bool CriteriaHandler::CanUpdateCriteria(Criteria const* criteria, CriteriaTreeLi
return true;
}
-bool CriteriaHandler::ConditionsSatisfied(Criteria const* criteria, Player* referencePlayer) const
+bool CriteriaHandler::ConditionsSatisfied(Criteria const* criteria, Player* /*referencePlayer*/) const
{
- if (!criteria->Entry->FailEvent)
- return true;
-
- switch (CriteriaFailEvent(criteria->Entry->FailEvent))
- {
- case CriteriaFailEvent::LeaveBattleground:
- if (!referencePlayer->InBattleground())
- return false;
- break;
- case CriteriaFailEvent::ModifyPartyStatus:
- if (referencePlayer->GetGroup())
- return false;
- break;
- default:
- break;
- }
+ if (criteria->Entry->StartEvent && !_startedCriteria.contains(criteria->ID))
+ return false;
return true;
}
@@ -4496,6 +4481,16 @@ CriteriaList const& CriteriaMgr::GetScenarioCriteriaByTypeAndScenario(CriteriaTy
return EmptyCriteriaList;
}
+CriteriaList const* CriteriaMgr::GetCriteriaByStartEvent(CriteriaStartEvent startEvent, int32 asset) const
+{
+ return Trinity::Containers::MapGetValuePtr(_criteriasByStartEvent[size_t(startEvent)], asset);
+}
+
+CriteriaList const* CriteriaMgr::GetCriteriaByFailEvent(CriteriaFailEvent failEvent, int32 asset) const
+{
+ return Trinity::Containers::MapGetValuePtr(_criteriasByFailEvent[size_t(failEvent)], asset);
+}
+
CriteriaMgr::CriteriaMgr() = default;
//==========================================================
@@ -4720,7 +4715,7 @@ void CriteriaMgr::LoadCriteriaList()
}
if (criteriaEntry->StartTimer)
- _criteriasByTimedType[criteriaEntry->StartEvent].push_back(criteria);
+ _criteriasByStartEvent[criteriaEntry->StartEvent][criteriaEntry->StartAsset].push_back(criteria);
if (criteriaEntry->FailEvent)
_criteriasByFailEvent[criteriaEntry->FailEvent][criteriaEntry->FailAsset].push_back(criteria);