Core/Quests: Quest flag fixups
* Update flag names * Implemented QUEST_FLAGS_COMPLETION_NO_DEATH and QUEST_FLAGS_FAIL_ON_LOGOUT * Started using QUEST_FLAGS_COMPLETION_EVENT and QUEST_FLAGS_COMPLETION_AREA_TRIGGER instead of a custom SpeclalFlag * Renamed Quest::IsAutoComplete to Quest::IsTurnIn to better describe what it means (a quest that can be turned in without accepting it to quest log) * Implemented QUEST_FLAGS_UPDATE_PHASESHIFT and removed forced phaseshift updates on every quest status change * Implemented QUEST_FLAGS_LAUNCH_GOSSIP_ACCEPT - reopens gossip menu with questgiver Port From (https://github.com/TrinityCore/TrinityCore/commit/4d4c7e68935df9ca40bd5539d602ac4e779f53d5)
This commit is contained in:
@@ -74,11 +74,15 @@ namespace Framework.Constants
|
||||
|
||||
public enum QuestType
|
||||
{
|
||||
AutoComplete= 0,
|
||||
Disabled = 1,
|
||||
TurnIn= 0,
|
||||
WithMaxLevel = 1,
|
||||
Normal = 2,
|
||||
Task = 3,
|
||||
Max = 4
|
||||
MaxDBAllowedQuestTypes = 4,
|
||||
|
||||
// values used in quest menu packets
|
||||
InProgress = 4,
|
||||
TaskInProgress = 5
|
||||
}
|
||||
|
||||
public enum QuestInfos
|
||||
@@ -428,37 +432,37 @@ namespace Framework.Constants
|
||||
public enum QuestFlags : uint
|
||||
{
|
||||
None = 0x00,
|
||||
StayAlive = 0x01, // Not Used Currently
|
||||
PartyAccept = 0x02, // Not Used Currently. If Player In Party, All Players That Can Accept This Quest Will Receive Confirmation Box To Accept Quest Cmsg_Quest_Confirm_Accept/Smsg_Quest_Confirm_Accept
|
||||
Exploration = 0x04, // Not Used Currently
|
||||
CompletionNoDeath = 0x01,
|
||||
CompletionEvent = 0x02,
|
||||
CompletionAreaTrigger = 0x04,
|
||||
Sharable = 0x08, // Can Be Shared: Player.Cansharequest()
|
||||
HasCondition = 0x10, // Not Used Currently
|
||||
HideRewardPoi = 0x20, // Not Used Currently: Unsure Of Content
|
||||
Raid = 0x40, // Can be completed while in raid
|
||||
HideRewardPoi = 0x20, // Hides questgiver turn-in minimap icon
|
||||
RaidGroupOk = 0x40, // Can be completed while in raid
|
||||
WarModeRewardsOptIn = 0x80, // Not Used Currently
|
||||
NoMoneyFromXp = 0x100, // Not Used Currently: Experience Is Not Converted To Gold At Max Level
|
||||
HiddenRewards = 0x200, // Items And Money Rewarded Only Sent In Smsg_Questgiver_Offer_Reward (Not In Smsg_Questgiver_Quest_Details Or In Client Quest Log(Smsg_Quest_Query_Response))
|
||||
Tracking = 0x400, // These Quests Are Automatically Rewarded On Quest Complete And They Will Never Appear In Quest Log Client Side.
|
||||
NoMoneyForXp = 0x100, // Experience is not converted to gold at max level
|
||||
HideReward = 0x200, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUEST_GIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
|
||||
TrackingEvent = 0x400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
|
||||
DeprecateReputation = 0x800, // Not Used Currently
|
||||
Daily = 0x1000, // Used To Know Quest Is Daily One
|
||||
Pvp = 0x2000, // Having This Quest In Log Forces Pvp Flag
|
||||
Unavailable = 0x4000, // Used On Quests That Are Not Generically Available
|
||||
Deprecated = 0x4000, // Used on quests that are not generally available
|
||||
Weekly = 0x8000,
|
||||
AutoComplete = 0x10000, // Quests with this flag player submit automatically by special button in player gui
|
||||
DisplayItemInTracker = 0x20000, // Displays Usable Item In Quest Tracker
|
||||
ObjText = 0x40000, // Use Objective Text As Complete Text
|
||||
DisableCompletionText = 0x40000, // Use Objective Text As Complete Text
|
||||
AutoAccept = 0x80000, // The client recognizes this flag as auto-accept.
|
||||
PlayerCastOnAccept = 0x100000,
|
||||
PlayerCastOnComplete = 0x200000,
|
||||
UpdatePhaseShift = 0x400000,
|
||||
PlayerCastAccept = 0x100000,
|
||||
PlayerCastComplete = 0x200000,
|
||||
UpdatePhaseshift = 0x400000,
|
||||
SorWhitelist = 0x800000,
|
||||
LaunchGossipComplete = 0x1000000,
|
||||
RemoveExtraGetItems = 0x2000000,
|
||||
HideUntilDiscovered = 0x4000000,
|
||||
RemoveSurplusItems = 0x2000000, // Remove all items from inventory that have the same id as the objective, not just the amount required by quest
|
||||
WellKnown = 0x04000000,
|
||||
PortraitInQuestLog = 0x8000000,
|
||||
ShowItemWhenCompleted = 0x10000000,
|
||||
LaunchGossipAccept = 0x20000000,
|
||||
ItemsGlowWhenDone = 0x40000000,
|
||||
ItemsGlowWhenComplete = 0x40000000,
|
||||
FailOnLogout = 0x80000000
|
||||
}
|
||||
|
||||
@@ -524,14 +528,14 @@ namespace Framework.Constants
|
||||
{
|
||||
None = 0x00,
|
||||
// Flags For Set Specialflags In Db If Required But Used Only At Server
|
||||
Repeatable = 0x001,
|
||||
ExplorationOrEvent = 0x002, // If Required Area Explore, Spell Spell_Effect_Quest_Complete Casting, Table `*_Script` Command Script_Command_Quest_Explored Use, Set From Script)
|
||||
AutoAccept = 0x004, // Quest Is To Be Auto-Accepted.
|
||||
DfQuest = 0x008, // Quest Is Used By Dungeon Finder.
|
||||
Monthly = 0x010, // Quest Is Reset At The Begining Of The Month
|
||||
Repeatable = 0x001, // Set by 1 in SpecialFlags from DB
|
||||
AutoPushToParty = 0x002, // Set by 2 in SpecialFlags from DB will make quest be pushed to entire party when one member accepts it
|
||||
AutoAccept = 0x004, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted.
|
||||
DfQuest = 0x008, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder.
|
||||
Monthly = 0x010, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month
|
||||
// Room For More Custom Flags
|
||||
|
||||
DbAllowed = Repeatable | ExplorationOrEvent | AutoAccept | DfQuest | Monthly,
|
||||
DbAllowed = Repeatable | AutoAccept | DfQuest | Monthly,
|
||||
|
||||
SequencedObjectives = 0x20 // Internal flag computed only
|
||||
}
|
||||
|
||||
@@ -1461,9 +1461,9 @@ namespace Game.AI
|
||||
Quest qid = Global.ObjectMgr.GetQuestTemplate(e.Action.quest.questId);
|
||||
if (qid != null)
|
||||
{
|
||||
if (!qid.HasSpecialFlag(QuestSpecialFlags.ExplorationOrEvent))
|
||||
if (!qid.HasFlag(QuestFlags.CompletionEvent) && !qid.HasFlag(QuestFlags.CompletionAreaTrigger))
|
||||
{
|
||||
Log.outError(LogFilter.ScriptsAi, $"SmartAIMgr: {e} SpecialFlags for Quest entry {e.Action.quest.questId} does not include FLAGS_EXPLORATION_OR_EVENT(2), skipped.");
|
||||
Log.outError(LogFilter.ScriptsAi, $"SmartAIMgr: {e} Flags for Quest entry {e.Action.quest.questId} does not include QUEST_FLAGS_COMPLETION_EVENT or QUEST_FLAGS_COMPLETION_AREA_TRIGGER, skipped.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ namespace Game.Misc
|
||||
gossipText.QuestType = item.QuestIcon;
|
||||
gossipText.QuestFlags = (uint)quest.Flags;
|
||||
gossipText.QuestFlagsEx = (uint)quest.FlagsEx;
|
||||
gossipText.Repeatable = quest.IsAutoComplete() && quest.IsRepeatable() && !quest.IsDailyOrWeekly() && !quest.IsMonthly();
|
||||
gossipText.Repeatable = quest.IsTurnIn() && quest.IsRepeatable() && !quest.IsDailyOrWeekly() && !quest.IsMonthly();
|
||||
|
||||
gossipText.QuestTitle = quest.LogTitle;
|
||||
Locale locale = _session.GetSessionDbLocaleIndex();
|
||||
@@ -374,7 +374,7 @@ namespace Game.Misc
|
||||
text.QuestType = questMenuItem.QuestIcon;
|
||||
text.QuestFlags = (uint)quest.Flags;
|
||||
text.QuestFlagsEx = (uint)quest.FlagsEx;
|
||||
text.Repeatable = quest.IsAutoComplete() && quest.IsRepeatable() && !quest.IsDailyOrWeekly() && !quest.IsMonthly();
|
||||
text.Repeatable = quest.IsTurnIn() && quest.IsRepeatable() && !quest.IsDailyOrWeekly() && !quest.IsMonthly();
|
||||
text.QuestTitle = quest.LogTitle;
|
||||
|
||||
if (localeConstant != Locale.enUS)
|
||||
|
||||
@@ -310,9 +310,9 @@ namespace Game.Entities
|
||||
if (!CanTakeQuest(quest, false))
|
||||
continue;
|
||||
|
||||
if (quest.IsAutoComplete() && (!quest.IsRepeatable() || quest.IsDaily() || quest.IsWeekly() || quest.IsMonthly()))
|
||||
if (quest.IsTurnIn() && (!quest.IsRepeatable() || quest.IsDaily() || quest.IsWeekly() || quest.IsMonthly()))
|
||||
qm.AddMenuItem(questId, 0);
|
||||
else if (quest.IsAutoComplete())
|
||||
else if (quest.IsTurnIn())
|
||||
qm.AddMenuItem(questId, 4);
|
||||
else if (GetQuestStatus(questId) == QuestStatus.None)
|
||||
qm.AddMenuItem(questId, 2);
|
||||
@@ -347,9 +347,9 @@ namespace Game.Entities
|
||||
if (quest.IsAutoAccept() && CanAddQuest(quest, true) && CanTakeQuest(quest, true))
|
||||
AddQuestAndCheckCompletion(quest, source);
|
||||
|
||||
if (quest.IsAutoComplete() && quest.IsRepeatable() && !quest.IsDailyOrWeekly() && !quest.IsMonthly())
|
||||
if (quest.IsTurnIn() && quest.IsRepeatable() && !quest.IsDailyOrWeekly() && !quest.IsMonthly())
|
||||
PlayerTalkClass.SendQuestGiverRequestItems(quest, source.GetGUID(), CanCompleteRepeatableQuest(quest), true);
|
||||
else if (quest.IsAutoComplete() && !quest.IsDailyOrWeekly() && !quest.IsMonthly())
|
||||
else if (quest.IsTurnIn() && !quest.IsDailyOrWeekly() && !quest.IsMonthly())
|
||||
PlayerTalkClass.SendQuestGiverRequestItems(quest, source.GetGUID(), CanRewardQuest(quest, false), true);
|
||||
else
|
||||
PlayerTalkClass.SendQuestGiverQuestDetails(quest, source.GetGUID(), true, false);
|
||||
@@ -376,7 +376,9 @@ namespace Game.Entities
|
||||
|
||||
if (questGiver == this)
|
||||
{
|
||||
Cypher.Assert(quest.HasFlag(QuestFlags.AutoComplete));
|
||||
if (!quest.HasFlag(QuestFlags.AutoComplete))
|
||||
return null;
|
||||
|
||||
return Global.ObjectMgr.GetQuestTemplate(nextQuestID);
|
||||
}
|
||||
|
||||
@@ -453,7 +455,7 @@ namespace Game.Entities
|
||||
return false; // not allow re-complete quest
|
||||
|
||||
// auto complete quest
|
||||
if (qInfo.IsAutoComplete() && CanTakeQuest(qInfo, false))
|
||||
if (qInfo.IsTurnIn() && CanTakeQuest(qInfo, false))
|
||||
return true;
|
||||
|
||||
var q_status = m_QuestStatus.LookupByKey(questId);
|
||||
@@ -474,7 +476,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
if (qInfo.HasSpecialFlag(QuestSpecialFlags.ExplorationOrEvent) && !q_status.Explored)
|
||||
if ((qInfo.HasFlag(QuestFlags.CompletionEvent) || qInfo.HasFlag(QuestFlags.CompletionAreaTrigger)) && !q_status.Explored)
|
||||
return false;
|
||||
|
||||
if (qInfo.LimitTime != 0 && q_status.Timer == 0)
|
||||
@@ -512,7 +514,7 @@ namespace Game.Entities
|
||||
return false;
|
||||
|
||||
// not auto complete quest and not completed quest (only cheating case, then ignore without message)
|
||||
if (!quest.IsDFQuest() && !quest.IsAutoComplete() && GetQuestStatus(quest.Id) != QuestStatus.Complete)
|
||||
if (!quest.IsDFQuest() && !quest.IsTurnIn() && GetQuestStatus(quest.Id) != QuestStatus.Complete)
|
||||
return false;
|
||||
|
||||
// daily quest can't be rewarded (25 daily quest already completed)
|
||||
@@ -784,7 +786,7 @@ namespace Game.Entities
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(quest.SourceSpellID, GetMap().GetDifficultyID());
|
||||
Unit caster = this;
|
||||
if (questGiver != null && questGiver.IsTypeMask(TypeMask.Unit) && !quest.HasFlag(QuestFlags.PlayerCastOnAccept) && !spellInfo.HasTargetType(Targets.UnitCaster) && !spellInfo.HasTargetType(Targets.DestCasterSummon))
|
||||
if (questGiver != null && questGiver.IsTypeMask(TypeMask.Unit) && !quest.HasFlag(QuestFlags.PlayerCastAccept) && !spellInfo.HasTargetType(Targets.UnitCaster) && !spellInfo.HasTargetType(Targets.DestCasterSummon))
|
||||
{
|
||||
Unit unit = questGiver.ToUnit();
|
||||
if (unit != null)
|
||||
@@ -819,7 +821,7 @@ namespace Game.Entities
|
||||
|
||||
Quest qInfo = Global.ObjectMgr.GetQuestTemplate(quest_id);
|
||||
if (qInfo != null)
|
||||
if (qInfo.HasFlag(QuestFlags.Tracking))
|
||||
if (qInfo.HasFlag(QuestFlags.TrackingEvent))
|
||||
RewardQuest(qInfo, LootItemType.Item, 0, this, false);
|
||||
}
|
||||
}
|
||||
@@ -943,8 +945,13 @@ namespace Game.Entities
|
||||
switch (obj.Type)
|
||||
{
|
||||
case QuestObjectiveType.Item:
|
||||
DestroyItemCount((uint)obj.ObjectID, (uint)obj.Amount, true);
|
||||
{
|
||||
int amountToDestroy = obj.Amount;
|
||||
if (quest.HasFlag(QuestFlags.RemoveSurplusItems))
|
||||
amountToDestroy = int.MaxValue;
|
||||
DestroyItemCount((uint)obj.ObjectID, (uint)amountToDestroy, true);
|
||||
break;
|
||||
}
|
||||
case QuestObjectiveType.Currency:
|
||||
RemoveCurrency((uint)obj.ObjectID, obj.Amount, CurrencyDestroyReason.QuestTurnin);
|
||||
break;
|
||||
@@ -958,7 +965,9 @@ namespace Game.Entities
|
||||
if (quest.ItemDrop[i] != 0)
|
||||
{
|
||||
uint count = quest.ItemDropQuantity[i];
|
||||
DestroyItemCount(quest.ItemDrop[i], count != 0 ? count : 9999, true);
|
||||
if (count == 0)
|
||||
count = uint.MaxValue;
|
||||
DestroyItemCount(quest.ItemDrop[i], count, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1117,7 +1126,7 @@ namespace Game.Entities
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(quest.RewardSpell, GetMap().GetDifficultyID());
|
||||
Unit caster = this;
|
||||
if (questGiver != null && questGiver.IsTypeMask(TypeMask.Unit) && !quest.HasFlag(QuestFlags.PlayerCastOnComplete) && !spellInfo.HasTargetType(Targets.UnitCaster))
|
||||
if (questGiver != null && questGiver.IsTypeMask(TypeMask.Unit) && !quest.HasFlag(QuestFlags.PlayerCastComplete) && !spellInfo.HasTargetType(Targets.UnitCaster))
|
||||
{
|
||||
Unit unit = questGiver.ToUnit();
|
||||
if (unit != null)
|
||||
@@ -1137,7 +1146,7 @@ namespace Game.Entities
|
||||
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(displaySpell.SpellId, GetMap().GetDifficultyID());
|
||||
Unit caster = this;
|
||||
if (questGiver && questGiver.IsTypeMask(TypeMask.Unit) && !quest.HasFlag(QuestFlags.PlayerCastOnComplete) && !spellInfo.HasTargetType(Targets.UnitCaster))
|
||||
if (questGiver && questGiver.IsTypeMask(TypeMask.Unit) && !quest.HasFlag(QuestFlags.PlayerCastComplete) && !spellInfo.HasTargetType(Targets.UnitCaster))
|
||||
{
|
||||
Unit unit = questGiver.ToUnit();
|
||||
if (unit)
|
||||
@@ -1170,69 +1179,69 @@ namespace Game.Entities
|
||||
|
||||
SendQuestGiverStatusMultiple();
|
||||
|
||||
bool conditionChanged = SendQuestUpdate(questId, false);
|
||||
SendQuestUpdate(questId);
|
||||
|
||||
bool updateVisibility = false;
|
||||
if (quest.HasFlag(QuestFlags.UpdatePhaseshift))
|
||||
updateVisibility = PhasingHandler.OnConditionChange(this, false);
|
||||
|
||||
//lets remove flag for delayed teleports
|
||||
SetCanDelayTeleport(false);
|
||||
|
||||
bool canHaveNextQuest = !quest.HasFlag(QuestFlags.AutoComplete) ? questGiver != null && !questGiver.IsPlayer() : true;
|
||||
if (canHaveNextQuest)
|
||||
switch (questGiver.GetTypeId())
|
||||
{
|
||||
switch (questGiver.GetTypeId())
|
||||
case TypeId.Unit:
|
||||
case TypeId.Player:
|
||||
{
|
||||
case TypeId.Unit:
|
||||
case TypeId.Player:
|
||||
//For AutoSubmition was added plr case there as it almost same exclute AI script cases.
|
||||
// Send next quest
|
||||
Quest nextQuest = GetNextQuest(questGiver, quest);
|
||||
if (nextQuest != null)
|
||||
{
|
||||
//For AutoSubmition was added plr case there as it almost same exclute AI script cases.
|
||||
// Send next quest
|
||||
Quest nextQuest = GetNextQuest(questGiver, quest);
|
||||
if (nextQuest != null)
|
||||
// Only send the quest to the player if the conditions are met
|
||||
if (CanTakeQuest(nextQuest, false))
|
||||
{
|
||||
// Only send the quest to the player if the conditions are met
|
||||
if (CanTakeQuest(nextQuest, false))
|
||||
{
|
||||
if (nextQuest.IsAutoAccept() && CanAddQuest(nextQuest, true))
|
||||
AddQuestAndCheckCompletion(nextQuest, questGiver);
|
||||
if (nextQuest.IsAutoAccept() && CanAddQuest(nextQuest, true))
|
||||
AddQuestAndCheckCompletion(nextQuest, questGiver);
|
||||
|
||||
PlayerTalkClass.SendQuestGiverQuestDetails(nextQuest, questGiver.GetGUID(), true, false);
|
||||
}
|
||||
PlayerTalkClass.SendQuestGiverQuestDetails(nextQuest, questGiver.GetGUID(), true, false);
|
||||
}
|
||||
|
||||
PlayerTalkClass.ClearMenus();
|
||||
Creature creatureQGiver = questGiver.ToCreature();
|
||||
if (creatureQGiver != null)
|
||||
creatureQGiver.GetAI().OnQuestReward(this, quest, rewardType, rewardId);
|
||||
break;
|
||||
}
|
||||
case TypeId.GameObject:
|
||||
{
|
||||
// Send next quest
|
||||
Quest nextQuest = GetNextQuest(questGiver, quest);
|
||||
if (nextQuest != null)
|
||||
{
|
||||
// Only send the quest to the player if the conditions are met
|
||||
if (CanTakeQuest(nextQuest, false))
|
||||
{
|
||||
if (nextQuest.IsAutoAccept() && CanAddQuest(nextQuest, true))
|
||||
AddQuestAndCheckCompletion(nextQuest, questGiver);
|
||||
|
||||
PlayerTalkClass.SendQuestGiverQuestDetails(nextQuest, questGiver.GetGUID(), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
PlayerTalkClass.ClearMenus();
|
||||
questGiver.ToGameObject()?.GetAI()?.OnQuestReward(this, quest, rewardType, rewardId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
PlayerTalkClass.ClearMenus();
|
||||
Creature creatureQGiver = questGiver.ToCreature();
|
||||
if (creatureQGiver != null)
|
||||
creatureQGiver.GetAI().OnQuestReward(this, quest, rewardType, rewardId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case TypeId.GameObject:
|
||||
{
|
||||
// Send next quest
|
||||
Quest nextQuest = GetNextQuest(questGiver, quest);
|
||||
if (nextQuest != null)
|
||||
{
|
||||
// Only send the quest to the player if the conditions are met
|
||||
if (CanTakeQuest(nextQuest, false))
|
||||
{
|
||||
if (nextQuest.IsAutoAccept() && CanAddQuest(nextQuest, true))
|
||||
AddQuestAndCheckCompletion(nextQuest, questGiver);
|
||||
|
||||
PlayerTalkClass.SendQuestGiverQuestDetails(nextQuest, questGiver.GetGUID(), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
PlayerTalkClass.ClearMenus();
|
||||
questGiver.ToGameObject()?.GetAI()?.OnQuestReward(this, quest, rewardType, rewardId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Global.ScriptMgr.OnQuestStatusChange(this, questId);
|
||||
Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, QuestStatus.Rewarded);
|
||||
|
||||
if (conditionChanged)
|
||||
if (updateVisibility)
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
|
||||
@@ -1299,6 +1308,21 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public void FailQuestsWithFlag(QuestFlags flag)
|
||||
{
|
||||
for (ushort slot = 0; slot < SharedConst.MaxQuestLogSize; ++slot)
|
||||
{
|
||||
uint questId = GetQuestSlotQuestId(slot);
|
||||
if (questId == 0)
|
||||
continue;
|
||||
|
||||
Quest quest = Global.ObjectMgr.GetQuestTemplate(questId);
|
||||
if (quest != null)
|
||||
if (quest.HasFlag(flag))
|
||||
FailQuest(questId);
|
||||
}
|
||||
}
|
||||
|
||||
public void AbandonQuest(uint questId)
|
||||
{
|
||||
Quest quest = Global.ObjectMgr.GetQuestTemplate(questId);
|
||||
@@ -1865,7 +1889,7 @@ namespace Game.Entities
|
||||
|
||||
QuestStatus oldStatus = m_QuestStatus[questId].Status;
|
||||
m_QuestStatus[questId].Status = status;
|
||||
if (!quest.IsAutoComplete())
|
||||
if (!quest.IsTurnIn())
|
||||
m_QuestStatusSave[questId] = QuestSaveType.Default;
|
||||
|
||||
Global.ScriptMgr.OnQuestStatusChange(this, questId);
|
||||
@@ -1922,7 +1946,7 @@ namespace Game.Entities
|
||||
SendQuestUpdate(questId);
|
||||
}
|
||||
|
||||
bool SendQuestUpdate(uint questId, bool updateVisiblity = true)
|
||||
void SendQuestUpdate(uint questId)
|
||||
{
|
||||
var saBounds = Global.SpellMgr.GetSpellAreaForQuestMapBounds(questId);
|
||||
if (!saBounds.Empty())
|
||||
@@ -1970,7 +1994,6 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
UpdateVisibleGameobjectsOrSpellClicks();
|
||||
return PhasingHandler.OnConditionChange(this, updateVisiblity);
|
||||
}
|
||||
|
||||
public QuestGiverStatus GetQuestDialogStatus(WorldObject questgiver)
|
||||
@@ -2042,7 +2065,7 @@ namespace Game.Entities
|
||||
break;
|
||||
}
|
||||
|
||||
if (quest.IsAutoComplete() && CanTakeQuest(quest, false) && quest.IsRepeatable() && !quest.IsDailyOrWeekly() && !quest.IsMonthly())
|
||||
if (quest.IsTurnIn() && CanTakeQuest(quest, false) && quest.IsRepeatable() && !quest.IsDailyOrWeekly() && !quest.IsMonthly())
|
||||
{
|
||||
if (GetLevel() <= (GetQuestLevel(quest) + WorldConfig.GetIntValue(WorldCfg.QuestLowLevelHideDiff)))
|
||||
result |= QuestGiverStatus.RepeatableTurnin;
|
||||
|
||||
@@ -650,6 +650,8 @@ namespace Game.Entities
|
||||
|
||||
InitializeSelfResurrectionSpells();
|
||||
|
||||
FailQuestsWithFlag(QuestFlags.CompletionNoDeath);
|
||||
|
||||
UpdateCriteria(CriteriaType.DieOnMap, 1);
|
||||
UpdateCriteria(CriteriaType.DieAnywhere, 1);
|
||||
UpdateCriteria(CriteriaType.DieInInstance, 1);
|
||||
|
||||
@@ -1214,15 +1214,12 @@ namespace Game
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!quest.HasSpecialFlag(QuestSpecialFlags.ExplorationOrEvent))
|
||||
if (!quest.HasFlag(QuestFlags.CompletionEvent) && !quest.HasFlag(QuestFlags.CompletionAreaTrigger))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `{0}` has quest (ID: {1}) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id {2}, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT in quest flags. Script command or quest flags wrong. Quest modified to require objective.",
|
||||
Log.outError(LogFilter.Sql, "Table `{0}` has quest (ID: {1}) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id {2}, but quest not have QUEST_FLAGS_COMPLETION_EVENT or QUEST_FLAGS_COMPLETION_AREA_TRIGGER in quest flags. Script command will do nothing.",
|
||||
tableName, tmp.QuestExplored.QuestID, tmp.id);
|
||||
|
||||
// this will prevent quest completing without objective
|
||||
quest.SetSpecialFlag(QuestSpecialFlags.ExplorationOrEvent);
|
||||
|
||||
// continue; - quest objective requirement set and command can be allowed
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tmp.QuestExplored.Distance > SharedConst.DefaultVisibilityDistance)
|
||||
@@ -7249,7 +7246,7 @@ namespace Game
|
||||
|
||||
// additional quest integrity checks (GO, creaturetemplate and itemtemplate must be loaded already)
|
||||
|
||||
if (qinfo.Type >= QuestType.Max)
|
||||
if (qinfo.Type >= QuestType.MaxDBAllowedQuestTypes)
|
||||
Log.outError(LogFilter.Sql, "Quest {0} has `Method` = {1}, expected values are 0, 1 or 2.", qinfo.Id, qinfo.Type);
|
||||
|
||||
if (Convert.ToBoolean(qinfo.SpecialFlags & ~QuestSpecialFlags.DbAllowed))
|
||||
@@ -7292,7 +7289,7 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
if (Convert.ToBoolean(qinfo.Flags & QuestFlags.Tracking))
|
||||
if (Convert.ToBoolean(qinfo.Flags & QuestFlags.TrackingEvent))
|
||||
{
|
||||
// at auto-reward can be rewarded only RewardChoiceItemId[0]
|
||||
for (int j = 1; j < qinfo.RewardChoiceItemId.Length; ++j)
|
||||
@@ -7878,35 +7875,7 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
// check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
|
||||
foreach (SpellNameRecord spellNameEntry in CliDB.SpellNameStorage.Values)
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellNameEntry.Id, Difficulty.None);
|
||||
if (spellInfo == null)
|
||||
continue;
|
||||
|
||||
foreach (var spellEffectInfo in spellInfo.GetEffects())
|
||||
{
|
||||
if (spellEffectInfo.Effect != SpellEffectName.QuestComplete)
|
||||
continue;
|
||||
|
||||
uint questId = (uint)spellEffectInfo.MiscValue;
|
||||
Quest quest = GetQuestTemplate(questId);
|
||||
|
||||
// some quest referenced in spells not exist (outdated spells)
|
||||
if (quest == null)
|
||||
continue;
|
||||
|
||||
if (!quest.HasSpecialFlag(QuestSpecialFlags.ExplorationOrEvent))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Spell (id: {0}) have SPELL_EFFECT_QUEST_COMPLETE for quest {1}, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. " +
|
||||
"Quest flags must be fixed, quest modified to enable objective.", spellInfo.Id, questId);
|
||||
|
||||
// this will prevent quest completing without objective
|
||||
quest.SetSpecialFlag(QuestSpecialFlags.ExplorationOrEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
// don't check spells with SPELL_EFFECT_QUEST_COMPLETE, a lot of invalid db2 data
|
||||
|
||||
// Make all paragon reward quests repeatable
|
||||
foreach (ParagonReputationRecord paragonReputation in CliDB.ParagonReputationStorage.Values)
|
||||
@@ -8122,35 +8091,30 @@ namespace Game
|
||||
{
|
||||
++count;
|
||||
|
||||
uint trigger_ID = result.Read<uint>(0);
|
||||
uint quest_ID = result.Read<uint>(1);
|
||||
uint triggerId = result.Read<uint>(0);
|
||||
uint questId = result.Read<uint>(1);
|
||||
|
||||
AreaTriggerRecord atEntry = CliDB.AreaTriggerStorage.LookupByKey(trigger_ID);
|
||||
AreaTriggerRecord atEntry = CliDB.AreaTriggerStorage.LookupByKey(triggerId);
|
||||
if (atEntry == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Area trigger (ID:{0}) does not exist in `AreaTrigger.dbc`.", trigger_ID);
|
||||
Log.outError(LogFilter.Sql, "Area trigger (ID:{0}) does not exist in `AreaTrigger.dbc`.", triggerId);
|
||||
continue;
|
||||
}
|
||||
|
||||
Quest quest = GetQuestTemplate(quest_ID);
|
||||
|
||||
Quest quest = GetQuestTemplate(questId);
|
||||
if (quest == null)
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `areatrigger_involvedrelation` has record (id: {0}) for not existing quest {1}", trigger_ID, quest_ID);
|
||||
Log.outError(LogFilter.Sql, "Table `areatrigger_involvedrelation` has record (id: {0}) for not existing quest {1}", triggerId, questId);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!quest.HasSpecialFlag(QuestSpecialFlags.ExplorationOrEvent))
|
||||
if (!quest.HasFlag(QuestFlags.CompletionAreaTrigger) && !quest.HasQuestObjectiveType(QuestObjectiveType.AreaTrigger))
|
||||
{
|
||||
Log.outError(LogFilter.Sql, "Table `areatrigger_involvedrelation` has record (id: {0}) for not quest {1}, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Trigger or quest flags must be fixed, quest modified to require objective.", trigger_ID, quest_ID);
|
||||
|
||||
// this will prevent quest completing without objective
|
||||
quest.SetSpecialFlag(QuestSpecialFlags.ExplorationOrEvent);
|
||||
|
||||
// continue; - quest modified to required objective and trigger can be allowed.
|
||||
Log.outError(LogFilter.Sql, $"Table `areatrigger_involvedrelation` has record (id: {triggerId}) for not quest {questId}, but quest not have flag QUEST_FLAGS_COMPLETION_AREA_TRIGGER and no objective with type QUEST_OBJECTIVE_AREATRIGGER. Trigger is obsolete, skipped.");
|
||||
continue;
|
||||
}
|
||||
|
||||
_questAreaTriggerStorage.Add(trigger_ID, quest_ID);
|
||||
_questAreaTriggerStorage.Add(triggerId, questId);
|
||||
|
||||
} while (result.NextRow());
|
||||
|
||||
|
||||
@@ -220,7 +220,8 @@ namespace Game
|
||||
break;
|
||||
}
|
||||
|
||||
player.AreaExploredOrEventHappens(questId);
|
||||
if (qInfo.HasFlag(QuestFlags.CompletionAreaTrigger))
|
||||
player.AreaExploredOrEventHappens(questId);
|
||||
|
||||
if (player.CanCompleteQuest(questId))
|
||||
player.CompleteQuest(questId);
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace Game
|
||||
{
|
||||
_player.AddQuestAndCheckCompletion(quest, obj);
|
||||
|
||||
if (quest.HasFlag(QuestFlags.PartyAccept))
|
||||
if (quest.IsPushedToPartyOnAccept())
|
||||
{
|
||||
var group = _player.GetGroup();
|
||||
if (group)
|
||||
@@ -175,6 +175,26 @@ namespace Game
|
||||
|
||||
_player.PlayerTalkClass.SendCloseGossip();
|
||||
|
||||
if (quest.HasFlag(QuestFlags.LaunchGossipAccept))
|
||||
{
|
||||
void launchGossip(WorldObject worldObject)
|
||||
{
|
||||
_player.PlayerTalkClass.ClearMenus();
|
||||
_player.PrepareGossipMenu(worldObject, _player.GetGossipMenuForSource(worldObject), true);
|
||||
_player.SendPreparedGossip(worldObject);
|
||||
}
|
||||
|
||||
Creature creature = obj.ToCreature();
|
||||
if (creature != null)
|
||||
launchGossip(creature);
|
||||
else
|
||||
{
|
||||
GameObject go = obj.ToGameObject();
|
||||
if (go != null)
|
||||
launchGossip(go);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -202,7 +222,7 @@ namespace Game
|
||||
if (quest.IsAutoAccept() && GetPlayer().CanAddQuest(quest, true))
|
||||
GetPlayer().AddQuestAndCheckCompletion(quest, obj);
|
||||
|
||||
if (quest.IsAutoComplete())
|
||||
if (quest.IsTurnIn())
|
||||
GetPlayer().PlayerTalkClass.SendQuestGiverRequestItems(quest, obj.GetGUID(), GetPlayer().CanCompleteQuest(quest.Id), true);
|
||||
else
|
||||
GetPlayer().PlayerTalkClass.SendQuestGiverQuestDetails(quest, obj.GetGUID(), true, false);
|
||||
@@ -331,7 +351,7 @@ namespace Game
|
||||
}
|
||||
|
||||
if ((!GetPlayer().CanSeeStartQuest(quest) && GetPlayer().GetQuestStatus(packet.QuestID) == QuestStatus.None) ||
|
||||
(GetPlayer().GetQuestStatus(packet.QuestID) != QuestStatus.Complete && !quest.IsAutoComplete()))
|
||||
(GetPlayer().GetQuestStatus(packet.QuestID) != QuestStatus.Complete && !quest.IsTurnIn()))
|
||||
{
|
||||
Log.outError(LogFilter.Network, "Error in QuestStatus.Complete: player {0} ({1}) tried to complete quest {2}, but is not allowed to do so (possible packet-hacking or high latency)",
|
||||
GetPlayer().GetName(), GetPlayer().GetGUID().ToString(), packet.QuestID);
|
||||
@@ -422,35 +442,34 @@ namespace Game
|
||||
[WorldPacketHandler(ClientOpcodes.QuestConfirmAccept)]
|
||||
void HandleQuestConfirmAccept(QuestConfirmAccept packet)
|
||||
{
|
||||
if (_player.GetSharedQuestID() != packet.QuestID)
|
||||
return;
|
||||
|
||||
_player.ClearQuestSharingInfo();
|
||||
Quest quest = Global.ObjectMgr.GetQuestTemplate(packet.QuestID);
|
||||
if (quest != null)
|
||||
{
|
||||
if (!quest.HasFlag(QuestFlags.PartyAccept))
|
||||
return;
|
||||
if (quest == null)
|
||||
return;
|
||||
|
||||
Player originalPlayer = Global.ObjAccessor.FindPlayer(GetPlayer().GetPlayerSharingQuest());
|
||||
if (originalPlayer == null)
|
||||
return;
|
||||
Player originalPlayer = Global.ObjAccessor.FindPlayer(GetPlayer().GetPlayerSharingQuest());
|
||||
if (originalPlayer == null)
|
||||
return;
|
||||
|
||||
if (!GetPlayer().IsInSameRaidWith(originalPlayer))
|
||||
return;
|
||||
if (!_player.IsInSameRaidWith(originalPlayer))
|
||||
return;
|
||||
|
||||
if (!originalPlayer.IsActiveQuest(packet.QuestID))
|
||||
return;
|
||||
if (!originalPlayer.IsActiveQuest(packet.QuestID))
|
||||
return;
|
||||
|
||||
if (!GetPlayer().CanTakeQuest(quest, true))
|
||||
return;
|
||||
if (!_player.CanTakeQuest(quest, true))
|
||||
return;
|
||||
|
||||
if (GetPlayer().CanAddQuest(quest, true))
|
||||
{
|
||||
GetPlayer().AddQuestAndCheckCompletion(quest, null); // NULL, this prevent DB script from duplicate running
|
||||
if (!_player.CanAddQuest(quest, true))
|
||||
return;
|
||||
|
||||
if (quest.SourceSpellID > 0)
|
||||
_player.CastSpell(_player, quest.SourceSpellID, true);
|
||||
}
|
||||
}
|
||||
_player.AddQuestAndCheckCompletion(quest, null); // NULL, this prevent DB script from duplicate running
|
||||
|
||||
GetPlayer().ClearQuestSharingInfo();
|
||||
if (quest.SourceSpellID > 0)
|
||||
_player.CastSpell(_player, quest.SourceSpellID, true);
|
||||
}
|
||||
|
||||
[WorldPacketHandler(ClientOpcodes.QuestGiverCompleteQuest, Processing = PacketProcessing.Inplace)]
|
||||
@@ -462,9 +481,6 @@ namespace Game
|
||||
if (quest == null)
|
||||
return;
|
||||
|
||||
if (autoCompleteMode && !quest.HasFlag(QuestFlags.AutoComplete))
|
||||
return;
|
||||
|
||||
WorldObject obj;
|
||||
if (autoCompleteMode)
|
||||
obj = GetPlayer();
|
||||
@@ -474,7 +490,7 @@ namespace Game
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
if (!autoCompleteMode)
|
||||
if (!quest.HasFlag(QuestFlags.AutoComplete))
|
||||
{
|
||||
if (!obj.HasInvolvedQuest(packet.QuestID))
|
||||
return;
|
||||
@@ -666,7 +682,7 @@ namespace Game
|
||||
|
||||
sender.SendPushToPartyResponse(receiver, QuestPushReason.Success);
|
||||
|
||||
if ((quest.IsAutoComplete() && quest.IsRepeatable() && !quest.IsDailyOrWeekly()) || quest.HasFlag(QuestFlags.AutoComplete))
|
||||
if (quest.IsTurnIn() && quest.IsRepeatable() && !quest.IsDailyOrWeekly())
|
||||
receiver.PlayerTalkClass.SendQuestGiverRequestItems(quest, sender.GetGUID(), receiver.CanCompleteRepeatableQuest(quest), true);
|
||||
else
|
||||
{
|
||||
|
||||
+15
-14
@@ -462,7 +462,7 @@ namespace Game
|
||||
{
|
||||
return (uint)(MaxMoneyValue() * WorldConfig.GetFloatValue(WorldCfg.RateMoneyQuest));
|
||||
}
|
||||
|
||||
|
||||
public QuestTagType? GetQuestTag()
|
||||
{
|
||||
QuestInfoRecord questInfo = CliDB.QuestInfoStorage.LookupByKey(QuestInfoID);
|
||||
@@ -471,7 +471,7 @@ namespace Game
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void BuildQuestRewards(QuestRewards rewards, Player player)
|
||||
{
|
||||
rewards.ChoiceItemCount = GetRewChoiceItemsCount();
|
||||
@@ -494,7 +494,7 @@ namespace Game
|
||||
if (++displaySpellIndex >= rewards.SpellCompletionDisplayID.Length)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
rewards.SpellCompletionID = RewardSpell;
|
||||
rewards.SkillLineID = RewardSkillId;
|
||||
rewards.NumSkillUps = RewardSkillPoints;
|
||||
@@ -532,7 +532,7 @@ namespace Game
|
||||
public uint GetRewMoneyMaxLevel()
|
||||
{
|
||||
// If Quest has flag to not give money on max level, it's 0
|
||||
if (HasFlag(QuestFlags.NoMoneyFromXp))
|
||||
if (HasFlag(QuestFlags.NoMoneyForXp))
|
||||
return 0;
|
||||
|
||||
// Else, return the rewarded copper sum modified by the rate
|
||||
@@ -544,9 +544,9 @@ namespace Game
|
||||
return !WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoAccept) && HasFlag(QuestFlags.AutoAccept);
|
||||
}
|
||||
|
||||
public bool IsAutoComplete()
|
||||
public bool IsTurnIn()
|
||||
{
|
||||
return !WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoComplete) && Type == QuestType.AutoComplete;
|
||||
return !WorldConfig.GetBoolValue(WorldCfg.QuestIgnoreAutoComplete) && Type == QuestType.TurnIn;
|
||||
}
|
||||
|
||||
public bool IsRaidQuest(Difficulty difficulty)
|
||||
@@ -563,7 +563,7 @@ namespace Game
|
||||
break;
|
||||
}
|
||||
|
||||
if (Flags.HasAnyFlag(QuestFlags.Raid))
|
||||
if (Flags.HasAnyFlag(QuestFlags.RaidGroupOk))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -655,7 +655,7 @@ namespace Game
|
||||
response.Info.RewardXPDifficulty = RewardXPDifficulty;
|
||||
response.Info.RewardXPMultiplier = RewardXPMultiplier;
|
||||
|
||||
if (!HasFlag(QuestFlags.HiddenRewards))
|
||||
if (!HasFlag(QuestFlags.HideReward))
|
||||
response.Info.RewardMoney = (int)(player != null ? player.GetQuestMoneyReward(this) : GetMaxMoneyReward());
|
||||
|
||||
response.Info.RewardMoneyDifficulty = RewardMoneyDifficulty;
|
||||
@@ -699,7 +699,7 @@ namespace Game
|
||||
response.Info.ItemDropQuantity[i] = (int)ItemDropQuantity[i];
|
||||
}
|
||||
|
||||
if (!HasFlag(QuestFlags.HiddenRewards))
|
||||
if (!HasFlag(QuestFlags.HideReward))
|
||||
{
|
||||
for (byte i = 0; i < SharedConst.QuestRewardItemCount; ++i)
|
||||
{
|
||||
@@ -780,12 +780,12 @@ namespace Game
|
||||
public void SetSpecialFlag(QuestSpecialFlags flag) { SpecialFlags |= flag; }
|
||||
|
||||
public bool HasQuestObjectiveType(QuestObjectiveType type) { return _usedQuestObjectiveTypes[(int)type]; }
|
||||
|
||||
public bool IsAutoPush() { return HasFlagEx(QuestFlagsEx.AutoPush); }
|
||||
public bool IsWorldQuest() { return HasFlagEx(QuestFlagsEx.IsWorldQuest);}
|
||||
|
||||
public bool IsAutoPush() { return HasFlagEx(QuestFlagsEx.AutoPush); }
|
||||
public bool IsWorldQuest() { return HasFlagEx(QuestFlagsEx.IsWorldQuest); }
|
||||
|
||||
// Possibly deprecated flag
|
||||
public bool IsUnavailable() { return HasFlag(QuestFlags.Unavailable); }
|
||||
public bool IsUnavailable() { return HasFlag(QuestFlags.Deprecated); }
|
||||
|
||||
// table data accessors:
|
||||
public bool IsRepeatable() { return SpecialFlags.HasAnyFlag(QuestSpecialFlags.Repeatable); }
|
||||
@@ -800,7 +800,8 @@ namespace Game
|
||||
}
|
||||
public bool IsDailyOrWeekly() { return Flags.HasAnyFlag(QuestFlags.Daily | QuestFlags.Weekly); }
|
||||
public bool IsDFQuest() { return SpecialFlags.HasAnyFlag(QuestSpecialFlags.DfQuest); }
|
||||
|
||||
public bool IsPushedToPartyOnAccept() { return HasSpecialFlag(QuestSpecialFlags.AutoPushToParty); }
|
||||
|
||||
public uint GetRewChoiceItemsCount() { return _rewChoiceItemsCount; }
|
||||
public uint GetRewItemsCount() { return _rewItemsCount; }
|
||||
public uint GetRewCurrencyCount() { return _rewCurrencyCount; }
|
||||
|
||||
@@ -153,6 +153,8 @@ namespace Game
|
||||
// Clear whisper whitelist
|
||||
_player.ClearWhisperWhiteList();
|
||||
|
||||
_player.FailQuestsWithFlag(QuestFlags.FailOnLogout);
|
||||
|
||||
// empty buyback items and save the player in the database
|
||||
// some save parts only correctly work in case player present in map/player_lists (pets, etc)
|
||||
if (save)
|
||||
|
||||
@@ -71,10 +71,10 @@ namespace Game.Spells
|
||||
_triggeredCastFlags = triggerFlags;
|
||||
|
||||
if (info.HasAttribute(SpellAttr2.DoNotReportSpellFailure))
|
||||
_triggeredCastFlags = _triggeredCastFlags | TriggerCastFlags.DontReportCastError;
|
||||
_triggeredCastFlags |= TriggerCastFlags.DontReportCastError;
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr4.AllowCastWhileCasting))
|
||||
_triggeredCastFlags = _triggeredCastFlags | TriggerCastFlags.IgnoreCastInProgress;
|
||||
_triggeredCastFlags |= TriggerCastFlags.IgnoreCastInProgress;
|
||||
|
||||
m_castItemLevel = -1;
|
||||
|
||||
|
||||
@@ -3362,7 +3362,7 @@ namespace Game.Spells
|
||||
ushort logSlot = player.FindQuestSlot(questId);
|
||||
if (logSlot < SharedConst.MaxQuestLogSize)
|
||||
player.AreaExploredOrEventHappens(questId);
|
||||
else if (quest.HasFlag(QuestFlags.Tracking)) // Check if the quest is used as a serverside flag.
|
||||
else if (quest.HasFlag(QuestFlags.TrackingEvent)) // Check if the quest is used as a serverside flag.
|
||||
player.SetRewardedQuest(questId); // If so, set status to rewarded without broadcasting it to client.
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user