mirror of
https://github.com/araxiaonline/TrinityCore.git
synced 2026-06-18 14:10:18 -04:00
Core/Quests: Quest flag fixups
* Update flag names * Implemented QUEST_FLAGS_COMPLETION_NO_DEATH and QUEST_FLAGS_FAIL_ON_LOGOUT * Started using QUEST_FLAGS_COMPLETION_EVENT and QUEST_FLAGS_COMPLETION_AREA_TRIGGER instead of a custom SpeclalFlag * Renamed Quest::IsAutoComplete to Quest::IsTurnIn to better describe what it means (a quest that can be turned in without accepting it to quest log) * Implemented QUEST_FLAGS_UPDATE_PHASESHIFT and removed forced phaseshift updates on every quest status change * Implemented QUEST_FLAGS_LAUNCH_GOSSIP_ACCEPT - reopens gossip menu with questgiver
This commit is contained in:
@@ -0,0 +1 @@
|
||||
UPDATE `quest_template_addon` SET `SpecialFlags`=`SpecialFlags`&~0x2; -- remove deprecated QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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:
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
if (nextQuest->IsAutoAccept() && CanAddQuest(nextQuest, true))
|
||||
AddQuestAndCheckCompletion(nextQuest, questGiver);
|
||||
|
||||
PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, questGiver->GetGUID(), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
PlayerTalkClass->ClearMenus();
|
||||
questGiver->ToGameObject()->AI()->OnQuestReward(this, quest, rewardType, rewardId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
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))
|
||||
{
|
||||
// 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);
|
||||
|
||||
PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, questGiver->GetGUID(), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Player* originalPlayer = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest());
|
||||
if (!originalPlayer)
|
||||
return;
|
||||
|
||||
if (!_player->IsInSameRaidWith(originalPlayer))
|
||||
return;
|
||||
|
||||
if (!originalPlayer->IsActiveQuest(packet.QuestID))
|
||||
return;
|
||||
|
||||
if (!_player->CanTakeQuest(quest, true))
|
||||
return;
|
||||
|
||||
if (_player->CanAddQuest(quest, true))
|
||||
{
|
||||
_player->AddQuestAndCheckCompletion(quest, nullptr); // NULL, this prevent DB script from duplicate running
|
||||
|
||||
if (quest->GetSrcSpell() > 0)
|
||||
_player->CastSpell(_player, quest->GetSrcSpell(), true);
|
||||
}
|
||||
}
|
||||
if (_player->GetSharedQuestID() != uint32(packet.QuestID))
|
||||
return;
|
||||
|
||||
_player->ClearQuestSharingInfo();
|
||||
Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID);
|
||||
if (!quest)
|
||||
return;
|
||||
|
||||
Player* originalPlayer = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest());
|
||||
if (!originalPlayer)
|
||||
return;
|
||||
|
||||
if (!_player->IsInSameRaidWith(originalPlayer))
|
||||
return;
|
||||
|
||||
if (!originalPlayer->IsActiveQuest(packet.QuestID))
|
||||
return;
|
||||
|
||||
if (!_player->CanTakeQuest(quest, true))
|
||||
return;
|
||||
|
||||
if (!_player->CanAddQuest(quest, true))
|
||||
return;
|
||||
|
||||
_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
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user