diff options
author | Xinef <none@empty.com> | 2017-01-21 18:40:35 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-01-21 18:40:35 +0100 |
commit | 9b44ed9cda347bfda1078666b3779d985fc37b2b (patch) | |
tree | 69e10c7042fcd6fc42029f3837748d9a4c3d73e0 /src | |
parent | 7c0234d10cc4ce7c629fdfdebc6a03f528cd7068 (diff) |
Core/Achievements: Greatly optimize achievement system by splitting large types by miscvalue
Closes #18633
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Achievements/AchievementMgr.cpp | 105 | ||||
-rw-r--r-- | src/server/game/Achievements/AchievementMgr.h | 11 | ||||
-rw-r--r-- | src/server/game/Battlegrounds/Battleground.cpp | 4 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 6 |
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()); } } |