Core/Achievements: Greatly optimize achievement system by splitting large types by miscvalue

Closes #18633
This commit is contained in:
Xinef
2017-01-21 18:40:35 +01:00
committed by Shauren
parent 7c0234d10c
commit 9b44ed9cda
5 changed files with 107 additions and 21 deletions
+95 -10
View File
@@ -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;
}
@@ -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
@@ -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)
+1 -1
View File
@@ -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
{
+3 -3
View File
@@ -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());
}
}