Skip to content

Commit

Permalink
Core/Quests: fixed exclusivegroup interaction with prevquestId and ne…
Browse files Browse the repository at this point in the history
…xtQuestId.

Port From (TrinityCore/TrinityCore@1536f01)
  • Loading branch information
hondacrx committed May 6, 2020
1 parent d0cc070 commit 52ed9a2
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 69 deletions.
124 changes: 61 additions & 63 deletions Source/Game/Entities/Player/Player.Quest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
using Game.Spells;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Game.Entities
{
Expand Down Expand Up @@ -406,7 +407,7 @@ public bool CanSeeStartQuest(Quest quest)
{
if (!Global.DisableMgr.IsDisabledFor(DisableType.Quest, quest.Id, 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))
{
Expand All @@ -422,7 +423,7 @@ public bool CanTakeQuest(Quest 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)
Expand Down Expand Up @@ -1299,89 +1300,86 @@ public bool SatisfyQuestLog(bool msg)
return false;
}

bool SatisfyQuestDependentQuests(Quest qInfo, bool msg)
{
return SatisfyQuestPreviousQuest(qInfo, msg) && SatisfyQuestDependentPreviousQuests(qInfo, msg);
}

public bool SatisfyQuestPreviousQuest(Quest qInfo, bool msg)
{
// No previous quest (might be first quest in a series)
if (qInfo.prevQuests.Empty())
if (qInfo.PrevQuestId == 0)
return true;

foreach (var prev in qInfo.prevQuests)
uint prevId = (uint)Math.Abs(qInfo.PrevQuestId);
// If positive previous quest rewarded, return true
if (qInfo.PrevQuestId > 0 && m_RewardedQuests.Contains(prevId))
return true;

// If negative previous quest active, return true
if (qInfo.PrevQuestId < 0 && GetQuestStatus(prevId) == QuestStatus.Incomplete)
return true;

// Has positive prev. quest in non-rewarded state
// and negative prev. quest in non-active state
if (msg)
{
uint prevId = (uint)Math.Abs(prev);
SendCanTakeQuestResponse(QuestFailedReasons.None);
Log.outDebug(LogFilter.Misc, $"Player.SatisfyQuestPreviousQuest: Sent QUEST_ERR_NONE (QuestID: {qInfo.Id}) because player '{GetName()}' ({GetGUID()}) doesn't have required quest {prevId}.");
}

Quest qPrevInfo = Global.ObjectMgr.GetQuestTemplate(prevId);
return false;
}

if (qPrevInfo != null)
{
// If any of the positive previous quests completed, return true
if (prev > 0 && m_RewardedQuests.Contains(prevId))
{
// skip one-from-all exclusive group
if (qPrevInfo.ExclusiveGroup >= 0)
return true;
bool SatisfyQuestDependentPreviousQuests(Quest qInfo, bool msg)
{
// No previous quest (might be first quest in a series)
if (qInfo.DependentPreviousQuests.Empty())
return true;

// each-from-all exclusive group (< 0)
// can be start if only all quests in prev quest exclusive group completed and rewarded
var bounds = Global.ObjectMgr.GetExclusiveQuestGroupBounds(qPrevInfo.ExclusiveGroup);
foreach (var exclude_Id in bounds)
{
// skip checked quest id, only state of other quests in group is interesting
if (exclude_Id == prevId)
continue;
foreach (uint prevId in qInfo.DependentPreviousQuests)
{
// checked in startup
Quest questInfo = Global.ObjectMgr.GetQuestTemplate(prevId);

// alternative quest from group also must be completed and rewarded (reported)
if (!m_RewardedQuests.Contains(exclude_Id))
{
if (msg)
{
SendCanTakeQuestResponse(QuestFailedReasons.None);
Log.outDebug(LogFilter.Server, "SatisfyQuestPreviousQuest: Sent QuestFailedReason.None (questId: {0}) because player does not have required quest (1).", qInfo.Id);
}
return false;
}
}
// If any of the previous quests completed, return true
if (IsQuestRewarded(prevId))
{
// skip one-from-all exclusive group
if (questInfo.ExclusiveGroup >= 0)
return true;
}

// If any of the negative previous quests active, return true
if (prev < 0 && GetQuestStatus(prevId) != QuestStatus.None)
// each-from-all exclusive group (< 0)
// can be start if only all quests in prev quest exclusive group completed and rewarded
var bounds = Global.ObjectMgr.GetExclusiveQuestGroupBounds(questInfo.ExclusiveGroup);
foreach (var exclusiveQuestId in bounds)
{
// skip one-from-all exclusive group
if (qPrevInfo.ExclusiveGroup >= 0)
return true;
// skip checked quest id, only state of other quests in group is interesting
if (exclusiveQuestId == prevId)
continue;

// each-from-all exclusive group (< 0)
// can be start if only all quests in prev quest exclusive group active
var range = Global.ObjectMgr.GetExclusiveQuestGroupBounds(qPrevInfo.ExclusiveGroup);
foreach (var exclude_Id in range)
// alternative quest from group also must be completed and rewarded (reported)
if (!IsQuestRewarded(exclusiveQuestId))
{
// 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) != QuestStatus.None)
if (msg)
{
if (msg)
{
SendCanTakeQuestResponse(QuestFailedReasons.None);
Log.outDebug(LogFilter.Server, "SatisfyQuestPreviousQuest: Sent QuestFailedReason.None (questId: {0}) because player does not have required quest (2).", qInfo.Id);

}
return false;
SendCanTakeQuestResponse(QuestFailedReasons.None);
Log.outDebug(LogFilter.Misc, $"Player.SatisfyQuestDependentPreviousQuests: Sent QUEST_ERR_NONE (QuestID: {qInfo.Id}) because player '{GetName()}' ({GetGUID()}) doesn't have the required quest (1).");
}

return false;
}
return true;
}

return true;
}
}

// Has only positive prev. quests in non-rewarded state
// and negative prev. quests in non-active state
// Has only prev. quests in non-rewarded state
if (msg)
{
SendCanTakeQuestResponse(QuestFailedReasons.None);
Log.outDebug(LogFilter.Server, "SatisfyQuestPreviousQuest: Sent QuestFailedReason.None (questId: {0}) because player does not have required quest (3).", qInfo.Id);
Log.outDebug(LogFilter.Misc, $"Player.SatisfyQuestDependentPreviousQuests: Sent QUEST_ERR_NONE (QuestID: {qInfo.Id}) because player '{GetName()}' ({GetGUID()}) doesn't have required quest (2).");
}

return false;
Expand Down Expand Up @@ -1586,12 +1584,12 @@ public bool SatisfyQuestNextChain(Quest qInfo, bool msg)
public bool SatisfyQuestPrevChain(Quest qInfo, bool msg)
{
// No previous quest in chain
if (qInfo.prevChainQuests.Empty())
if (qInfo.PrevChainQuests.Empty())
return true;

foreach (var questId in qInfo.prevChainQuests)
foreach (var prevQuestId in qInfo.PrevChainQuests)
{
var questStatusData = m_QuestStatus.LookupByKey(questId);
var questStatusData = m_QuestStatus.LookupByKey(prevQuestId);

// If any of the previous quests in chain active, return false
if (questStatusData != null && questStatusData.Status != QuestStatus.None)
Expand Down
6 changes: 2 additions & 4 deletions Source/Game/Globals/ObjectManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7022,7 +7022,7 @@ public void LoadQuests()
qinfo.NextQuestInChain = 0;
}
else
qNext.prevChainQuests.Add(qinfo.Id);
qNext.PrevChainQuests.Add(qinfo.Id);
}

for (var j = 0; j < SharedConst.QuestRewardCurrencyCount; ++j)
Expand Down Expand Up @@ -7105,8 +7105,6 @@ public void LoadQuests()
{
if (!_questTemplates.ContainsKey((uint)Math.Abs(qinfo.PrevQuestId)))
Log.outError(LogFilter.Sql, "Quest {0} has PrevQuestId {1}, but no such quest", qinfo.Id, qinfo.PrevQuestId);
else
qinfo.prevQuests.Add(qinfo.PrevQuestId);
}

if (qinfo.NextQuestId != 0)
Expand All @@ -7115,7 +7113,7 @@ public void LoadQuests()
if (nextquest == null)
Log.outError(LogFilter.Sql, "Quest {0} has NextQuestId {1}, but no such quest", qinfo.Id, qinfo.NextQuestId);
else
nextquest.prevQuests.Add((int)qinfo.Id);
nextquest.DependentPreviousQuests.Add(qinfo.Id);
}

if (qinfo.ExclusiveGroup != 0)
Expand Down
4 changes: 2 additions & 2 deletions Source/Game/Quest/Quest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -661,8 +661,8 @@ public bool IsSeasonal()
public QuestSpecialFlags SpecialFlags; // custom flags, not sniffed/WDB
public uint ScriptId;

public List<int> prevQuests = new List<int>();
public List<uint> prevChainQuests = new List<uint>();
public List<uint> DependentPreviousQuests = new List<uint>();
public List<uint> PrevChainQuests = new List<uint>();
public QueryQuestInfoResponse QueryData;

uint _rewChoiceItemsCount;
Expand Down

0 comments on commit 52ed9a2

Please sign in to comment.