diff options
-rw-r--r-- | sql/updates/world/master/2021_05_09_00_world.sql | 20 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartAI.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/GossipDef.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 157 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 29 | ||||
-rw-r--r-- | src/server/game/Handlers/QuestHandler.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Quests/QuestDef.h | 18 |
8 files changed, 105 insertions, 130 deletions
diff --git a/sql/updates/world/master/2021_05_09_00_world.sql b/sql/updates/world/master/2021_05_09_00_world.sql new file mode 100644 index 00000000000..5945bbbade7 --- /dev/null +++ b/sql/updates/world/master/2021_05_09_00_world.sql @@ -0,0 +1,20 @@ +UPDATE `quest_template_addon` SET `SpecialFlags`=`SpecialFlags`&~32; + +DELETE FROM `quest_template_addon` WHERE + `MaxLevel`=0 + AND `AllowableClasses`=0 + AND `SourceSpellID`=0 + AND `PrevQuestID`=0 + AND `NextQuestID`=0 + AND `ExclusiveGroup`=0 + AND `RewardMailTemplateID`=0 + AND `RewardMailDelay`=0 + AND `RequiredSkillID`=0 + AND `RequiredSkillPoints`=0 + AND `RequiredMinRepFaction`=0 + AND `RequiredMaxRepFaction`=0 + AND `RequiredMinRepValue`=0 + AND `RequiredMaxRepValue`=0 + AND `ProvidedItemCount`=0 + AND `SpecialFlags`=0 + AND `ScriptName`=''; diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 10efffbca77..ef6bb5943b8 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -1172,7 +1172,7 @@ public: SmartQuest() : QuestScript("SmartQuest") { } // Called when a quest status change - void OnQuestStatusChange(Player* player, Quest const* quest, QuestStatus /*oldStatus*/, QuestStatus newStatus) + void OnQuestStatusChange(Player* player, Quest const* quest, QuestStatus /*oldStatus*/, QuestStatus newStatus) override { SmartScript smartScript; smartScript.OnInitialize(nullptr, nullptr, nullptr, quest); @@ -1197,7 +1197,7 @@ public: } // Called when a quest objective data change - void OnQuestObjectiveChange(Player* player, Quest const* quest, QuestObjective const& objective, int32 /*oldAmount*/, int32 /*newAmount*/) + void OnQuestObjectiveChange(Player* player, Quest const* quest, QuestObjective const& objective, int32 /*oldAmount*/, int32 /*newAmount*/) override { if (player->IsQuestObjectiveComplete(objective)) { diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index e9e407d64d9..304fb9e273f 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -542,7 +542,7 @@ void PlayerMenu::SendQuestGiverRequestItems(Quest const* quest, ObjectGuid npcGU // We can always call to RequestItems, but this packet only goes out if there are actually // items. Otherwise, we'll skip straight to the OfferReward - if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER) && canComplete) + if (!quest->HasQuestObjectiveType(QUEST_OBJECTIVE_ITEM) && canComplete) { SendQuestGiverOfferReward(quest, npcGUID, true); return; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 4507a8a8d7d..1443d0d72d0 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -15069,7 +15069,7 @@ bool Player::CanCompleteQuest(uint32 quest_id) } } - if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) && q_status.Timer == 0) + if (qInfo->GetLimitTime() && q_status.Timer == 0) return false; return true; @@ -15086,7 +15086,7 @@ bool Player::CanCompleteRepeatableQuest(Quest const* quest) if (!CanTakeQuest(quest, false)) return false; - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) + if (quest->HasQuestObjectiveType(QUEST_OBJECTIVE_ITEM)) for (QuestObjective const& obj : quest->GetObjectives()) if (obj.Type == QUEST_OBJECTIVE_ITEM && !HasItemCount(obj.ObjectID, obj.Amount)) return false; @@ -15112,7 +15112,7 @@ bool Player::CanRewardQuest(Quest const* quest, bool msg) const return false; // prevent receive reward with quest items in bank - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) + if (quest->HasQuestObjectiveType(QUEST_OBJECTIVE_ITEM)) { for (QuestObjective const& obj : quest->GetObjectives()) { @@ -15345,10 +15345,8 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) } uint32 qtime = 0; - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) + if (uint32 limittime = quest->GetLimitTime()) { - uint32 limittime = quest->GetLimitTime(); - // shared timed quest if (questGiver && questGiver->GetTypeId() == TYPEID_PLAYER) limittime = questGiver->ToPlayer()->getQuestStatusMap()[quest_id].Timer / IN_MILLISECONDS; @@ -15776,7 +15774,7 @@ void Player::FailQuest(uint32 questId) if (qStatus != QUEST_STATUS_INCOMPLETE) { // completed timed quest with no requirements - if (qStatus != QUEST_STATUS_COMPLETE || !quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) || !quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_COMPLETED_AT_START)) + if (qStatus != QUEST_STATUS_COMPLETE || !quest->GetLimitTime() || !quest->GetObjectives().empty()) return; } @@ -15790,7 +15788,7 @@ void Player::FailQuest(uint32 questId) SetQuestSlotState(log_slot, QUEST_STATE_FAIL); } - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) + if (quest->GetLimitTime()) { QuestStatusData& q_status = m_QuestStatus[questId]; @@ -16115,7 +16113,7 @@ bool Player::SatisfyQuestConditions(Quest const* qInfo, bool msg) bool Player::SatisfyQuestTimed(Quest const* qInfo, bool msg) const { - if (!m_timedquests.empty() && qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) + if (!m_timedquests.empty() && qInfo->GetLimitTime()) { if (msg) { @@ -16550,16 +16548,17 @@ uint16 Player::GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry) const void Player::AdjustQuestReqItemCount(Quest const* quest) { - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) + // adjust progress of quest objectives that rely on external counters, like items + if (quest->HasQuestObjectiveType(QUEST_OBJECTIVE_ITEM)) { for (QuestObjective const& obj : quest->GetObjectives()) { - if (obj.Type != QUEST_OBJECTIVE_ITEM) - continue; - - uint32 reqItemCount = obj.Amount; - uint32 curItemCount = GetItemCount(obj.ObjectID, true); - SetQuestObjectiveData(obj, std::min(curItemCount, reqItemCount)); + if (obj.Type == QUEST_OBJECTIVE_ITEM) + { + uint32 reqItemCount = obj.Amount; + uint32 curItemCount = GetItemCount(obj.ObjectID, true); + SetQuestObjectiveData(obj, std::min(curItemCount, reqItemCount)); + } } } } @@ -16725,7 +16724,7 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count) continue; Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); - if (!qInfo || !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) + if (!qInfo || !qInfo->HasQuestObjectiveType(QUEST_OBJECTIVE_ITEM)) continue; for (QuestObjective const& obj : qInfo->GetObjectives()) @@ -16766,10 +16765,7 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count) continue; Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); - if (!qInfo) - continue; - - if (!qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) + if (!qInfo || !qInfo->HasQuestObjectiveType(QUEST_OBJECTIVE_ITEM)) continue; for (QuestObjective const& obj : qInfo->GetObjectives()) @@ -16834,38 +16830,35 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid /*= ObjectGuid::E continue; Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); - if (!qInfo) + if (!qInfo || !qInfo->HasQuestObjectiveType(QUEST_OBJECTIVE_MONSTER)) continue; // just if !ingroup || !noraidgroup || raidgroup QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficultyID()))) { - if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL) /*&& !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAST)*/) + for (QuestObjective const& obj : qInfo->GetObjectives()) { - for (QuestObjective const& obj : qInfo->GetObjectives()) - { - if (obj.Type != QUEST_OBJECTIVE_MONSTER) - continue; + if (obj.Type != QUEST_OBJECTIVE_MONSTER) + continue; - uint32 reqkill = obj.ObjectID; + uint32 reqkill = obj.ObjectID; - if (reqkill == real_entry) + if (reqkill == real_entry) + { + uint32 reqKillCount = obj.Amount; + uint16 curKillCount = GetQuestObjectiveData(qInfo, obj.StorageIndex); + if (curKillCount < reqKillCount) { - uint32 reqKillCount = obj.Amount; - uint16 curKillCount = GetQuestObjectiveData(qInfo, obj.StorageIndex); - if (curKillCount < reqKillCount) - { - SetQuestObjectiveData(obj, curKillCount + addKillCount); - SendQuestUpdateAddCredit(qInfo, guid, obj, curKillCount + addKillCount); - } + SetQuestObjectiveData(obj, curKillCount + addKillCount); + SendQuestUpdateAddCredit(qInfo, guid, obj, curKillCount + addKillCount); + } - if (CanCompleteQuest(questid)) - CompleteQuest(questid); + 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; - } + // same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization). + break; } } } @@ -16883,11 +16876,7 @@ void Player::KilledPlayerCredit() continue; Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid); - if (!qInfo) - continue; - - // This flag is only used for performance optimisation to prevent iterating over all quests - if (!qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL)) + if (!qInfo || !qInfo->HasQuestObjectiveType(QUEST_OBJECTIVE_PLAYERKILLS)) continue; // just if !ingroup || !noraidgroup || raidgroup @@ -16933,33 +16922,30 @@ void Player::KillCreditGO(uint32 entry, ObjectGuid guid) if (q_status.Status == QUEST_STATUS_INCOMPLETE) { - if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAST) /*&& !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL)*/) + for (QuestObjective const& obj : qInfo->GetObjectives()) { - for (QuestObjective const& obj : qInfo->GetObjectives()) - { - if (obj.Type != QUEST_OBJECTIVE_GAMEOBJECT) - continue; + if (obj.Type != QUEST_OBJECTIVE_GAMEOBJECT) + continue; - uint32 reqTarget = obj.ObjectID; + uint32 reqTarget = obj.ObjectID; - // other not this creature/GO related objectives - if (reqTarget != entry) - continue; + // other not this creature/GO related objectives + if (reqTarget != entry) + continue; - uint32 reqCastCount = obj.Amount; - uint32 curCastCount = GetQuestObjectiveData(qInfo, obj.StorageIndex); - if (curCastCount < reqCastCount) - { - SetQuestObjectiveData(obj, curCastCount + addCastCount); - SendQuestUpdateAddCredit(qInfo, guid, obj, curCastCount + addCastCount); - } + uint32 reqCastCount = obj.Amount; + uint32 curCastCount = GetQuestObjectiveData(qInfo, obj.StorageIndex); + if (curCastCount < reqCastCount) + { + SetQuestObjectiveData(obj, curCastCount + addCastCount); + SendQuestUpdateAddCredit(qInfo, guid, obj, curCastCount + addCastCount); + } - if (CanCompleteQuest(questid)) - CompleteQuest(questid); + 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; - } + // same objective target can be in many active quests, but not in 2 objectives for single quest (code optimization). + break; } } } @@ -16982,31 +16968,28 @@ void Player::TalkedToCreature(uint32 entry, ObjectGuid guid) if (q_status.Status == QUEST_STATUS_INCOMPLETE) { - if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) + for (QuestObjective const& obj : qInfo->GetObjectives()) { - for (QuestObjective const& obj : qInfo->GetObjectives()) - { - if (obj.Type != QUEST_OBJECTIVE_TALKTO) - continue; + if (obj.Type != QUEST_OBJECTIVE_TALKTO) + continue; - uint32 reqTarget = obj.ObjectID; + uint32 reqTarget = obj.ObjectID; - if (reqTarget == entry) + if (reqTarget == entry) + { + uint32 reqTalkCount = obj.Amount; + uint32 curTalkCount = GetQuestObjectiveData(qInfo, obj.StorageIndex); + if (curTalkCount < reqTalkCount) { - uint32 reqTalkCount = obj.Amount; - uint32 curTalkCount = GetQuestObjectiveData(qInfo, obj.StorageIndex); - if (curTalkCount < reqTalkCount) - { - SetQuestObjectiveData(obj, curTalkCount + addTalkCount); - SendQuestUpdateAddCredit(qInfo, guid, obj, curTalkCount + addTalkCount); - } + SetQuestObjectiveData(obj, curTalkCount + addTalkCount); + SendQuestUpdateAddCredit(qInfo, guid, obj, curTalkCount + addTalkCount); + } - if (CanCompleteQuest(questid)) - CompleteQuest(questid); + if (CanCompleteQuest(questid)) + CompleteQuest(questid); - // Quest can't have more than one objective for the same creature (code optimisation) - break; - } + // Quest can't have more than one objective for the same creature (code optimisation) + break; } } } @@ -19489,7 +19472,7 @@ void Player::_LoadQuestStatus(PreparedQueryResult result) time_t quest_time = fields[2].GetInt64(); - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) && !GetQuestRewardStatus(quest_id)) + if (quest->GetLimitTime() && !GetQuestRewardStatus(quest_id)) { AddTimedQuest(quest_id); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 1aad9f94285..241ffcc3535 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4562,26 +4562,21 @@ void ObjectMgr::LoadQuests() switch (obj.Type) { case QUEST_OBJECTIVE_ITEM: - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER); if (!sObjectMgr->GetItemTemplate(obj.ObjectID)) TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing item entry %u, quest can't be done.", qinfo->GetQuestId(), obj.ID, obj.ObjectID); break; case QUEST_OBJECTIVE_MONSTER: - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST); if (!sObjectMgr->GetCreatureTemplate(obj.ObjectID)) TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing creature entry %u, quest can't be done.", qinfo->GetQuestId(), obj.ID, uint32(obj.ObjectID)); break; case QUEST_OBJECTIVE_GAMEOBJECT: - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST); if (!sObjectMgr->GetGameObjectTemplate(obj.ObjectID)) TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing gameobject entry %u, quest can't be done.", qinfo->GetQuestId(), obj.ID, uint32(obj.ObjectID)); break; case QUEST_OBJECTIVE_TALKTO: - // Need checks (is it creature only?) - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO); break; case QUEST_OBJECTIVE_MIN_REPUTATION: case QUEST_OBJECTIVE_MAX_REPUTATION: @@ -4589,7 +4584,6 @@ void ObjectMgr::LoadQuests() TC_LOG_ERROR("sql.sql", "Quest %u objective %u has non existing faction id %d", qinfo->GetQuestId(), obj.ID, obj.ObjectID); break; case QUEST_OBJECTIVE_PLAYERKILLS: - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL); if (obj.Amount <= 0) TC_LOG_ERROR("sql.sql", "Quest %u objective %u has invalid player kills count %d", qinfo->GetQuestId(), obj.ID, obj.Amount); break; @@ -4893,29 +4887,6 @@ void ObjectMgr::LoadQuests() if (qinfo->_exclusiveGroup) _exclusiveQuestGroups.insert(std::pair<int32, uint32>(qinfo->_exclusiveGroup, qinfo->GetQuestId())); - if (qinfo->_limitTime) - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED); - - // Special flag to determine if quest is completed from the start, used to determine if we can fail timed quest if it is completed - if (!qinfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT)) - { - bool addFlag = true; - if (qinfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) - { - for (QuestObjective const& obj : qinfo->GetObjectives()) - { - if (obj.Type == QUEST_OBJECTIVE_ITEM) - if (static_cast<uint32>(obj.ObjectID) != qinfo->GetSrcItemId() || static_cast<uint32>(obj.Amount) > qinfo->GetSrcItemCount()) - { - addFlag = false; - break; - } - } - } - - if (addFlag) - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_COMPLETED_AT_START); - } } // check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 52ed231c53f..f1380aef1be 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -472,7 +472,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPackets::Quest::QuestLogRemove if (quest) { - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED)) + if (quest->GetLimitTime()) _player->RemoveTimedQuest(questId); if (quest->HasFlag(QUEST_FLAGS_FLAGS_PVP)) @@ -604,7 +604,7 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPackets::Quest::QuestGiver } else { - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER)) // some items required + if (quest->HasQuestObjectiveType(QUEST_OBJECTIVE_ITEM)) // some items required _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, packet.QuestGiverGUID, _player->CanRewardQuest(quest, false), false); else // no items required _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, packet.QuestGiverGUID, true); diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index c252076c3c4..88fe8510784 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -252,6 +252,7 @@ void Quest::LoadQuestObjective(Field* fields) obj.Description = fields[9].GetString(); Objectives.push_back(obj); + _usedQuestObjectiveTypes[obj.Type] = true; } void Quest::LoadQuestObjectiveVisualEffect(Field* fields) diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index cc31c021b49..c497f332b05 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -25,6 +25,7 @@ #include "RaceMask.h" #include "SharedDefines.h" #include "WorldPacket.h" +#include <bitset> #include <vector> class Player; @@ -248,17 +249,10 @@ enum QuestSpecialFlags QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x004, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted. QUEST_SPECIAL_FLAGS_DF_QUEST = 0x008, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder. QUEST_SPECIAL_FLAGS_MONTHLY = 0x010, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month - QUEST_SPECIAL_FLAGS_CAST = 0x020, // Set by 32 in SpecialFlags in DB if the quest requires RequiredOrNpcGo killcredit but NOT kill (a spell cast) // room for more custom flags - QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST, + QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY, - QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only - QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only - QUEST_SPECIAL_FLAGS_KILL = 0x200, // Internal flag computed only - QUEST_SPECIAL_FLAGS_TIMED = 0x400, // Internal flag computed only - QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x800, // Internal flag computed only - QUEST_SPECIAL_FLAGS_COMPLETED_AT_START = 0x1000 // Internal flag computed only }; enum class QuestTagType @@ -303,7 +297,9 @@ enum QuestObjectiveType QUEST_OBJECTIVE_OBTAIN_CURRENCY = 17, // requires the player to gain X currency after starting the quest but not required to keep it until the end (does not consume) QUEST_OBJECTIVE_INCREASE_REPUTATION = 18, // requires the player to gain X reputation with a faction QUEST_OBJECTIVE_AREA_TRIGGER_ENTER = 19, - QUEST_OBJECTIVE_AREA_TRIGGER_EXIT = 20 + QUEST_OBJECTIVE_AREA_TRIGGER_EXIT = 20, + + MAX_QUEST_OBJECTIVE_TYPE }; enum QuestObjectiveFlags @@ -384,6 +380,8 @@ struct QuestObjective case QUEST_OBJECTIVE_WINPETBATTLEAGAINSTNPC: case QUEST_OBJECTIVE_DEFEATBATTLEPET: case QUEST_OBJECTIVE_CRITERIA_TREE: + case QUEST_OBJECTIVE_AREA_TRIGGER_ENTER: + case QUEST_OBJECTIVE_AREA_TRIGGER_EXIT: return true; default: break; @@ -434,6 +432,7 @@ class TC_GAME_API Quest bool HasSpecialFlag(uint32 flag) const { return (_specialFlags & flag) != 0; } void SetSpecialFlag(uint32 flag) { _specialFlags |= flag; } + bool HasQuestObjectiveType(QuestObjectiveType type) const { return _usedQuestObjectiveTypes[type]; } bool IsAutoPush() const { return HasFlagEx(QUEST_FLAGS_EX_AUTO_PUSH); } bool IsWorldQuest() const { return HasFlagEx(QUEST_FLAGS_EX_IS_WORLD_QUEST); } @@ -662,6 +661,7 @@ class TC_GAME_API Quest uint32 _sourceItemIdCount = 0; uint32 _rewardMailSenderEntry = 0; uint32 _specialFlags = 0; // custom flags, not sniffed/WDB + std::bitset<MAX_QUEST_OBJECTIVE_TYPE> _usedQuestObjectiveTypes; uint32 _scriptId = 0; // Helpers |