From b017ef8e8412de912c668aa5f5a617892460f906 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Mon, 4 Dec 2017 14:30:01 -0500 Subject: [PATCH] Core/Scripts: Added new QuestScript hooks --- Source/Framework/Constants/CreatureConst.cs | 1 + Source/Game/Chat/Commands/QuestCommands.cs | 3 +++ Source/Game/Entities/Player/Player.Quest.cs | 17 ++++++++++++++--- Source/Game/Globals/ObjectManager.cs | 7 +++++-- Source/Game/Handlers/QuestHandler.cs | 5 +++++ Source/Game/Quest/Quest.cs | 2 ++ Source/Game/Scripting/CoreScripts.cs | 16 ++++++++++++++++ Source/Game/Scripting/ScriptManager.cs | 17 +++++++++++++++++ Source/Game/Spells/SpellEffects.cs | 5 ++++- 9 files changed, 67 insertions(+), 6 deletions(-) diff --git a/Source/Framework/Constants/CreatureConst.cs b/Source/Framework/Constants/CreatureConst.cs index dc349df38..2b93bb6b3 100644 --- a/Source/Framework/Constants/CreatureConst.cs +++ b/Source/Framework/Constants/CreatureConst.cs @@ -142,6 +142,7 @@ namespace Framework.Constants ArtifactPowerRespec = 0x8000000, Transmogrifier = 0x10000000, VaultKeeper = 0x20000000, + WildBattlePet = 0x0040000000, BlackMarket = 0x80000000, ItemUpgradeMaster = 0x100000000, GarrisonArchitect = 0x200000000, diff --git a/Source/Game/Chat/Commands/QuestCommands.cs b/Source/Game/Chat/Commands/QuestCommands.cs index 4a53f793a..ece9bf66c 100644 --- a/Source/Game/Chat/Commands/QuestCommands.cs +++ b/Source/Game/Chat/Commands/QuestCommands.cs @@ -182,6 +182,8 @@ namespace Game.Chat return false; } + QuestStatus oldStatus = player.GetQuestStatus(entry); + // remove all quest entries for 'entry' from quest log for (byte slot = 0; slot < SharedConst.MaxQuestLogSize; ++slot) { @@ -205,6 +207,7 @@ namespace Game.Chat player.RemoveRewardedQuest(entry); Global.ScriptMgr.OnQuestStatusChange(player, entry); + Global.ScriptMgr.OnQuestStatusChange(player, quest, oldStatus, QuestStatus.None); handler.SendSysMessage(CypherStrings.CommandQuestRemoved); return true; diff --git a/Source/Game/Entities/Player/Player.Quest.cs b/Source/Game/Entities/Player/Player.Quest.cs index 9a8c0395a..5cd093c54 100644 --- a/Source/Game/Entities/Player/Player.Quest.cs +++ b/Source/Game/Entities/Player/Player.Quest.cs @@ -693,6 +693,7 @@ namespace Game.Entities m_QuestStatus[quest_id] = new QuestStatusData(); QuestStatusData questStatusData = m_QuestStatus.LookupByKey(quest_id); + QuestStatus oldStatus = questStatusData.Status; // check for repeatable quests status reset questStatusData.Status = QuestStatus.Incomplete; @@ -757,6 +758,7 @@ namespace Game.Entities SendQuestUpdate(quest_id); Global.ScriptMgr.OnQuestStatusChange(this, quest_id); + Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, questStatusData.Status); } public void CompleteQuest(uint quest_id) @@ -843,6 +845,7 @@ namespace Game.Entities SetCanDelayTeleport(true); uint quest_id = quest.Id; + QuestStatus oldStatus = GetQuestStatus(quest_id); foreach (QuestObjective obj in quest.Objectives) { @@ -1101,6 +1104,7 @@ namespace Game.Entities SetCanDelayTeleport(false); Global.ScriptMgr.OnQuestStatusChange(this, quest_id); + Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, QuestStatus.Rewarded); } public void SetRewardedQuest(uint quest_id) @@ -1741,18 +1745,20 @@ namespace Game.Entities Quest quest = Global.ObjectMgr.GetQuestTemplate(questId); if (quest != null) { + QuestStatus oldStatus = m_QuestStatus[questId].Status; if (!m_QuestStatus.ContainsKey(questId)) m_QuestStatus[questId] = new QuestStatusData(); m_QuestStatus[questId].Status = status; if (!quest.IsAutoComplete()) m_QuestStatusSave[questId] = QuestSaveType.Default; + + Global.ScriptMgr.OnQuestStatusChange(this, questId); + Global.ScriptMgr.OnQuestStatusChange(this, quest, oldStatus, status); } if (update) SendQuestUpdate(questId); - - Global.ScriptMgr.OnQuestStatusChange(this, questId); } public void RemoveActiveQuest(uint quest_id, bool update = true) @@ -2663,9 +2669,14 @@ namespace Game.Entities } // No change - if (status.ObjectiveData[objective.StorageIndex] == data) + int oldData = status.ObjectiveData[objective.StorageIndex]; + if (oldData == data) return; + Quest quest = Global.ObjectMgr.GetQuestTemplate(objective.QuestID); + if (quest != null) + Global.ScriptMgr.OnQuestObjectiveChange(this, quest, objective, oldData, data); + // Set data status.ObjectiveData[objective.StorageIndex] = data; diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index aff9a9981..36b529375 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -1046,6 +1046,7 @@ namespace Game "UNION SELECT DISTINCT(ScriptName) FROM conditions WHERE ScriptName <> '' " + "UNION SELECT DISTINCT(ScriptName) FROM outdoorpvp_template WHERE ScriptName <> '' " + "UNION SELECT DISTINCT(ScriptName) FROM scene_template WHERE ScriptName <> '' " + + "UNION SELECT DISTINCT(ScriptName) FROM quest_template_addon WHERE ScriptName <> '' " + "UNION SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); if (result.IsEmpty()) @@ -6298,8 +6299,10 @@ namespace Game // Load `quest_template_addon` // 0 1 2 3 4 5 6 7 8 result = DB.World.Query("SELECT ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, RewardMailTemplateID, RewardMailDelay, " + - //9 10 11 12 13 14 15 16 17 - "RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, RewardMailSenderEntry, SpecialFlags FROM quest_template_addon LEFT JOIN quest_mail_sender ON Id=QuestId"); + //9 10 11 12 13 14 15 16 + "RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, RewardMailSenderEntry, " + + //17 18 + "SpecialFlags, ScriptName FROM quest_template_addon LEFT JOIN quest_mail_sender ON Id=QuestId"); if (result.IsEmpty()) { diff --git a/Source/Game/Handlers/QuestHandler.cs b/Source/Game/Handlers/QuestHandler.cs index bc3ba9655..8087d9c1b 100644 --- a/Source/Game/Handlers/QuestHandler.cs +++ b/Source/Game/Handlers/QuestHandler.cs @@ -419,6 +419,8 @@ namespace Game return; // can't un-equip some items, reject quest cancel Quest quest = Global.ObjectMgr.GetQuestTemplate(questId); + QuestStatus oldStatus = _player.GetQuestStatus(questId); + if (quest != null) { if (quest.HasSpecialFlag(QuestSpecialFlags.Timed)) @@ -439,6 +441,9 @@ namespace Game Log.outInfo(LogFilter.Network, "Player {0} abandoned quest {1}", GetPlayer().GetGUID().ToString(), questId); Global.ScriptMgr.OnQuestStatusChange(_player, questId); + + if (quest != null) + Global.ScriptMgr.OnQuestStatusChange(_player, quest, oldStatus, QuestStatus.None); } GetPlayer().SetQuestSlot(packet.Entry, 0); diff --git a/Source/Game/Quest/Quest.cs b/Source/Game/Quest/Quest.cs index ef7402a47..b340eddbd 100644 --- a/Source/Game/Quest/Quest.cs +++ b/Source/Game/Quest/Quest.cs @@ -202,6 +202,7 @@ namespace Game SourceItemIdCount = fields.Read(15); RewardMailSenderEntry = fields.Read(16); SpecialFlags = (QuestSpecialFlags)fields.Read(17); + ScriptId = Global.ObjectMgr.GetScriptId(fields.Read(18)); if (SpecialFlags.HasAnyFlag(QuestSpecialFlags.AutoAccept)) Flags |= QuestFlags.AutoAccept; @@ -524,6 +525,7 @@ namespace Game public uint SourceItemIdCount; public uint RewardMailSenderEntry; public QuestSpecialFlags SpecialFlags; // custom flags, not sniffed/WDB + public uint ScriptId; public List prevQuests = new List(); public List prevChainQuests = new List(); diff --git a/Source/Game/Scripting/CoreScripts.cs b/Source/Game/Scripting/CoreScripts.cs index f489a31a7..0627a41db 100644 --- a/Source/Game/Scripting/CoreScripts.cs +++ b/Source/Game/Scripting/CoreScripts.cs @@ -770,4 +770,20 @@ namespace Game.Scripting // Called when a scene is completed public virtual void OnSceneComplete(Player player, uint sceneInstanceID, SceneTemplate sceneTemplate) { } } + + class QuestScript : ScriptObject + { + public QuestScript(string name) : base(name) + { + Global.ScriptMgr.AddScript(this); + } + + public override bool IsDatabaseBound() { return true; } + + // Called when a quest status change + public virtual void OnQuestStatusChange(Player player, Quest quest, QuestStatus oldStatus, QuestStatus newStatus) { } + + // Called when a quest objective data change + public virtual void OnQuestObjectiveChange(Player player, Quest quest, QuestObjective objective, int oldAmount, int newAmount) { } + } } diff --git a/Source/Game/Scripting/ScriptManager.cs b/Source/Game/Scripting/ScriptManager.cs index 66db8b928..8aeea75f0 100644 --- a/Source/Game/Scripting/ScriptManager.cs +++ b/Source/Game/Scripting/ScriptManager.cs @@ -1327,6 +1327,23 @@ namespace Game.Scripting RunScript(script => script.OnSceneComplete(player, sceneInstanceID, sceneTemplate), sceneTemplate.ScriptId); } + //QuestScript + public void OnQuestStatusChange(Player player, Quest quest, QuestStatus oldStatus, QuestStatus newStatus) + { + Contract.Assert(player); + Contract.Assert(quest != null); + + RunScript(script => script.OnQuestStatusChange(player, quest, oldStatus, newStatus), quest.ScriptId); + } + + public void OnQuestObjectiveChange(Player player, Quest quest, QuestObjective objective, int oldAmount, int newAmount) + { + Contract.Assert(player); + Contract.Assert(quest != null); + + RunScript(script => script.OnQuestObjectiveChange(player, quest, objective, oldAmount, newAmount), quest.ScriptId); + } + public void ForEach(Action a) where T : ScriptObject { var reg = GetScriptRegistry(); diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index d1e8f63f9..5f8950d1f 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -4264,8 +4264,10 @@ namespace Game.Spells if (quest == null) return; + QuestStatus oldStatus = player.GetQuestStatus(quest_id); + // Player has never done this quest - if (player.GetQuestStatus(quest_id) == QuestStatus.None) + if (oldStatus == QuestStatus.None) return; // remove all quest entries for 'entry' from quest log @@ -4291,6 +4293,7 @@ namespace Game.Spells player.RemoveRewardedQuest(quest_id); Global.ScriptMgr.OnQuestStatusChange(player, quest_id); + Global.ScriptMgr.OnQuestStatusChange(player, quest, oldStatus, QuestStatus.None); } [SpellEffectHandler(SpellEffectName.SendTaxi)]