Core/Globals: some changes in quest loading
- Made load/reload associated quest tables data-driven, so removed a bunch of similar looking code from ObjectMgr (yay!) - Codestyle and encapsulation for ExclusiveQuestGroups
This commit is contained in:
1 parent
ef6f5abf75
commit
330f399de3
5 files changed
+73
-108
No files matched your search
@@ -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())
|
||||
|
||||
@@ -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<uint32, uint32> 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<QuestLoaderHelper> 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<int32, uint32>(qinfo->_exclusiveGroup, qinfo->GetQuestId()));
|
||||
_exclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->_exclusiveGroup, qinfo->GetQuestId()));
|
||||
if (qinfo->_timeAllowed)
|
||||
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED);
|
||||
if (qinfo->_requiredPlayerKills)
|
||||
|
||||
@@ -596,6 +596,9 @@ typedef std::multimap<uint32, uint32> QuestRelationsReverse; // quest -> unit/go
|
||||
typedef std::pair<QuestRelations::const_iterator, QuestRelations::const_iterator> QuestRelationBounds;
|
||||
typedef std::pair<QuestRelationsReverse::const_iterator, QuestRelationsReverse::const_iterator> QuestRelationReverseBounds;
|
||||
|
||||
typedef std::multimap<int32, uint32> ExclusiveQuestGroups; // exclusiveGroupId -> quest
|
||||
typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> 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<SpawnGroupLinkContainer::const_iterator> GetSpawnDataForGroup(uint32 groupId) const { return Trinity::Containers::MapEqualRange(_spawnGroupMapStore, groupId); }
|
||||
std::vector<InstanceSpawnGroupInfo> const* GetSpawnGroupsForInstance(uint32 instanceId) const { auto it = _instanceSpawnGroupStore.find(instanceId); return it != _instanceSpawnGroupStore.end() ? &it->second : nullptr; }
|
||||
|
||||
typedef std::multimap<int32, uint32> ExclusiveQuestGroups;
|
||||
typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> 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<std::wstring> ReservedNamesContainer;
|
||||
ReservedNamesContainer _reservedNamesStore;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in new issue
Block a user