bool AchievementMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const { AchievementEntry const* achievement = tree->Achievement; if (!achievement) return false; if (HasAchieved(achievement->ID)) { TC_LOG_TRACE("criteria.achievement", "AchievementMgr::CanUpdateCriteriaTree: (Id: %u Type %s Achievement %u) Achievement already earned", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), achievement->ID); return false; } if (achievement->InstanceID != -1 && referencePlayer->GetMapId() != uint32(achievement->InstanceID)) { TC_LOG_TRACE("criteria.achievement", "AchievementMgr::CanUpdateCriteriaTree: (Id: %u Type %s Achievement %u) Wrong map", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), achievement->ID); return false; } if ((achievement->Faction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) || (achievement->Faction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE)) { TC_LOG_TRACE("criteria.achievement", "AchievementMgr::CanUpdateCriteriaTree: (Id: %u Type %s Achievement %u) Wrong faction", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), achievement->ID); return false; } return CriteriaHandler::CanUpdateCriteriaTree(criteria, tree, referencePlayer); }
void PlayerAchievementMgr::ResetCriteria(CriteriaTypes type, uint64 miscValue1, uint64 miscValue2, bool evenIfCriteriaComplete) { TC_LOG_DEBUG("criteria.achievement", "PlayerAchievementMgr::ResetCriteria(%u, " UI64FMTD ", " UI64FMTD ")", type, miscValue1, miscValue2); // disable for gamemasters with GM-mode enabled if (_owner->IsGameMaster()) return; CriteriaList const& achievementCriteriaList = GetCriteriaByType(type); for (Criteria const* achievementCriteria : achievementCriteriaList) { if (achievementCriteria->Entry->FailEvent != miscValue1 || (achievementCriteria->Entry->FailAsset && achievementCriteria->Entry->FailAsset != int64(miscValue2))) continue; std::vector<CriteriaTree const*> const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(achievementCriteria->ID); bool allComplete = true; for (CriteriaTree const* tree : *trees) { // don't update already completed criteria if not forced or achievement already complete if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete) || !HasAchieved(tree->Achievement->ID)) { allComplete = false; break; } } if (allComplete) continue; RemoveCriteriaProgress(achievementCriteria); } }
void AchievementMgr::CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer) { // counter can never complete if (tree->Achievement->Flags & ACHIEVEMENT_FLAG_COUNTER) return; // already completed and stored if (HasAchieved(tree->Achievement->ID)) return; if (IsCompletedAchievement(tree->Achievement)) CompletedAchievement(tree->Achievement, referencePlayer); }
void GuildAchievementMgr::CompletedAchievement(AchievementEntry const* achievement, Player* player) { if (!(achievement->flags & ACHIEVEMENT_FLAG_GUILD_ACHIEVEMENT)) return; if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID)) return; SendAchievementEarned(achievement); CompletedAchievementData& ca = m_completedAchievements[achievement->ID]; ca.date = time(NULL); ca.changed = true; m_achievementPoints += achievement->points; UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, player); }
void GuildAchievementMgr::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer) { TC_LOG_DEBUG("criteria.achievement", "GuildAchievementMgr::CompletedAchievement(%u)", achievement->ID); if (achievement->Flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID)) return; if (achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS) if (Guild* guild = referencePlayer->GetGuild()) guild->AddGuildNews(GUILD_NEWS_GUILD_ACHIEVEMENT, ObjectGuid::Empty, achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID); SendAchievementEarned(achievement); CompletedAchievementData& ca = _completedAchievements[achievement->ID]; ca.Date = time(NULL); ca.Changed = true; if (achievement->Flags & ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS) { if (referencePlayer->GetGuildId() == _owner->GetId()) ca.CompletingPlayers.insert(referencePlayer->GetGUID()); if (Group const* group = referencePlayer->GetGroup()) for (GroupReference const* ref = group->GetFirstMember(); ref != NULL; ref = ref->next()) if (Player const* groupMember = ref->GetSource()) if (groupMember->GetGuildId() == _owner->GetId()) ca.CompletingPlayers.insert(groupMember->GetGUID()); } if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) sAchievementMgr->SetRealmCompleted(achievement); if (!(achievement->Flags & ACHIEVEMENT_FLAG_TRACKING_FLAG)) _achievementPoints += achievement->Points; UpdateCriteria(CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer); UpdateCriteria(CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->Points, 0, 0, NULL, referencePlayer); }
void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) { sLog->outDetail("AchievementMgr::CompletedAchievement(%u)", achievement->ID); // disable for gamemasters with GM-mode enabled if (_player->isGameMaster()) return; if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID)) return; SendAchievementEarned(achievement); CompletedAchievementData& ca = m_completedAchievements[achievement->ID]; ca.date = time(NULL); ca.changed = true; // 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)) sAchievementMgr->SetRealmCompleted(achievement); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, _player); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, _player, achievement->points); m_achievementPoints += achievement->points; // reward items and titles if any AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement); // no rewards if (!reward) return; // titles //! Currently there's only one achievement that deals with gender-specific titles. //! Since no common attributes were found, (not even in titleRewardFlags field) //! we explicitly check by ID. Maybe in the future we could move the achievement_reward //! condition fields to the condition system. if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->getGender() : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)]) if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId)) GetPlayer()->SetTitle(titleEntry); // mail if (reward->sender) { Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetPlayer ()) : NULL; int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex(); // subject and text std::string subject = reward->subject; std::string text = reward->text; if (loc_idx >= 0) { if (AchievementRewardLocale const* loc = sAchievementMgr->GetAchievementRewardLocale(achievement)) { ObjectMgr::GetLocaleString(loc->subject, loc_idx, subject); ObjectMgr::GetLocaleString(loc->text, loc_idx, text); } } MailDraft draft(subject, text); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (item) { // save new item before send item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted // item draft.AddItem(item); } draft.SendMailTo(trans, GetPlayer(), MailSender(MAIL_CREATURE, reward->sender)); CharacterDatabase.CommitTransaction(trans); } }
void PlayerAchievementMgr::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer) { // disable for gamemasters with GM-mode enabled if (_owner->IsGameMaster()) return; if ((achievement->Faction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) || (achievement->Faction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE)) return; if (achievement->Flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID)) return; if (achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS) if (Guild* guild = referencePlayer->GetGuild()) guild->AddGuildNews(GUILD_NEWS_PLAYER_ACHIEVEMENT, referencePlayer->GetGUID(), achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID); if (!_owner->GetSession()->PlayerLoading()) SendAchievementEarned(achievement); TC_LOG_INFO("criteria.achievement", "PlayerAchievementMgr::CompletedAchievement(%u). %s", achievement->ID, GetOwnerInfo().c_str()); CompletedAchievementData& ca = _completedAchievements[achievement->ID]; ca.Date = time(NULL); ca.Changed = true; if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) sAchievementMgr->SetRealmCompleted(achievement); if (!(achievement->Flags & ACHIEVEMENT_FLAG_TRACKING_FLAG)) _achievementPoints += achievement->Points; UpdateCriteria(CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer); UpdateCriteria(CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->Points, 0, 0, NULL, referencePlayer); // reward items and titles if any AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement); // no rewards if (!reward) return; // titles //! Currently there's only one achievement that deals with gender-specific titles. //! Since no common attributes were found, (not even in titleRewardFlags field) //! we explicitly check by ID. Maybe in the future we could move the achievement_reward //! condition fields to the condition system. if (uint32 titleId = reward->TitleId[achievement->ID == 1793 ? _owner->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER) : (_owner->GetTeam() == ALLIANCE ? 0 : 1)]) if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId)) _owner->SetTitle(titleEntry); // mail if (reward->SenderCreatureId) { MailDraft draft(uint16(reward->MailTemplateId)); if (!reward->MailTemplateId) { // subject and text std::string subject = reward->Subject; std::string text = reward->Body; LocaleConstant localeConstant = _owner->GetSession()->GetSessionDbLocaleIndex(); if (localeConstant != LOCALE_enUS) { if (AchievementRewardLocale const* loc = sAchievementMgr->GetAchievementRewardLocale(achievement)) { ObjectMgr::GetLocaleString(loc->Subject, localeConstant, subject); ObjectMgr::GetLocaleString(loc->Body, localeConstant, text); } } draft = MailDraft(subject, text); } SQLTransaction trans = CharacterDatabase.BeginTransaction(); Item* item = reward->ItemId ? Item::CreateItem(reward->ItemId, 1, _owner) : NULL; if (item) { // save new item before send item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted // item draft.AddItem(item); } draft.SendMailTo(trans, _owner, MailSender(MAIL_CREATURE, uint64(reward->SenderCreatureId))); CharacterDatabase.CommitTransaction(trans); } }
bool AchievementMgr::RequiredAchievementSatisfied(uint32 achievementId) const { return HasAchieved(achievementId); }