From a2be8d202823706ad4b29c2dc988c0fe978ae652 Mon Sep 17 00:00:00 2001 From: Shauren Date: Fri, 2 Jun 2023 00:50:30 +0200 Subject: Core/Quests: Implemented new db table quest_objectives_completion_effect * Turn off automatic phase updates on quest objective completion * Allow more convenient conversation and spell casts on quest objective completion --- src/server/game/Entities/Player/Player.cpp | 26 +++++++++++++++++++++++++- src/server/game/Globals/ObjectMgr.cpp | 6 ++++-- src/server/game/Quests/QuestDef.cpp | 25 +++++++++++++++++++++++-- src/server/game/Quests/QuestDef.h | 11 +++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 6d28af5cd21..cb269842145 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -55,6 +55,7 @@ #include "EquipmentSetPackets.h" #include "Formulas.h" #include "GameEventMgr.h" +#include "GameEventSender.h" #include "GameObjectAI.h" #include "Garrison.h" #include "GarrisonMgr.h" @@ -16544,6 +16545,8 @@ void Player::CurrencyChanged(uint32 currencyId, int32 change) void Player::UpdateQuestObjectiveProgress(QuestObjectiveType objectiveType, int32 objectId, int64 addCount, ObjectGuid victimGuid) { bool anyObjectiveChangedCompletionState = false; + bool updatePhaseShift = false; + bool updateZoneAuras = false; for (QuestObjectiveStatusMap::value_type const& objectiveItr : Trinity::Containers::MapEqualRange(m_questObjectiveStatus, { objectiveType, objectId })) { @@ -16648,6 +16651,20 @@ void Player::UpdateQuestObjectiveProgress(QuestObjectiveType objectiveType, int3 if (objectiveWasComplete != objectiveIsNowComplete) anyObjectiveChangedCompletionState = true; + if (objectiveIsNowComplete && objective.CompletionEffect) + { + if (objective.CompletionEffect->GameEventId) + GameEvents::Trigger(*objective.CompletionEffect->GameEventId, this, nullptr); + if (objective.CompletionEffect->SpellId) + CastSpell(this, *objective.CompletionEffect->SpellId, true); + if (objective.CompletionEffect->ConversationId) + Conversation::CreateConversation(*objective.CompletionEffect->ConversationId, this, GetPosition(), GetGUID()); + if (objective.CompletionEffect->UpdatePhaseShift) + updatePhaseShift = true; + if (objective.CompletionEffect->UpdateZoneAuras) + updateZoneAuras = true; + } + if (objectiveIsNowComplete && CanCompleteQuest(questId, objective.ID)) CompleteQuest(questId); else if (objectiveItr.second.QuestStatusItr->second.Status == QUEST_STATUS_COMPLETE) @@ -16658,7 +16675,14 @@ void Player::UpdateQuestObjectiveProgress(QuestObjectiveType objectiveType, int3 if (anyObjectiveChangedCompletionState) UpdateVisibleGameobjectsOrSpellClicks(); - PhasingHandler::OnConditionChange(this); + if (updatePhaseShift) + PhasingHandler::OnConditionChange(this); + + if (updateZoneAuras) + { + UpdateZoneDependentAuras(GetZoneId()); + UpdateAreaDependentAuras(GetAreaId()); + } } bool Player::HasQuestForItem(uint32 itemid) const diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 60ab1dfa41b..94f0b5cd966 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4554,8 +4554,10 @@ void ObjectMgr::LoadQuests() // 0 1 { "QuestId, RewardMailSenderEntry", "quest_mail_sender", "", "mail sender entries", &Quest::LoadQuestMailSender }, - // 0 1 2 3 4 5 6 7 8 9 - { "QuestID, ID, Type, StorageIndex, ObjectID, Amount, Flags, Flags2, ProgressBarWeight, Description", "quest_objectives", "ORDER BY `Order` ASC, StorageIndex ASC", "quest objectives", &Quest::LoadQuestObjective }, + // 0 1 2 3 4 5 6 7 8 9 + { "qo.QuestID, qo.ID, qo.Type, qo.StorageIndex, qo.ObjectID, qo.Amount, qo.Flags, qo.Flags2, qo.ProgressBarWeight, qo.Description, " + // 10 11 12 13 14 + "qoce.GameEventID, qoce.SpellID, qoce.ConversationID, qoce.UpdatePhaseShift, qoce.UpdateZoneAuras", "quest_objectives qo", "LEFT JOIN quest_objectives_completion_effect qoce ON qo.ID = qoce.ObjectiveID ORDER BY `Order` ASC, StorageIndex ASC", "quest objectives", &Quest::LoadQuestObjective }, // 0 1 2 3 4 { "QuestId, PlayerConditionId, QuestgiverCreatureId, Text, locale", "quest_description_conditional", "ORDER BY OrderIndex", "conditional details", &Quest::LoadConditionalConditionalQuestDescription }, diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index b4e18f2ed97..e3d39cef7a9 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -131,6 +131,12 @@ Quest::Quest(Field* questRecord) _questCompletionLog = questRecord[115].GetString(); } +Quest::~Quest() +{ + for (QuestObjective& objective : Objectives) + delete objective.CompletionEffect; +} + void Quest::LoadRewardDisplaySpell(Field* fields) { uint32 spellId = fields[1].GetUInt32(); @@ -248,7 +254,7 @@ void Quest::LoadQuestMailSender(Field* fields) void Quest::LoadQuestObjective(Field* fields) { - QuestObjective obj; + QuestObjective& obj = Objectives.emplace_back(); obj.QuestID = fields[0].GetUInt32(); obj.ID = fields[1].GetUInt32(); obj.Type = fields[2].GetUInt8(); @@ -260,7 +266,22 @@ void Quest::LoadQuestObjective(Field* fields) obj.ProgressBarWeight = fields[8].GetFloat(); obj.Description = fields[9].GetString(); - Objectives.push_back(obj); + bool hasCompletionEffect = std::any_of(fields + 10, fields + 15, [](Field const& f) { return !f.IsNull(); }); + if (hasCompletionEffect) + { + obj.CompletionEffect = new QuestObjectiveAction(); + if (!fields[10].IsNull()) + obj.CompletionEffect->GameEventId = fields[10].GetUInt32(); + if (!fields[11].IsNull()) + obj.CompletionEffect->SpellId = fields[11].GetUInt32(); + if (!fields[12].IsNull()) + obj.CompletionEffect->ConversationId = fields[12].GetUInt32(); + if (!fields[13].IsNull()) + obj.CompletionEffect->UpdatePhaseShift = fields[13].GetBool(); + if (!fields[14].IsNull()) + obj.CompletionEffect->UpdateZoneAuras = fields[14].GetBool(); + } + _usedQuestObjectiveTypes[obj.Type] = true; } diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 3660d2da57f..016ec2dc958 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -403,6 +403,15 @@ struct QuestOfferRewardLocale std::vector RewardText; }; +struct QuestObjectiveAction +{ + Optional GameEventId; + Optional SpellId; + Optional ConversationId; + bool UpdatePhaseShift = false; + bool UpdateZoneAuras = false; +}; + struct QuestObjective { uint32 ID = 0; @@ -416,6 +425,7 @@ struct QuestObjective float ProgressBarWeight = 0.0f; std::string Description; std::vector VisualEffects; + QuestObjectiveAction* CompletionEffect = nullptr; bool IsStoringValue() const { @@ -504,6 +514,7 @@ class TC_GAME_API Quest public: // Loading data. All queries are in ObjectMgr::LoadQuests() explicit Quest(Field* questRecord); + ~Quest(); void LoadRewardDisplaySpell(Field* fields); void LoadRewardChoiceItems(Field* fields); void LoadQuestDetails(Field* fields); -- cgit v1.2.3