diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 1d3a0e150..fcdc5fd97 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -577,11 +577,11 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri progress.changed = false; progress.timedCriteriaFailed = false; + AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); + // A failed achievement will be removed on next tick - TODO: Possible that timer 2 is reseted if (criteria->timeLimit) { - AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); - // Add not-completed achievements to time map if (!IsCompletedCriteria(criteria, achievement)) { @@ -594,7 +594,7 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri } // check intergiry with max allowed counter value - if (uint32 maxcounter = GetCriteriaProgressMaxCounter(criteria)) + if (uint32 maxcounter = GetCriteriaProgressMaxCounter(criteria, achievement)) { if (progress.counter > maxcounter) { @@ -1699,98 +1699,141 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui } } -uint32 AchievementMgr::GetCriteriaProgressMaxCounter(AchievementCriteriaEntry const* achievementCriteria) +uint32 AchievementMgr::GetCriteriaProgressMaxCounter(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement) { - switch(achievementCriteria->requiredType) + uint32 resultValue = 0; + switch (achievementCriteria->requiredType) { case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: - return achievementCriteria->win_bg.winCount; + resultValue = achievementCriteria->win_bg.winCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: - return achievementCriteria->kill_creature.creatureCount; + resultValue = achievementCriteria->kill_creature.creatureCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: - return achievementCriteria->reach_level.level; + resultValue = achievementCriteria->reach_level.level; + break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: - return achievementCriteria->reach_skill_level.skillLevel; + resultValue = achievementCriteria->reach_skill_level.skillLevel; + break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: - return 1; + resultValue = 1; + break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: - return achievementCriteria->complete_quest_count.totalQuestCount; + resultValue = achievementCriteria->complete_quest_count.totalQuestCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: - return achievementCriteria->complete_quests_in_zone.questCount; + resultValue = achievementCriteria->complete_quests_in_zone.questCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE: case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE: - return achievementCriteria->healing_done.count; + resultValue = achievementCriteria->healing_done.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: - return achievementCriteria->complete_daily_quest.questCount; + resultValue = achievementCriteria->complete_daily_quest.questCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: - return achievementCriteria->fall_without_dying.fallHeight; + resultValue = achievementCriteria->fall_without_dying.fallHeight; + break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: - return 1; + resultValue = 1; + break; case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: - return achievementCriteria->be_spell_target.spellCount; + resultValue = achievementCriteria->be_spell_target.spellCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: - return achievementCriteria->cast_spell.castCount; + resultValue = achievementCriteria->cast_spell.castCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: - return 1; + resultValue = 1; + break; case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: - return achievementCriteria->own_item.itemCount; + resultValue = achievementCriteria->own_item.itemCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA: - return achievementCriteria->win_rated_arena.count; + resultValue = achievementCriteria->win_rated_arena.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL: - return achievementCriteria->learn_skill_level.skillLevel * 75; + resultValue = achievementCriteria->learn_skill_level.skillLevel * 75; + break; case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: - return achievementCriteria->use_item.itemCount; + resultValue = achievementCriteria->use_item.itemCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: - return achievementCriteria->loot_item.itemCount; + resultValue = achievementCriteria->loot_item.itemCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: - return 1; + resultValue = 1; + break; case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: - return achievementCriteria->buy_bank_slot.numberOfSlots; + resultValue = achievementCriteria->buy_bank_slot.numberOfSlots; + break; case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: - return achievementCriteria->gain_reputation.reputationAmount; + resultValue = achievementCriteria->gain_reputation.reputationAmount; + break; case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: - return achievementCriteria->gain_exalted_reputation.numberOfExaltedFactions; + resultValue = achievementCriteria->gain_exalted_reputation.numberOfExaltedFactions; + break; case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: - return achievementCriteria->visit_barber.numberOfVisits; + resultValue = achievementCriteria->visit_barber.numberOfVisits; + break; case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: - return achievementCriteria->equip_epic_item.count; + resultValue = achievementCriteria->equip_epic_item.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: - return achievementCriteria->roll_greed_on_loot.count; + resultValue = achievementCriteria->roll_greed_on_loot.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS: - return achievementCriteria->hk_class.count; + resultValue = achievementCriteria->hk_class.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE: - return achievementCriteria->hk_race.count; + resultValue = achievementCriteria->hk_race.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: - return achievementCriteria->do_emote.count; + resultValue = achievementCriteria->do_emote.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM: - return achievementCriteria->equip_item.count; + resultValue = achievementCriteria->equip_item.count; + break; case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: - return achievementCriteria->quest_reward_money.goldInCopper; + resultValue = achievementCriteria->quest_reward_money.goldInCopper; + break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: - return achievementCriteria->loot_money.goldInCopper; + resultValue = achievementCriteria->loot_money.goldInCopper; + break; case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: - return achievementCriteria->use_gameobject.useCount; + resultValue = achievementCriteria->use_gameobject.useCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: - return achievementCriteria->special_pvp_kill.killCount; + resultValue = achievementCriteria->special_pvp_kill.killCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: - return achievementCriteria->fish_in_gameobject.lootCount; + resultValue = achievementCriteria->fish_in_gameobject.lootCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN: - return 1; + resultValue = 1; + break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: - return achievementCriteria->learn_skillline_spell.spellCount; + resultValue = achievementCriteria->learn_skillline_spell.spellCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL: - return achievementCriteria->win_duel.duelCount; + resultValue = achievementCriteria->win_duel.duelCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: - return achievementCriteria->loot_type.lootTypeCount; + resultValue = achievementCriteria->loot_type.lootTypeCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE: - return achievementCriteria->learn_skill_line.spellCount; + resultValue = achievementCriteria->learn_skill_line.spellCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL: - return achievementCriteria->honorable_kill.killCount; + resultValue = achievementCriteria->honorable_kill.killCount; + break; case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING: - return achievementCriteria->highest_personal_rating.teamrating; + resultValue = achievementCriteria->highest_personal_rating.teamrating; + break; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: @@ -1825,44 +1868,44 @@ uint32 AchievementMgr::GetCriteriaProgressMaxCounter(AchievementCriteriaEntry co case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED: case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN: case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS: - return 0; + resultValue = 0; + break; } - return 0; + if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + resultValue = std::numeric_limits::max(); + + return resultValue; } bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement) const { // counter can never complete - if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER) return false; - if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) + if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) { // someone on this realm has already completed that achievement - if(sAchievementMgr.IsRealmCompleted(achievement)) + if (sAchievementMgr.IsRealmCompleted(achievement)) return false; } CriteriaProgressMap::const_iterator itr = m_criteriaProgress.find(achievementCriteria->ID); - if(itr == m_criteriaProgress.end()) + if (itr == m_criteriaProgress.end()) return false; CriteriaProgress const* progress = &itr->second; - uint32 maxcounter = GetCriteriaProgressMaxCounter(achievementCriteria); + uint32 maxcounter = GetCriteriaProgressMaxCounter(achievementCriteria, achievement); - // different counters or non-completable criteria - if (!maxcounter) - return false; - - return progress->counter >= maxcounter; + return progress->counter >= maxcounter || (achievement->flags & ACHIEVEMENT_FLAG_REQ_COUNT && progress->counter); } void AchievementMgr::CompletedCriteriaFor(AchievementEntry const* achievement) { // counter can never complete - if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER) return; // already completed and stored @@ -1876,7 +1919,7 @@ void AchievementMgr::CompletedCriteriaFor(AchievementEntry const* achievement) bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry) { // counter can never complete - if(entry->flags & ACHIEVEMENT_FLAG_COUNTER) + if (entry->flags & ACHIEVEMENT_FLAG_COUNTER) return false; // for achievement with referenced achievement criterias get from referenced and counter from self @@ -1884,7 +1927,7 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry) uint32 achievementForTestCount = entry->count; AchievementCriteriaEntryList const* cList = sAchievementMgr.GetAchievementCriteriaByAchievement(achievementForTestId); - if(!cList) + if (!cList) return false; uint32 count = 0; @@ -1892,7 +1935,7 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry) // 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) + for (AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr) { AchievementCriteriaEntry const* criteria = *itr; @@ -1912,25 +1955,25 @@ bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry) // Default case - need complete all or bool completed_all = true; - for(AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr) + for (AchievementCriteriaEntryList::const_iterator itr = cList->begin(); itr != cList->end(); ++itr) { AchievementCriteriaEntry const* criteria = *itr; - bool completed = IsCompletedCriteria(criteria,entry); + bool completed = IsCompletedCriteria(criteria, entry); // found an uncompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL - if(completed) + if (completed) ++count; else completed_all = false; // completed as have req. count of completed criterias - if(achievementForTestCount > 0 && achievementForTestCount <= count) + if (achievementForTestCount > 0 && achievementForTestCount <= count) return true; } // all criterias completed requirement - if(completed_all && achievementForTestCount==0) + if (completed_all && achievementForTestCount == 0) return true; return false; @@ -1940,10 +1983,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri { DETAIL_FILTER_LOG(LOG_FILTER_ACHIEVEMENT_UPDATES, "AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", criteria->ID, changeValue, m_player->GetGUIDLow()); - uint32 max_value = GetCriteriaProgressMaxCounter(criteria); - - if (!max_value) - max_value = std::numeric_limits::max(); + uint32 max_value = GetCriteriaProgressMaxCounter(criteria, achievement); // change value must be in allowed value range for SET/HIGHEST directly if (changeValue > max_value) @@ -1954,10 +1994,10 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri uint32 newValue = 0; CriteriaProgressMap::iterator iter = m_criteriaProgress.find(criteria->ID); - if(iter == m_criteriaProgress.end()) + if (iter == m_criteriaProgress.end()) { // not create record for 0 counter - if(changeValue == 0) + if (changeValue == 0) return; // not start manually started timed achievements @@ -2001,7 +2041,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri } // not update (not mark as changed) if counter will have same value - if(progress->counter == newValue) + if (progress->counter == newValue) return; } @@ -2009,16 +2049,12 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri progress->changed = true; // update client side value - SendCriteriaUpdate(criteria->ID,progress); - - // nothing do for counter case - if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER) - return; + SendCriteriaUpdate(criteria->ID, progress); // update dependent achievements state at criteria complete if (old_value < progress->counter) { - if(IsCompletedCriteria(criteria, achievement)) + if (IsCompletedCriteria(criteria, achievement)) CompletedCriteriaFor(achievement); // check again the completeness for SUMM and REQ COUNT achievements, @@ -2029,10 +2065,10 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri CompletedAchievement(achievement); } - if(AchievementEntryList const* achRefList = sAchievementMgr.GetAchievementByReferencedId(achievement->ID)) + if (AchievementEntryList const* achRefList = sAchievementMgr.GetAchievementByReferencedId(achievement->ID)) { - for(AchievementEntryList::const_iterator itr = achRefList->begin(); itr != achRefList->end(); ++itr) - if(IsCompletedAchievement(*itr)) + for (AchievementEntryList::const_iterator itr = achRefList->begin(); itr != achRefList->end(); ++itr) + if (IsCompletedAchievement(*itr)) CompletedAchievement(*itr); } } @@ -2047,13 +2083,13 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* criteri } if (HasAchievement(achievement->ID)) - if(!IsCompletedAchievement(achievement)) + if (!IsCompletedAchievement(achievement)) IncompletedAchievement(achievement); - if(AchievementEntryList const* achRefList = sAchievementMgr.GetAchievementByReferencedId(achievement->ID)) - for(AchievementEntryList::const_iterator itr = achRefList->begin(); itr != achRefList->end(); ++itr) + if (AchievementEntryList const* achRefList = sAchievementMgr.GetAchievementByReferencedId(achievement->ID)) + for (AchievementEntryList::const_iterator itr = achRefList->begin(); itr != achRefList->end(); ++itr) if (HasAchievement((*itr)->ID)) - if(!IsCompletedAchievement(*itr)) + if (!IsCompletedAchievement(*itr)) IncompletedAchievement(*itr); } } diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index f6ff44831..f18a0ade9 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -287,7 +287,7 @@ class AchievementMgr return iter != m_criteriaProgress.end() ? iter->second.counter : 0; } - static uint32 GetCriteriaProgressMaxCounter(AchievementCriteriaEntry const* entry); + static uint32 GetCriteriaProgressMaxCounter(AchievementCriteriaEntry const* entry, AchievementEntry const* achievement); // Use PROGRESS_SET only for reset/downgrade criteria progress enum ProgressType { PROGRESS_SET, PROGRESS_ACCUMULATE, PROGRESS_HIGHEST }; diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 211709aa9..0d225f396 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1243,7 +1243,7 @@ void ChatHandler::ShowAchievementCriteriaListHelper(AchievementCriteriaEntry con ss << GetMangosString(LANG_COUNTER); else { - ss << " [" << AchievementMgr::GetCriteriaProgressMaxCounter(criEntry) << "]"; + ss << " [" << AchievementMgr::GetCriteriaProgressMaxCounter(criEntry, achEntry) << "]"; if (target && target->GetAchievementMgr().IsCompletedCriteria(criEntry, achEntry)) ss << GetMangosString(LANG_COMPLETE); @@ -1323,7 +1323,9 @@ bool ChatHandler::HandleAchievementAddCommand(char* args) if (mgr.IsCompletedCriteria(*itr, achEntry)) continue; - uint32 maxValue = AchievementMgr::GetCriteriaProgressMaxCounter(*itr); + uint32 maxValue = AchievementMgr::GetCriteriaProgressMaxCounter(*itr, achEntry); + if (maxValue == std::numeric_limits::max()) + maxValue = 1; // Exception for counter like achievements, set them only to 1 mgr.SetCriteriaProgress(*itr, achEntry, maxValue, AchievementMgr::PROGRESS_SET); } } @@ -1398,7 +1400,9 @@ bool ChatHandler::HandleAchievementCriteriaAddCommand(char* args) LocaleConstant loc = GetSessionDbcLocale(); - uint32 maxValue = AchievementMgr::GetCriteriaProgressMaxCounter(criEntry); + uint32 maxValue = AchievementMgr::GetCriteriaProgressMaxCounter(criEntry, achEntry); + if (maxValue == std::numeric_limits::max()) + maxValue = 1; // Exception for counter like achievements, set them only to 1 AchievementMgr& mgr = target->GetAchievementMgr(); @@ -1463,7 +1467,9 @@ bool ChatHandler::HandleAchievementCriteriaRemoveCommand(char* args) LocaleConstant loc = GetSessionDbcLocale(); - uint32 maxValue = AchievementMgr::GetCriteriaProgressMaxCounter(criEntry); + uint32 maxValue = AchievementMgr::GetCriteriaProgressMaxCounter(criEntry, achEntry); + if (maxValue == std::numeric_limits::max()) + maxValue = 1; // Exception for counter like achievements, set them only to 1 AchievementMgr& mgr = target->GetAchievementMgr(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 586387060..ffb4985f5 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11944" + #define REVISION_NR "11945" #endif // __REVISION_NR_H__