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

(cherry picked from commit 076293f1f2)
This commit is contained in:
ariel-
2017-03-16 00:40:27 -03:00
committed by funjoker
parent 4472a3cbf3
commit feb8205d6a
5 changed files with 83 additions and 136 deletions

View File

@@ -16108,11 +16108,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)
@@ -16142,11 +16141,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)
@@ -16326,11 +16324,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())

View File

@@ -3879,7 +3879,7 @@ void ObjectMgr::LoadQuests()
_questTemplates.clear();
_questObjectives.clear();
mExclusiveQuestGroups.clear();
_exclusiveQuestGroups.clear();
QueryResult result = WorldDatabase.Query("SELECT "
//0 1 2 3 4 5 6 7 8 9 10 11 12
@@ -3930,123 +3930,63 @@ void ObjectMgr::LoadQuests()
_questTemplates[newQuest->GetQuestId()] = newQuest;
} while (result->NextRow());
// 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* QueryExtra;
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 4 5
{ "ID, EmoteOnComplete, EmoteOnIncomplete, EmoteOnCompleteDelay, EmoteOnIncompleteDelay, 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,"
// 17
" ScriptName", "quest_template_addon", "", "template addons", &Quest::LoadQuestTemplateAddon },
// 0 1
{ "QuestId, RewardMailSenderEntry", "quest_mail_sender", "", "mail sender entries", &Quest::LoadQuestMailSender },
// QuestID needs to be fields[0]
// 0 1 2 3 4 5 6 7 8 9
{ "QuestID, ID, Type, StorageIndex, ObjectID, Amount, Flags, Flags2, ProgressBarWeight, Description", "quest_objectives", "ORDER BY `Order` ASC, StorageIndex ASC", "quest objectives", &Quest::LoadQuestObjective }
};
for (QuestLoaderHelper const& loader : QuestLoaderHelpers)
{
do
QueryResult result = WorldDatabase.Query(Trinity::StringFormat("SELECT %s FROM %s %s", loader.QueryFields, loader.TableName, loader.QueryExtra).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 4 5
result = WorldDatabase.Query("SELECT ID, EmoteOnComplete, EmoteOnIncomplete, EmoteOnCompleteDelay, EmoteOnIncompleteDelay, 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
"RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, RewardMailSenderEntry, "
//17 18
"SpecialFlags, ScriptName 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());
}
// Load `quest_objectives`
// 0 1 2 3 4 5 6 7 8 9
result = WorldDatabase.Query("SELECT ID, QuestID, Type, StorageIndex, ObjectID, Amount, Flags, Flags2, ProgressBarWeight, Description FROM quest_objectives ORDER BY `Order` ASC, StorageIndex ASC");
if (!result)
{
TC_LOG_ERROR("server.loading", ">> Loaded 0 quest objectives. DB table `quest_objectives` is empty.");
}
else
{
do
{
Field* fields = result->Fetch();
uint32 questId = fields[1].GetUInt32();
auto itr = _questTemplates.find(questId);
if (itr != _questTemplates.end())
itr->second->LoadQuestObjective(fields);
else
TC_LOG_ERROR("server.loading", "Table `quest_objectives` has objective 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());
}
}
// Load `quest_visual_effect` join table with quest_objectives because visual effects are based on objective ID (core stores objectives by their index in quest)
@@ -4694,7 +4634,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->_limitTime)
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED);
}

View File

@@ -540,6 +540,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) { }
@@ -1206,6 +1209,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();
@@ -1344,11 +1352,6 @@ class TC_GAME_API ObjectMgr
uint64 GenerateCreatureSpawnId();
uint64 GenerateGameObjectSpawnId();
typedef std::multimap<int32, uint32> ExclusiveQuestGroups;
typedef std::pair<ExclusiveQuestGroups::const_iterator, ExclusiveQuestGroups::const_iterator> ExclusiveQuestGroupsBounds;
ExclusiveQuestGroups mExclusiveQuestGroups;
MailLevelReward const* GetMailLevelReward(uint8 level, uint8 race)
{
MailLevelRewardContainer::const_iterator map_itr = _mailLevelRewardStore.find(level);
@@ -1677,6 +1680,8 @@ class TC_GAME_API ObjectMgr
QuestRelations _creatureQuestInvolvedRelations;
QuestRelationsReverse _creatureQuestInvolvedRelationsReverse;
ExclusiveQuestGroups _exclusiveQuestGroups;
//character reserved names
typedef std::set<std::wstring> ReservedNamesContainer;
ReservedNamesContainer _reservedNamesStore;

View File

@@ -202,19 +202,23 @@ void Quest::LoadQuestTemplateAddon(Field* fields)
_requiredMinRepValue = fields[13].GetInt32();
_requiredMaxRepValue = fields[14].GetInt32();
_sourceItemIdCount = fields[15].GetUInt8();
_rewardMailSenderEntry = fields[16].GetUInt32();
_specialFlags = fields[17].GetUInt8();
_scriptId = sObjectMgr->GetScriptId(fields[18].GetString());
_specialFlags = fields[16].GetUInt8();
_scriptId = sObjectMgr->GetScriptId(fields[17].GetString());
if (_specialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT)
_flags |= QUEST_FLAGS_AUTO_ACCEPT;
}
void Quest::LoadQuestMailSender(Field* fields)
{
_rewardMailSenderEntry = fields[1].GetUInt32();
}
void Quest::LoadQuestObjective(Field* fields)
{
QuestObjective obj;
obj.ID = fields[0].GetUInt32();
obj.QuestID = fields[1].GetUInt32();
obj.QuestID = fields[0].GetUInt32();
obj.ID = fields[1].GetUInt32();
obj.Type = fields[2].GetUInt8();
obj.StorageIndex = fields[3].GetInt8();
obj.ObjectID = fields[4].GetInt32();

View File

@@ -351,6 +351,7 @@ class TC_GAME_API Quest
void LoadQuestRequestItems(Field* fields);
void LoadQuestOfferReward(Field* fields);
void LoadQuestTemplateAddon(Field* fields);
void LoadQuestMailSender(Field* fields);
void LoadQuestObjective(Field* fields);
void LoadQuestObjectiveVisualEffect(Field* fields);