Core/Quests: Unify quest objective updating into one function and replace iterating entire quest log to find objective with direct {type, id} lookup
Port From (https://github.com/TrinityCore/TrinityCore/commit/6352a84bf78a7afe0ea8d8caccee33dd09e09694)
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
using Framework.Constants;
|
using Framework.Constants;
|
||||||
using Game.Achievements;
|
using Game.Achievements;
|
||||||
|
using Game.BattleGrounds;
|
||||||
using Game.Chat;
|
using Game.Chat;
|
||||||
using Game.DataStorage;
|
using Game.DataStorage;
|
||||||
using Game.Garrisons;
|
using Game.Garrisons;
|
||||||
@@ -25,9 +26,9 @@ using Game.Mails;
|
|||||||
using Game.Maps;
|
using Game.Maps;
|
||||||
using Game.Misc;
|
using Game.Misc;
|
||||||
using Game.Spells;
|
using Game.Spells;
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Game.BattleGrounds;
|
|
||||||
|
|
||||||
namespace Game.Entities
|
namespace Game.Entities
|
||||||
{
|
{
|
||||||
@@ -164,6 +165,7 @@ namespace Game.Entities
|
|||||||
List<uint> m_monthlyquests = new();
|
List<uint> m_monthlyquests = new();
|
||||||
MultiMap<uint, uint> m_seasonalquests = new();
|
MultiMap<uint, uint> m_seasonalquests = new();
|
||||||
Dictionary<uint, QuestStatusData> m_QuestStatus = new();
|
Dictionary<uint, QuestStatusData> m_QuestStatus = new();
|
||||||
|
MultiMap<Tuple<QuestObjectiveType, int>, QuestObjectiveStatusData> m_questObjectiveStatus = new();
|
||||||
Dictionary<uint, QuestSaveType> m_QuestStatusSave = new();
|
Dictionary<uint, QuestSaveType> m_QuestStatusSave = new();
|
||||||
List<uint> m_DFQuests = new();
|
List<uint> m_DFQuests = new();
|
||||||
List<uint> m_RewardedQuests = new();
|
List<uint> m_RewardedQuests = new();
|
||||||
@@ -625,4 +627,10 @@ namespace Game.Entities
|
|||||||
Deleted
|
Deleted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct QuestObjectiveStatusData
|
||||||
|
{
|
||||||
|
public KeyValuePair<uint, QuestStatusData> QuestStatusPair;
|
||||||
|
public QuestObjective Objective;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ using Game.Networking.Packets;
|
|||||||
using Game.Spells;
|
using Game.Spells;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Game.Entities
|
namespace Game.Entities
|
||||||
{
|
{
|
||||||
@@ -462,22 +461,22 @@ namespace Game.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanCompleteQuest(uint quest_id)
|
public bool CanCompleteQuest(uint questId, uint ignoredQuestObjectiveId = 0)
|
||||||
{
|
{
|
||||||
if (quest_id != 0)
|
if (questId != 0)
|
||||||
{
|
{
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(quest_id);
|
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questId);
|
||||||
if (qInfo == null)
|
if (qInfo == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!qInfo.IsRepeatable() && GetQuestRewardStatus(quest_id))
|
if (!qInfo.IsRepeatable() && GetQuestRewardStatus(questId))
|
||||||
return false; // not allow re-complete quest
|
return false; // not allow re-complete quest
|
||||||
|
|
||||||
// auto complete quest
|
// auto complete quest
|
||||||
if ((qInfo.IsAutoComplete() || qInfo.Flags.HasAnyFlag(QuestFlags.AutoComplete)) && CanTakeQuest(qInfo, false))
|
if ((qInfo.IsAutoComplete() || qInfo.Flags.HasAnyFlag(QuestFlags.AutoComplete)) && CanTakeQuest(qInfo, false))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var q_status = m_QuestStatus.LookupByKey(quest_id);
|
var q_status = m_QuestStatus.LookupByKey(questId);
|
||||||
if (q_status == null)
|
if (q_status == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -485,6 +484,9 @@ namespace Game.Entities
|
|||||||
{
|
{
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
foreach (QuestObjective obj in qInfo.Objectives)
|
||||||
{
|
{
|
||||||
|
if (ignoredQuestObjectiveId != 0 && obj.Id == ignoredQuestObjectiveId)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!obj.Flags.HasAnyFlag(QuestObjectiveFlags.Optional) && !obj.Flags.HasAnyFlag(QuestObjectiveFlags.PartOfProgressBar))
|
if (!obj.Flags.HasAnyFlag(QuestObjectiveFlags.Optional) && !obj.Flags.HasAnyFlag(QuestObjectiveFlags.PartOfProgressBar))
|
||||||
{
|
{
|
||||||
if (!IsQuestObjectiveComplete(q_status.Slot, qInfo, obj))
|
if (!IsQuestObjectiveComplete(q_status.Slot, qInfo, obj))
|
||||||
@@ -731,6 +733,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
uint quest_id = quest.Id;
|
uint quest_id = quest.Id;
|
||||||
|
|
||||||
|
// if not exist then created with set uState == NEW and rewarded=false
|
||||||
if (!m_QuestStatus.ContainsKey(quest_id))
|
if (!m_QuestStatus.ContainsKey(quest_id))
|
||||||
m_QuestStatus[quest_id] = new QuestStatusData();
|
m_QuestStatus[quest_id] = new QuestStatusData();
|
||||||
|
|
||||||
@@ -745,6 +748,7 @@ namespace Game.Entities
|
|||||||
|
|
||||||
foreach (QuestObjective obj in quest.Objectives)
|
foreach (QuestObjective obj in quest.Objectives)
|
||||||
{
|
{
|
||||||
|
m_questObjectiveStatus.Add(Tuple.Create(obj.Type, obj.ObjectID), new QuestObjectiveStatusData() { QuestStatusPair = KeyValuePair.Create(quest_id, questStatusData), Objective = obj });
|
||||||
switch (obj.Type)
|
switch (obj.Type)
|
||||||
{
|
{
|
||||||
case QuestObjectiveType.MinReputation:
|
case QuestObjectiveType.MinReputation:
|
||||||
@@ -1775,16 +1779,22 @@ namespace Game.Entities
|
|||||||
SendQuestUpdate(questId);
|
SendQuestUpdate(questId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveActiveQuest(uint quest_id, bool update = true)
|
public void RemoveActiveQuest(uint questId, bool update = true)
|
||||||
{
|
{
|
||||||
if (m_QuestStatus.ContainsKey(quest_id))
|
var questStatus = m_QuestStatus.LookupByKey(questId);
|
||||||
|
if (questStatus != null)
|
||||||
{
|
{
|
||||||
m_QuestStatus.Remove(quest_id);
|
foreach (var objective in m_questObjectiveStatus.KeyValueList)
|
||||||
m_QuestStatusSave[quest_id] = QuestSaveType.Delete;
|
{
|
||||||
|
if (objective.Value.QuestStatusPair.Value == questStatus)
|
||||||
|
m_questObjectiveStatus.Remove(objective);
|
||||||
|
}
|
||||||
|
m_QuestStatus.Remove(questId);
|
||||||
|
m_QuestStatusSave[questId] = QuestSaveType.Delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update)
|
if (update)
|
||||||
SendQuestUpdate(quest_id);
|
SendQuestUpdate(questId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRewardedQuest(uint questId, bool update = true)
|
public void RemoveRewardedQuest(uint questId, bool update = true)
|
||||||
@@ -2162,81 +2172,31 @@ namespace Game.Entities
|
|||||||
|
|
||||||
public void ItemAddedQuestCheck(uint entry, uint count)
|
public void ItemAddedQuestCheck(uint entry, uint count)
|
||||||
{
|
{
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
UpdateQuestObjectiveProgress(QuestObjectiveType.Item, (int)entry, count);
|
||||||
{
|
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
|
||||||
if (questid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QuestStatusData q_status = m_QuestStatus[questid];
|
|
||||||
|
|
||||||
if (q_status.Status != QuestStatus.Incomplete)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
|
||||||
if (qInfo == null || !qInfo.HasQuestObjectiveType(QuestObjectiveType.Item))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
|
||||||
{
|
|
||||||
if (obj.Type != QuestObjectiveType.Item || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (obj.ObjectID != entry)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int reqItemCount = obj.Amount;
|
|
||||||
int curItemCount = GetQuestSlotObjectiveData(i, obj);
|
|
||||||
if (curItemCount < reqItemCount)
|
|
||||||
{
|
|
||||||
int newItemCount = (int)Math.Min(curItemCount + count, reqItemCount);
|
|
||||||
SetQuestObjectiveData(obj, newItemCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateForQuestWorldObjects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ItemRemovedQuestCheck(uint entry, uint count)
|
public void ItemRemovedQuestCheck(uint entry, uint count)
|
||||||
{
|
{
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
foreach (var objectiveStatusData in m_questObjectiveStatus.LookupByKey(Tuple.Create(QuestObjectiveType.Item, entry)))
|
||||||
{
|
{
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
uint questId = objectiveStatusData.QuestStatusPair.Key;
|
||||||
if (questid == 0)
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(questId);
|
||||||
|
ushort logSlot = objectiveStatusData.QuestStatusPair.Value.Slot;
|
||||||
|
QuestObjective objective = objectiveStatusData.Objective;
|
||||||
|
|
||||||
|
if (!IsQuestObjectiveCompletable(logSlot, quest, objective))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
int curItemCount = GetQuestSlotObjectiveData(logSlot, objective);
|
||||||
if (qInfo == null || !qInfo.HasQuestObjectiveType(QuestObjectiveType.Item))
|
if (curItemCount >= objective.Amount) // we may have more than what the status shows
|
||||||
continue;
|
curItemCount = (int)GetItemCount(entry, false);
|
||||||
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
int newItemCount = (int)((count > curItemCount) ? 0 : curItemCount - count);
|
||||||
|
|
||||||
|
if (newItemCount < objective.Amount)
|
||||||
{
|
{
|
||||||
if (obj.Type != QuestObjectiveType.Item || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
SetQuestObjectiveData(objective, newItemCount);
|
||||||
continue;
|
IncompleteQuest(questId);
|
||||||
|
|
||||||
if (obj.ObjectID != entry)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint reqItemCount = (uint)obj.Amount;
|
|
||||||
int curItemCount = GetQuestSlotObjectiveData(i, obj);
|
|
||||||
|
|
||||||
if (curItemCount >= reqItemCount) // we may have more than what the status shows
|
|
||||||
curItemCount = (int)GetItemCount(entry, false);
|
|
||||||
|
|
||||||
int newItemCount = (int)((count > curItemCount) ? 0 : curItemCount - count);
|
|
||||||
|
|
||||||
if (newItemCount < reqItemCount)
|
|
||||||
{
|
|
||||||
SetQuestObjectiveData(obj, newItemCount);
|
|
||||||
IncompleteQuest(questid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2270,489 +2230,209 @@ namespace Game.Entities
|
|||||||
StartCriteriaTimer(CriteriaTimedTypes.Creature, real_entry); // MUST BE CALLED FIRST
|
StartCriteriaTimer(CriteriaTimedTypes.Creature, real_entry); // MUST BE CALLED FIRST
|
||||||
UpdateCriteria(CriteriaTypes.KillCreature, real_entry, addKillCount, 0, killed);
|
UpdateCriteria(CriteriaTypes.KillCreature, real_entry, addKillCount, 0, killed);
|
||||||
|
|
||||||
bool completedObjectiveInSequencedQuest = false;
|
UpdateQuestObjectiveProgress(QuestObjectiveType.Monster, (int)entry, 1, guid);
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
|
||||||
{
|
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
|
||||||
if (questid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
|
||||||
if (qInfo == null || !qInfo.HasQuestObjectiveType(QuestObjectiveType.Monster))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_QuestStatus[questid].Status != QuestStatus.Incomplete)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (GetGroup() && GetGroup().IsRaidGroup() && qInfo.IsAllowedInRaid(GetMap().GetDifficultyID()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
|
||||||
{
|
|
||||||
if (obj.Type != QuestObjectiveType.Monster || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (obj.ObjectID != entry)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint reqKillCount = (uint)obj.Amount;
|
|
||||||
int curKillCount = GetQuestSlotObjectiveData(i, obj);
|
|
||||||
if (curKillCount < reqKillCount)
|
|
||||||
{
|
|
||||||
SetQuestObjectiveData(obj, curKillCount + addKillCount);
|
|
||||||
SendQuestUpdateAddCredit(qInfo, guid, obj, (uint)(curKillCount + addKillCount));
|
|
||||||
if (!completedObjectiveInSequencedQuest && qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives) && IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
// same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization).
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completedObjectiveInSequencedQuest)
|
|
||||||
UpdateForQuestWorldObjects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void KilledPlayerCredit()
|
public void KilledPlayerCredit()
|
||||||
{
|
{
|
||||||
ushort addKillCount = 1;
|
UpdateQuestObjectiveProgress(QuestObjectiveType.PlayerKills, 0, 1);
|
||||||
|
|
||||||
bool completedObjectiveInSequencedQuest = false;
|
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
|
||||||
{
|
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
|
||||||
if (questid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
|
||||||
if (qInfo == null || !qInfo.HasQuestObjectiveType(QuestObjectiveType.PlayerKills))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// just if !ingroup || !noraidgroup || raidgroup
|
|
||||||
QuestStatusData q_status = m_QuestStatus[questid];
|
|
||||||
if (q_status.Status == QuestStatus.Incomplete && (GetGroup() == null || !GetGroup().IsRaidGroup() || qInfo.IsAllowedInRaid(GetMap().GetDifficultyID())))
|
|
||||||
{
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
|
||||||
{
|
|
||||||
if (obj.Type != QuestObjectiveType.PlayerKills || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int curKillCount = GetQuestSlotObjectiveData(i, obj);
|
|
||||||
if (curKillCount < obj.Amount)
|
|
||||||
{
|
|
||||||
SetQuestObjectiveData(obj, curKillCount + addKillCount);
|
|
||||||
SendQuestUpdateAddPlayer(qInfo, (uint)(curKillCount + addKillCount));
|
|
||||||
if (!completedObjectiveInSequencedQuest && qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives) && IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
// Quest can't have more than one player kill objective (code optimisation)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completedObjectiveInSequencedQuest)
|
|
||||||
UpdateForQuestWorldObjects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void KillCreditGO(uint entry, ObjectGuid guid = default)
|
public void KillCreditGO(uint entry, ObjectGuid guid = default)
|
||||||
{
|
{
|
||||||
ushort addCastCount = 1;
|
UpdateQuestObjectiveProgress(QuestObjectiveType.GameObject, (int)entry, 1, guid);
|
||||||
bool completedObjectiveInSequencedQuest = false;
|
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
|
||||||
{
|
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
|
||||||
if (questid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
|
||||||
if (qInfo == null || !qInfo.HasQuestObjectiveType(QuestObjectiveType.GameObject))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_QuestStatus[questid].Status != QuestStatus.Incomplete)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (GetGroup() && GetGroup().IsRaidGroup() && qInfo.IsAllowedInRaid(GetMap().GetDifficultyID()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
|
||||||
{
|
|
||||||
if (obj.Type != QuestObjectiveType.GameObject || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
int reqTarget = obj.ObjectID;
|
|
||||||
|
|
||||||
// other not this creature/GO related objectives
|
|
||||||
if (obj.ObjectID != entry)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint reqCastCount = (uint)obj.Amount;
|
|
||||||
int curCastCount = GetQuestSlotObjectiveData(i, obj);
|
|
||||||
if (curCastCount < reqCastCount)
|
|
||||||
{
|
|
||||||
SetQuestObjectiveData(obj, curCastCount + addCastCount);
|
|
||||||
SendQuestUpdateAddCredit(qInfo, guid, obj, (uint)(curCastCount + addCastCount));
|
|
||||||
if (!completedObjectiveInSequencedQuest && qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives) && IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
// same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization).
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completedObjectiveInSequencedQuest)
|
|
||||||
UpdateForQuestWorldObjects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void KillCreditCriteriaTreeObjective(QuestObjective questObjective)
|
public void KillCreditCriteriaTreeObjective(QuestObjective questObjective)
|
||||||
{
|
{
|
||||||
if (questObjective.Type != QuestObjectiveType.CriteriaTree)
|
UpdateQuestObjectiveProgress(QuestObjectiveType.CriteriaTree, questObjective.ObjectID, 1);
|
||||||
return;
|
|
||||||
|
|
||||||
Quest quest = Global.ObjectMgr.GetQuestTemplate(questObjective.QuestID);
|
|
||||||
if (!IsQuestObjectiveComplete(FindQuestSlot(questObjective.QuestID), quest, questObjective))
|
|
||||||
{
|
|
||||||
SetQuestObjectiveData(questObjective, 1);
|
|
||||||
SendQuestUpdateAddCreditSimple(questObjective);
|
|
||||||
|
|
||||||
if (CanCompleteQuest(questObjective.QuestID))
|
|
||||||
CompleteQuest(questObjective.QuestID);
|
|
||||||
|
|
||||||
if (quest.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives))
|
|
||||||
UpdateForQuestWorldObjects();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TalkedToCreature(uint entry, ObjectGuid guid)
|
public void TalkedToCreature(uint entry, ObjectGuid guid)
|
||||||
{
|
{
|
||||||
ushort addTalkCount = 1;
|
UpdateQuestObjectiveProgress(QuestObjectiveType.TalkTo, (int)entry, 1, guid);
|
||||||
bool completedObjectiveInSequencedQuest = false;
|
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
|
||||||
{
|
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
|
||||||
if (questid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
|
||||||
if (qInfo == null || !qInfo.HasQuestObjectiveType(QuestObjectiveType.TalkTo))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (m_QuestStatus[questid].Status != QuestStatus.Incomplete)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (GetGroup() && GetGroup().IsRaidGroup() && qInfo.IsAllowedInRaid(GetMap().GetDifficultyID()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
|
||||||
{
|
|
||||||
if (obj.Type != QuestObjectiveType.TalkTo || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (obj.ObjectID != entry)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint reqTalkCount = (uint)obj.Amount;
|
|
||||||
int curTalkCount = GetQuestSlotObjectiveData(i, obj);
|
|
||||||
if (curTalkCount < reqTalkCount)
|
|
||||||
{
|
|
||||||
SetQuestObjectiveData(obj, curTalkCount + addTalkCount);
|
|
||||||
SendQuestUpdateAddCredit(qInfo, guid, obj, (uint)(curTalkCount + addTalkCount));
|
|
||||||
if (!completedObjectiveInSequencedQuest && qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives) && IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
// Quest can't have more than one objective for the same creature (code optimisation)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completedObjectiveInSequencedQuest)
|
|
||||||
UpdateForQuestWorldObjects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MoneyChanged(ulong value)
|
public void MoneyChanged(ulong value)
|
||||||
{
|
{
|
||||||
bool completedObjectiveInSequencedQuest = false;
|
UpdateQuestObjectiveProgress(QuestObjectiveType.Money, 0, (long)value - (long)GetMoney());
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
|
||||||
{
|
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
|
||||||
if (questid == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
|
||||||
if (qInfo == null || !qInfo.HasQuestObjectiveType(QuestObjectiveType.Money))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QuestStatusData q_status = m_QuestStatus[questid];
|
|
||||||
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
|
||||||
{
|
|
||||||
if (obj.Type != QuestObjectiveType.Money || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
{
|
|
||||||
if ((long)value >= obj.Amount)
|
|
||||||
{
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
if (!completedObjectiveInSequencedQuest && qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (q_status.Status == QuestStatus.Complete)
|
|
||||||
{
|
|
||||||
if ((long)value < obj.Amount)
|
|
||||||
IncompleteQuest(questid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completedObjectiveInSequencedQuest)
|
|
||||||
UpdateForQuestWorldObjects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReputationChanged(FactionRecord FactionRecord, int change)
|
public void ReputationChanged(FactionRecord FactionRecord, int change)
|
||||||
{
|
{
|
||||||
bool completedObjectiveInSequencedQuest = false;
|
UpdateQuestObjectiveProgress(QuestObjectiveType.MinReputation, (int)FactionRecord.Id, change);
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
UpdateQuestObjectiveProgress(QuestObjectiveType.MaxReputation, (int)FactionRecord.Id, change);
|
||||||
{
|
UpdateQuestObjectiveProgress(QuestObjectiveType.IncreaseReputation, (int)FactionRecord.Id, change);
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
|
||||||
if (questid != 0)
|
|
||||||
{
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
|
||||||
if (qInfo != null)
|
|
||||||
{
|
|
||||||
QuestStatusData q_status = m_QuestStatus[questid];
|
|
||||||
|
|
||||||
if (!qInfo.HasQuestObjectiveType(QuestObjectiveType.MinReputation) && !qInfo.HasQuestObjectiveType(QuestObjectiveType.MaxReputation)
|
|
||||||
&& (!qInfo.HasQuestObjectiveType(QuestObjectiveType.IncreaseReputation) || q_status.Status != QuestStatus.Incomplete))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
|
||||||
{
|
|
||||||
if (obj.ObjectID != FactionRecord.Id || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (obj.Type)
|
|
||||||
{
|
|
||||||
case QuestObjectiveType.MinReputation:
|
|
||||||
if (!IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
{
|
|
||||||
if (GetReputationMgr().GetReputation(FactionRecord) + change >= obj.Amount)
|
|
||||||
{
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
if (qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (q_status.Status == QuestStatus.Complete)
|
|
||||||
{
|
|
||||||
if (GetReputationMgr().GetReputation(FactionRecord) + change < obj.Amount)
|
|
||||||
IncompleteQuest(questid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QuestObjectiveType.MaxReputation:
|
|
||||||
if (!IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
{
|
|
||||||
if (GetReputationMgr().GetReputation(FactionRecord) + change <= obj.Amount)
|
|
||||||
{
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
if (qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (q_status.Status == QuestStatus.Complete)
|
|
||||||
{
|
|
||||||
if (GetReputationMgr().GetReputation(FactionRecord) + change > obj.Amount)
|
|
||||||
IncompleteQuest(questid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QuestObjectiveType.IncreaseReputation:
|
|
||||||
int currentProgress = GetQuestSlotObjectiveData(i, obj);
|
|
||||||
if (change > 0 && currentProgress < obj.Amount)
|
|
||||||
{
|
|
||||||
SetQuestObjectiveData(obj, currentProgress + change);
|
|
||||||
SendQuestUpdateAddCredit(qInfo, ObjectGuid.Empty, obj, (uint)(currentProgress + change));
|
|
||||||
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
if (!completedObjectiveInSequencedQuest && qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives) && IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completedObjectiveInSequencedQuest)
|
|
||||||
UpdateForQuestWorldObjects();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CurrencyChanged(uint currencyId, int change)
|
void CurrencyChanged(uint currencyId, int change)
|
||||||
{
|
{
|
||||||
bool completedObjectiveInSequencedQuest = false;
|
UpdateQuestObjectiveProgress(QuestObjectiveType.Currency, (int)currencyId, change);
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
UpdateQuestObjectiveProgress(QuestObjectiveType.HaveCurrency, (int)currencyId, change);
|
||||||
|
UpdateQuestObjectiveProgress(QuestObjectiveType.ObtainCurrency, (int)currencyId, change);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateQuestObjectiveProgress(QuestObjectiveType objectiveType, int objectId, long addCount, ObjectGuid victimGuid = default)
|
||||||
|
{
|
||||||
|
bool anyObjectiveChangedCompletionState = false;
|
||||||
|
|
||||||
|
foreach (var objectiveStatusData in m_questObjectiveStatus.LookupByKey(Tuple.Create(objectiveType, objectId)))
|
||||||
{
|
{
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
uint questId = objectiveStatusData.QuestStatusPair.Key;
|
||||||
if (questid == 0)
|
Quest quest = Global.ObjectMgr.GetQuestTemplate(questId);
|
||||||
continue;
|
|
||||||
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
if (!QuestObjective.CanAlwaysBeProgressedInRaid(objectiveType))
|
||||||
if (qInfo == null)
|
if (GetGroup() && GetGroup().IsRaidGroup() && quest.IsAllowedInRaid(GetMap().GetDifficultyID()))
|
||||||
continue;
|
|
||||||
|
|
||||||
QuestStatusData q_status = m_QuestStatus[questid];
|
|
||||||
|
|
||||||
if (!qInfo.HasQuestObjectiveType(QuestObjectiveType.Currency) && !qInfo.HasQuestObjectiveType(QuestObjectiveType.HaveCurrency)
|
|
||||||
&& (!qInfo.HasQuestObjectiveType(QuestObjectiveType.ObtainCurrency) || q_status.Status != QuestStatus.Incomplete))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
|
||||||
{
|
|
||||||
if (obj.ObjectID != currencyId || !IsQuestObjectiveCompletable(i, qInfo, obj))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (obj.Type)
|
ushort logSlot = objectiveStatusData.QuestStatusPair.Value.Slot;
|
||||||
|
QuestObjective objective = objectiveStatusData.Objective;
|
||||||
|
if (!IsQuestObjectiveCompletable(logSlot, quest, objective))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool objectiveWasComplete = IsQuestObjectiveComplete(logSlot, quest, objective);
|
||||||
|
if (!objectiveWasComplete || addCount < 0)
|
||||||
|
{
|
||||||
|
bool objectiveIsNowComplete = false;
|
||||||
|
if (objective.IsStoringValue())
|
||||||
{
|
{
|
||||||
case QuestObjectiveType.Currency:
|
if (objectiveType == QuestObjectiveType.PlayerKills && objective.Flags.HasAnyFlag(QuestObjectiveFlags.KillPlayersSameFaction))
|
||||||
if (!IsQuestObjectiveComplete(i, qInfo, obj))
|
{
|
||||||
{
|
Player victim = Global.ObjAccessor.GetPlayer(GetMap(), victimGuid);
|
||||||
if (GetCurrency(currencyId) + change >= obj.Amount)
|
if (victim?.GetTeam() != GetTeam())
|
||||||
{
|
continue;
|
||||||
if (CanCompleteQuest(questid))
|
}
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
if (qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives))
|
int currentProgress = GetQuestSlotObjectiveData(logSlot, objective);
|
||||||
completedObjectiveInSequencedQuest = true;
|
if (addCount > 0 ? (currentProgress < objective.Amount) : (currentProgress > 0))
|
||||||
}
|
{
|
||||||
}
|
int newProgress = (int)Math.Clamp(currentProgress + addCount, 0, objective.Amount);
|
||||||
else if (q_status.Status == QuestStatus.Complete)
|
SetQuestObjectiveData(objective, newProgress);
|
||||||
|
if (addCount > 0 && !objective.Flags.HasAnyFlag(QuestObjectiveFlags.HideCreditMsg))
|
||||||
{
|
{
|
||||||
if (GetCurrency(currencyId) + change < obj.Amount)
|
if (objectiveType != QuestObjectiveType.PlayerKills)
|
||||||
IncompleteQuest(questid);
|
SendQuestUpdateAddCredit(quest, victimGuid, objective, (uint)newProgress);
|
||||||
|
else
|
||||||
|
SendQuestUpdateAddPlayer(quest, (uint)newProgress);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case QuestObjectiveType.HaveCurrency:
|
objectiveIsNowComplete = IsQuestObjectiveComplete(logSlot, quest, objective);
|
||||||
int newProgress = (int)Math.Min(GetCurrency(currencyId) + change, obj.Amount);
|
}
|
||||||
SetQuestObjectiveData(obj, newProgress);
|
|
||||||
if (!IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
{
|
|
||||||
if (newProgress >= obj.Amount)
|
|
||||||
{
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
if (qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (q_status.Status == QuestStatus.Complete)
|
|
||||||
{
|
|
||||||
if (newProgress < obj.Amount)
|
|
||||||
IncompleteQuest(questid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QuestObjectiveType.ObtainCurrency:
|
|
||||||
int currentProgress = GetQuestSlotObjectiveData(i, obj);
|
|
||||||
if (change > 0 && currentProgress < obj.Amount)
|
|
||||||
{
|
|
||||||
SetQuestObjectiveData(obj, currentProgress + change);
|
|
||||||
SendQuestUpdateAddCredit(qInfo, ObjectGuid.Empty, obj, (uint)(currentProgress + change));
|
|
||||||
|
|
||||||
if (CanCompleteQuest(questid))
|
|
||||||
CompleteQuest(questid);
|
|
||||||
|
|
||||||
if (!completedObjectiveInSequencedQuest && qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives) && IsQuestObjectiveComplete(i, qInfo, obj))
|
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else if (objective.IsStoringFlag())
|
||||||
|
{
|
||||||
|
SetQuestObjectiveData(objective, addCount > 0 ? 1 : 0);
|
||||||
|
|
||||||
|
if (addCount > 0 && !objective.Flags.HasAnyFlag(QuestObjectiveFlags.HideCreditMsg))
|
||||||
|
SendQuestUpdateAddCreditSimple(objective);
|
||||||
|
|
||||||
|
objectiveIsNowComplete = IsQuestObjectiveComplete(logSlot, quest, objective);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (objectiveType)
|
||||||
|
{
|
||||||
|
case QuestObjectiveType.Currency:
|
||||||
|
objectiveIsNowComplete = GetCurrency((uint)objectId) + addCount >= objective.Amount;
|
||||||
|
break;
|
||||||
|
case QuestObjectiveType.LearnSpell:
|
||||||
|
objectiveIsNowComplete = addCount != 0;
|
||||||
|
break;
|
||||||
|
case QuestObjectiveType.MinReputation:
|
||||||
|
objectiveIsNowComplete = GetReputationMgr().GetReputation((uint)objectId) + addCount >= objective.Amount;
|
||||||
|
break;
|
||||||
|
case QuestObjectiveType.MaxReputation:
|
||||||
|
objectiveIsNowComplete = GetReputationMgr().GetReputation((uint)objectId) + addCount <= objective.Amount;
|
||||||
|
break;
|
||||||
|
case QuestObjectiveType.Money:
|
||||||
|
objectiveIsNowComplete = (long)GetMoney() + addCount >= objective.Amount;
|
||||||
|
break;
|
||||||
|
case QuestObjectiveType.ProgressBar:
|
||||||
|
objectiveIsNowComplete = IsQuestObjectiveProgressBarComplete(logSlot, quest);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Cypher.Assert(false, "Unhandled quest objective type {objectiveType}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objective.Flags.HasAnyFlag(QuestObjectiveFlags.PartOfProgressBar))
|
||||||
|
{
|
||||||
|
if (IsQuestObjectiveProgressBarComplete(logSlot, quest))
|
||||||
|
{
|
||||||
|
var progressBarObjective = quest.Objectives.Find(otherObjective => otherObjective.Type == QuestObjectiveType.ProgressBar && !otherObjective.Flags.HasAnyFlag(QuestObjectiveFlags.PartOfProgressBar));
|
||||||
|
if (progressBarObjective != null)
|
||||||
|
SendQuestUpdateAddCreditSimple(progressBarObjective);
|
||||||
|
|
||||||
|
objectiveIsNowComplete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objectiveWasComplete != objectiveIsNowComplete)
|
||||||
|
anyObjectiveChangedCompletionState = true;
|
||||||
|
|
||||||
|
if (objectiveIsNowComplete && CanCompleteQuest(questId, objective.Id))
|
||||||
|
CompleteQuest(questId);
|
||||||
|
else if (objectiveStatusData.QuestStatusPair.Value.Status == QuestStatus.Complete)
|
||||||
|
IncompleteQuest(questId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completedObjectiveInSequencedQuest)
|
if (anyObjectiveChangedCompletionState)
|
||||||
UpdateForQuestWorldObjects();
|
UpdateForQuestWorldObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasQuestForItem(uint itemid)
|
public bool HasQuestForItem(uint itemid)
|
||||||
{
|
{
|
||||||
for (byte i = 0; i < SharedConst.MaxQuestLogSize; ++i)
|
// Search incomplete objective first
|
||||||
|
foreach (var objectiveItr in m_questObjectiveStatus.LookupByKey(Tuple.Create(QuestObjectiveType.Item, itemid)))
|
||||||
{
|
{
|
||||||
uint questid = GetQuestSlotQuestId(i);
|
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(objectiveItr.QuestStatusPair.Key);
|
||||||
if (questid == 0)
|
QuestObjective objective = objectiveItr.Objective;
|
||||||
|
if (!IsQuestObjectiveCompletable(objectiveItr.QuestStatusPair.Value.Slot, qInfo, objective))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var q_status = m_QuestStatus.LookupByKey(questid);
|
// hide quest if player is in raid-group and quest is no raid quest
|
||||||
if (q_status == null)
|
if (GetGroup() && GetGroup().IsRaidGroup() && !qInfo.IsAllowedInRaid(GetMap().GetDifficultyID()))
|
||||||
continue;
|
if (!InBattleground()) //there are two ways.. we can make every bg-quest a raidquest, or add this code here.. i don't know if this can be exploited by other quests, but i think all other quests depend on a specific area.. but keep this in mind, if something strange happens later
|
||||||
|
|
||||||
if (q_status.Status == QuestStatus.Incomplete)
|
|
||||||
{
|
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questid);
|
|
||||||
if (qInfo == null)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// hide quest if player is in raid-group and quest is no raid quest
|
if (!IsQuestObjectiveComplete(objectiveItr.QuestStatusPair.Value.Slot, qInfo, objective))
|
||||||
if (GetGroup() != null && GetGroup().IsRaidGroup() && !qInfo.IsAllowedInRaid(GetMap().GetDifficultyID()))
|
return true;
|
||||||
if (!InBattleground()) //there are two ways.. we can make every bg-quest a raidquest, or add this code here.. i don't know if this can be exploited by other quests, but i think all other quests depend on a specific area.. but keep this in mind, if something strange happens later
|
}
|
||||||
continue;
|
|
||||||
|
|
||||||
// There should be no mixed ReqItem/ReqSource drop
|
// This part - for ItemDrop
|
||||||
// This part for ReqItem drop
|
foreach (var questStatus in m_QuestStatus)
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
{
|
||||||
{
|
if (questStatus.Value.Status != QuestStatus.Incomplete)
|
||||||
if (obj.Type == QuestObjectiveType.Item && IsQuestObjectiveCompletable(i, qInfo, obj) && itemid == obj.ObjectID && GetQuestSlotObjectiveData(i, obj) < obj.Amount)
|
continue;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// This part - for ReqSource
|
|
||||||
for (byte j = 0; j < SharedConst.QuestItemDropCount; ++j)
|
|
||||||
{
|
|
||||||
// examined item is a source item
|
|
||||||
if (qInfo.ItemDrop[j] == itemid)
|
|
||||||
{
|
|
||||||
ItemTemplate pProto = Global.ObjectMgr.GetItemTemplate(itemid);
|
|
||||||
|
|
||||||
// 'unique' item
|
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questStatus.Key);
|
||||||
if (pProto.GetMaxCount() != 0 && GetItemCount(itemid, true) < pProto.GetMaxCount())
|
// hide quest if player is in raid-group and quest is no raid quest
|
||||||
return true;
|
if (GetGroup() && GetGroup().IsRaidGroup() && !qInfo.IsAllowedInRaid(GetMap().GetDifficultyID()))
|
||||||
|
if (!InBattleground())
|
||||||
|
continue;
|
||||||
|
|
||||||
// allows custom amount drop when not 0
|
for (byte j = 0; j < SharedConst.QuestItemDropCount; ++j)
|
||||||
if (qInfo.ItemDropQuantity[j] != 0)
|
{
|
||||||
{
|
// examined item is a source item
|
||||||
if (GetItemCount(itemid, true) < qInfo.ItemDropQuantity[j])
|
if (qInfo.ItemDrop[j] != itemid)
|
||||||
return true;
|
continue;
|
||||||
}
|
|
||||||
else if (GetItemCount(itemid, true) < pProto.GetMaxStackSize())
|
ItemTemplate pProto = Global.ObjectMgr.GetItemTemplate(itemid);
|
||||||
return true;
|
|
||||||
}
|
// allows custom amount drop when not 0
|
||||||
}
|
uint maxAllowedCount = qInfo.ItemDropQuantity[j] != 0 ? qInfo.ItemDropQuantity[j] : pProto.GetMaxStackSize();
|
||||||
|
|
||||||
|
// 'unique' item
|
||||||
|
if (pProto.GetMaxCount() != 0 && pProto.GetMaxCount() < maxAllowedCount)
|
||||||
|
maxAllowedCount = pProto.GetMaxCount();
|
||||||
|
|
||||||
|
if (GetItemCount(itemid, true) < maxAllowedCount)
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -201,10 +201,11 @@ namespace Game
|
|||||||
|
|
||||||
if (player.IsAlive())
|
if (player.IsAlive())
|
||||||
{
|
{
|
||||||
|
// not using Player.UpdateQuestObjectiveProgress, ObjectID in quest_objectives can be set to -1, areatrigger_involvedrelation then holds correct id
|
||||||
List<uint> quests = Global.ObjectMgr.GetQuestsForAreaTrigger(packet.AreaTriggerID);
|
List<uint> quests = Global.ObjectMgr.GetQuestsForAreaTrigger(packet.AreaTriggerID);
|
||||||
if (quests != null)
|
if (quests != null)
|
||||||
{
|
{
|
||||||
bool completedObjectiveInSequencedQuest = false;
|
bool anyObjectiveChangedCompletionState = false;
|
||||||
foreach (uint questId in quests)
|
foreach (uint questId in quests)
|
||||||
{
|
{
|
||||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questId);
|
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(questId);
|
||||||
@@ -213,14 +214,22 @@ namespace Game
|
|||||||
{
|
{
|
||||||
foreach (QuestObjective obj in qInfo.Objectives)
|
foreach (QuestObjective obj in qInfo.Objectives)
|
||||||
{
|
{
|
||||||
if (obj.Type == QuestObjectiveType.AreaTrigger && !player.IsQuestObjectiveComplete(slot, qInfo, obj))
|
if (obj.Type != QuestObjectiveType.AreaTrigger)
|
||||||
{
|
continue;
|
||||||
player.SetQuestObjectiveData(obj, 1);
|
|
||||||
player.SendQuestUpdateAddCreditSimple(obj);
|
if (!player.IsQuestObjectiveCompletable(slot, qInfo, obj))
|
||||||
if (qInfo.HasSpecialFlag(QuestSpecialFlags.SequencedObjectives))
|
continue;
|
||||||
completedObjectiveInSequencedQuest = true;
|
|
||||||
break;
|
if (player.IsQuestObjectiveComplete(slot, qInfo, obj))
|
||||||
}
|
continue;
|
||||||
|
|
||||||
|
if (obj.ObjectID != -1 && obj.ObjectID != packet.AreaTriggerID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
player.SetQuestObjectiveData(obj, 1);
|
||||||
|
player.SendQuestUpdateAddCreditSimple(obj);
|
||||||
|
anyObjectiveChangedCompletionState = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.CanCompleteQuest(questId))
|
if (player.CanCompleteQuest(questId))
|
||||||
@@ -228,7 +237,7 @@ namespace Game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completedObjectiveInSequencedQuest)
|
if (anyObjectiveChangedCompletionState)
|
||||||
player.UpdateForQuestWorldObjects();
|
player.UpdateForQuestWorldObjects();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -810,6 +810,26 @@ namespace Game
|
|||||||
public string Description;
|
public string Description;
|
||||||
public int[] VisualEffects = new int[0];
|
public int[] VisualEffects = new int[0];
|
||||||
|
|
||||||
|
public bool IsStoringValue()
|
||||||
|
{
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case QuestObjectiveType.Monster:
|
||||||
|
case QuestObjectiveType.Item:
|
||||||
|
case QuestObjectiveType.GameObject:
|
||||||
|
case QuestObjectiveType.TalkTo:
|
||||||
|
case QuestObjectiveType.PlayerKills:
|
||||||
|
case QuestObjectiveType.WinPvpPetBattles:
|
||||||
|
case QuestObjectiveType.HaveCurrency:
|
||||||
|
case QuestObjectiveType.ObtainCurrency:
|
||||||
|
case QuestObjectiveType.IncreaseReputation:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsStoringFlag()
|
public bool IsStoringFlag()
|
||||||
{
|
{
|
||||||
switch (Type)
|
switch (Type)
|
||||||
@@ -826,5 +846,24 @@ namespace Game
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool CanAlwaysBeProgressedInRaid(QuestObjectiveType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case QuestObjectiveType.Item:
|
||||||
|
case QuestObjectiveType.Currency:
|
||||||
|
case QuestObjectiveType.LearnSpell:
|
||||||
|
case QuestObjectiveType.MinReputation:
|
||||||
|
case QuestObjectiveType.MaxReputation:
|
||||||
|
case QuestObjectiveType.Money:
|
||||||
|
case QuestObjectiveType.HaveCurrency:
|
||||||
|
case QuestObjectiveType.IncreaseReputation:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user