Achievement stuff in ObjectMgr grouped an tweaked

* we have an AchievementMgr, why does the ObjectMgr do stuff for it? Move it as soo as possible.
This commit is contained in:
Zyres
2023-07-21 22:36:52 +02:00
parent 7004ca570a
commit 95996c5885
6 changed files with 219 additions and 206 deletions

View File

@@ -619,7 +619,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, in
{
selectedGUID = GetPlayer()->getTargetGuid();
}
AchievementCriteriaEntryList const & achievementCriteriaList = sObjectMgr.GetAchievementCriteriaByType(type);
AchievementCriteriaEntryList const & achievementCriteriaList = sObjectMgr.getAchievementCriteriaByType(type);
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
DBC::Structures::AchievementCriteriaEntry const* achievementCriteria = (*i);
@@ -1212,7 +1212,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type)
if (m_player->getSession()->HasGMPermissions() && worldConfig.gm.disableAchievements)
return;
AchievementCriteriaEntryList const & achievementCriteriaList = sObjectMgr.GetAchievementCriteriaByType(type);
AchievementCriteriaEntryList const & achievementCriteriaList = sObjectMgr.getAchievementCriteriaByType(type);
for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
{
DBC::Structures::AchievementCriteriaEntry const* achievementCriteria = (*i);
@@ -1364,7 +1364,7 @@ bool AchievementMgr::IsCompletedCriteria(DBC::Structures::AchievementCriteriaEnt
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
{
if (sObjectMgr.allCompletedAchievements.find(achievement->ID) != sObjectMgr.allCompletedAchievements.end())
if (sObjectMgr.getAllCompleteAchievements().find(achievement->ID) != sObjectMgr.getAllCompleteAchievements().end())
{
return false;
}
@@ -1621,7 +1621,7 @@ void AchievementMgr::CompletedAchievement(DBC::Structures::AchievementEntry cons
}
m_completedAchievements[achievement->ID] = time(nullptr);
sObjectMgr.allCompletedAchievements.insert(achievement->ID);
sObjectMgr.addCompletedAchievement(achievement->ID);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT);
// check for reward
@@ -1976,7 +1976,7 @@ void AchievementMgr::GiveAchievementReward(DBC::Structures::AchievementEntry con
{
return;
}
AchievementReward const * Reward = sObjectMgr.GetAchievementReward(entry->ID, GetPlayer()->getGender());
AchievementReward const * Reward = sObjectMgr.getAchievementReward(entry->ID, GetPlayer()->getGender());
if (!Reward)
return;

View File

@@ -66,7 +66,7 @@ struct CriteriaProgress
struct AchievementReward
{
uint32_t gender;
uint8_t gender;
uint32_t titel_A;
uint32_t titel_H;
uint32_t itemId;
@@ -80,6 +80,7 @@ typedef std::unordered_map<uint32_t, time_t> CompletedAchievementMap;
typedef std::multimap<uint32_t, AchievementReward> AchievementRewardsMap;
typedef std::pair<AchievementRewardsMap::const_iterator, AchievementRewardsMap::const_iterator> AchievementRewardsMapBounds;
typedef std::set<uint32_t> AchievementSet;
typedef std::list<DBC::Structures::AchievementCriteriaEntry const*> AchievementCriteriaEntryList;
class Player;
class WorldPacket;

View File

@@ -679,6 +679,187 @@ void ObjectMgr::delinkCorpseForPlayer(const Player* _player)
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// Achievement
#if VERSION_STRING > TBC
void ObjectMgr::loadAchievementCriteriaList()
{
for (uint32 rowId = 0; rowId < sAchievementCriteriaStore.GetNumRows(); ++rowId)
{
auto criteria = sAchievementCriteriaStore.LookupEntry(rowId);
if (!criteria)
continue;
#if VERSION_STRING > WotLK
auto achievement = sAchievementStore.LookupEntry(criteria->referredAchievement);
if (achievement && achievement->flags & ACHIEVEMENT_FLAG_GUILD)
m_GuildAchievementCriteriasByType[criteria->requiredType].push_back(criteria);
else
#endif
m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
}
}
void ObjectMgr::loadAchievementRewards()
{
m_achievementRewards.clear();
QueryResult* result = WorldDatabase.Query("SELECT entry, gender, title_A, title_H, item, sender, subject, text FROM achievement_reward");
if (!result)
{
sLogger.info("Loaded 0 achievement rewards. DB table `achievement_reward` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
if (!sAchievementStore.LookupEntry(entry))
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : Achievement reward entry %u has wrong achievement, ignore", entry);
continue;
}
AchievementReward reward;
reward.gender = fields[1].GetUInt8();
reward.titel_A = fields[2].GetUInt32();
reward.titel_H = fields[3].GetUInt32();
reward.itemId = fields[4].GetUInt32();
reward.sender = fields[5].GetUInt32();
reward.subject = fields[6].GetString() ? fields[6].GetString() : "";
reward.text = fields[7].GetString() ? fields[7].GetString() : "";
if (reward.gender > 2)
sLogger.debug("ObjectMgr : achievement reward %u has wrong gender %u.", entry, static_cast<uint32_t>(reward.gender));
bool dup = false;
AchievementRewardsMapBounds bounds = m_achievementRewards.equal_range(entry);
for (AchievementRewardsMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
{
if (iter->second.gender == 2 || reward.gender == 2)
{
dup = true;
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : Achievement reward %u must have single GENDER_NONE (%u), ignore duplicate case", 2, entry);
break;
}
}
if (dup)
continue;
// must be title or mail at least
if (!reward.titel_A && !reward.titel_H && !reward.sender)
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u not have title or item reward data, ignore.", entry);
continue;
}
if (reward.titel_A)
{
auto const* char_title_entry = sCharTitlesStore.LookupEntry(reward.titel_A);
if (!char_title_entry)
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u has invalid title id (%u) in `title_A`, set to 0", entry, reward.titel_A);
reward.titel_A = 0;
}
}
if (reward.titel_H)
{
auto const* char_title_entry = sCharTitlesStore.LookupEntry(reward.titel_H);
if (!char_title_entry)
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u has invalid title id (%u) in `title_A`, set to 0", entry, reward.titel_H);
reward.titel_H = 0;
}
}
//check mail data before item for report including wrong item case
if (reward.sender)
{
if (!sMySQLStore.getCreatureProperties(reward.sender))
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u has invalid creature entry %u as sender, mail reward skipped.", entry, reward.sender);
reward.sender = 0;
}
}
else
{
if (reward.itemId)
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u not have sender data but have item reward, item will not rewarded", entry);
if (!reward.subject.empty())
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u not have sender data but have mail subject.", entry);
if (!reward.text.empty())
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u not have sender data but have mail text.", entry);
}
if (reward.itemId == 0)
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u has invalid item id %u, reward mail will be without item.", entry, reward.itemId);
}
m_achievementRewards.insert(AchievementRewardsMap::value_type(entry, reward));
++count;
} while (result->NextRow());
delete result;
sLogger.info("ObjectMgr : Loaded %u achievement rewards", count);
}
void ObjectMgr::loadCompletedAchievements()
{
QueryResult* result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
if (!result)
{
sLogger.failure("Query failed: SELECT achievement FROM character_achievement");
return;
}
do
{
Field* fields = result->Fetch();
m_allCompletedAchievements.insert(fields[0].GetUInt32());
} while (result->NextRow());
delete result;
}
AchievementReward const* ObjectMgr::getAchievementReward(uint32_t entry, uint8_t gender)
{
AchievementRewardsMapBounds bounds = m_achievementRewards.equal_range(entry);
for (AchievementRewardsMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
{
if (iter->second.gender == 2 || iter->second.gender == gender)
return &iter->second;
}
return nullptr;
}
AchievementCriteriaEntryList const& ObjectMgr::getAchievementCriteriaByType(AchievementCriteriaTypes type)
{
return m_AchievementCriteriasByType[type];
}
void ObjectMgr::addCompletedAchievement(uint32_t _achievementId)
{
m_allCompletedAchievements.insert(_achievementId);
}
std::set<uint32_t> ObjectMgr::getAllCompleteAchievements()
{
return m_allCompletedAchievements;
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// Misc
void ObjectMgr::generateDatabaseGossipMenu(Object* object, uint32_t gossipMenuId, Player* player, uint32_t forcedTextId /*= 0*/)
@@ -1201,145 +1382,6 @@ Group* ObjectMgr::GetGroupById(uint32 id)
return nullptr;
}
#if VERSION_STRING > TBC
void ObjectMgr::LoadCompletedAchievements()
{
QueryResult* result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
if (!result)
{
sLogger.failure("Query failed: SELECT achievement FROM character_achievement");
return;
}
do
{
Field* fields = result->Fetch();
allCompletedAchievements.insert(fields[0].GetUInt32());
}
while (result->NextRow());
delete result;
}
#endif
#if VERSION_STRING > TBC
void ObjectMgr::LoadAchievementRewards()
{
AchievementRewards.clear(); // need for reload case
QueryResult* result = WorldDatabase.Query("SELECT entry, gender, title_A, title_H, item, sender, subject, text FROM achievement_reward");
if (!result)
{
sLogger.info("Loaded 0 achievement rewards. DB table `achievement_reward` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
if (!sAchievementStore.LookupEntry(entry))
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : Achievement reward entry %u has wrong achievement, ignore", entry);
continue;
}
AchievementReward reward;
reward.gender = fields[1].GetUInt32();
reward.titel_A = fields[2].GetUInt32();
reward.titel_H = fields[3].GetUInt32();
reward.itemId = fields[4].GetUInt32();
reward.sender = fields[5].GetUInt32();
reward.subject = fields[6].GetString() ? fields[6].GetString() : "";
reward.text = fields[7].GetString() ? fields[7].GetString() : "";
if (reward.gender > 2)
sLogger.debug("ObjectMgr : achievement reward %u has wrong gender %u.", entry, reward.gender);
bool dup = false;
AchievementRewardsMapBounds bounds = AchievementRewards.equal_range(entry);
for (AchievementRewardsMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
{
if (iter->second.gender == 2 || reward.gender == 2)
{
dup = true;
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : Achievement reward %u must have single GENDER_NONE (%u), ignore duplicate case", 2, entry);
break;
}
}
if (dup)
continue;
// must be title or mail at least
if (!reward.titel_A && !reward.titel_H && !reward.sender)
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u not have title or item reward data, ignore.", entry);
continue;
}
if (reward.titel_A)
{
auto const* char_title_entry = sCharTitlesStore.LookupEntry(reward.titel_A);
if (!char_title_entry)
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u has invalid title id (%u) in `title_A`, set to 0", entry, reward.titel_A);
reward.titel_A = 0;
}
}
if (reward.titel_H)
{
auto const* char_title_entry = sCharTitlesStore.LookupEntry(reward.titel_H);
if (!char_title_entry)
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u has invalid title id (%u) in `title_A`, set to 0", entry, reward.titel_H);
reward.titel_H = 0;
}
}
//check mail data before item for report including wrong item case
if (reward.sender)
{
if (!sMySQLStore.getCreatureProperties(reward.sender))
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u has invalid creature entry %u as sender, mail reward skipped.", entry, reward.sender);
reward.sender = 0;
}
}
else
{
if (reward.itemId)
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u not have sender data but have item reward, item will not rewarded", entry);
if (!reward.subject.empty())
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u not have sender data but have mail subject.", entry);
if (!reward.text.empty())
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u not have sender data but have mail text.", entry);
}
if (reward.itemId == 0)
{
sLogger.debugFlag(AscEmu::Logging::LF_DB_TABLES, "ObjectMgr : achievement_reward %u has invalid item id %u, reward mail will be without item.", entry, reward.itemId);
}
AchievementRewards.insert(AchievementRewardsMap::value_type(entry, reward));
++count;
}
while (result->NextRow());
delete result;
sLogger.info("ObjectMgr : Loaded %u achievement rewards", count);
}
#endif
void ObjectMgr::SetHighestGuids()
{
QueryResult* result = CharacterDatabase.Query("SELECT MAX(guid) FROM characters");
@@ -1661,31 +1703,6 @@ Item* ObjectMgr::LoadItem(uint32 lowguid)
return pReturn;
}
#if VERSION_STRING > TBC
AchievementCriteriaEntryList const & ObjectMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type)
{
return m_AchievementCriteriasByType[type];
}
void ObjectMgr::LoadAchievementCriteriaList()
{
for (uint32 rowId = 0; rowId < sAchievementCriteriaStore.GetNumRows(); ++rowId)
{
auto criteria = sAchievementCriteriaStore.LookupEntry(rowId);
if (!criteria)
continue;
#if VERSION_STRING > WotLK
auto achievement = sAchievementStore.LookupEntry(criteria->referredAchievement);
if (achievement && achievement->flags & ACHIEVEMENT_FLAG_GUILD)
m_GuildAchievementCriteriasByType[criteria->requiredType].push_back(criteria);
else
#endif
m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria);
}
}
#endif
Trainer* ObjectMgr::GetTrainer(uint32 Entry)
{
TrainerMap::iterator iter = mTrainers.find(Entry);

View File

@@ -190,10 +190,6 @@ struct InstanceReputationModifier
typedef std::unordered_map<uint32, Player*> PlayerStorageMap;
#if VERSION_STRING > TBC
typedef std::list<DBC::Structures::AchievementCriteriaEntry const*> AchievementCriteriaEntryList;
#endif
// finally we are here, the base class of this file ;)
//MIT
class SERVER_DECL ObjectMgr : public EventableObject
@@ -283,6 +279,33 @@ private:
std::unordered_map<uint32_t, std::shared_ptr<Corpse>> m_corpses;
std::mutex m_corpseLock;
//////////////////////////////////////////////////////////////////////////////////////////
// Achievement - todo: We have an AchievementMgr for that stuff... why here?
#if VERSION_STRING > TBC
public:
void loadAchievementCriteriaList();
void loadAchievementRewards();
void loadCompletedAchievements();
AchievementReward const* getAchievementReward(uint32_t entry, uint8_t gender);
AchievementCriteriaEntryList const& getAchievementCriteriaByType(AchievementCriteriaTypes type);
void addCompletedAchievement(uint32_t _achievementId);
std::set<uint32_t> getAllCompleteAchievements();
private:
AchievementRewardsMap m_achievementRewards;
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
#if VERSION_STRING > WotLK
AchievementCriteriaEntryList m_GuildAchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
#endif
std::set<uint32_t> m_allCompletedAchievements;
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// Misc
public:
@@ -357,24 +380,6 @@ public:
void AddPlayer(Player* p); //add it to global storage
void RemovePlayer(Player* p);
// Serialization
#if VERSION_STRING > TBC
void LoadCompletedAchievements();
AchievementRewardsMap AchievementRewards;
AchievementReward const * GetAchievementReward(uint32 entry, uint8 gender)
{
AchievementRewardsMapBounds bounds = AchievementRewards.equal_range(entry);
for (AchievementRewardsMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
{
if (iter->second.gender == 2 || uint8(iter->second.gender) == gender)
return &iter->second;
}
return NULL;
}
void LoadAchievementRewards();
#endif
void LoadVendors();
void ReloadVendors();
@@ -452,11 +457,6 @@ public:
void EventScriptsUpdate(Player* plr, uint32 next_event);
//////////////////////////////////////////////////////////////////////////////////////////
#if VERSION_STRING > TBC
void LoadAchievementCriteriaList();
AchievementCriteriaEntryList const & GetAchievementCriteriaByType(AchievementCriteriaTypes type);
std::set<uint32> allCompletedAchievements;
#endif
#ifdef FT_VEHICLES
void LoadVehicleAccessories();
@@ -523,12 +523,7 @@ public:
TrainerMap mTrainers;
LevelInfoMap mLevelInfo;
PetSpellCooldownMap mPetSpellCooldowns;
#if VERSION_STRING > TBC
AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
#endif
#if VERSION_STRING > WotLK
AchievementCriteriaEntryList m_GuildAchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
#endif
#ifdef FT_VEHICLES
VehicleAccessoryContainer _vehicleAccessoryStore;
VehicleSeatAddonContainer _vehicleSeatAddonStore;

View File

@@ -1492,7 +1492,7 @@ void WorldSession::handleGuildFinderGetRecruits(WorldPacket& recvPacket)
MembershipRequest request = *itr;
WoWGuid playerGuid(request.getPlayerGUID(), 0, HIGHGUID_TYPE_PLAYER);
std::shared_ptr<CachedCharacterInfo> info = sObjectMgr.getCachedCharacterInfo(request.getPlayerGUID())
std::shared_ptr<CachedCharacterInfo> info = sObjectMgr.getCachedCharacterInfo(request.getPlayerGUID());
std::string name = info->name;
data.writeBits(request.getComment().size(), 11);

View File

@@ -736,7 +736,7 @@ bool World::setInitialWorldSettings()
#if VERSION_STRING > TBC
sLogger.info("World : Starting Achievement System...");
sObjectMgr.LoadAchievementCriteriaList();
sObjectMgr.loadAchievementCriteriaList();
#endif
sLogger.info("World : Starting Transport System...");
@@ -952,7 +952,7 @@ void World::loadMySQLTablesByTask()
sObjectMgr.LoadWorldStateTemplates();
#if VERSION_STRING > TBC
sObjectMgr.LoadAchievementRewards();
sObjectMgr.loadAchievementRewards();
#endif
sLootMgr.loadAndGenerateLoot(0);