aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Globals/ObjectMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp56
1 files changed, 52 insertions, 4 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 486c1712d35..365f23323fb 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -4437,9 +4437,9 @@ void ObjectMgr::LoadQuests()
// 0 1 2 3 4 5 6 7 8 9
{ "ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4, RewardText", "quest_offer_reward", "reward emotes", &Quest::LoadQuestOfferReward },
- // 0 1 2 3 4 5 6 7 8
- { "ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, RewardMailTemplateID, RewardMailDelay,"
- // 9 10 11 12 13 14 15 16
+ // 0 1 2 3 4 5 6 7 8 9
+ { "ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, BreadcrumbForQuestId, RewardMailTemplateID, RewardMailDelay,"
+ // 10 11 12 13 14 15 16 17
" RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, SpecialFlags", "quest_template_addon", "template addons", &Quest::LoadQuestTemplateAddon },
// 0 1
@@ -4978,8 +4978,11 @@ void ObjectMgr::LoadQuests()
// fill additional data stores
if (uint32 prevQuestId = std::abs(qinfo->_prevQuestId))
{
- if (!_questTemplates.count(prevQuestId))
+ auto prevQuestItr = _questTemplates.find(prevQuestId);
+ if (prevQuestItr == _questTemplates.end())
TC_LOG_ERROR("sql.sql", "Quest %u has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->_prevQuestId);
+ else if (prevQuestItr->second._breadcrumbForQuestId)
+ TC_LOG_ERROR("sql.sql", "Quest %u should not be unlocked by breadcrumb quest %u", qinfo->_id, prevQuestId);
}
if (uint32 nextQuestId = qinfo->_nextQuestId)
@@ -4991,6 +4994,19 @@ void ObjectMgr::LoadQuests()
nextQuestItr->second.DependentPreviousQuests.push_back(qinfo->GetQuestId());
}
+ if (uint32 breadcrumbForQuestId = std::abs(qinfo->_breadcrumbForQuestId))
+ {
+ if (_questTemplates.find(breadcrumbForQuestId) == _questTemplates.end())
+ {
+ TC_LOG_ERROR("sql.sql", "Quest %u is a breadcrumb for quest %u, but no such quest exists", qinfo->_id, breadcrumbForQuestId);
+ qinfo->_breadcrumbForQuestId = 0;
+ }
+ if (qinfo->_nextQuestId)
+ TC_LOG_ERROR("sql.sql", "Quest %u is a breadcrumb, should not unlock quest %u", qinfo->_id, qinfo->_nextQuestId);
+ if (qinfo->_exclusiveGroup)
+ TC_LOG_ERROR("sql.sql", "Quest %u is a breadcrumb in exclusive group %i", qinfo->_id, qinfo->_exclusiveGroup);
+ }
+
if (qinfo->_exclusiveGroup)
_exclusiveQuestGroups.emplace(qinfo->_exclusiveGroup, qinfo->GetQuestId());
if (qinfo->_timeAllowed)
@@ -5019,6 +5035,38 @@ void ObjectMgr::LoadQuests()
}
}
+ // Disallow any breadcrumb loops and inform quests of their breadcrumbs
+ for (auto& questPair : _questTemplates)
+ {
+ // skip post-loading checks for disabled quests
+ if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, questPair.first, nullptr))
+ continue;
+
+ Quest* qinfo = &questPair.second;
+ uint32 qid = qinfo->GetQuestId();
+ uint32 breadcrumbForQuestId = std::abs(qinfo->_breadcrumbForQuestId);
+ std::set<uint32> questSet;
+
+ while(breadcrumbForQuestId)
+ {
+ //a previously visited quest was found as a breadcrumb quest
+ //breadcrumb loop found!
+ if (!questSet.insert(qinfo->_id).second)
+ {
+ TC_LOG_ERROR("sql.sql", "Breadcrumb quests %u and %u are in a loop", qid, breadcrumbForQuestId);
+ qinfo->_breadcrumbForQuestId = 0;
+ break;
+ }
+
+ qinfo = const_cast<Quest*>(sObjectMgr->GetQuestTemplate(breadcrumbForQuestId));
+
+ //every quest has a list of every breadcrumb towards it
+ qinfo->DependentBreadcrumbQuests.push_back(qid);
+
+ breadcrumbForQuestId = qinfo->GetBreadcrumbForQuestId();
+ }
+ }
+
// check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
{