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); } }
bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry) { // counter can never complete if (entry->Flags & ACHIEVEMENT_FLAG_COUNTER) return false; CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(entry->CriteriaTree); if (!tree) return false; // For SUMM achievements, we have to count the progress of each criteria of the achievement. // Oddly, the target count is NOT contained in the achievement, but in each individual criteria if (entry->Flags & ACHIEVEMENT_FLAG_SUMM) { int64 progress = 0; CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree) { if (criteriaTree->Criteria) if (CriteriaProgress const* criteriaProgress = this->GetCriteriaProgress(criteriaTree->Criteria)) progress += criteriaProgress->Counter; }); return progress >= tree->Entry->Amount; } return IsCompletedCriteriaTree(tree); }
void InstanceScenario::LoadInstanceData(uint32 instanceId) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE); stmt->setUInt32(0, instanceId); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); time_t now = time(nullptr); std::vector<CriteriaTree const*> criteriaTrees; do { Field* fields = result->Fetch(); uint32 id = fields[0].GetUInt32(); uint64 counter = fields[1].GetUInt64(); time_t date = time_t(fields[2].GetUInt32()); Criteria const* criteria = sCriteriaMgr->GetCriteria(id); if (!criteria) { // Removing non-existing criteria data for all instances TC_LOG_ERROR("criteria.instancescenarios", "Removing scenario criteria %u data from the table `instance_scenario_progress`.", id); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA); stmt->setUInt32(0, instanceId); stmt->setUInt32(1, uint32(id)); trans->Append(stmt); continue; } if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now) continue; switch (CriteriaTypes(criteria->Entry->Type)) { // Blizzard appears to only stores creatures killed progress for unknown reasons. Either technical shortcoming or intentional case CRITERIA_TYPE_KILL_CREATURE: break; default: continue; } SetCriteriaProgress(criteria, counter, nullptr, PROGRESS_SET); if (CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID)) for (CriteriaTree const* tree : *trees) criteriaTrees.push_back(tree); } while (result->NextRow()); CharacterDatabase.CommitTransaction(trans); for (CriteriaTree const* tree : criteriaTrees) { ScenarioStepEntry const* step = tree->ScenarioStep; if (!step) continue; if (IsCompletedCriteriaTree(tree)) SetStepState(step, SCENARIO_STEP_DONE); } } }