mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 05:36:23 +00:00
Core: fixed realm first achievement
Porting of @shauren fix:
c75fcbe20b
This commit is contained in:
@@ -2163,9 +2163,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
|
||||
}
|
||||
}
|
||||
|
||||
// don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement
|
||||
// TODO: where do set this instead?
|
||||
if (!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
|
||||
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
|
||||
sAchievementMgr->SetRealmCompleted(achievement);
|
||||
|
||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, achievement->ID);
|
||||
@@ -2307,6 +2305,35 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AchievementGlobalMgr::IsRealmCompleted(AchievementEntry const* achievement) const
|
||||
{
|
||||
auto itr = m_allCompletedAchievements.find(achievement->ID);
|
||||
if (itr == m_allCompletedAchievements.end())
|
||||
return false;
|
||||
|
||||
if (itr->second == std::chrono::system_clock::time_point::min())
|
||||
return false;
|
||||
|
||||
if (itr->second == std::chrono::system_clock::time_point::max())
|
||||
return true;
|
||||
|
||||
// Allow completing the realm first kill for entire minute after first person did it
|
||||
// it may allow more than one group to achieve it (highly unlikely)
|
||||
// but apparently this is how blizz handles it as well
|
||||
if (achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL)
|
||||
return (std::chrono::system_clock::now() - itr->second) > std::chrono::minutes(1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AchievementGlobalMgr::SetRealmCompleted(AchievementEntry const* achievement)
|
||||
{
|
||||
if (IsRealmCompleted(achievement))
|
||||
return;
|
||||
|
||||
m_allCompletedAchievements[achievement->ID] = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
void AchievementGlobalMgr::LoadAchievementCriteriaList()
|
||||
{
|
||||
@@ -2628,6 +2655,14 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
|
||||
|
||||
QueryResult result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
|
||||
|
||||
// Populate _allCompletedAchievements with all realm first achievement ids to make multithreaded access safer
|
||||
// while it will not prevent races, it will prevent crashes that happen because std::unordered_map key was added
|
||||
// instead the only potential race will happen on value associated with the key
|
||||
for (uint32 i = 0; i < sAchievementStore.GetNumRows(); ++i)
|
||||
if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(i))
|
||||
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
|
||||
m_allCompletedAchievements[achievement->ID] = std::chrono::system_clock::time_point::min();
|
||||
|
||||
if (!result)
|
||||
{
|
||||
sLog->outString(">> Loaded 0 completed achievements. DB table `character_achievement` is empty.");
|
||||
@@ -2655,7 +2690,7 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
|
||||
continue;
|
||||
}
|
||||
else if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
|
||||
m_allCompletedAchievements.insert(achievementId);
|
||||
m_allCompletedAchievements[achievementId] = std::chrono::system_clock::time_point::max();
|
||||
} while (result->NextRow());
|
||||
|
||||
sLog->outString(">> Loaded %lu completed achievements in %u ms", (unsigned long)m_allCompletedAchievements.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||
|
||||
Reference in New Issue
Block a user