From 986c129bc0d7db60f56e094d1eef55970c1e92d8 Mon Sep 17 00:00:00 2001 From: sevi Date: Fri, 1 Dec 2023 16:07:39 +0100 Subject: [PATCH] Core/Quests: implement the option to cast spells upon abandoning quests (#434) * Core/Quest: Implement a way to cast Spells on Quest Abandon. * Core/Player: add a missing ; * Core/Quest: moved the Abandon Spell away from a own table into quest_template_addon. --- ...23_11_29_01_world_quest_abandon_spells.sql | 6 ++++++ src/server/game/Entities/Player/Player.cpp | 4 ++++ src/server/game/Globals/ObjectMgr.cpp | 21 +++++++++++++++++-- src/server/game/Quests/QuestDef.cpp | 1 + src/server/game/Quests/QuestDef.h | 2 ++ 5 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 sql/updates/world/4.3.4/2023_11_29_01_world_quest_abandon_spells.sql diff --git a/sql/updates/world/4.3.4/2023_11_29_01_world_quest_abandon_spells.sql b/sql/updates/world/4.3.4/2023_11_29_01_world_quest_abandon_spells.sql new file mode 100644 index 0000000000..b14a2c6d77 --- /dev/null +++ b/sql/updates/world/4.3.4/2023_11_29_01_world_quest_abandon_spells.sql @@ -0,0 +1,6 @@ +-- +ALTER TABLE `quest_template_addon` + ADD COLUMN `AbandonSpellID` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `TimeAllowed`; + +-- Example +UPDATE `quest_template_addon` SET `AbandonSpellID` = 74113 WHERE `ID` = 24958; -- Volcanoth! \ No newline at end of file diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 41bb98efaf..309e873eda 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -14595,6 +14595,10 @@ void Player::AbandonQuest(uint32 questId) if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->ItemDrop[i])) if (quest->ItemDropQuantity[i] > 0 && itemTemplate->GetBonding() == BIND_QUEST) DestroyItemCount(quest->ItemDrop[i], 9999, true); + + // If Quest has a Abandon Spell cast it now + if (quest->GetQuestAbandonSpell() != 0) + CastSpell(this, quest->GetQuestAbandonSpell(), true); } } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index d92c32ce2c..4f91c4ef03 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4092,8 +4092,8 @@ void ObjectMgr::LoadQuests() // 0 1 2 3 4 5 6 7 8 9 { "ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, BreadcrumbForQuestId, RewardMailTemplateID, RewardMailDelay," - // 10 11 12 13 14 15 16 17 18 19 - " RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, SpecialFlags, AllowableRaces, TimeAllowed", "quest_template_addon", "template addons", &Quest::LoadQuestTemplateAddon }, + // 10 11 12 13 14 15 16 17 18 19 20 + " RequiredSkillID, RequiredSkillPoints, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, ProvidedItemCount, SpecialFlags, AllowableRaces, TimeAllowed, AbandonSpellID", "quest_template_addon", "template addons", &Quest::LoadQuestTemplateAddon }, // 0 1 { "QuestId, RewardMailSenderEntry", "quest_mail_sender", "mail sender entries", &Quest::LoadQuestMailSender } @@ -4757,6 +4757,23 @@ void ObjectMgr::LoadQuests() } } + if (qinfo->_questAbandonSpell) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(qinfo->_questAbandonSpell); + if (!spellInfo) + { + TC_LOG_ERROR("sql.sql", "Quest %u has `QuestAbandonSpell` = %u but spell %u doesn't exist, quest abandon Spell can't be work.", + qinfo->GetQuestId(), qinfo->_questAbandonSpell, qinfo->_questAbandonSpell); + qinfo->_questAbandonSpell = 0; // quest can't be done for this requirement + } + else if (!SpellMgr::IsSpellValid(spellInfo)) + { + TC_LOG_ERROR("sql.sql", "Quest %u has `QuestAbandonSpell` = %u but spell %u is broken, quest abandon Spell can't be work", + qinfo->GetQuestId(), qinfo->_questAbandonSpell, qinfo->_questAbandonSpell); + qinfo->_questAbandonSpell = 0; // quest can't be done for this requirement + } + } + // fill additional data stores if (uint32 prevQuestId = std::abs(qinfo->_prevQuestId)) { diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 65cd610339..b607546f2b 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -232,6 +232,7 @@ void Quest::LoadQuestTemplateAddon(Field* fields) _allowableRaces = fields[18].GetUInt32(); _timeAllowed = fields[19].GetInt32(); + _questAbandonSpell = fields[20].GetUInt32(); } void Quest::LoadQuestMailSender(Field* fields) diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index cb110c808a..9fba55ebdb 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -371,6 +371,7 @@ class TC_GAME_API Quest uint32 GetRewItemsCount() const { return _rewItemsCount; } uint32 GetRewCurrencyCount() const { return _rewCurrencyCount; } uint32 GetReqCurrencyCount() const { return _reqCurrencyCount; } + uint32 GetQuestAbandonSpell() const { return _questAbandonSpell; } void SetEventIdForQuest(uint16 eventId) { _eventIdForQuest = eventId; } uint16 GetEventIdForQuest() const { return _eventIdForQuest; } @@ -475,6 +476,7 @@ class TC_GAME_API Quest uint32 _specialFlags = 0; // custom flags, not sniffed/WDB uint32 _allowableRaces = 0; uint32 _timeAllowed = 0; + uint32 _questAbandonSpell = 0; }; struct QuestStatusData