aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp4
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp4
-rw-r--r--src/server/game/Entities/Player/Player.cpp141
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp54
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp3
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp72
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h10
-rw-r--r--src/server/game/Quests/QuestDef.cpp12
-rw-r--r--src/server/game/Quests/QuestDef.h47
-rw-r--r--src/server/game/Server/WorldSession.cpp2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
12 files changed, 182 insertions, 172 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index 7ac71ca5625..9ae7999e86f 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -1661,9 +1661,9 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
if (Quest const* qid = sObjectMgr->GetQuestTemplate(e.action.quest.quest))
{
- if (!qid->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
+ if (!qid->HasFlag(QUEST_FLAGS_COMPLETION_EVENT) && !qid->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER))
{
- TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} SpecialFlags for Quest entry {} does not include FLAGS_EXPLORATION_OR_EVENT(2), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} Flags for Quest entry {} does not include QUEST_FLAGS_COMPLETION_EVENT or QUEST_FLAGS_COMPLETION_AREA_TRIGGER, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.quest.quest);
return false;
}
}
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index 574d016eb06..632fb3f366a 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -283,7 +283,7 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID)
text.QuestType = item.QuestIcon;
text.QuestFlags[0] = quest->GetFlags();
text.QuestFlags[1] = quest->GetFlagsEx();
- text.Repeatable = quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly();
+ text.Repeatable = quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly();
text.QuestTitle = quest->GetLogTitle();
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
@@ -410,7 +410,7 @@ void PlayerMenu::SendQuestGiverQuestListMessage(Object* questgiver)
text.QuestType = questMenuItem.QuestIcon;
text.QuestFlags[0] = quest->GetFlags();
text.QuestFlags[1] = quest->GetFlagsEx();
- text.Repeatable = quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly();
+ text.Repeatable = quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly();
text.QuestTitle = quest->GetLogTitle();
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 67fcd09e365..d24aae288ed 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1264,6 +1264,8 @@ void Player::setDeathState(DeathState s)
InitializeSelfResurrectionSpells();
+ FailQuestsWithFlag(QUEST_FLAGS_COMPLETION_NO_DEATH);
+
UpdateCriteria(CriteriaType::DieOnMap, 1);
UpdateCriteria(CriteriaType::DieAnywhere, 1);
UpdateCriteria(CriteriaType::DieInInstance, 1);
@@ -14419,9 +14421,9 @@ void Player::PrepareQuestMenu(ObjectGuid guid)
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(quest_id, 0);
- else if (quest->IsAutoComplete())
+ else if (quest->IsTurnIn())
qm.AddMenuItem(quest_id, 4);
else if (GetQuestStatus(quest_id) == QUEST_STATUS_NONE)
qm.AddMenuItem(quest_id, 2);
@@ -14454,9 +14456,9 @@ void Player::SendPreparedQuest(WorldObject* source)
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);
@@ -14482,7 +14484,9 @@ Quest const* Player::GetNextQuest(Object const* questGiver, Quest const* quest)
if (questGiver == this)
{
- ASSERT(quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE));
+ if (!quest->HasFlag(QUEST_FLAGS_AUTO_COMPLETE))
+ return nullptr;
+
return sObjectMgr->GetQuestTemplate(nextQuestID);
}
@@ -14560,7 +14564,7 @@ bool Player::CanCompleteQuest(uint32 quest_id, uint32 ignoredQuestObjectiveId /*
return false; // not allow re-complete quest
// auto complete quest
- if (qInfo->IsAutoComplete() && CanTakeQuest(qInfo, false))
+ if (qInfo->IsTurnIn() && CanTakeQuest(qInfo, false))
return true;
QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id);
@@ -14583,7 +14587,7 @@ bool Player::CanCompleteQuest(uint32 quest_id, uint32 ignoredQuestObjectiveId /*
}
}
- if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT) && !q_status.Explored)
+ if ((qInfo->HasFlag(QUEST_FLAGS_COMPLETION_EVENT) || qInfo->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER)) && !q_status.Explored)
return false;
if (qInfo->GetLimitTime() && q_status.Timer == 0)
@@ -14621,7 +14625,7 @@ bool Player::CanRewardQuest(Quest const* quest, bool msg) const
return false;
// not auto complete quest and not completed quest (only cheating case, then ignore without message)
- if (!quest->IsDFQuest() && !quest->IsAutoComplete() && GetQuestStatus(quest->GetQuestId()) != QUEST_STATUS_COMPLETE)
+ if (!quest->IsDFQuest() && !quest->IsTurnIn() && GetQuestStatus(quest->GetQuestId()) != QUEST_STATUS_COMPLETE)
return false;
// daily quest can't be rewarded (25 daily quest already completed)
@@ -14893,7 +14897,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetSrcSpell(), GetMap()->GetDifficultyID());
Unit* caster = this;
- if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_ACCEPT) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER) && !spellInfo->HasTargetType(TARGET_DEST_CASTER_SUMMON))
+ if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ACCEPT) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER) && !spellInfo->HasTargetType(TARGET_DEST_CASTER_SUMMON))
if (Unit* unit = questGiver->ToUnit())
caster = unit;
@@ -14936,7 +14940,7 @@ void Player::CompleteQuest(uint32 quest_id)
SetQuestSlotState(questStatus->Slot, QUEST_STATE_COMPLETE);
if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id))
- if (qInfo->HasFlag(QUEST_FLAGS_TRACKING))
+ if (qInfo->HasFlag(QUEST_FLAGS_TRACKING_EVENT))
RewardQuest(qInfo, LootItemType::Item, 0, this, false);
}
@@ -15069,23 +15073,29 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
switch (obj.Type)
{
case QUEST_OBJECTIVE_ITEM:
- if (!(quest->GetFlagsEx() & QUEST_FLAGS_EX_KEEP_ADDITIONAL_ITEMS))
- DestroyItemCount(obj.ObjectID, obj.Amount, true);
+ {
+ int32 amountToDestroy = obj.Amount;
+ if (quest->HasFlag(QUEST_FLAGS_REMOVE_SURPLUS_ITEMS))
+ amountToDestroy = std::numeric_limits<uint32>::max();
+ DestroyItemCount(obj.ObjectID, amountToDestroy, true);
break;
+ }
case QUEST_OBJECTIVE_CURRENCY:
RemoveCurrency(obj.ObjectID, obj.Amount, CurrencyDestroyReason::QuestTurnin);
break;
}
}
- if (!(quest->GetFlagsEx() & QUEST_FLAGS_EX_KEEP_ADDITIONAL_ITEMS))
+ if (!quest->HasFlagEx(QUEST_FLAGS_EX_KEEP_ADDITIONAL_ITEMS))
{
for (uint8 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i)
{
if (quest->ItemDrop[i])
{
uint32 count = quest->ItemDropQuantity[i];
- DestroyItemCount(quest->ItemDrop[i], count ? count : 9999, true);
+ if (!count)
+ count = std::numeric_limits<uint32>::max();
+ DestroyItemCount(quest->ItemDrop[i], count, true);
}
}
}
@@ -15246,7 +15256,7 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
{
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(quest->GetRewSpell(), GetMap()->GetDifficultyID());
Unit* caster = this;
- if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER))
+ if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_COMPLETE) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER))
if (Unit* unit = questGiver->ToUnit())
caster = unit;
@@ -15262,7 +15272,7 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(displaySpell.SpellId, GetMap()->GetDifficultyID());
Unit* caster = this;
- if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER))
+ if (questGiver && questGiver->isType(TYPEMASK_UNIT) && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_COMPLETE) && !spellInfo->HasTargetType(TARGET_UNIT_CASTER))
if (Unit* unit = questGiver->ToUnit())
caster = unit;
@@ -15290,66 +15300,66 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
SendQuestGiverStatusMultiple();
- bool conditionChanged = SendQuestUpdate(quest_id, false);
+ SendQuestUpdate(quest_id);
+
+ bool updateVisibility = false;
+ if (quest->HasFlag(QUEST_FLAGS_UPDATE_PHASESHIFT))
+ updateVisibility = PhasingHandler::OnConditionChange(this, false);
//lets remove flag for delayed teleports
SetCanDelayTeleport(false);
- bool canHaveNextQuest = !quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE) ? questGiver && !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
+ if (Quest const* nextQuest = GetNextQuest(questGiver, quest))
{
- //For AutoSubmition was added plr case there as it almost same exclute AI script cases.
- // Send next quest
- if (Quest const* nextQuest = GetNextQuest(questGiver, quest))
+ // 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();
- if (Creature* creatureQGiver = questGiver->ToCreature())
- creatureQGiver->AI()->OnQuestReward(this, quest, rewardType, rewardId);
- break;
}
- case TYPEID_GAMEOBJECT:
+
+ PlayerTalkClass->ClearMenus();
+ if (Creature* creatureQGiver = questGiver->ToCreature())
+ creatureQGiver->AI()->OnQuestReward(this, quest, rewardType, rewardId);
+ break;
+ }
+ case TYPEID_GAMEOBJECT:
+ {
+ // Send next quest
+ if (Quest const* nextQuest = GetNextQuest(questGiver, quest))
{
- // Send next quest
- if (Quest const* nextQuest = GetNextQuest(questGiver, quest))
+ // 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();
- questGiver->ToGameObject()->AI()->OnQuestReward(this, quest, rewardType, rewardId);
- break;
}
- default:
- break;
+
+ PlayerTalkClass->ClearMenus();
+ questGiver->ToGameObject()->AI()->OnQuestReward(this, quest, rewardType, rewardId);
+ break;
}
+ default:
+ break;
}
sScriptMgr->OnQuestStatusChange(this, quest_id);
sScriptMgr->OnQuestStatusChange(this, quest, oldStatus, QUEST_STATUS_REWARDED);
- if (conditionChanged)
+ if (updateVisibility)
UpdateObjectVisibility();
}
@@ -15407,6 +15417,20 @@ void Player::FailQuest(uint32 questId)
}
}
+void Player::FailQuestsWithFlag(QuestFlags flag)
+{
+ for (uint16 slot = 0; MAX_QUEST_LOG_SIZE; ++slot)
+ {
+ uint32 questId = GetQuestSlotQuestId(slot);
+ if (!questId)
+ continue;
+
+ if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
+ if (quest->HasFlag(flag))
+ FailQuest(questId);
+ }
+}
+
void Player::AbandonQuest(uint32 questId)
{
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
@@ -15981,7 +16005,7 @@ void Player::SetQuestStatus(uint32 questId, QuestStatus status, bool update /*=
QuestStatus oldStatus = m_QuestStatus[questId].Status;
m_QuestStatus[questId].Status = status;
- if (!quest->IsAutoComplete())
+ if (!quest->IsTurnIn())
m_QuestStatusSave[questId] = QUEST_DEFAULT_SAVE_TYPE;
sScriptMgr->OnQuestStatusChange(this, questId);
@@ -16041,7 +16065,7 @@ void Player::RemoveRewardedQuest(uint32 questId, bool update /*= true*/)
SendQuestUpdate(questId);
}
-bool Player::SendQuestUpdate(uint32 questId, bool updateVisiblity /*= true*/)
+void Player::SendQuestUpdate(uint32 questId)
{
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(questId);
@@ -16090,7 +16114,6 @@ bool Player::SendQuestUpdate(uint32 questId, bool updateVisiblity /*= true*/)
}
UpdateVisibleGameobjectsOrSpellClicks();
- return PhasingHandler::OnConditionChange(this, updateVisiblity);
}
QuestGiverStatus Player::GetQuestDialogStatus(Object const* questgiver) const
@@ -16152,7 +16175,7 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object const* questgiver) const
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) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF)))
result |= QuestGiverStatus::RepeatableTurnin;
@@ -16951,7 +16974,7 @@ void Player::SendQuestReward(Quest const* quest, Creature const* questGiver, uin
if (questGiver->IsQuestGiver())
packet.LaunchQuest = (GetQuestDialogStatus(questGiver) & ~QuestGiverStatus::Future) != QuestGiverStatus::None;
- if (!quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
+ if (!quest->HasFlag(QUEST_FLAGS_AUTO_COMPLETE))
if (Quest const* rewardQuest = GetNextQuest(questGiver, quest))
packet.UseQuestReward = CanTakeQuest(rewardQuest, false);
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index e52f4d4bd29..71b00fe46d9 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1589,6 +1589,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rewardId, Object* questGiver, bool announce = true);
void SetRewardedQuest(uint32 quest_id);
void FailQuest(uint32 quest_id);
+ void FailQuestsWithFlag(QuestFlags flag);
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
bool SatisfyQuestLevel(Quest const* qInfo, bool msg) const;
bool SatisfyQuestMinLevel(Quest const* qInfo, bool msg) const;
@@ -1618,7 +1619,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SetQuestStatus(uint32 questId, QuestStatus status, bool update = true);
void RemoveActiveQuest(uint32 questId, bool update = true);
void RemoveRewardedQuest(uint32 questId, bool update = true);
- bool SendQuestUpdate(uint32 questId, bool updateVisiblity = true);
+ void SendQuestUpdate(uint32 questId);
QuestGiverStatus GetQuestDialogStatus(Object const* questGiver) const;
void SetDailyQuestStatus(uint32 quest_id);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 94f0b5cd966..fb004f8b6eb 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -4645,7 +4645,7 @@ void ObjectMgr::LoadQuests()
// additional quest integrity checks (GO, creature_template and items must be loaded already)
- if (qinfo->GetQuestType() >= MAX_QUEST_TYPES)
+ if (qinfo->GetQuestType() >= MAX_DB_ALLOWED_QUEST_TYPES)
TC_LOG_ERROR("sql.sql", "Quest {} has `Method` = {}, expected values are 0, 1 or 2.", qinfo->GetQuestId(), qinfo->GetQuestType());
if (qinfo->_specialFlags & ~QUEST_SPECIAL_FLAGS_DB_ALLOWED)
@@ -4688,7 +4688,7 @@ void ObjectMgr::LoadQuests()
}
}
- if (qinfo->_flags & QUEST_FLAGS_TRACKING)
+ if (qinfo->_flags & QUEST_FLAGS_TRACKING_EVENT)
{
// at auto-reward can be rewarded only RewardChoiceItemId[0]
for (uint32 j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j )
@@ -5283,35 +5283,7 @@ void ObjectMgr::LoadQuests()
}
}
- // check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
- for (SpellNameEntry const* spellNameEntry : sSpellNameStore)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellNameEntry->ID, DIFFICULTY_NONE);
- if (!spellInfo)
- continue;
-
- for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
- {
- if (spellEffectInfo.Effect != SPELL_EFFECT_QUEST_COMPLETE)
- continue;
-
- uint32 quest_id = spellEffectInfo.MiscValue;
-
- Quest const* quest = GetQuestTemplate(quest_id);
-
- // some quest referenced in spells not exist (outdated spells)
- if (!quest)
- continue;
-
- if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
- {
- TC_LOG_ERROR("sql.sql", "Spell (id: {}) have SPELL_EFFECT_QUEST_COMPLETE for quest {}, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Quest flags must be fixed, quest modified to enable objective.", spellInfo->Id, quest_id);
-
- // this will prevent quest completing without objective
- const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT);
- }
- }
- }
+ // don't check spells with SPELL_EFFECT_QUEST_COMPLETE, a lot of invalid db2 data
// Make all paragon reward quests repeatable
for (ParagonReputationEntry const* paragonReputation : sParagonReputationStore)
@@ -5620,15 +5592,11 @@ void ObjectMgr::LoadScripts(ScriptsType type)
continue;
}
- if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
+ if (!quest->HasFlag(QUEST_FLAGS_COMPLETION_EVENT) && !quest->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER))
{
- TC_LOG_ERROR("sql.sql", "Table `{}` has quest (ID: {}) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id {}, 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.",
+ TC_LOG_ERROR("sql.sql", "Table `{}` has quest (ID: {}) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id {}, 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
- const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT);
-
- // continue; - quest objective requirement set and command can be allowed
+ continue;
}
if (float(tmp.QuestExplored.Distance) > DEFAULT_VISIBILITY_DISTANCE)
@@ -6543,14 +6511,10 @@ void ObjectMgr::LoadQuestAreaTriggers()
continue;
}
- if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
+ if (!quest->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER) && !quest->HasQuestObjectiveType(QUEST_OBJECTIVE_AREATRIGGER))
{
- TC_LOG_ERROR("sql.sql", "Table `areatrigger_involvedrelation` has record (id: {}) for not quest {}, 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
- const_cast<Quest*>(quest)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT);
-
- // continue; - quest modified to required objective and trigger can be allowed.
+ TC_LOG_ERROR("sql.sql", "Table `areatrigger_involvedrelation` has record (id: {}) for not quest {}, but quest not have flag QUEST_FLAGS_COMPLETION_AREA_TRIGGER and no objective with type QUEST_OBJECTIVE_AREATRIGGER. Trigger is obsolete, skipped.", trigger_ID, quest_ID);
+ continue;
}
_questAreaTriggerStore[trigger_ID].insert(quest_ID);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index b0eca9c6b93..7e870b0a291 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -541,6 +541,9 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::AreaTrigger::AreaTrigge
break;
}
+ if (qInfo->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER))
+ player->AreaExploredOrEventHappens(questId);
+
if (player->CanCompleteQuest(questId))
player->CompleteQuest(questId);
}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index aa80e11e1cd..9010a3d629e 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -177,7 +177,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG
{
_player->AddQuestAndCheckCompletion(quest, object);
- if (quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT))
+ if (quest->IsPushedToPartyOnAccept())
{
if (Group* group = _player->GetGroup())
{
@@ -203,6 +203,21 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG
_player->PlayerTalkClass->SendCloseGossip();
+ if (quest->HasFlag(QUEST_FLAGS_LAUNCH_GOSSIP_ACCEPT))
+ {
+ auto launchGossip = [&](WorldObject* worldObject)
+ {
+ _player->PlayerTalkClass->ClearMenus();
+ _player->PrepareGossipMenu(worldObject, _player->GetGossipMenuForSource(worldObject), true);
+ _player->SendPreparedGossip(worldObject);
+ };
+
+ if (Creature* creature = object->ToCreature())
+ launchGossip(creature);
+ else if (GameObject* go = object->ToGameObject())
+ launchGossip(go);
+ }
+
return;
}
}
@@ -230,7 +245,7 @@ void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPackets::Quest::QuestGi
if (quest->IsAutoAccept() && _player->CanAddQuest(quest, true))
_player->AddQuestAndCheckCompletion(quest, object);
- if (quest->IsAutoComplete())
+ if (quest->IsTurnIn())
_player->PlayerTalkClass->SendQuestGiverRequestItems(quest, object->GetGUID(), _player->CanCompleteQuest(quest->GetQuestId()), true);
else
_player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, object->GetGUID(), true, false);
@@ -359,7 +374,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest
Object* object = _player;
- if (!quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
+ if (!quest->HasFlag(QUEST_FLAGS_AUTO_COMPLETE))
{
object = ObjectAccessor::GetObjectByTypeMask(*_player, packet.QuestGiverGUID, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
if (!object || !object->hasInvolvedQuest(packet.QuestID))
@@ -371,7 +386,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest
}
if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(packet.QuestID) == QUEST_STATUS_NONE) ||
- (_player->GetQuestStatus(packet.QuestID) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete()))
+ (_player->GetQuestStatus(packet.QuestID) != QUEST_STATUS_COMPLETE && !quest->IsTurnIn()))
{
TC_LOG_ERROR("network", "Error in QUEST_STATUS_COMPLETE: player {} {} tried to complete quest {}, but is not allowed to do so (possible packet-hacking or high latency)",
_player->GetName(), _player->GetGUID().ToString(), packet.QuestID);
@@ -474,34 +489,34 @@ void WorldSession::HandleQuestConfirmAccept(WorldPackets::Quest::QuestConfirmAcc
{
TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT questId = {}", packet.QuestID);
- if (Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID))
- {
- if (!quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT))
- return;
+ if (_player->GetSharedQuestID() != uint32(packet.QuestID))
+ return;
- Player* originalPlayer = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest());
- if (!originalPlayer)
- return;
+ _player->ClearQuestSharingInfo();
+ Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID);
+ if (!quest)
+ return;
- if (!_player->IsInSameRaidWith(originalPlayer))
- return;
+ Player* originalPlayer = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest());
+ if (!originalPlayer)
+ return;
- if (!originalPlayer->IsActiveQuest(packet.QuestID))
- return;
+ if (!_player->IsInSameRaidWith(originalPlayer))
+ return;
- if (!_player->CanTakeQuest(quest, true))
- return;
+ if (!originalPlayer->IsActiveQuest(packet.QuestID))
+ return;
- if (_player->CanAddQuest(quest, true))
- {
- _player->AddQuestAndCheckCompletion(quest, nullptr); // NULL, this prevent DB script from duplicate running
+ if (!_player->CanTakeQuest(quest, true))
+ return;
- if (quest->GetSrcSpell() > 0)
- _player->CastSpell(_player, quest->GetSrcSpell(), true);
- }
- }
+ if (!_player->CanAddQuest(quest, true))
+ return;
- _player->ClearQuestSharingInfo();
+ _player->AddQuestAndCheckCompletion(quest, nullptr); // NULL, this prevent DB script from duplicate running
+
+ if (quest->GetSrcSpell() > 0)
+ _player->CastSpell(_player, quest->GetSrcSpell(), true);
}
void WorldSession::HandleQuestgiverCompleteQuest(WorldPackets::Quest::QuestGiverCompleteQuest& packet)
@@ -514,9 +529,6 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPackets::Quest::QuestGiver
if (!quest)
return;
- if (autoCompleteMode && !quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
- return;
-
Object* object = nullptr;
if (autoCompleteMode)
object = _player;
@@ -526,7 +538,7 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPackets::Quest::QuestGiver
if (!object)
return;
- if (!autoCompleteMode)
+ if (!quest->HasFlag(QUEST_FLAGS_AUTO_COMPLETE))
{
if (!object->hasInvolvedQuest(packet.QuestID))
return;
@@ -716,7 +728,7 @@ void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty&
sender->SendPushToPartyResponse(receiver, QuestPushReason::Success);
- if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
+ if (quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true);
else
{
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index 250628f3d05..f39a9937d85 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -5060,11 +5060,15 @@ enum HolidayIds
enum QuestType
{
- QUEST_TYPE_AUTOCOMPLETE = 0,
- QUEST_TYPE_DISABLED = 1,
+ QUEST_TYPE_TURNIN = 0,
+ QUEST_TYPE_WITH_MAX_LEVEL = 1,
QUEST_TYPE_NORMAL = 2,
QUEST_TYPE_TASK = 3,
- MAX_QUEST_TYPES = 4
+ MAX_DB_ALLOWED_QUEST_TYPES = 4,
+
+ // values used in quest menu packets
+ QUEST_TYPE_IN_PROGRESS = 4,
+ QUEST_TYPE_TASK_IN_PROGRESS = 5
};
// QuestInfo.dbc (9.0.2.37176)
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index e3d39cef7a9..2feff84a03d 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -521,7 +521,7 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player
uint32 Quest::GetRewMoneyMaxLevel() const
{
// If Quest has flag to not give money on max level, it's 0
- if (HasFlag(QUEST_FLAGS_NO_MONEY_FROM_XP))
+ if (HasFlag(QUEST_FLAGS_NO_MONEY_FOR_XP))
return 0;
// Else, return the rewarded copper sum modified by the rate
@@ -533,9 +533,9 @@ bool Quest::IsAutoAccept() const
return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) && HasFlag(QUEST_FLAGS_AUTO_ACCEPT);
}
-bool Quest::IsAutoComplete() const
+bool Quest::IsTurnIn() const
{
- return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) && _type == QUEST_TYPE_AUTOCOMPLETE;
+ return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) && _type == QUEST_TYPE_TURNIN;
}
bool Quest::IsRaidQuest(Difficulty difficulty) const
@@ -552,7 +552,7 @@ bool Quest::IsRaidQuest(Difficulty difficulty) const
break;
}
- if ((_flags & QUEST_FLAGS_RAID) != 0)
+ if ((_flags & QUEST_FLAGS_RAID_GROUP_OK) != 0)
return true;
return false;
@@ -654,7 +654,7 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc, Player* player) const
response.Info.RewardXPDifficulty = GetXPDifficulty();
response.Info.RewardXPMultiplier = GetXPMultiplier();
- if (!HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
+ if (!HasFlag(QUEST_FLAGS_HIDE_REWARD))
response.Info.RewardMoney = player ? player->GetQuestMoneyReward(this) : GetMaxMoneyReward();
response.Info.RewardMoneyDifficulty = GetRewMoneyDifficulty();
@@ -697,7 +697,7 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc, Player* player) const
response.Info.ItemDropQuantity[i] = ItemDropQuantity[i];
}
- if (!HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
+ if (!HasFlag(QUEST_FLAGS_HIDE_REWARD))
{
for (uint8 i = 0; i < QUEST_REWARD_ITEM_COUNT; ++i)
{
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 016ec2dc958..d16e8b1ad09 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -179,37 +179,37 @@ DEFINE_ENUM_FLAG(QuestGiverStatus);
enum QuestFlags : uint32
{
QUEST_FLAGS_NONE = 0x00000000,
- QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently
- QUEST_FLAGS_PARTY_ACCEPT = 0x00000002, // 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
- QUEST_FLAGS_EXPLORATION = 0x00000004, // Not used currently
+ QUEST_FLAGS_COMPLETION_NO_DEATH = 0x00000001,
+ QUEST_FLAGS_COMPLETION_EVENT = 0x00000002,
+ QUEST_FLAGS_COMPLETION_AREA_TRIGGER = 0x00000004,
QUEST_FLAGS_SHARABLE = 0x00000008, // Can be shared: Player::CanShareQuest()
QUEST_FLAGS_HAS_CONDITION = 0x00000010, // Not used currently
- QUEST_FLAGS_HIDE_REWARD_POI = 0x00000020, // Not used currently: Unsure of content
- QUEST_FLAGS_RAID = 0x00000040, // Can be completed while in raid
+ QUEST_FLAGS_HIDE_REWARD_POI = 0x00000020, // Hides questgiver turn-in minimap icon
+ QUEST_FLAGS_RAID_GROUP_OK = 0x00000040, // Can be completed while in raid
QUEST_FLAGS_WAR_MODE_REWARDS_OPT_IN = 0x00000080, // Not used currently
- QUEST_FLAGS_NO_MONEY_FROM_XP = 0x00000100, // Not used currently: Experience is not converted to gold at max level
- QUEST_FLAGS_HIDDEN_REWARDS = 0x00000200, // 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))
- QUEST_FLAGS_TRACKING = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
+ QUEST_FLAGS_NO_MONEY_FOR_XP = 0x00000100, // Experience is not converted to gold at max level
+ QUEST_FLAGS_HIDE_REWARD = 0x00000200, // 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))
+ QUEST_FLAGS_TRACKING_EVENT = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
QUEST_FLAGS_DEPRECATE_REPUTATION = 0x00000800, // Not used currently
QUEST_FLAGS_DAILY = 0x00001000, // Used to know quest is Daily one
QUEST_FLAGS_FLAGS_PVP = 0x00002000, // Having this quest in log forces PvP flag
- QUEST_FLAGS_UNAVAILABLE = 0x00004000, // Used on quests that are not generically available
+ QUEST_FLAGS_DEPRECATED = 0x00004000, // Used on quests that are not generally available
QUEST_FLAGS_WEEKLY = 0x00008000,
- QUEST_FLAGS_AUTOCOMPLETE = 0x00010000, // Quests with this flag player submit automatically by special button in player gui
+ QUEST_FLAGS_AUTO_COMPLETE = 0x00010000, // Quests with this flag player submit automatically by special button in player gui
QUEST_FLAGS_DISPLAY_ITEM_IN_TRACKER = 0x00020000, // Displays usable item in quest tracker
- QUEST_FLAGS_OBJ_TEXT = 0x00040000, // use Objective text as Complete text
+ QUEST_FLAGS_DISABLE_COMPLETION_TEXT = 0x00040000, // use Objective text as Complete text
QUEST_FLAGS_AUTO_ACCEPT = 0x00080000, // The client recognizes this flag as auto-accept.
- QUEST_FLAGS_PLAYER_CAST_ON_ACCEPT = 0x00100000,
- QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE = 0x00200000,
- QUEST_FLAGS_UPDATE_PHASE_SHIFT = 0x00400000,
+ QUEST_FLAGS_PLAYER_CAST_ACCEPT = 0x00100000,
+ QUEST_FLAGS_PLAYER_CAST_COMPLETE = 0x00200000,
+ QUEST_FLAGS_UPDATE_PHASESHIFT = 0x00400000,
QUEST_FLAGS_SOR_WHITELIST = 0x00800000,
QUEST_FLAGS_LAUNCH_GOSSIP_COMPLETE = 0x01000000,
- QUEST_FLAGS_REMOVE_EXTRA_GET_ITEMS = 0x02000000,
- QUEST_FLAGS_HIDE_UNTIL_DISCOVERED = 0x04000000,
+ QUEST_FLAGS_REMOVE_SURPLUS_ITEMS = 0x02000000, // Remove all items from inventory that have the same id as the objective, not just the amount required by quest
+ QUEST_FLAGS_WELL_KNOWN = 0x04000000,
QUEST_FLAGS_PORTRAIT_IN_QUEST_LOG = 0x08000000,
QUEST_FLAGS_SHOW_ITEM_WHEN_COMPLETED = 0x10000000,
QUEST_FLAGS_LAUNCH_GOSSIP_ACCEPT = 0x20000000,
- QUEST_FLAGS_ITEMS_GLOW_WHEN_DONE = 0x40000000,
+ QUEST_FLAGS_ITEMS_GLOW_WHEN_COMPLETE = 0x40000000,
QUEST_FLAGS_FAIL_ON_LOGOUT = 0x80000000
};
@@ -276,13 +276,13 @@ enum QuestSpecialFlags
QUEST_SPECIAL_FLAGS_NONE = 0x000,
// Trinity flags for set SpecialFlags in DB if required but used only at server
QUEST_SPECIAL_FLAGS_REPEATABLE = 0x001, // Set by 1 in SpecialFlags from DB
- QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x002, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `FECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script)
+ QUEST_SPECIAL_FLAGS_AUTO_PUSH_TO_PARTY = 0x002, // Set by 2 in SpecialFlags from DB will make quest be pushed to entire party when one member accepts it
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
// 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_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY,
QUEST_SPECIAL_FLAGS_SEQUENCED_OBJECTIVES = 0x020, // Internal flag computed only
};
@@ -540,15 +540,15 @@ class TC_GAME_API Quest
bool HasFlagEx(QuestFlagsEx flag) const { return (_flagsEx & uint32(flag)) != 0; }
bool HasFlagEx2(QuestFlagsEx2 flag) const { return (_flagsEx2 & uint32(flag)) != 0; }
- bool HasSpecialFlag(uint32 flag) const { return (_specialFlags & flag) != 0; }
- void SetSpecialFlag(uint32 flag) { _specialFlags |= flag; }
+ bool HasSpecialFlag(QuestSpecialFlags flag) const { return (_specialFlags & flag) != 0; }
+ void SetSpecialFlag(QuestSpecialFlags 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); }
// Possibly deprecated flag
- bool IsUnavailable() const { return HasFlag(QUEST_FLAGS_UNAVAILABLE); }
+ bool IsUnavailable() const { return HasFlag(QUEST_FLAGS_DEPRECATED); }
// whether the quest is globally enabled (spawned by pool, game event active etc.)
static bool IsTakingQuestEnabled(uint32 questId);
@@ -623,7 +623,7 @@ class TC_GAME_API Quest
uint32 GetCompleteEmoteDelay() const { return _emoteOnCompleteDelay; }
bool IsRepeatable() const { return _specialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE; }
bool IsAutoAccept() const;
- bool IsAutoComplete() const;
+ bool IsTurnIn() const;
uint32 GetFlags() const { return _flags; }
uint32 GetFlagsEx() const { return _flagsEx; }
uint32 GetFlagsEx2() const { return _flagsEx2; }
@@ -649,6 +649,7 @@ class TC_GAME_API Quest
bool IsRaidQuest(Difficulty difficulty) const;
bool IsAllowedInRaid(Difficulty difficulty) const;
bool IsDFQuest() const { return (_specialFlags & QUEST_SPECIAL_FLAGS_DF_QUEST) != 0; }
+ bool IsPushedToPartyOnAccept() const { return HasSpecialFlag(QUEST_SPECIAL_FLAGS_AUTO_PUSH_TO_PARTY); }
uint32 CalculateHonorGain(uint8 level) const;
bool CanIncreaseRewardedQuestCounters() const;
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 021f22abc10..c4c46c044d9 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -615,6 +615,8 @@ void WorldSession::LogoutPlayer(bool save)
///- Clear whisper whitelist
_player->ClearWhisperWhiteList();
+ _player->FailQuestsWithFlag(QUEST_FLAGS_FAIL_ON_LOGOUT);
+
///- 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)
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 09f80cfd2c7..c39de7d0c1c 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3652,7 +3652,7 @@ void Spell::EffectQuestComplete()
uint16 logSlot = player->FindQuestSlot(questId);
if (logSlot < MAX_QUEST_LOG_SIZE)
player->AreaExploredOrEventHappens(questId);
- else if (quest->HasFlag(QUEST_FLAGS_TRACKING)) // Check if the quest is used as a serverside flag.
+ else if (quest->HasFlag(QUEST_FLAGS_TRACKING_EVENT)) // Check if the quest is used as a serverside flag.
player->SetRewardedQuest(questId); // If so, set status to rewarded without broadcasting it to client.
}
}