Core/Quests: fixed exclusivegroup interaction with prevquestId and nextQuestId.
- They should work as documented by wiki now. - Add some consts to Player methods - Fixed negative PrevQuestID to mean only active quest (ie not rewarded/complete, as those quests are required to complete another) Closes #19300
This commit is contained in:
1 parent
d78ad034d0
commit
a7484837a8
4 files changed
+93
-97
No files matched your search
@@ -14666,7 +14666,7 @@ bool Player::CanSeeStartQuest(Quest const* quest)
|
||||
{
|
||||
if (!DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, quest->GetQuestId(), this) && SatisfyQuestClass(quest, false) && SatisfyQuestRace(quest, false) &&
|
||||
SatisfyQuestSkill(quest, false) && SatisfyQuestExclusiveGroup(quest, false) && SatisfyQuestReputation(quest, false) &&
|
||||
SatisfyQuestPreviousQuest(quest, false) && SatisfyQuestNextChain(quest, false) &&
|
||||
SatisfyQuestDependentQuests(quest, false) && SatisfyQuestNextChain(quest, false) &&
|
||||
SatisfyQuestPrevChain(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) &&
|
||||
SatisfyQuestMonth(quest, false) && SatisfyQuestSeasonal(quest, false))
|
||||
{
|
||||
@@ -14682,7 +14682,7 @@ bool Player::CanTakeQuest(Quest const* quest, bool msg)
|
||||
&& SatisfyQuestStatus(quest, msg) && SatisfyQuestExclusiveGroup(quest, msg)
|
||||
&& SatisfyQuestClass(quest, msg) && SatisfyQuestRace(quest, msg) && SatisfyQuestLevel(quest, msg)
|
||||
&& SatisfyQuestSkill(quest, msg) && SatisfyQuestReputation(quest, msg)
|
||||
&& SatisfyQuestPreviousQuest(quest, msg) && SatisfyQuestTimed(quest, msg)
|
||||
&& SatisfyQuestDependentQuests(quest, msg) && SatisfyQuestTimed(quest, msg)
|
||||
&& SatisfyQuestNextChain(quest, msg) && SatisfyQuestPrevChain(quest, msg)
|
||||
&& SatisfyQuestDay(quest, msg) && SatisfyQuestWeek(quest, msg)
|
||||
&& SatisfyQuestMonth(quest, msg) && SatisfyQuestSeasonal(quest, msg)
|
||||
@@ -15436,95 +15436,91 @@ bool Player::SatisfyQuestLog(bool msg) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg)
|
||||
bool Player::SatisfyQuestDependentQuests(Quest const* qInfo, bool msg) const
|
||||
{
|
||||
return SatisfyQuestPreviousQuest(qInfo, msg) && SatisfyQuestDependentPreviousQuests(qInfo, msg);
|
||||
}
|
||||
|
||||
bool Player::SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const
|
||||
{
|
||||
// No previous quest (might be first quest in a series)
|
||||
if (qInfo->PrevQuests.empty())
|
||||
if (!qInfo->GetPrevQuestId())
|
||||
return true;
|
||||
|
||||
for (auto iter = qInfo->PrevQuests.begin(); iter != qInfo->PrevQuests.end(); ++iter)
|
||||
{
|
||||
uint32 prevId = abs(*iter);
|
||||
uint32 prevId = std::abs(qInfo->GetPrevQuestId());
|
||||
// If positive previous quest rewarded, return true
|
||||
if (qInfo->GetPrevQuestId() > 0 && m_RewardedQuests.count(prevId) > 0)
|
||||
return true;
|
||||
|
||||
Quest const* qPrevInfo = sObjectMgr->GetQuestTemplate(prevId);
|
||||
// If negative previous quest active, return true
|
||||
if (qInfo->GetPrevQuestId() < 0 && GetQuestStatus(prevId) == QUEST_STATUS_INCOMPLETE)
|
||||
return true;
|
||||
|
||||
if (qPrevInfo)
|
||||
{
|
||||
// If any of the positive previous quests completed, return true
|
||||
if (*iter > 0 && m_RewardedQuests.find(prevId) != m_RewardedQuests.end())
|
||||
{
|
||||
// skip one-from-all exclusive group
|
||||
if (qPrevInfo->GetExclusiveGroup() >= 0)
|
||||
return true;
|
||||
|
||||
// each-from-all exclusive group (< 0)
|
||||
// can be start if only all quests in prev quest exclusive group completed and rewarded
|
||||
auto bounds = sObjectMgr->GetExclusiveQuestGroupBounds(qPrevInfo->GetExclusiveGroup());
|
||||
for (auto itr = bounds.first; itr != bounds.second; ++itr)
|
||||
{
|
||||
uint32 exclude_Id = itr->second;
|
||||
|
||||
// skip checked quest id, only state of other quests in group is interesting
|
||||
if (exclude_Id == prevId)
|
||||
continue;
|
||||
|
||||
// alternative quest from group also must be completed and rewarded (reported)
|
||||
if (m_RewardedQuests.find(exclude_Id) == m_RewardedQuests.end())
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||
TC_LOG_DEBUG("misc", "Player::SatisfyQuestPreviousQuest: Sent INVALIDREASON_DONT_HAVE_REQ (QuestID: %u) because player '%s' (%s) doesn't have the required quest (1).",
|
||||
qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// If any of the negative previous quests active, return true
|
||||
if (*iter < 0 && GetQuestStatus(prevId) != QUEST_STATUS_NONE)
|
||||
{
|
||||
// skip one-from-all exclusive group
|
||||
if (qPrevInfo->GetExclusiveGroup() >= 0)
|
||||
return true;
|
||||
|
||||
// each-from-all exclusive group (< 0)
|
||||
// can be start if only all quests in prev quest exclusive group active
|
||||
auto bounds = sObjectMgr->GetExclusiveQuestGroupBounds(qPrevInfo->GetExclusiveGroup());
|
||||
for (auto itr = bounds.first; itr != bounds.second; ++itr)
|
||||
{
|
||||
uint32 exclude_Id = itr->second;
|
||||
|
||||
// skip checked quest id, only state of other quests in group is interesting
|
||||
if (exclude_Id == prevId)
|
||||
continue;
|
||||
|
||||
// alternative quest from group also must be active
|
||||
if (GetQuestStatus(exclude_Id) != QUEST_STATUS_NONE)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||
TC_LOG_DEBUG("misc", "Player::SatisfyQuestPreviousQuest: Sent INVALIDREASON_DONT_HAVE_REQ (QuestID: %u) because player '%s' (%s) doesn't have the required quest (2).",
|
||||
qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str());
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Has only positive prev. quests in non-rewarded state
|
||||
// and negative prev. quests in non-active state
|
||||
// Has positive prev. quest in non-rewarded state
|
||||
// and negative prev. quest in non-active state
|
||||
if (msg)
|
||||
{
|
||||
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||
TC_LOG_DEBUG("misc", "Player::SatisfyQuestPreviousQuest: Sent INVALIDREASON_DONT_HAVE_REQ (QuestID: %u) because player '%s' (%s) doesn't have required quest (3).",
|
||||
TC_LOG_DEBUG("misc", "Player::SatisfyQuestPreviousQuest: Sent INVALIDREASON_DONT_HAVE_REQ (QuestID: %u) because player '%s' (%s) doesn't have required quest %u.",
|
||||
qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str(), prevId);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Player::SatisfyQuestDependentPreviousQuests(Quest const* qInfo, bool msg) const
|
||||
{
|
||||
// No previous quest (might be first quest in a series)
|
||||
if (qInfo->DependentPreviousQuests.empty())
|
||||
return true;
|
||||
|
||||
for (uint32 prevId : qInfo->DependentPreviousQuests)
|
||||
{
|
||||
// checked in startup
|
||||
Quest const* questInfo = sObjectMgr->GetQuestTemplate(prevId);
|
||||
ASSERT(questInfo);
|
||||
|
||||
// If any of the previous quests completed, return true
|
||||
if (IsQuestRewarded(prevId))
|
||||
{
|
||||
// skip one-from-all exclusive group
|
||||
if (questInfo->GetExclusiveGroup() >= 0)
|
||||
return true;
|
||||
|
||||
// each-from-all exclusive group (< 0)
|
||||
// can be start if only all quests in prev quest exclusive group completed and rewarded
|
||||
auto bounds = sObjectMgr->GetExclusiveQuestGroupBounds(questInfo->GetExclusiveGroup());
|
||||
for (auto itr = bounds.first; itr != bounds.second; ++itr)
|
||||
{
|
||||
// skip checked quest id, only state of other quests in group is interesting
|
||||
uint32 exclusiveQuestId = itr->second;
|
||||
if (exclusiveQuestId == prevId)
|
||||
continue;
|
||||
|
||||
// alternative quest from group also must be completed and rewarded (reported)
|
||||
if (!IsQuestRewarded(exclusiveQuestId))
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||
TC_LOG_DEBUG("misc", "Player::SatisfyQuestDependentPreviousQuests: Sent INVALIDREASON_DONT_HAVE_REQ (QuestID: %u) because player '%s' (%s) doesn't have the required quest (1).",
|
||||
qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Has only prev. quests in non-rewarded state
|
||||
if (msg)
|
||||
{
|
||||
SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ);
|
||||
TC_LOG_DEBUG("misc", "Player::SatisfyQuestDependentPreviousQuests: Sent INVALIDREASON_DONT_HAVE_REQ (QuestID: %u) because player '%s' (%s) doesn't have required quest (2).",
|
||||
qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str());
|
||||
}
|
||||
|
||||
@@ -15671,7 +15667,7 @@ bool Player::SatisfyQuestTimed(Quest const* qInfo, bool msg) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg)
|
||||
bool Player::SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) const
|
||||
{
|
||||
// non positive exclusive group, if > 0 then can be start if any other quest in exclusive group already started/completed
|
||||
if (qInfo->GetExclusiveGroup() <= 0)
|
||||
@@ -15746,9 +15742,9 @@ bool Player::SatisfyQuestPrevChain(Quest const* qInfo, bool msg)
|
||||
if (qInfo->PrevChainQuests.empty())
|
||||
return true;
|
||||
|
||||
for (auto iter = qInfo->PrevChainQuests.begin(); iter != qInfo->PrevChainQuests.end(); ++iter)
|
||||
for (uint32 prevQuestId : qInfo->PrevChainQuests)
|
||||
{
|
||||
QuestStatusMap::const_iterator itr = m_QuestStatus.find(*iter);
|
||||
auto itr = m_QuestStatus.find(prevQuestId);
|
||||
|
||||
// If any of the previous quests in chain active, return false
|
||||
if (itr != m_QuestStatus.end() && itr->second.Status != QUEST_STATUS_NONE)
|
||||
@@ -15801,7 +15797,7 @@ bool Player::SatisfyQuestDay(Quest const* qInfo, bool msg) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::SatisfyQuestWeek(Quest const* qInfo, bool /*msg*/)
|
||||
bool Player::SatisfyQuestWeek(Quest const* qInfo, bool /*msg*/) const
|
||||
{
|
||||
if (!qInfo->IsWeekly() || m_weeklyquests.empty())
|
||||
return true;
|
||||
@@ -15823,7 +15819,7 @@ bool Player::SatisfyQuestSeasonal(Quest const* qInfo, bool /*msg*/) const
|
||||
return itr->second.find(qInfo->GetQuestId()) == itr->second.end();
|
||||
}
|
||||
|
||||
bool Player::SatisfyQuestMonth(Quest const* qInfo, bool /*msg*/)
|
||||
bool Player::SatisfyQuestMonth(Quest const* qInfo, bool /*msg*/) const
|
||||
{
|
||||
if (!qInfo->IsMonthly() || m_monthlyquests.empty())
|
||||
return true;
|
||||
|
||||
@@ -1366,19 +1366,21 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
||||
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestLevel(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestLog(bool msg) const;
|
||||
bool SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg);
|
||||
bool SatisfyQuestDependentQuests(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestDependentPreviousQuests(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestClass(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestRace(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestReputation(Quest const* qInfo, bool msg);
|
||||
bool SatisfyQuestStatus(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestConditions(Quest const* qInfo, bool msg);
|
||||
bool SatisfyQuestTimed(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg);
|
||||
bool SatisfyQuestExclusiveGroup(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestNextChain(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestPrevChain(Quest const* qInfo, bool msg);
|
||||
bool SatisfyQuestDay(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestWeek(Quest const* qInfo, bool msg);
|
||||
bool SatisfyQuestMonth(Quest const* qInfo, bool msg);
|
||||
bool SatisfyQuestWeek(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestMonth(Quest const* qInfo, bool msg) const;
|
||||
bool SatisfyQuestSeasonal(Quest const* qInfo, bool msg) const;
|
||||
bool GiveQuestSourceItem(Quest const* quest);
|
||||
bool TakeQuestSourceItem(uint32 questId, bool msg);
|
||||
|
||||
@@ -4223,7 +4223,7 @@ void ObjectMgr::LoadQuests()
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
// For reload case
|
||||
for (QuestMap::const_iterator itr=_questTemplates.begin(); itr != _questTemplates.end(); ++itr)
|
||||
for (auto itr = _questTemplates.begin(); itr != _questTemplates.end(); ++itr)
|
||||
delete itr->second;
|
||||
_questTemplates.clear();
|
||||
|
||||
@@ -4312,7 +4312,7 @@ void ObjectMgr::LoadQuests()
|
||||
|
||||
for (QuestLoaderHelper const& loader : QuestLoaderHelpers)
|
||||
{
|
||||
QueryResult result = WorldDatabase.Query(Trinity::StringFormat("SELECT %s FROM %s", loader.QueryFields, loader.TableName).c_str());
|
||||
QueryResult result = WorldDatabase.PQuery("SELECT %s FROM %s", loader.QueryFields, loader.TableName);
|
||||
|
||||
if (!result)
|
||||
TC_LOG_ERROR("server.loading", ">> Loaded 0 quest %s. DB table `%s` is empty.", loader.TableDesc, loader.TableName);
|
||||
@@ -4976,8 +4976,6 @@ void ObjectMgr::LoadQuests()
|
||||
{
|
||||
if (_questTemplates.find(std::abs(qinfo->GetPrevQuestId())) == _questTemplates.end())
|
||||
TC_LOG_ERROR("sql.sql", "Quest %d has PrevQuestId %i, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId());
|
||||
else
|
||||
qinfo->PrevQuests.push_back(qinfo->_prevQuestId);
|
||||
}
|
||||
|
||||
if (qinfo->_nextQuestId)
|
||||
@@ -4986,7 +4984,7 @@ void ObjectMgr::LoadQuests()
|
||||
if (qNextItr == _questTemplates.end())
|
||||
TC_LOG_ERROR("sql.sql", "Quest %u has NextQuestId %u, but no such quest", qinfo->GetQuestId(), qinfo->GetNextQuestId());
|
||||
else
|
||||
qNextItr->second->PrevQuests.push_back(static_cast<int32>(qinfo->GetQuestId()));
|
||||
qNextItr->second->DependentPreviousQuests.push_back(qinfo->GetQuestId());
|
||||
}
|
||||
|
||||
if (qinfo->_exclusiveGroup)
|
||||
|
||||
@@ -367,7 +367,7 @@ class TC_GAME_API Quest
|
||||
|
||||
void BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player* player) const;
|
||||
|
||||
std::vector<int32> PrevQuests;
|
||||
std::vector<uint32> DependentPreviousQuests;
|
||||
std::vector<uint32> PrevChainQuests;
|
||||
|
||||
// cached data
|
||||
|
||||
Reference in new issue
Block a user