aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp701
-rw-r--r--src/server/game/Achievements/CriteriaHandler.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp18
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.h2
5 files changed, 370 insertions, 355 deletions
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index 783eb38daad..d7df88bb8e1 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -489,382 +489,385 @@ void CriteriaHandler::UpdateCriteria(CriteriaType type, uint64 miscValue1 /*= 0*
CriteriaList const& criteriaList = GetCriteriaByType(type, uint32(miscValue1));
for (Criteria const* criteria : criteriaList)
+ UpdateCriteria(criteria, miscValue1, miscValue2, miscValue3, ref, referencePlayer);
+}
+
+void CriteriaHandler::UpdateCriteria(Criteria const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const* ref, Player* referencePlayer)
+{
+ CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
+ if (!CanUpdateCriteria(criteria, trees, miscValue1, miscValue2, miscValue3, ref, referencePlayer))
+ return;
+
+ // requirements not found in the dbc
+ if (CriteriaDataSet const* data = sCriteriaMgr->GetCriteriaDataSet(criteria))
+ if (!data->Meets(referencePlayer, ref, uint32(miscValue1), uint32(miscValue2)))
+ return;
+
+ switch (CriteriaType(criteria->Entry->Type))
{
- CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
- if (!CanUpdateCriteria(criteria, trees, miscValue1, miscValue2, miscValue3, ref, referencePlayer))
- continue;
+ // std. case: increment at 1
+ case CriteriaType::WinBattleground:
+ case CriteriaType::TotalRespecs:
+ case CriteriaType::LoseDuel:
+ case CriteriaType::ItemsPostedAtAuction:
+ case CriteriaType::AuctionsWon: /* FIXME: for online player only currently */
+ case CriteriaType::RollAnyNeed:
+ case CriteriaType::RollAnyGreed:
+ case CriteriaType::AbandonAnyQuest:
+ case CriteriaType::BuyTaxi:
+ case CriteriaType::AcceptSummon:
+ case CriteriaType::LootAnyItem:
+ case CriteriaType::ObtainAnyItem:
+ case CriteriaType::DieAnywhere:
+ case CriteriaType::CompleteDailyQuest:
+ case CriteriaType::ParticipateInBattleground:
+ case CriteriaType::DieOnMap:
+ case CriteriaType::DieInInstance:
+ case CriteriaType::KilledByCreature:
+ case CriteriaType::KilledByPlayer:
+ case CriteriaType::DieFromEnviromentalDamage:
+ case CriteriaType::BeSpellTarget:
+ case CriteriaType::GainAura:
+ case CriteriaType::CastSpell:
+ case CriteriaType::LandTargetedSpellOnTarget:
+ case CriteriaType::WinAnyRankedArena:
+ case CriteriaType::UseItem:
+ case CriteriaType::RollNeed:
+ case CriteriaType::RollGreed:
+ case CriteriaType::DoEmote:
+ case CriteriaType::UseGameobject:
+ case CriteriaType::CatchFishInFishingHole:
+ case CriteriaType::WinDuel:
+ case CriteriaType::DeliverKillingBlowToClass:
+ case CriteriaType::DeliverKillingBlowToRace:
+ case CriteriaType::TrackedWorldStateUIModified:
+ case CriteriaType::EarnHonorableKill:
+ case CriteriaType::KillPlayer:
+ case CriteriaType::DeliveredKillingBlow:
+ case CriteriaType::PVPKillInArea:
+ case CriteriaType::WinArena: // This also behaves like CriteriaType::WinAnyRankedArena
+ case CriteriaType::ParticipateInArena:
+ case CriteriaType::PlayerTriggerGameEvent:
+ case CriteriaType::Login:
+ case CriteriaType::AnyoneTriggerGameEventScenario:
+ case CriteriaType::DefeatDungeonEncounterWhileElegibleForLoot:
+ case CriteriaType::CompleteAnyScenario:
+ case CriteriaType::CompleteScenario:
+ case CriteriaType::BattlePetReachLevel:
+ case CriteriaType::ActivelyEarnPetLevel:
+ case CriteriaType::DefeatDungeonEncounter:
+ case CriteriaType::PlaceGarrisonBuilding:
+ case CriteriaType::ActivateAnyGarrisonBuilding:
+ case CriteriaType::LearnAnyHeirloom:
+ case CriteriaType::LearnAnyTransmog:
+ case CriteriaType::HonorLevelIncrease:
+ case CriteriaType::PrestigeLevelIncrease:
+ case CriteriaType::LearnAnyTransmogInSlot:
+ case CriteriaType::CompleteAnyReplayQuest:
+ case CriteriaType::BuyItemsFromVendors:
+ case CriteriaType::SellItemsToVendors:
+ case CriteriaType::ReachMaxLevel:
+ case CriteriaType::LearnTaxiNode:
+ SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ // std case: increment at miscValue1
+ case CriteriaType::MoneyEarnedFromSales:
+ case CriteriaType::MoneySpentOnRespecs:
+ case CriteriaType::MoneyEarnedFromQuesting:
+ case CriteriaType::MoneySpentOnTaxis:
+ case CriteriaType::MoneySpentAtBarberShop:
+ case CriteriaType::MoneySpentOnPostage:
+ case CriteriaType::MoneyLootedFromCreatures:
+ case CriteriaType::MoneyEarnedFromAuctions:/* FIXME: for online player only currently */
+ case CriteriaType::TotalDamageTaken:
+ case CriteriaType::TotalHealReceived:
+ case CriteriaType::CompletedLFGDungeon:
+ case CriteriaType::CompletedLFGDungeonWithStrangers:
+ case CriteriaType::DamageDealt:
+ case CriteriaType::HealingDone:
+ case CriteriaType::EarnArtifactXPForAzeriteItem:
+ case CriteriaType::GainLevels:
+ case CriteriaType::EarnArtifactXP:
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ case CriteriaType::KillCreature:
+ case CriteriaType::KillAnyCreature:
+ case CriteriaType::GetLootByType:
+ case CriteriaType::AcquireItem:
+ case CriteriaType::LootItem:
+ case CriteriaType::CurrencyGained:
+ SetCriteriaProgress(criteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ // std case: high value at miscValue1
+ case CriteriaType::HighestAuctionBid:
+ case CriteriaType::HighestAuctionSale: /* FIXME: for online player only currently */
+ case CriteriaType::HighestDamageDone:
+ case CriteriaType::HighestDamageTaken:
+ case CriteriaType::HighestHealCast:
+ case CriteriaType::HighestHealReceived:
+ case CriteriaType::AnyArtifactPowerRankPurchased:
+ case CriteriaType::AzeriteLevelReached:
+ case CriteriaType::ReachRenownLevel:
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
+ break;
+ case CriteriaType::ReachLevel:
+ SetCriteriaProgress(criteria, referencePlayer->GetLevel(), referencePlayer);
+ break;
+ case CriteriaType::SkillRaised:
+ if (uint32 skillvalue = referencePlayer->GetBaseSkillValue(criteria->Entry->Asset.SkillID))
+ SetCriteriaProgress(criteria, skillvalue, referencePlayer);
+ break;
+ case CriteriaType::AchieveSkillStep:
+ if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(criteria->Entry->Asset.SkillID))
+ SetCriteriaProgress(criteria, maxSkillvalue, referencePlayer);
+ break;
+ case CriteriaType::CompleteQuestsCount:
+ SetCriteriaProgress(criteria, referencePlayer->GetRewardedQuestCount(), referencePlayer);
+ break;
+ case CriteriaType::CompleteAnyDailyQuestPerDay:
+ {
+ time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
+ CriteriaProgress *progress = GetCriteriaProgress(criteria);
- // requirements not found in the dbc
- if (CriteriaDataSet const* data = sCriteriaMgr->GetCriteriaDataSet(criteria))
- if (!data->Meets(referencePlayer, ref, uint32(miscValue1), uint32(miscValue2)))
- continue;
+ if (!miscValue1) // Login case.
+ {
+ // reset if player missed one day.
+ if (progress && progress->Date < (nextDailyResetTime - 2 * DAY))
+ SetCriteriaProgress(criteria, 0, referencePlayer, PROGRESS_SET);
+ return;
+ }
+
+ ProgressType progressType;
+ if (!progress)
+ // 1st time. Start count.
+ progressType = PROGRESS_SET;
+ else if (progress->Date < (nextDailyResetTime - 2 * DAY))
+ // last progress is older than 2 days. Player missed 1 day => Restart count.
+ progressType = PROGRESS_SET;
+ else if (progress->Date < (nextDailyResetTime - DAY))
+ // last progress is between 1 and 2 days. => 1st time of the day.
+ progressType = PROGRESS_ACCUMULATE;
+ else
+ // last progress is within the day before the reset => Already counted today.
+ return;
- switch (type)
- {
- // std. case: increment at 1
- case CriteriaType::WinBattleground:
- case CriteriaType::TotalRespecs:
- case CriteriaType::LoseDuel:
- case CriteriaType::ItemsPostedAtAuction:
- case CriteriaType::AuctionsWon: /* FIXME: for online player only currently */
- case CriteriaType::RollAnyNeed:
- case CriteriaType::RollAnyGreed:
- case CriteriaType::AbandonAnyQuest:
- case CriteriaType::BuyTaxi:
- case CriteriaType::AcceptSummon:
- case CriteriaType::LootAnyItem:
- case CriteriaType::ObtainAnyItem:
- case CriteriaType::DieAnywhere:
- case CriteriaType::CompleteDailyQuest:
- case CriteriaType::ParticipateInBattleground:
- case CriteriaType::DieOnMap:
- case CriteriaType::DieInInstance:
- case CriteriaType::KilledByCreature:
- case CriteriaType::KilledByPlayer:
- case CriteriaType::DieFromEnviromentalDamage:
- case CriteriaType::BeSpellTarget:
- case CriteriaType::GainAura:
- case CriteriaType::CastSpell:
- case CriteriaType::LandTargetedSpellOnTarget:
- case CriteriaType::WinAnyRankedArena:
- case CriteriaType::UseItem:
- case CriteriaType::RollNeed:
- case CriteriaType::RollGreed:
- case CriteriaType::DoEmote:
- case CriteriaType::UseGameobject:
- case CriteriaType::CatchFishInFishingHole:
- case CriteriaType::WinDuel:
- case CriteriaType::DeliverKillingBlowToClass:
- case CriteriaType::DeliverKillingBlowToRace:
- case CriteriaType::TrackedWorldStateUIModified:
- case CriteriaType::EarnHonorableKill:
- case CriteriaType::KillPlayer:
- case CriteriaType::DeliveredKillingBlow:
- case CriteriaType::PVPKillInArea:
- case CriteriaType::WinArena: // This also behaves like CriteriaType::WinAnyRankedArena
- case CriteriaType::ParticipateInArena:
- case CriteriaType::PlayerTriggerGameEvent:
- case CriteriaType::Login:
- case CriteriaType::AnyoneTriggerGameEventScenario:
- case CriteriaType::DefeatDungeonEncounterWhileElegibleForLoot:
- case CriteriaType::CompleteAnyScenario:
- case CriteriaType::CompleteScenario:
- case CriteriaType::BattlePetReachLevel:
- case CriteriaType::ActivelyEarnPetLevel:
- case CriteriaType::DefeatDungeonEncounter:
- case CriteriaType::PlaceGarrisonBuilding:
- case CriteriaType::ActivateAnyGarrisonBuilding:
- case CriteriaType::LearnAnyHeirloom:
- case CriteriaType::LearnAnyTransmog:
- case CriteriaType::HonorLevelIncrease:
- case CriteriaType::PrestigeLevelIncrease:
- case CriteriaType::LearnAnyTransmogInSlot:
- case CriteriaType::CompleteAnyReplayQuest:
- case CriteriaType::BuyItemsFromVendors:
- case CriteriaType::SellItemsToVendors:
- case CriteriaType::ReachMaxLevel:
- case CriteriaType::LearnTaxiNode:
+ SetCriteriaProgress(criteria, 1, referencePlayer, progressType);
+ break;
+ }
+ case CriteriaType::CompleteQuestsInZone:
+ {
+ if (miscValue1)
+ {
SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
- break;
- // std case: increment at miscValue1
- case CriteriaType::MoneyEarnedFromSales:
- case CriteriaType::MoneySpentOnRespecs:
- case CriteriaType::MoneyEarnedFromQuesting:
- case CriteriaType::MoneySpentOnTaxis:
- case CriteriaType::MoneySpentAtBarberShop:
- case CriteriaType::MoneySpentOnPostage:
- case CriteriaType::MoneyLootedFromCreatures:
- case CriteriaType::MoneyEarnedFromAuctions:/* FIXME: for online player only currently */
- case CriteriaType::TotalDamageTaken:
- case CriteriaType::TotalHealReceived:
- case CriteriaType::CompletedLFGDungeon:
- case CriteriaType::CompletedLFGDungeonWithStrangers:
- case CriteriaType::DamageDealt:
- case CriteriaType::HealingDone:
- case CriteriaType::EarnArtifactXPForAzeriteItem:
- case CriteriaType::GainLevels:
- case CriteriaType::EarnArtifactXP:
- SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
- break;
- case CriteriaType::KillCreature:
- case CriteriaType::KillAnyCreature:
- case CriteriaType::GetLootByType:
- case CriteriaType::AcquireItem:
- case CriteriaType::LootItem:
- case CriteriaType::CurrencyGained:
- SetCriteriaProgress(criteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE);
- break;
- // std case: high value at miscValue1
- case CriteriaType::HighestAuctionBid:
- case CriteriaType::HighestAuctionSale: /* FIXME: for online player only currently */
- case CriteriaType::HighestDamageDone:
- case CriteriaType::HighestDamageTaken:
- case CriteriaType::HighestHealCast:
- case CriteriaType::HighestHealReceived:
- case CriteriaType::AnyArtifactPowerRankPurchased:
- case CriteriaType::AzeriteLevelReached:
- case CriteriaType::ReachRenownLevel:
- SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
- break;
- case CriteriaType::ReachLevel:
- SetCriteriaProgress(criteria, referencePlayer->GetLevel(), referencePlayer);
- break;
- case CriteriaType::SkillRaised:
- if (uint32 skillvalue = referencePlayer->GetBaseSkillValue(criteria->Entry->Asset.SkillID))
- SetCriteriaProgress(criteria, skillvalue, referencePlayer);
- break;
- case CriteriaType::AchieveSkillStep:
- if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(criteria->Entry->Asset.SkillID))
- SetCriteriaProgress(criteria, maxSkillvalue, referencePlayer);
- break;
- case CriteriaType::CompleteQuestsCount:
- SetCriteriaProgress(criteria, referencePlayer->GetRewardedQuestCount(), referencePlayer);
- break;
- case CriteriaType::CompleteAnyDailyQuestPerDay:
+ }
+ else // login case
{
- time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
- CriteriaProgress *progress = GetCriteriaProgress(criteria);
+ uint32 counter = 0;
- if (!miscValue1) // Login case.
+ RewardedQuestSet const& rewQuests = referencePlayer->getRewardedQuests();
+ for (uint32 rewQuest : rewQuests)
{
- // reset if player missed one day.
- if (progress && progress->Date < (nextDailyResetTime - 2 * DAY))
- SetCriteriaProgress(criteria, 0, referencePlayer, PROGRESS_SET);
- continue;
+ Quest const* quest = sObjectMgr->GetQuestTemplate(rewQuest);
+ if (quest && quest->GetZoneOrSort() >= 0 && quest->GetZoneOrSort() == criteria->Entry->Asset.ZoneID)
+ ++counter;
}
-
- ProgressType progressType;
- if (!progress)
- // 1st time. Start count.
- progressType = PROGRESS_SET;
- else if (progress->Date < (nextDailyResetTime - 2 * DAY))
- // last progress is older than 2 days. Player missed 1 day => Restart count.
- progressType = PROGRESS_SET;
- else if (progress->Date < (nextDailyResetTime - DAY))
- // last progress is between 1 and 2 days. => 1st time of the day.
- progressType = PROGRESS_ACCUMULATE;
- else
- // last progress is within the day before the reset => Already counted today.
- continue;
-
- SetCriteriaProgress(criteria, 1, referencePlayer, progressType);
- break;
+ SetCriteriaProgress(criteria, counter, referencePlayer, PROGRESS_HIGHEST);
}
- case CriteriaType::CompleteQuestsInZone:
+ break;
+ }
+ case CriteriaType::MaxDistFallenWithoutDying:
+ // miscValue1 is the ingame fallheight*100 as stored in dbc
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer);
+ break;
+ case CriteriaType::EarnAchievement:
+ case CriteriaType::CompleteQuest:
+ case CriteriaType::LearnOrKnowSpell:
+ case CriteriaType::RevealWorldMapOverlay:
+ case CriteriaType::GotHaircut:
+ case CriteriaType::EquipItemInSlot:
+ case CriteriaType::EquipItem:
+ case CriteriaType::EnterAreaTriggerWithActionSet:
+ case CriteriaType::LeaveAreaTriggerWithActionSet:
+ case CriteriaType::LearnedNewPet:
+ case CriteriaType::EnterArea:
+ case CriteriaType::LeaveArea:
+ case CriteriaType::RecruitGarrisonFollower:
+ case CriteriaType::LearnHeirloom:
+ case CriteriaType::ActivelyReachLevel:
+ case CriteriaType::CollectTransmogSetFromGroup:
+ case CriteriaType::EnterTopLevelArea:
+ case CriteriaType::LeaveTopLevelArea:
+ SetCriteriaProgress(criteria, 1, referencePlayer);
+ break;
+ case CriteriaType::BankSlotsPurchased:
+ SetCriteriaProgress(criteria, referencePlayer->GetBankBagSlotCount(), referencePlayer);
+ break;
+ case CriteriaType::ReputationGained:
+ {
+ int32 reputation = referencePlayer->GetReputationMgr().GetReputation(criteria->Entry->Asset.FactionID);
+ if (reputation > 0)
+ SetCriteriaProgress(criteria, reputation, referencePlayer);
+ break;
+ }
+ case CriteriaType::TotalExaltedFactions:
+ SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer);
+ break;
+ case CriteriaType::LearnSpellFromSkillLine:
+ case CriteriaType::LearnTradeskillSkillLine:
+ {
+ uint32 spellCount = 0;
+ for (auto& [spellId, _] : referencePlayer->GetSpellMap())
{
- if (miscValue1)
+ SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
+ for (SkillLineAbilityMap::const_iterator skillIter = bounds.first; skillIter != bounds.second; ++skillIter)
{
- SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
- }
- else // login case
- {
- uint32 counter = 0;
-
- RewardedQuestSet const& rewQuests = referencePlayer->getRewardedQuests();
- for (uint32 rewQuest : rewQuests)
+ if (skillIter->second->SkillLine == uint32(criteria->Entry->Asset.SkillID))
{
- Quest const* quest = sObjectMgr->GetQuestTemplate(rewQuest);
- if (quest && quest->GetZoneOrSort() >= 0 && quest->GetZoneOrSort() == criteria->Entry->Asset.ZoneID)
- ++counter;
+ // do not add couter twice if by any chance skill is listed twice in dbc (eg. skill 777 and spell 22717)
+ ++spellCount;
+ break;
}
- SetCriteriaProgress(criteria, counter, referencePlayer, PROGRESS_HIGHEST);
}
- break;
}
- case CriteriaType::MaxDistFallenWithoutDying:
- // miscValue1 is the ingame fallheight*100 as stored in dbc
- SetCriteriaProgress(criteria, miscValue1, referencePlayer);
- break;
- case CriteriaType::EarnAchievement:
- case CriteriaType::CompleteQuest:
- case CriteriaType::LearnOrKnowSpell:
- case CriteriaType::RevealWorldMapOverlay:
- case CriteriaType::GotHaircut:
- case CriteriaType::EquipItemInSlot:
- case CriteriaType::EquipItem:
- case CriteriaType::EnterAreaTriggerWithActionSet:
- case CriteriaType::LeaveAreaTriggerWithActionSet:
- case CriteriaType::LearnedNewPet:
- case CriteriaType::EnterArea:
- case CriteriaType::LeaveArea:
- case CriteriaType::RecruitGarrisonFollower:
- case CriteriaType::LearnHeirloom:
- case CriteriaType::ActivelyReachLevel:
- case CriteriaType::CollectTransmogSetFromGroup:
- case CriteriaType::EnterTopLevelArea:
- case CriteriaType::LeaveTopLevelArea:
- SetCriteriaProgress(criteria, 1, referencePlayer);
- break;
- case CriteriaType::BankSlotsPurchased:
- SetCriteriaProgress(criteria, referencePlayer->GetBankBagSlotCount(), referencePlayer);
- break;
- case CriteriaType::ReputationGained:
+ SetCriteriaProgress(criteria, spellCount, referencePlayer);
+ break;
+ }
+ case CriteriaType::TotalReveredFactions:
+ SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetReveredFactionCount(), referencePlayer);
+ break;
+ case CriteriaType::TotalHonoredFactions:
+ SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetHonoredFactionCount(), referencePlayer);
+ break;
+ case CriteriaType::TotalFactionsEncountered:
+ SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
+ break;
+ case CriteriaType::HonorableKills:
+ SetCriteriaProgress(criteria, referencePlayer->m_activePlayerData->LifetimeHonorableKills, referencePlayer);
+ break;
+ case CriteriaType::MostMoneyOwned:
+ SetCriteriaProgress(criteria, referencePlayer->GetMoney(), referencePlayer, PROGRESS_HIGHEST);
+ break;
+ case CriteriaType::EarnAchievementPoints:
+ if (!miscValue1)
+ return;
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ case CriteriaType::EarnPersonalArenaRating:
+ {
+ uint32 reqTeamType = criteria->Entry->Asset.TeamType;
+
+ if (miscValue1)
{
- int32 reputation = referencePlayer->GetReputationMgr().GetReputation(criteria->Entry->Asset.FactionID);
- if (reputation > 0)
- SetCriteriaProgress(criteria, reputation, referencePlayer);
- break;
+ if (miscValue2 != reqTeamType)
+ return;
+
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
}
- case CriteriaType::TotalExaltedFactions:
- SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer);
- break;
- case CriteriaType::LearnSpellFromSkillLine:
- case CriteriaType::LearnTradeskillSkillLine:
+ else // login case
{
- uint32 spellCount = 0;
- for (auto& [spellId, _] : referencePlayer->GetSpellMap())
+ for (uint8 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
- SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellId);
- for (SkillLineAbilityMap::const_iterator skillIter = bounds.first; skillIter != bounds.second; ++skillIter)
- {
- if (skillIter->second->SkillLine == uint32(criteria->Entry->Asset.SkillID))
- {
- // do not add couter twice if by any chance skill is listed twice in dbc (eg. skill 777 and spell 22717)
- ++spellCount;
- break;
- }
- }
- }
- SetCriteriaProgress(criteria, spellCount, referencePlayer);
- break;
- }
- case CriteriaType::TotalReveredFactions:
- SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetReveredFactionCount(), referencePlayer);
- break;
- case CriteriaType::TotalHonoredFactions:
- SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetHonoredFactionCount(), referencePlayer);
- break;
- case CriteriaType::TotalFactionsEncountered:
- SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
- break;
- case CriteriaType::HonorableKills:
- SetCriteriaProgress(criteria, referencePlayer->m_activePlayerData->LifetimeHonorableKills, referencePlayer);
- break;
- case CriteriaType::MostMoneyOwned:
- SetCriteriaProgress(criteria, referencePlayer->GetMoney(), referencePlayer, PROGRESS_HIGHEST);
- break;
- case CriteriaType::EarnAchievementPoints:
- if (!miscValue1)
- continue;
- SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
- break;
- case CriteriaType::EarnPersonalArenaRating:
- {
- uint32 reqTeamType = criteria->Entry->Asset.TeamType;
+ uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
+ if (!teamId)
+ continue;
- if (miscValue1)
- {
- if (miscValue2 != reqTeamType)
+ ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId);
+ if (!team || team->GetType() != reqTeamType)
continue;
- SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
- }
- else // login case
- {
- for (uint8 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
+ if (ArenaTeamMember const* member = team->GetMember(referencePlayer->GetGUID()))
{
- uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
- if (!teamId)
- continue;
-
- ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId);
- if (!team || team->GetType() != reqTeamType)
- continue;
-
- if (ArenaTeamMember const* member = team->GetMember(referencePlayer->GetGUID()))
- {
- SetCriteriaProgress(criteria, member->PersonalRating, referencePlayer, PROGRESS_HIGHEST);
- break;
- }
+ SetCriteriaProgress(criteria, member->PersonalRating, referencePlayer, PROGRESS_HIGHEST);
+ break;
}
}
- break;
}
- case CriteriaType::UniquePetsOwned:
- SetCriteriaProgress(criteria, referencePlayer->GetSession()->GetBattlePetMgr()->GetPetUniqueSpeciesCount(), referencePlayer);
- break;
- case CriteriaType::GuildAttainedLevel:
- SetCriteriaProgress(criteria, miscValue1, referencePlayer);
- break;
- // FIXME: not triggered in code as result, need to implement
- case CriteriaType::RunInstance:
- case CriteriaType::EarnTeamArenaRating:
- case CriteriaType::EarnTitle:
- case CriteriaType::MoneySpentOnGuildRepair:
- case CriteriaType::CreatedItemsByCastingSpell:
- case CriteriaType::FishInAnyPool:
- case CriteriaType::GuildBankTabsPurchased:
- case CriteriaType::EarnGuildAchievementPoints:
- case CriteriaType::WinAnyBattleground:
- case CriteriaType::EarnBattlegroundRating:
- case CriteriaType::GuildTabardCreated:
- case CriteriaType::CompleteQuestsCountForGuild:
- case CriteriaType::HonorableKillsForGuild:
- case CriteriaType::KillAnyCreatureForGuild:
- case CriteriaType::CompleteAnyResearchProject:
- case CriteriaType::CompleteGuildChallenge:
- case CriteriaType::CompleteAnyGuildChallenge:
- case CriteriaType::CompletedLFRDungeon:
- case CriteriaType::AbandonedLFRDungeon:
- case CriteriaType::KickInitiatorInLFRDungeon:
- case CriteriaType::KickVoterInLFRDungeon:
- case CriteriaType::KickTargetInLFRDungeon:
- case CriteriaType::GroupedTankLeftEarlyInLFRDungeon:
- case CriteriaType::AccountObtainPetThroughBattle:
- case CriteriaType::WinPetBattle:
- case CriteriaType::PlayerObtainPetThroughBattle:
- case CriteriaType::ActivateGarrisonBuilding:
- case CriteriaType::UpgradeGarrison:
- case CriteriaType::StartAnyGarrisonMissionWithFollowerType:
- case CriteriaType::SucceedAnyGarrisonMissionWithFollowerType:
- case CriteriaType::SucceedGarrisonMission:
- case CriteriaType::RecruitAnyGarrisonFollower:
- case CriteriaType::LearnAnyGarrisonBlueprint:
- case CriteriaType::CollectGarrisonShipment:
- case CriteriaType::ItemLevelChangedForGarrisonFollower:
- case CriteriaType::LevelChangedForGarrisonFollower:
- case CriteriaType::LearnToy:
- case CriteriaType::LearnAnyToy:
- case CriteriaType::FindResearchObject:
- case CriteriaType::ExhaustAnyResearchSite:
- case CriteriaType::CompleteInternalCriteria:
- case CriteriaType::CompleteAnyChallengeMode:
- case CriteriaType::KilledAllUnitsInSpawnRegion:
- case CriteriaType::CompleteChallengeMode:
- case CriteriaType::CreatedItemsByCastingSpellWithLimit:
- case CriteriaType::BattlePetAchievementPointsEarned:
- case CriteriaType::ReleasedSpirit:
- case CriteriaType::AccountKnownPet:
- case CriteriaType::KickInitiatorInLFGDungeon:
- case CriteriaType::KickVoterInLFGDungeon:
- case CriteriaType::KickTargetInLFGDungeon:
- case CriteriaType::AbandonedLFGDungeon:
- case CriteriaType::GroupedTankLeftEarlyInLFGDungeon:
- case CriteriaType::StartGarrisonMission:
- case CriteriaType::QualityUpgradedForGarrisonFollower:
- case CriteriaType::CompleteResearchGarrisonTalent:
- case CriteriaType::RecruitAnyGarrisonTroop:
- case CriteriaType::CompleteAnyWorldQuest:
- case CriteriaType::ParagonLevelIncreaseWithFaction:
- case CriteriaType::PlayerHasEarnedHonor:
- case CriteriaType::ChooseRelicTalent:
- case CriteriaType::AccountHonorLevelReached:
- case CriteriaType::MythicPlusCompleted:
- case CriteriaType::SocketAnySoulbindConduit:
- case CriteriaType::ObtainAnyItemWithCurrencyValue:
- case CriteriaType::EarnExpansionLevel:
- case CriteriaType::LearnTransmog:
- default:
- break; // Not implemented yet :(
- }
-
- for (CriteriaTree const* tree : *trees)
- {
- if (IsCompletedCriteriaTree(tree))
- CompletedCriteriaTree(tree, referencePlayer);
-
- AfterCriteriaTreeUpdate(tree, referencePlayer);
+ break;
}
+ case CriteriaType::UniquePetsOwned:
+ SetCriteriaProgress(criteria, referencePlayer->GetSession()->GetBattlePetMgr()->GetPetUniqueSpeciesCount(), referencePlayer);
+ break;
+ case CriteriaType::GuildAttainedLevel:
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer);
+ break;
+ // FIXME: not triggered in code as result, need to implement
+ case CriteriaType::RunInstance:
+ case CriteriaType::EarnTeamArenaRating:
+ case CriteriaType::EarnTitle:
+ case CriteriaType::MoneySpentOnGuildRepair:
+ case CriteriaType::CreatedItemsByCastingSpell:
+ case CriteriaType::FishInAnyPool:
+ case CriteriaType::GuildBankTabsPurchased:
+ case CriteriaType::EarnGuildAchievementPoints:
+ case CriteriaType::WinAnyBattleground:
+ case CriteriaType::EarnBattlegroundRating:
+ case CriteriaType::GuildTabardCreated:
+ case CriteriaType::CompleteQuestsCountForGuild:
+ case CriteriaType::HonorableKillsForGuild:
+ case CriteriaType::KillAnyCreatureForGuild:
+ case CriteriaType::CompleteAnyResearchProject:
+ case CriteriaType::CompleteGuildChallenge:
+ case CriteriaType::CompleteAnyGuildChallenge:
+ case CriteriaType::CompletedLFRDungeon:
+ case CriteriaType::AbandonedLFRDungeon:
+ case CriteriaType::KickInitiatorInLFRDungeon:
+ case CriteriaType::KickVoterInLFRDungeon:
+ case CriteriaType::KickTargetInLFRDungeon:
+ case CriteriaType::GroupedTankLeftEarlyInLFRDungeon:
+ case CriteriaType::AccountObtainPetThroughBattle:
+ case CriteriaType::WinPetBattle:
+ case CriteriaType::PlayerObtainPetThroughBattle:
+ case CriteriaType::ActivateGarrisonBuilding:
+ case CriteriaType::UpgradeGarrison:
+ case CriteriaType::StartAnyGarrisonMissionWithFollowerType:
+ case CriteriaType::SucceedAnyGarrisonMissionWithFollowerType:
+ case CriteriaType::SucceedGarrisonMission:
+ case CriteriaType::RecruitAnyGarrisonFollower:
+ case CriteriaType::LearnAnyGarrisonBlueprint:
+ case CriteriaType::CollectGarrisonShipment:
+ case CriteriaType::ItemLevelChangedForGarrisonFollower:
+ case CriteriaType::LevelChangedForGarrisonFollower:
+ case CriteriaType::LearnToy:
+ case CriteriaType::LearnAnyToy:
+ case CriteriaType::FindResearchObject:
+ case CriteriaType::ExhaustAnyResearchSite:
+ case CriteriaType::CompleteInternalCriteria:
+ case CriteriaType::CompleteAnyChallengeMode:
+ case CriteriaType::KilledAllUnitsInSpawnRegion:
+ case CriteriaType::CompleteChallengeMode:
+ case CriteriaType::CreatedItemsByCastingSpellWithLimit:
+ case CriteriaType::BattlePetAchievementPointsEarned:
+ case CriteriaType::ReleasedSpirit:
+ case CriteriaType::AccountKnownPet:
+ case CriteriaType::KickInitiatorInLFGDungeon:
+ case CriteriaType::KickVoterInLFGDungeon:
+ case CriteriaType::KickTargetInLFGDungeon:
+ case CriteriaType::AbandonedLFGDungeon:
+ case CriteriaType::GroupedTankLeftEarlyInLFGDungeon:
+ case CriteriaType::StartGarrisonMission:
+ case CriteriaType::QualityUpgradedForGarrisonFollower:
+ case CriteriaType::CompleteResearchGarrisonTalent:
+ case CriteriaType::RecruitAnyGarrisonTroop:
+ case CriteriaType::CompleteAnyWorldQuest:
+ case CriteriaType::ParagonLevelIncreaseWithFaction:
+ case CriteriaType::PlayerHasEarnedHonor:
+ case CriteriaType::ChooseRelicTalent:
+ case CriteriaType::AccountHonorLevelReached:
+ case CriteriaType::MythicPlusCompleted:
+ case CriteriaType::SocketAnySoulbindConduit:
+ case CriteriaType::ObtainAnyItemWithCurrencyValue:
+ case CriteriaType::EarnExpansionLevel:
+ case CriteriaType::LearnTransmog:
+ default:
+ break; // Not implemented yet :(
+ }
+
+ for (CriteriaTree const* tree : *trees)
+ {
+ if (IsCompletedCriteriaTree(tree))
+ CompletedCriteriaTree(tree, referencePlayer);
+
+ AfterCriteriaTreeUpdate(tree, referencePlayer);
}
}
diff --git a/src/server/game/Achievements/CriteriaHandler.h b/src/server/game/Achievements/CriteriaHandler.h
index 82c8f2ac7d1..067566d0bde 100644
--- a/src/server/game/Achievements/CriteriaHandler.h
+++ b/src/server/game/Achievements/CriteriaHandler.h
@@ -22,6 +22,7 @@
#include "DBCEnums.h"
#include "Duration.h"
#include "ObjectGuid.h"
+#include <span>
#include <unordered_map>
#include <vector>
#include <ctime>
@@ -284,6 +285,7 @@ public:
protected:
virtual void SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, Seconds timeElapsed, bool timedCompleted) const = 0;
+ void UpdateCriteria(Criteria const* criteria, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, WorldObject const* ref = nullptr, Player* referencePlayer = nullptr);
CriteriaProgress* GetCriteriaProgress(Criteria const* entry);
void SetCriteriaProgress(Criteria const* criteria, uint64 changeValue, Player* referencePlayer, ProgressType progressType = PROGRESS_SET);
void RemoveCriteriaProgress(Criteria const* criteria);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index f71eba989dd..7ec14e6ac99 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14892,7 +14892,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
GetReputationMgr().SetVisible(factionEntry);
break;
case QUEST_OBJECTIVE_CRITERIA_TREE:
- m_questObjectiveCriteriaMgr->ResetCriteriaTree(obj.ObjectID);
+ m_questObjectiveCriteriaMgr->ResetCriteriaTree(&obj);
break;
default:
break;
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
index 09c29dbac4d..4fe4e246663 100644
--- a/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
@@ -165,9 +165,11 @@ void QuestObjectiveCriteriaMgr::SaveToDB(CharacterDatabaseTransaction trans)
}
}
-void QuestObjectiveCriteriaMgr::ResetCriteriaTree(uint32 criteriaTreeId)
+void QuestObjectiveCriteriaMgr::ResetCriteriaTree(QuestObjective const* questObjective)
{
- CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(criteriaTreeId);
+ _completedObjectives.erase(questObjective->ID);
+
+ CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(questObjective->ObjectID);
if (!tree)
return;
@@ -175,6 +177,12 @@ void QuestObjectiveCriteriaMgr::ResetCriteriaTree(uint32 criteriaTreeId)
{
RemoveCriteriaProgress(criteriaTree->Criteria);
});
+
+ CriteriaMgr::WalkCriteriaTree(tree, [this](CriteriaTree const* criteriaTree)
+ {
+ if (criteriaTree->Criteria && advstd::ranges::contains(CriteriaMgr::GetRetroactivelyUpdateableCriteriaTypes(), CriteriaType(criteriaTree->Criteria->Entry->Type)))
+ UpdateCriteria(criteriaTree->Criteria, 0, 0, 0, nullptr, _owner);
+ });
}
void QuestObjectiveCriteriaMgr::SendAllData(Player const* /*receiver*/) const
@@ -210,7 +218,7 @@ void QuestObjectiveCriteriaMgr::CompletedObjective(QuestObjective const* questOb
bool QuestObjectiveCriteriaMgr::HasCompletedObjective(QuestObjective const* questObjective) const
{
- return _completedObjectives.find(questObjective->ID) != _completedObjectives.end();
+ return _completedObjectives.contains(questObjective->ID);
}
void QuestObjectiveCriteriaMgr::SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, Seconds timeElapsed, bool timedCompleted) const
@@ -293,7 +301,9 @@ void QuestObjectiveCriteriaMgr::CompletedCriteriaTree(CriteriaTree const* tree,
if (!objective)
return;
- CompletedObjective(objective, referencePlayer);
+ CriteriaTree const* entireObjectiveTree = sCriteriaMgr->GetCriteriaTree(objective->ObjectID);
+ if (IsCompletedCriteriaTree(entireObjectiveTree))
+ CompletedObjective(objective, referencePlayer);
}
void QuestObjectiveCriteriaMgr::SendPacket(WorldPacket const* data) const
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.h b/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
index f3ba31c2ac1..f38c456539b 100644
--- a/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
@@ -35,7 +35,7 @@ public:
void LoadFromDB(PreparedQueryResult objectiveResult, PreparedQueryResult criteriaResult);
void SaveToDB(CharacterDatabaseTransaction trans);
- void ResetCriteriaTree(uint32 criteriaTreeId);
+ void ResetCriteriaTree(QuestObjective const* questObjective);
void SendAllData(Player const* receiver) const override;