aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinef <none@empty.com>2017-01-21 18:40:35 +0100
committerShauren <shauren.trinity@gmail.com>2017-01-21 18:40:35 +0100
commit9b44ed9cda347bfda1078666b3779d985fc37b2b (patch)
tree69e10c7042fcd6fc42029f3837748d9a4c3d73e0
parent7c0234d10cc4ce7c629fdfdebc6a03f528cd7068 (diff)
Core/Achievements: Greatly optimize achievement system by splitting large types by miscvalue
Closes #18633
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp105
-rw-r--r--src/server/game/Achievements/AchievementMgr.h11
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp4
-rw-r--r--src/server/game/DataStores/DBCEnums.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp6
5 files changed, 107 insertions, 21 deletions
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index a377f83201f..39b09ecf29d 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -482,7 +482,7 @@ void AchievementMgr::ResetAchievementCriteria(AchievementCriteriaTypes type, uin
if (m_player->IsGameMaster())
return;
- AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type);
+ AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type, 0/*get all*/);
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
AchievementCriteriaEntry const* achievementCriteria = (*i);
@@ -741,7 +741,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: %s, %s (%u), %u, %u"
, m_player->GetGUID().ToString().c_str(), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2);
- AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type);
+ AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type, miscValue1);
for (AchievementCriteriaEntry const* achievementCriteria : achievementCriteriaList)
{
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->ReferredAchievement);
@@ -768,7 +768,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
switch (type)
{
// std. case: increment at 1
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
@@ -808,9 +810,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
// std case: increment at miscvalue1
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
@@ -864,7 +864,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, maxSkillvalue);
break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
- if (m_completedAchievements.find(achievementCriteria->Asset.AchievementID) != m_completedAchievements.end())
+ if ((miscValue1 && achievementCriteria->Asset.AchievementID == miscValue1) || (!miscValue1 && m_completedAchievements.find(achievementCriteria->Asset.AchievementID) != m_completedAchievements.end()))
SetCriteriaProgress(achievementCriteria, 1);
break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
@@ -1492,7 +1492,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
sAchievementMgr->SetRealmCompleted(achievement, GetPlayer()->GetInstanceId());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, achievement->ID);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->Points);
// reward items and titles if any
@@ -1879,11 +1879,11 @@ bool AchievementMgr::RequirementsSatisfied(AchievementCriteriaEntry const* achie
return false;
break;
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- // miscvalue1 = itemid
- // miscvalue2 = itemSlot
- if (!miscValue1)
+ // miscvalue1 = itemSlot
+ // miscvalue2 = itemid
+ if (!miscValue2)
return false;
- if (miscValue2 != achievementCriteria->Asset.ItemSlot)
+ if (miscValue1 != achievementCriteria->Asset.ItemSlot)
return false;
break;
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
@@ -2187,6 +2187,60 @@ AchievementGlobalMgr* AchievementGlobalMgr::instance()
return &instance;
}
+inline bool IsAchievementCriteriaTypeStoredByMiscValue(AchievementCriteriaTypes type)
+{
+ switch (type)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+AchievementCriteriaEntryList const& AchievementGlobalMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type, uint32 miscValue) const
+{
+ if (miscValue && IsAchievementCriteriaTypeStoredByMiscValue(type))
+ {
+ auto itr = m_AchievementCriteriasByMiscValue[type].find(miscValue);
+ if (itr != m_AchievementCriteriasByMiscValue[type].end())
+ return itr->second;
+ }
+
+ return m_AchievementCriteriasByType[type];
+}
+
//==========================================================
void AchievementGlobalMgr::LoadAchievementCriteriaList()
{
@@ -2205,11 +2259,42 @@ void AchievementGlobalMgr::LoadAchievementCriteriaList()
if (!criteria)
continue;
+ ASSERT(criteria->Type < ACHIEVEMENT_CRITERIA_TYPE_TOTAL, "ACHIEVEMENT_CRITERIA_TYPE_TOTAL must be greater than or equal to %u but is currently equal to %u",
+ criteria->Type + 1, ACHIEVEMENT_CRITERIA_TYPE_TOTAL);
+
m_AchievementCriteriasByType[criteria->Type].push_back(criteria);
m_AchievementCriteriaListByAchievement[criteria->ReferredAchievement].push_back(criteria);
+ if (IsAchievementCriteriaTypeStoredByMiscValue(AchievementCriteriaTypes(criteria->Type)))
+ {
+ if (criteria->Type != ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA)
+ m_AchievementCriteriasByMiscValue[criteria->Type][criteria->Asset.ID].push_back(criteria);
+ else
+ {
+ WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(criteria->Asset.WorldMapOverlayID);
+ if (!worldOverlayEntry)
+ break;
+
+ for (uint8 j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
+ {
+ if (worldOverlayEntry->areatableID[j])
+ {
+ bool valid = true;
+ for (uint8 i = 0; i < j; ++i)
+ if (worldOverlayEntry->areatableID[j] == worldOverlayEntry->areatableID[i])
+ valid = false;
+ if (valid)
+ m_AchievementCriteriasByMiscValue[criteria->Type][worldOverlayEntry->areatableID[j]].push_back(criteria);
+ }
+ }
+ }
+ }
if (criteria->StartTimer)
+ {
+ ASSERT(criteria->StartEvent < ACHIEVEMENT_TIMED_TYPE_MAX, "ACHIEVEMENT_TIMED_TYPE_MAX must be greater than or equal to %u but is currently equal to %u",
+ criteria->StartEvent + 1, ACHIEVEMENT_TIMED_TYPE_MAX);
m_AchievementCriteriasByTimedType[criteria->StartEvent].push_back(criteria);
+ }
++loaded;
}
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index 00e53a54789..e39c8e03b73 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -36,6 +36,7 @@ typedef std::vector<AchievementCriteriaEntry const*> AchievementCriteriaEntryLis
typedef std::vector<AchievementEntry const*> AchievementEntryList;
typedef std::unordered_map<uint32, AchievementCriteriaEntryList> AchievementCriteriaListByAchievement;
+typedef std::unordered_map<uint32, AchievementCriteriaEntryList> AchievementCriteriaListByMiscValue;
typedef std::unordered_map<uint32, AchievementEntryList> AchievementListByReferencedId;
struct CriteriaProgress
@@ -231,7 +232,7 @@ struct TC_GAME_API AchievementCriteriaDataSet
Storage storage;
};
-typedef std::map<uint32, AchievementCriteriaDataSet> AchievementCriteriaDataMap;
+typedef std::unordered_map<uint32, AchievementCriteriaDataSet> AchievementCriteriaDataMap;
struct AchievementReward
{
@@ -324,10 +325,7 @@ class TC_GAME_API AchievementGlobalMgr
static AchievementGlobalMgr* instance();
- AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type) const
- {
- return m_AchievementCriteriasByType[type];
- }
+ AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type, uint32 miscValue) const;
AchievementCriteriaEntryList const& GetTimedAchievementCriteriaByType(AchievementCriteriaTimedTypes type) const
{
@@ -401,6 +399,9 @@ class TC_GAME_API AchievementGlobalMgr
// store achievement criterias by type to speed up lookup
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
+ // store achievement criterias split by misc values
+ AchievementCriteriaListByMiscValue m_AchievementCriteriasByMiscValue[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
+
AchievementCriteriaEntryList m_AchievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
// store achievement criterias by achievement to speed up lookup
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 9e7c263d746..af4f177d5fb 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -823,7 +823,7 @@ void Battleground::EndBattleground(uint32 winner)
player->SetRandomWinner(true);
}
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, player->GetMapId());
}
else
{
@@ -841,7 +841,7 @@ void Battleground::EndBattleground(uint32 winner)
WorldPacket data;
sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, this, player->GetBattlegroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime(), GetArenaType(), player->GetBGTeam());
player->SendDirectMessage(&data);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
+ player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, player->GetMapId());
}
if (winmsg_id)
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 20fa6f7d7f1..3f4a2190857 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -231,7 +231,7 @@ enum AchievementCriteriaTypes
ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
};
-#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 120
+#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 124
enum AchievementCategory
{
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 30fd605e58d..44864eaa9a1 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -6512,7 +6512,7 @@ void Player::CheckAreaExploreAndOutdoor()
{
SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val));
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA, GetAreaId());
if (areaEntry->area_level > 0)
{
@@ -12108,7 +12108,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
// only for full equip instead adding to stack
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, slot, pItem->GetEntry());
return pItem;
}
@@ -12133,7 +12133,7 @@ void Player::QuickEquipItem(uint16 pos, Item* pItem)
CheckTitanGripPenalty();
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot);
+ UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, slot, pItem->GetEntry());
}
}