diff options
Diffstat (limited to 'src/server/game/Achievements/CriteriaHandler.cpp')
-rw-r--r-- | src/server/game/Achievements/CriteriaHandler.cpp | 183 |
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); |