Jump to content

[7653][fix] Loremaster Achievement

Guest Trazom

Recommended Posts

Description of the bug?

The credit for the The Loremaster achievement is not given, even when the quest count is OK

For example: Loremaster of Eastern Kingdoms http://www.wowhead.com/?achievement=1676

For which repository revision was the patch created?


Is there a thread in the bug report section or at lighthouse?

None I know

Who has been writing this patch?


I tried to fix this some time ago but didn't find the correct flag to test. I've seen the new flag ACHIEVEMENT_FLAG_SUMM in a late patch and this is exactly what I was searching for. For the achievements having this flag (which is the case for the Loremaster achievement), the achievement is completed when the sum of the progress of the criteria meet the count (and not the count of completed criteria as usual).

For example, the Loremaster of Eastern Kingdomw has 59 criteria (for the 59 sub-zones), each criteria quest count being 700, it is impossible to complete 700 quests in all sub-zones.

This patch implements the support of the achievements having this flag.

BTW, the UpdateAchievementCriteria for the ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE is called at quest reward to update the criteria directly and not only at login.

diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp
index 36006c8..c338188 100644
--- a/src/game/AchievementMgr.cpp
+++ b/src/game/AchievementMgr.cpp
@@ -600,6 +600,10 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
+                // speedup for non-login case
+                if(miscvalue1 && miscvalue1 != achievementCriteria->complete_quests_in_zone.zoneID)
+                    continue;
                uint32 counter =0;
                for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++)
@@ -1019,6 +1023,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui

+        // check again the completeness for SUMM achievements, 
+        // as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
+        if (achievement->flags & ACHIEVEMENT_FLAG_SUMM)
+        {
+            if (IsCompletedAchievement(achievement))
+                CompletedAchievement(achievement);
+        }

        if(AchievementEntryList const* achRefList = achievementmgr.GetAchievementByReferencedId(achievement->ID))
@@ -1167,6 +1178,10 @@ void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria,
// TODO: achievement 705 requires 4 criteria to be fulfilled
bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
+    // counter can never complete
+    if(entry->flags & ACHIEVEMENT_FLAG_COUNTER)
+        return false;
    // for achievement with referenced achievement criterias get from referenced and counter from self
    uint32 achievmentForTestId = entry->refAchievement ? entry->refAchievement : entry->ID;
    uint32 achievmentForTestCount = entry->count;
@@ -1178,6 +1193,30 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
    uint32 count = 0;
    bool completed_all = true;

+    // For SUMM achievements, we have to count the progress of each criteria of the achievement.
+    // Oddly, the target count is NOT countained in the achievement, but in each individual criteria
+    if (entry->flags & ACHIEVEMENT_FLAG_SUMM)
+    {
+        for(AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
+        {
+            AchievementCriteriaEntry const* criteria = *itr;
+            CriteriaProgressMap::const_iterator itrProgress = m_criteriaProgress.find(criteria->ID);
+            if(itrProgress == m_criteriaProgress.end())
+                continue;
+            CriteriaProgress const* progress = &itrProgress->second;
+            count += progress->counter;
+            // for counters, field4 contains the main count requirement
+            // TODO: add a function to do this properly depending on the type
+            if (count >= criteria->raw.field4)
+                return true;
+        }
+        return false;
+    }
    for(AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr)
        AchievementCriteriaEntry const* criteria = *itr;
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index c6c6cce..4237add 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -12471,6 +12471,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
        SendQuestReward( pQuest, XP, questGiver );

    if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED;
+    if (pQuest->GetZoneOrSort() > 0)
+        GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, pQuest->GetZoneOrSort());

Link to comment
Share on other sites

The patch got errors.

../../../src/game/AchievementMgr.cpp: In member function bool AchievementMgr::IsCompletedAchievement(const AchievementEntry*):
../../../src/game/AchievementMgr.cpp:1224: error: achievement was not declared in this scope
../../../src/game/AchievementMgr.cpp:1225: error: return-statement with no value, in function returning int

Link to comment
Share on other sites

  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use