diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 75409502e2..13d41a591b 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -15459,11 +15459,10 @@ bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) // each-from-all exclusive group (< 0) // can be start if only all quests in prev quest exclusive group completed and rewarded - ObjectMgr::ExclusiveQuestGroupsBounds range(sObjectMgr->mExclusiveQuestGroups.equal_range(qPrevInfo->GetExclusiveGroup())); - - for (; range.first != range.second; ++range.first) + auto bounds = sObjectMgr->GetExclusiveQuestGroupBounds(qPrevInfo->GetExclusiveGroup()); + for (auto itr = bounds.first; itr != bounds.second; ++itr) { - uint32 exclude_Id = range.first->second; + uint32 exclude_Id = itr->second; // skip checked quest id, only state of other quests in group is interesting if (exclude_Id == prevId) @@ -15493,11 +15492,10 @@ bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) // each-from-all exclusive group (< 0) // can be start if only all quests in prev quest exclusive group active - ObjectMgr::ExclusiveQuestGroupsBounds range(sObjectMgr->mExclusiveQuestGroups.equal_range(qPrevInfo->GetExclusiveGroup())); - - for (; range.first != range.second; ++range.first) + auto bounds = sObjectMgr->GetExclusiveQuestGroupBounds(qPrevInfo->GetExclusiveGroup()); + for (auto itr = bounds.first; itr != bounds.second; ++itr) { - uint32 exclude_Id = range.first->second; + uint32 exclude_Id = itr->second; // skip checked quest id, only state of other quests in group is interesting if (exclude_Id == prevId) @@ -15679,11 +15677,10 @@ bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) if (qInfo->GetExclusiveGroup() <= 0) return true; - ObjectMgr::ExclusiveQuestGroupsBounds range(sObjectMgr->mExclusiveQuestGroups.equal_range(qInfo->GetExclusiveGroup())); - - for (; range.first != range.second; ++range.first) + auto bounds = sObjectMgr->GetExclusiveQuestGroupBounds(qInfo->GetExclusiveGroup()); + for (auto itr = bounds.first; itr != bounds.second; ++itr) { - uint32 exclude_Id = range.first->second; + uint32 exclude_Id = itr->second; // skip checked quest id, only state of other quests in group is interesting if (exclude_Id == qInfo->GetQuestId()) diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 3f5e9a7433..5772f3cbdd 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4227,7 +4227,7 @@ void ObjectMgr::LoadQuests() delete itr->second; _questTemplates.clear(); - mExclusiveQuestGroups.clear(); + _exclusiveQuestGroups.clear(); QueryResult result = WorldDatabase.Query("SELECT " //0 1 2 3 4 5 6 7 8 @@ -4280,98 +4280,56 @@ void ObjectMgr::LoadQuests() std::unordered_map usedMailTemplates; - // Load `quest_details` - // 0 1 2 3 4 5 6 7 8 - result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4 FROM quest_details"); + struct QuestLoaderHelper + { + typedef void(Quest::* QuestLoaderFunction)(Field* fields); - if (!result) + char const* QueryFields; + char const* TableName; + char const* TableDesc; + QuestLoaderFunction LoaderFunction; + }; + + static std::vector const QuestLoaderHelpers = { - TC_LOG_ERROR("server.loading", ">> Loaded 0 quest details. DB table `quest_details` is empty."); - } - else + // 0 1 2 3 4 5 6 7 8 + { "ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4", "quest_details", "details", &Quest::LoadQuestDetails }, + + // 0 1 2 3 + { "ID, EmoteOnComplete, EmoteOnIncomplete, CompletionText", "quest_request_items", "request items", &Quest::LoadQuestRequestItems }, + + // 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 + " RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, SpecialFlags", "quest_template_addon", "template addons", &Quest::LoadQuestTemplateAddon }, + + // 0 1 + { "QuestId, RewardMailSenderEntry", "quest_mail_sender", "mail sender entries", &Quest::LoadQuestMailSender } + }; + + for (QuestLoaderHelper const& loader : QuestLoaderHelpers) { - do + QueryResult result = WorldDatabase.Query(Trinity::StringFormat("SELECT %s FROM %s", loader.QueryFields, loader.TableName).c_str()); + + if (!result) + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest %s. DB table `%s` is empty.", loader.TableDesc, loader.TableName); + else { - Field* fields = result->Fetch(); - uint32 questId = fields[0].GetUInt32(); + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[0].GetUInt32(); - auto itr = _questTemplates.find(questId); - if (itr != _questTemplates.end()) - itr->second->LoadQuestDetails(fields); - else - TC_LOG_ERROR("server.loading", "Table `quest_details` has data for quest %u but such quest does not exist", questId); - } while (result->NextRow()); - } - - // Load `quest_request_items` - // 0 1 2 3 - result = WorldDatabase.Query("SELECT ID, EmoteOnComplete, EmoteOnIncomplete, CompletionText FROM quest_request_items"); - - if (!result) - { - TC_LOG_ERROR("server.loading", ">> Loaded 0 quest request items. DB table `quest_request_items` is empty."); - } - else - { - do - { - Field* fields = result->Fetch(); - uint32 questId = fields[0].GetUInt32(); - - auto itr = _questTemplates.find(questId); - if (itr != _questTemplates.end()) - itr->second->LoadQuestRequestItems(fields); - else - TC_LOG_ERROR("server.loading", "Table `quest_request_items` has data for quest %u but such quest does not exist", questId); - } while (result->NextRow()); - } - - // Load `quest_offer_reward` - // 0 1 2 3 4 5 6 7 8 9 - result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4, RewardText FROM quest_offer_reward"); - - if (!result) - { - TC_LOG_ERROR("server.loading", ">> Loaded 0 quest reward emotes. DB table `quest_offer_reward` is empty."); - } - else - { - do - { - Field* fields = result->Fetch(); - uint32 questId = fields[0].GetUInt32(); - - auto itr = _questTemplates.find(questId); - if (itr != _questTemplates.end()) - itr->second->LoadQuestOfferReward(fields); - else - TC_LOG_ERROR("server.loading", "Table `quest_offer_reward` has data for quest %u but such quest does not exist", questId); - } while (result->NextRow()); - } - - // Load `quest_template_addon` - // 0 1 2 3 4 5 6 7 8 - result = WorldDatabase.Query("SELECT ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, RewardMailTemplateID, RewardMailDelay, " - //9 10 11 12 13 14 15 16 17 - "RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, RewardMailSenderEntry, SpecialFlags FROM quest_template_addon LEFT JOIN quest_mail_sender ON Id=QuestId"); - - if (!result) - { - TC_LOG_ERROR("server.loading", ">> Loaded 0 quest template addons. DB table `quest_template_addon` is empty."); - } - else - { - do - { - Field* fields = result->Fetch(); - uint32 questId = fields[0].GetUInt32(); - - auto itr = _questTemplates.find(questId); - if (itr != _questTemplates.end()) - itr->second->LoadQuestTemplateAddon(fields); - else - TC_LOG_ERROR("server.loading", "Table `quest_template_addon` has data for quest %u but such quest does not exist", questId); - } while (result->NextRow()); + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + (itr->second->*loader.LoaderFunction)(fields); + else + TC_LOG_ERROR("server.loading", "Table `%s` has data for quest %u but such quest does not exist", loader.TableName, questId); + } while (result->NextRow()); + } } // Post processing @@ -5035,7 +4993,7 @@ void ObjectMgr::LoadQuests() } if (qinfo->_exclusiveGroup) - mExclusiveQuestGroups.insert(std::pair(qinfo->_exclusiveGroup, qinfo->GetQuestId())); + _exclusiveQuestGroups.insert(std::pair(qinfo->_exclusiveGroup, qinfo->GetQuestId())); if (qinfo->_timeAllowed) qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED); if (qinfo->_requiredPlayerKills) diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index d631657733..bb14ce710e 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -596,6 +596,9 @@ typedef std::multimap QuestRelationsReverse; // quest -> unit/go typedef std::pair QuestRelationBounds; typedef std::pair QuestRelationReverseBounds; +typedef std::multimap ExclusiveQuestGroups; // exclusiveGroupId -> quest +typedef std::pair ExclusiveQuestGroupsBounds; + struct PlayerCreateInfoItem { PlayerCreateInfoItem(uint32 id, uint32 amount) : item_id(id), item_amount(amount) { } @@ -1125,6 +1128,11 @@ class TC_GAME_API ObjectMgr return _creatureQuestInvolvedRelationsReverse.equal_range(questId); } + ExclusiveQuestGroupsBounds GetExclusiveQuestGroupBounds(int32 exclusiveGroupId) const + { + return _exclusiveQuestGroups.equal_range(exclusiveGroupId); + } + bool LoadTrinityStrings(); void LoadEventScripts(); @@ -1261,11 +1269,6 @@ class TC_GAME_API ObjectMgr Trinity::IteratorPair GetSpawnDataForGroup(uint32 groupId) const { return Trinity::Containers::MapEqualRange(_spawnGroupMapStore, groupId); } std::vector const* GetSpawnGroupsForInstance(uint32 instanceId) const { auto it = _instanceSpawnGroupStore.find(instanceId); return it != _instanceSpawnGroupStore.end() ? &it->second : nullptr; } - typedef std::multimap ExclusiveQuestGroups; - typedef std::pair ExclusiveQuestGroupsBounds; - - ExclusiveQuestGroups mExclusiveQuestGroups; - MailLevelReward const* GetMailLevelReward(uint32 level, uint32 raceMask) const { MailLevelRewardContainer::const_iterator map_itr = _mailLevelRewardStore.find(level); @@ -1623,6 +1626,8 @@ class TC_GAME_API ObjectMgr QuestRelations _creatureQuestInvolvedRelations; QuestRelationsReverse _creatureQuestInvolvedRelationsReverse; + ExclusiveQuestGroups _exclusiveQuestGroups; + //character reserved names typedef std::set ReservedNamesContainer; ReservedNamesContainer _reservedNamesStore; diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index e0a585c550..b643818f17 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -225,13 +225,17 @@ void Quest::LoadQuestTemplateAddon(Field* fields) _requiredMinRepValue = fields[13].GetInt32(); _requiredMaxRepValue = fields[14].GetInt32(); _startItemCount = fields[15].GetUInt8(); - _rewardMailSenderEntry = fields[16].GetUInt32(); - _specialFlags = fields[17].GetUInt8(); + _specialFlags = fields[16].GetUInt8(); if (_specialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT) _flags |= QUEST_FLAGS_AUTO_ACCEPT; } +void Quest::LoadQuestMailSender(Field* fields) +{ + _rewardMailSenderEntry = fields[1].GetUInt32(); +} + uint32 Quest::GetXPReward(Player const* player) const { if (player) diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index d5c027844f..0ba77b1e44 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -233,6 +233,7 @@ class TC_GAME_API Quest void LoadQuestRequestItems(Field* fields); void LoadQuestOfferReward(Field* fields); void LoadQuestTemplateAddon(Field* fields); + void LoadQuestMailSender(Field* fields); uint32 GetXPReward(Player const* player) const;