Core/Quests: ported quest flag and visbility update changes from master branch
This commit is contained in:
1 parent
833b77c05e
commit
a3dd0d75cf
16 files changed
+282
-278
No files matched your search
@@ -1205,9 +1205,9 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
|||||||
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
|
case SMART_ACTION_CALL_GROUPEVENTHAPPENS:
|
||||||
if (Quest const* qid = sObjectMgr->GetQuestTemplate(e.action.quest.quest))
|
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 %d SourceType %u Event %u Action %u SpecialFlags for Quest entry %u 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 %d SourceType %u Event %u Action %u Flags for Quest entry %u 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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID)
|
|||||||
text.QuestType = itr.QuestIcon;
|
text.QuestType = itr.QuestIcon;
|
||||||
text.QuestFlags = quest->GetFlags();
|
text.QuestFlags = quest->GetFlags();
|
||||||
text.QuestLevel = quest->GetQuestLevel();
|
text.QuestLevel = quest->GetQuestLevel();
|
||||||
text.Repeatable = quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly();
|
text.Repeatable = quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly();
|
||||||
|
|
||||||
text.QuestTitle = quest->GetTitle();
|
text.QuestTitle = quest->GetTitle();
|
||||||
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
|
LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex();
|
||||||
@@ -373,7 +373,7 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string
|
|||||||
if (questLevelInTitle)
|
if (questLevelInTitle)
|
||||||
Quest::AddQuestLevelToTitle(title, quest->GetQuestLevel());
|
Quest::AddQuestLevelToTitle(title, quest->GetQuestLevel());
|
||||||
|
|
||||||
bool repeatable = quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly();
|
bool repeatable = quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly();
|
||||||
questList.QuestDataText.emplace_back(questID, questMenuItem.QuestIcon, quest->GetQuestLevel(), quest->GetFlags(), repeatable, title);
|
questList.QuestDataText.emplace_back(questID, questMenuItem.QuestIcon, quest->GetQuestLevel(), quest->GetFlags(), repeatable, title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1342,6 +1342,9 @@ void Player::setDeathState(DeathState s)
|
|||||||
// passive spell
|
// passive spell
|
||||||
if (!ressSpellId)
|
if (!ressSpellId)
|
||||||
ressSpellId = GetResurrectionSpellId();
|
ressSpellId = GetResurrectionSpellId();
|
||||||
|
|
||||||
|
FailQuestsWithFlag(QUEST_FLAGS_COMPLETION_NO_DEATH);
|
||||||
|
|
||||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1);
|
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1);
|
||||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH, 1);
|
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH, 1);
|
||||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON, 1);
|
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON, 1);
|
||||||
@@ -13705,9 +13708,9 @@ void Player::PrepareQuestMenu(ObjectGuid guid)
|
|||||||
if (!CanTakeQuest(quest, false))
|
if (!CanTakeQuest(quest, false))
|
||||||
continue;
|
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);
|
qm.AddMenuItem(quest_id, 0);
|
||||||
else if (quest->IsAutoComplete())
|
else if (quest->IsTurnIn())
|
||||||
qm.AddMenuItem(quest_id, 4);
|
qm.AddMenuItem(quest_id, 4);
|
||||||
else if (GetQuestStatus(quest_id) == QUEST_STATUS_NONE)
|
else if (GetQuestStatus(quest_id) == QUEST_STATUS_NONE)
|
||||||
qm.AddMenuItem(quest_id, 2);
|
qm.AddMenuItem(quest_id, 2);
|
||||||
@@ -13745,7 +13748,7 @@ void Player::SendPreparedQuest(ObjectGuid guid)
|
|||||||
if (quest->IsAutoAccept() && CanAddQuest(quest, true) && CanTakeQuest(quest, true))
|
if (quest->IsAutoAccept() && CanAddQuest(quest, true) && CanTakeQuest(quest, true))
|
||||||
AddQuestAndCheckCompletion(quest, object);
|
AddQuestAndCheckCompletion(quest, object);
|
||||||
|
|
||||||
if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
|
if (quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
|
||||||
PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, CanCompleteRepeatableQuest(quest), true);
|
PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, CanCompleteRepeatableQuest(quest), true);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -13808,48 +13811,30 @@ bool Player::IsActiveQuest(uint32 quest_id) const
|
|||||||
return m_QuestStatus.find(quest_id) != m_QuestStatus.end();
|
return m_QuestStatus.find(quest_id) != m_QuestStatus.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
Quest const* Player::GetNextQuest(ObjectGuid guid, Quest const* quest) const
|
Quest const* Player::GetNextQuest(Object const* questGiver, Quest const* quest) const
|
||||||
{
|
{
|
||||||
QuestRelationResult quests;
|
|
||||||
uint32 nextQuestID = quest->GetNextQuestInChain();
|
uint32 nextQuestID = quest->GetNextQuestInChain();
|
||||||
|
if (!nextQuestID)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
switch (guid.GetHigh())
|
if (questGiver == this)
|
||||||
{
|
{
|
||||||
case HighGuid::Player:
|
if (!quest->HasFlag(QUEST_FLAGS_AUTO_COMPLETE))
|
||||||
ASSERT(quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE));
|
|
||||||
return sObjectMgr->GetQuestTemplate(nextQuestID);
|
|
||||||
case HighGuid::Unit:
|
|
||||||
case HighGuid::Pet:
|
|
||||||
case HighGuid::Vehicle:
|
|
||||||
{
|
|
||||||
if (Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, guid))
|
|
||||||
quests = sObjectMgr->GetCreatureQuestRelations(creature->GetEntry());
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HighGuid::GameObject:
|
|
||||||
{
|
|
||||||
//we should obtain map pointer from GetMap() in 99% of cases. Special case
|
|
||||||
//only for quests which cast teleport spells on player
|
|
||||||
Map* _map = IsInWorld() ? GetMap() : sMapMgr->FindMap(GetMapId(), GetInstanceId());
|
|
||||||
ASSERT(_map);
|
|
||||||
if (GameObject* gameObject = _map->GetGameObject(guid))
|
|
||||||
quests = sObjectMgr->GetGOQuestRelations(gameObject->GetEntry());
|
|
||||||
else
|
|
||||||
return nullptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
return sObjectMgr->GetQuestTemplate(nextQuestID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for unit and go state
|
//we should obtain map pointer from GetMap() in 99% of cases. Special case
|
||||||
if (nextQuestID)
|
//only for quests which cast teleport spells on player
|
||||||
if (quests.HasQuest(nextQuestID))
|
if (WorldObject const* worldObjectQuestGiver = dynamic_cast<WorldObject const*>(questGiver))
|
||||||
return sObjectMgr->GetQuestTemplate(nextQuestID);
|
if (!IsInMap(worldObjectQuestGiver))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
return nullptr;
|
if (questGiver && !questGiver->hasQuest(nextQuestID))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return sObjectMgr->GetQuestTemplate(nextQuestID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::CanSeeStartQuest(Quest const* quest) const
|
bool Player::CanSeeStartQuest(Quest const* quest) const
|
||||||
@@ -13914,7 +13899,7 @@ bool Player::CanCompleteQuest(uint32 quest_id)
|
|||||||
return false; // not allow re-complete quest
|
return false; // not allow re-complete quest
|
||||||
|
|
||||||
// auto complete quest
|
// auto complete quest
|
||||||
if (qInfo->IsAutoComplete() && CanTakeQuest(qInfo, false))
|
if (qInfo->IsTurnIn() && CanTakeQuest(qInfo, false))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id);
|
QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id);
|
||||||
@@ -13934,7 +13919,7 @@ bool Player::CanCompleteQuest(uint32 quest_id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO))
|
if (qInfo->HasSpecialFlag(QuestSpecialFlags(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)))
|
||||||
{
|
{
|
||||||
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
|
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++)
|
||||||
{
|
{
|
||||||
@@ -13950,7 +13935,7 @@ bool Player::CanCompleteQuest(uint32 quest_id)
|
|||||||
if (qInfo->GetPlayersSlain() != 0 && q_status.PlayerCount < qInfo->GetPlayersSlain())
|
if (qInfo->GetPlayersSlain() != 0 && q_status.PlayerCount < qInfo->GetPlayersSlain())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
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;
|
return false;
|
||||||
|
|
||||||
if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) && q_status.Timer == 0)
|
if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED) && q_status.Timer == 0)
|
||||||
@@ -13994,7 +13979,7 @@ bool Player::CanCompleteRepeatableQuest(Quest const* quest)
|
|||||||
bool Player::CanRewardQuest(Quest const* quest, bool msg)
|
bool Player::CanRewardQuest(Quest const* quest, bool msg)
|
||||||
{
|
{
|
||||||
// not auto complete quest and not completed quest (only cheating case, then ignore without message)
|
// 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;
|
return false;
|
||||||
|
|
||||||
// daily quest can't be rewarded (25 daily quest already completed)
|
// daily quest can't be rewarded (25 daily quest already completed)
|
||||||
@@ -14156,7 +14141,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
|
|||||||
questStatusData.ItemCount[i] = 0;
|
questStatusData.ItemCount[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO))
|
if (quest->HasSpecialFlag(QuestSpecialFlags(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)))
|
||||||
{
|
{
|
||||||
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
|
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
|
||||||
questStatusData.CreatureOrGOCount[i] = 0;
|
questStatusData.CreatureOrGOCount[i] = 0;
|
||||||
@@ -14198,6 +14183,17 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
|
|||||||
UpdatePvPState();
|
UpdatePvPState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (quest->GetSrcSpell() > 0)
|
||||||
|
{
|
||||||
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetSrcSpell());
|
||||||
|
Unit* caster = this;
|
||||||
|
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;
|
||||||
|
|
||||||
|
caster->CastSpell(this, spellInfo->Id, CastSpellExtraArgs(TRIGGERED_FULL_MASK));
|
||||||
|
}
|
||||||
|
|
||||||
SetQuestSlot(log_slot, quest_id, qtime);
|
SetQuestSlot(log_slot, quest_id, qtime);
|
||||||
|
|
||||||
m_QuestStatusSave[quest_id] = QUEST_DEFAULT_SAVE_TYPE;
|
m_QuestStatusSave[quest_id] = QUEST_DEFAULT_SAVE_TYPE;
|
||||||
@@ -14235,7 +14231,7 @@ void Player::CompleteQuest(uint32 quest_id)
|
|||||||
SetQuestSlotState(log_slot, QUEST_STATE_COMPLETE);
|
SetQuestSlotState(log_slot, QUEST_STATE_COMPLETE);
|
||||||
|
|
||||||
if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id))
|
if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id))
|
||||||
if (qInfo->HasFlag(QUEST_FLAGS_TRACKING))
|
if (qInfo->HasFlag(QUEST_FLAGS_TRACKING_EVENT))
|
||||||
RewardQuest(qInfo, 0, this, false);
|
RewardQuest(qInfo, 0, this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14273,14 +14269,16 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
|
|||||||
|
|
||||||
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
|
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
|
||||||
{
|
{
|
||||||
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(quest->RequiredItemId[i]))
|
if (quest->RequiredItemId[i])
|
||||||
{
|
{
|
||||||
if (quest->RequiredItemCount[i] > 0 && itemTemplate->GetBonding() == BIND_QUEST && !quest->IsRepeatable() && !HasQuestForItem(quest->RequiredItemId[i], quest_id, true))
|
uint32 amountToDestroy = quest->RequiredItemCount[i];
|
||||||
DestroyItemCount(quest->RequiredItemId[i], 9999, true);
|
if (quest->HasFlag(QUEST_FLAGS_REMOVE_SURPLUS_ITEMS))
|
||||||
else
|
amountToDestroy = std::numeric_limits<uint32>::max();
|
||||||
DestroyItemCount(quest->RequiredItemId[i], quest->RequiredItemCount[i], true);
|
|
||||||
|
DestroyItemCount(quest->RequiredItemId[i], amountToDestroy, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
|
for (uint8 i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i)
|
||||||
if (quest->RequiredCurrencyId[i])
|
if (quest->RequiredCurrencyId[i])
|
||||||
ModifyCurrency(quest->RequiredCurrencyId[i], -int32(quest->RequiredCurrencyCount[i]));
|
ModifyCurrency(quest->RequiredCurrencyId[i], -int32(quest->RequiredCurrencyCount[i]));
|
||||||
@@ -14445,7 +14443,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
|
|||||||
if (quest->GetRewSpellCast() > 0)
|
if (quest->GetRewSpellCast() > 0)
|
||||||
{
|
{
|
||||||
SpellInfo const* spellInfo = ASSERT_NOTNULL(sSpellMgr->GetSpellInfo(quest->GetRewSpellCast()));
|
SpellInfo const* spellInfo = ASSERT_NOTNULL(sSpellMgr->GetSpellInfo(quest->GetRewSpellCast()));
|
||||||
if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL) && !spellInfo->HasEffect(SPELL_EFFECT_CREATE_ITEM) && !spellInfo->IsSelfCast() && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE))
|
if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL) && !spellInfo->HasEffect(SPELL_EFFECT_CREATE_ITEM) && !spellInfo->IsSelfCast() && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_COMPLETE))
|
||||||
{
|
{
|
||||||
if (Creature* creature = GetMap()->GetCreature(questGiver->GetGUID()))
|
if (Creature* creature = GetMap()->GetCreature(questGiver->GetGUID()))
|
||||||
creature->CastSpell(this, quest->GetRewSpellCast(), true);
|
creature->CastSpell(this, quest->GetRewSpellCast(), true);
|
||||||
@@ -14456,7 +14454,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
|
|||||||
else if (quest->GetRewSpell() > 0)
|
else if (quest->GetRewSpell() > 0)
|
||||||
{
|
{
|
||||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell());
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell());
|
||||||
if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL) && !spellInfo->HasEffect(SPELL_EFFECT_CREATE_ITEM) && !spellInfo->IsSelfCast() && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE))
|
if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL) && !spellInfo->HasEffect(SPELL_EFFECT_CREATE_ITEM) && !spellInfo->IsSelfCast() && !quest->HasFlag(QUEST_FLAGS_PLAYER_CAST_COMPLETE))
|
||||||
{
|
{
|
||||||
if (Creature* creature = GetMap()->GetCreature(questGiver->GetGUID()))
|
if (Creature* creature = GetMap()->GetCreature(questGiver->GetGUID()))
|
||||||
creature->CastSpell(this, quest->GetRewSpell(), true);
|
creature->CastSpell(this, quest->GetRewSpell(), true);
|
||||||
@@ -14481,13 +14479,43 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
|
|||||||
|
|
||||||
SendQuestUpdate(quest_id);
|
SendQuestUpdate(quest_id);
|
||||||
|
|
||||||
|
bool updateVisibility = false;
|
||||||
|
if (quest->HasFlag(QUEST_FLAGS_UPDATE_PHASESHIFT))
|
||||||
|
updateVisibility = PhasingHandler::OnConditionChange(this, false);
|
||||||
|
|
||||||
//Update QuestGivers
|
//Update QuestGivers
|
||||||
SendQuestGiverStatusMultiple();
|
SendQuestGiverStatusMultiple();
|
||||||
|
|
||||||
//lets remove flag for delayed teleports
|
//lets remove flag for delayed teleports
|
||||||
SetCanDelayTeleport(false);
|
SetCanDelayTeleport(false);
|
||||||
|
|
||||||
|
if (questGiver && questGiver->isType(TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT))
|
||||||
|
{
|
||||||
|
//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))
|
||||||
|
{
|
||||||
|
if (nextQuest->IsAutoAccept() && CanAddQuest(nextQuest, true))
|
||||||
|
AddQuestAndCheckCompletion(nextQuest, questGiver);
|
||||||
|
|
||||||
|
PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, questGiver->GetGUID(), true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerTalkClass->ClearMenus();
|
||||||
|
if (Creature* creatureQGiver = questGiver->ToCreature())
|
||||||
|
creatureQGiver->AI()->QuestReward(this, quest, reward);
|
||||||
|
else if (GameObject* goQGiver = questGiver->ToGameObject())
|
||||||
|
goQGiver->AI()->QuestReward(this, quest, reward);
|
||||||
|
}
|
||||||
|
|
||||||
sScriptMgr->OnQuestStatusChange(this, quest_id);
|
sScriptMgr->OnQuestStatusChange(this, quest_id);
|
||||||
|
|
||||||
|
if (updateVisibility)
|
||||||
|
UpdateObjectVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SetRewardedQuest(uint32 quest_id)
|
void Player::SetRewardedQuest(uint32 quest_id)
|
||||||
@@ -14545,6 +14573,21 @@ void Player::FailQuest(uint32 questId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Player::FailQuestsWithFlag(QuestFlags flag)
|
||||||
|
{
|
||||||
|
for (uint16 slot = 0; slot < 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)
|
void Player::AbandonQuest(uint32 questId)
|
||||||
{
|
{
|
||||||
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
|
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
|
||||||
@@ -15133,7 +15176,7 @@ void Player::SetQuestStatus(uint32 questId, QuestStatus status, bool update /*=
|
|||||||
{
|
{
|
||||||
m_QuestStatus[questId].Status = status;
|
m_QuestStatus[questId].Status = status;
|
||||||
|
|
||||||
if (!quest->IsAutoComplete())
|
if (!quest->IsTurnIn())
|
||||||
m_QuestStatusSave[questId] = QUEST_DEFAULT_SAVE_TYPE;
|
m_QuestStatusSave[questId] = QUEST_DEFAULT_SAVE_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15230,7 +15273,6 @@ void Player::SendQuestUpdate(uint32 questId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdateVisibleGameobjectsOrSpellClicks();
|
UpdateVisibleGameobjectsOrSpellClicks();
|
||||||
PhasingHandler::OnConditionChange(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::SatisfyFirstLFGReward(uint32 dungeonId, uint8 maxRewCount) const
|
bool Player::SatisfyFirstLFGReward(uint32 dungeonId, uint8 maxRewCount) const
|
||||||
@@ -15294,7 +15336,7 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
|
|||||||
else if (status == QUEST_STATUS_INCOMPLETE)
|
else if (status == QUEST_STATUS_INCOMPLETE)
|
||||||
result2 = DIALOG_STATUS_INCOMPLETE;
|
result2 = DIALOG_STATUS_INCOMPLETE;
|
||||||
|
|
||||||
if (quest->IsAutoComplete() && CanTakeQuest(quest, false) && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
|
if (quest->IsTurnIn() && CanTakeQuest(quest, false) && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
|
||||||
result2 = DIALOG_STATUS_REWARD_REP;
|
result2 = DIALOG_STATUS_REWARD_REP;
|
||||||
|
|
||||||
if (result2 > result)
|
if (result2 > result)
|
||||||
@@ -15335,7 +15377,7 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
|
|||||||
else
|
else
|
||||||
result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE;
|
result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE;
|
||||||
}
|
}
|
||||||
else if (quest->IsAutoComplete())
|
else if (quest->IsTurnIn())
|
||||||
{
|
{
|
||||||
if (isNotLowLevelQuest)
|
if (isNotLowLevelQuest)
|
||||||
result2 = DIALOG_STATUS_REWARD_REP;
|
result2 = DIALOG_STATUS_REWARD_REP;
|
||||||
@@ -15804,7 +15846,7 @@ void Player::TalkedToCreature(uint32 entry, ObjectGuid guid)
|
|||||||
|
|
||||||
if (q_status.Status == QUEST_STATUS_INCOMPLETE)
|
if (q_status.Status == QUEST_STATUS_INCOMPLETE)
|
||||||
{
|
{
|
||||||
if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO))
|
if (qInfo->HasSpecialFlag(QuestSpecialFlags(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)))
|
||||||
{
|
{
|
||||||
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
|
for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j)
|
||||||
{
|
{
|
||||||
@@ -16022,9 +16064,10 @@ void Player::SendQuestReward(Quest const* quest, Creature const* questGiver, uin
|
|||||||
|
|
||||||
if (questGiver)
|
if (questGiver)
|
||||||
{
|
{
|
||||||
if (questGiver->IsGossip() && quest->HasFlag(QUEST_FLAGS_LAUNCH_GOSSIP_COMPLETE))
|
if (questGiver->IsGossip())
|
||||||
packet.LaunchGossip = true;
|
packet.LaunchGossip = quest->HasFlag(QUEST_FLAGS_LAUNCH_GOSSIP_COMPLETE);
|
||||||
else if (quest->GetNextQuestInChain() && !quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
|
|
||||||
|
else if (quest->GetNextQuestInChain() && !quest->HasFlag(QUEST_FLAGS_AUTO_COMPLETE))
|
||||||
if (Quest const* rewardQuest = sObjectMgr->GetQuestTemplate(quest->GetNextQuestInChain()))
|
if (Quest const* rewardQuest = sObjectMgr->GetQuestTemplate(quest->GetNextQuestInChain()))
|
||||||
packet.UseQuestReward = CanTakeQuest(rewardQuest, false);
|
packet.UseQuestReward = CanTakeQuest(rewardQuest, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1331,7 +1331,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
|||||||
void PrepareQuestMenu(ObjectGuid guid);
|
void PrepareQuestMenu(ObjectGuid guid);
|
||||||
void SendPreparedQuest(ObjectGuid guid);
|
void SendPreparedQuest(ObjectGuid guid);
|
||||||
bool IsActiveQuest(uint32 quest_id) const;
|
bool IsActiveQuest(uint32 quest_id) const;
|
||||||
Quest const* GetNextQuest(ObjectGuid guid, Quest const* quest) const;
|
Quest const* GetNextQuest(Object const* questGiver, Quest const* quest) const;
|
||||||
bool CanSeeStartQuest(Quest const* quest) const;
|
bool CanSeeStartQuest(Quest const* quest) const;
|
||||||
bool CanTakeQuest(Quest const* quest, bool msg) const;
|
bool CanTakeQuest(Quest const* quest, bool msg) const;
|
||||||
bool CanAddQuest(Quest const* quest, bool msg) const;
|
bool CanAddQuest(Quest const* quest, bool msg) const;
|
||||||
@@ -1347,6 +1347,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
|
|||||||
void RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, bool announce = true);
|
void RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, bool announce = true);
|
||||||
void SetRewardedQuest(uint32 quest_id);
|
void SetRewardedQuest(uint32 quest_id);
|
||||||
void FailQuest(uint32 quest_id);
|
void FailQuest(uint32 quest_id);
|
||||||
|
void FailQuestsWithFlag(QuestFlags flag);
|
||||||
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
|
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
|
||||||
bool SatisfyQuestLevel(Quest const* qInfo, bool msg) const;
|
bool SatisfyQuestLevel(Quest const* qInfo, bool msg) const;
|
||||||
bool SatisfyQuestLog(bool msg) const;
|
bool SatisfyQuestLog(bool msg) const;
|
||||||
|
|||||||
@@ -4119,8 +4119,8 @@ void ObjectMgr::LoadQuests()
|
|||||||
|
|
||||||
// additional quest integrity checks (GO, creature_template and item_template must be loaded already)
|
// additional quest integrity checks (GO, creature_template and item_template must be loaded already)
|
||||||
|
|
||||||
if (qinfo->GetQuestMethod() >= 3)
|
if (qinfo->GetQuestType() >= MAX_DB_ALLOWED_QUEST_TYPES)
|
||||||
TC_LOG_ERROR("sql.sql", "Quest %u has `Method` = %u, expected values are 0, 1 or 2.", qinfo->GetQuestId(), qinfo->GetQuestMethod());
|
TC_LOG_ERROR("sql.sql", "Quest %u has `Method` = %u, expected values are 0, 1 or 2.", qinfo->GetQuestId(), qinfo->GetQuestType());
|
||||||
|
|
||||||
if (qinfo->_specialFlags & ~QUEST_SPECIAL_FLAGS_DB_ALLOWED)
|
if (qinfo->_specialFlags & ~QUEST_SPECIAL_FLAGS_DB_ALLOWED)
|
||||||
{
|
{
|
||||||
@@ -4162,7 +4162,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]
|
// at auto-reward can be rewarded only RewardChoiceItemId[0]
|
||||||
for (uint32 j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j)
|
for (uint32 j = 1; j < QUEST_REWARD_CHOICES_COUNT; ++j)
|
||||||
@@ -4445,7 +4445,7 @@ void ObjectMgr::LoadQuests()
|
|||||||
{
|
{
|
||||||
// In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast
|
// In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast
|
||||||
|
|
||||||
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO);
|
qinfo->SetSpecialFlag(QuestSpecialFlags(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO));
|
||||||
|
|
||||||
if (!qinfo->RequiredNpcOrGoCount[j])
|
if (!qinfo->RequiredNpcOrGoCount[j])
|
||||||
{
|
{
|
||||||
@@ -4784,7 +4784,8 @@ void ObjectMgr::LoadQuests()
|
|||||||
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL);
|
qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_PLAYER_KILL);
|
||||||
|
|
||||||
// Special flag to determine if quest is completed from the start, used to determine if we can fail timed quest if it is completed
|
// 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))
|
if (!qinfo->HasSpecialFlag(QuestSpecialFlags(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) &&
|
||||||
|
!qinfo->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER | QUEST_FLAGS_COMPLETION_EVENT))
|
||||||
{
|
{
|
||||||
bool addFlag = true;
|
bool addFlag = true;
|
||||||
if (qinfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
|
if (qinfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
|
||||||
@@ -4836,35 +4837,7 @@ void ObjectMgr::LoadQuests()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT for spell with SPELL_EFFECT_QUEST_COMPLETE
|
// don't check spells with SPELL_EFFECT_QUEST_COMPLETE, a lot of invalid db2 data
|
||||||
for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i)
|
|
||||||
{
|
|
||||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i);
|
|
||||||
if (!spellInfo)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
|
|
||||||
{
|
|
||||||
if (spellInfo->Effects[j].Effect != SPELL_EFFECT_QUEST_COMPLETE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
uint32 quest_id = spellInfo->Effects[j].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: %u) have SPELL_EFFECT_QUEST_COMPLETE for quest %u, 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TC_LOG_INFO("server.loading", ">> Loaded %lu quests definitions in %u ms", (unsigned long)_questTemplates.size(), GetMSTimeDiffToNow(oldMSTime));
|
TC_LOG_INFO("server.loading", ">> Loaded %lu quests definitions in %u ms", (unsigned long)_questTemplates.size(), GetMSTimeDiffToNow(oldMSTime));
|
||||||
}
|
}
|
||||||
@@ -5033,15 +5006,11 @@ void ObjectMgr::LoadScripts(ScriptsType type)
|
|||||||
continue;
|
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 `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, 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 `%s` has quest (ID: %u) in SCRIPT_COMMAND_QUEST_EXPLORED in `datalong` for script id %u, 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.",
|
||||||
tableName.c_str(), tmp.QuestExplored.QuestID, tmp.id);
|
tableName.c_str(), tmp.QuestExplored.QuestID, tmp.id);
|
||||||
|
continue;
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (float(tmp.QuestExplored.Distance) > DEFAULT_VISIBILITY_DISTANCE)
|
if (float(tmp.QuestExplored.Distance) > DEFAULT_VISIBILITY_DISTANCE)
|
||||||
@@ -6007,14 +5976,10 @@ void ObjectMgr::LoadQuestAreaTriggers()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
|
if (!quest->HasFlag(QUEST_FLAGS_COMPLETION_AREA_TRIGGER))
|
||||||
{
|
{
|
||||||
TC_LOG_ERROR("sql.sql", "Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, 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);
|
TC_LOG_ERROR("sql.sql", "Table `areatrigger_involvedrelation` has record (id: %u) for not quest %u, but quest not have flag QUEST_FLAGS_COMPLETION_AREA_TRIGGER. Trigger or quest flags must be fixed, quest modified to require objective.", trigger_ID, quest_ID);
|
||||||
|
continue;
|
||||||
// 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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_questAreaTriggerStore[trigger_ID] = quest_ID;
|
_questAreaTriggerStore[trigger_ID] = quest_ID;
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG
|
|||||||
{
|
{
|
||||||
_player->AddQuestAndCheckCompletion(quest, object);
|
_player->AddQuestAndCheckCompletion(quest, object);
|
||||||
|
|
||||||
if (quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT))
|
if (quest->IsPushedToPartyOnAccept())
|
||||||
{
|
{
|
||||||
if (Group* group = _player->GetGroup())
|
if (Group* group = _player->GetGroup())
|
||||||
{
|
{
|
||||||
@@ -222,6 +222,21 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG
|
|||||||
|
|
||||||
_player->PlayerTalkClass->SendCloseGossip();
|
_player->PlayerTalkClass->SendCloseGossip();
|
||||||
|
|
||||||
|
if (quest->HasFlag(QUEST_FLAGS_LAUNCH_GOSSIP_ACCEPT))
|
||||||
|
{
|
||||||
|
auto launchGossip = [&](WorldObject* worldObject)
|
||||||
|
{
|
||||||
|
_player->PlayerTalkClass->ClearMenus();
|
||||||
|
_player->PrepareGossipMenu(worldObject, _player->GetDefaultGossipMenuForSource(worldObject), true);
|
||||||
|
_player->SendPreparedGossip(worldObject);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Creature* creature = object->ToCreature())
|
||||||
|
launchGossip(creature);
|
||||||
|
else if (GameObject* go = object->ToGameObject())
|
||||||
|
launchGossip(go);
|
||||||
|
}
|
||||||
|
|
||||||
if (quest->GetSrcSpell() > 0)
|
if (quest->GetSrcSpell() > 0)
|
||||||
_player->CastSpell(_player, quest->GetSrcSpell(), true);
|
_player->CastSpell(_player, quest->GetSrcSpell(), true);
|
||||||
|
|
||||||
@@ -258,7 +273,7 @@ void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPackets::Quest::QuestGi
|
|||||||
if (quest->IsAutoAccept() && _player->CanAddQuest(quest, true))
|
if (quest->IsAutoAccept() && _player->CanAddQuest(quest, true))
|
||||||
_player->AddQuestAndCheckCompletion(quest, object);
|
_player->AddQuestAndCheckCompletion(quest, object);
|
||||||
|
|
||||||
if (quest->IsAutoComplete())
|
if (quest->IsTurnIn())
|
||||||
_player->PlayerTalkClass->SendQuestGiverRequestItems(quest, object->GetGUID(), _player->CanCompleteQuest(quest->GetQuestId()), true);
|
_player->PlayerTalkClass->SendQuestGiverRequestItems(quest, object->GetGUID(), _player->CanCompleteQuest(quest->GetQuestId()), true);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -295,7 +310,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest
|
|||||||
|
|
||||||
Object* object = _player;
|
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);
|
object = ObjectAccessor::GetObjectByTypeMask(*_player, packet.QuestGiverGUID, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
|
||||||
if (!object || !object->hasInvolvedQuest(packet.QuestID))
|
if (!object || !object->hasInvolvedQuest(packet.QuestID))
|
||||||
@@ -307,70 +322,17 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(packet.QuestID) == QUEST_STATUS_NONE) ||
|
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("entities.player.cheat", "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)",
|
TC_LOG_ERROR("entities.player.cheat", "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)",
|
||||||
_player->GetName().c_str(), _player->GetGUID().GetCounter(), packet.QuestID);
|
_player->GetName().c_str(), _player->GetGUID().GetCounter(), packet.QuestID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_player->CanRewardQuest(quest, packet.ItemChoiceID, true))
|
if (_player->CanRewardQuest(quest, true))
|
||||||
{
|
{
|
||||||
_player->RewardQuest(quest, packet.ItemChoiceID, object);
|
if (_player->CanRewardQuest(quest, packet.ItemChoiceID, true))
|
||||||
|
_player->RewardQuest(quest, packet.ItemChoiceID, object);
|
||||||
switch (object->GetTypeId())
|
|
||||||
{
|
|
||||||
case TYPEID_UNIT:
|
|
||||||
case TYPEID_PLAYER:
|
|
||||||
{
|
|
||||||
// Send next quest
|
|
||||||
if (Quest const* nextQuest = _player->GetNextQuest(packet.QuestGiverGUID, quest))
|
|
||||||
{
|
|
||||||
// Only send the quest to the player if the conditions are met
|
|
||||||
if (_player->CanTakeQuest(nextQuest, false))
|
|
||||||
{
|
|
||||||
if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true))
|
|
||||||
_player->AddQuestAndCheckCompletion(nextQuest, object);
|
|
||||||
|
|
||||||
// Previous quest has been rewarded via popup. The player may now accept the follow quest from himself.
|
|
||||||
if (object->IsPlayer() && quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE) && !nextQuest->IsAutoAccept())
|
|
||||||
_player->SetPopupQuestId(nextQuest->GetQuestId());
|
|
||||||
else
|
|
||||||
_player->SetPopupQuestId(0);
|
|
||||||
|
|
||||||
_player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, packet.QuestGiverGUID, true, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_player->PlayerTalkClass->ClearMenus();
|
|
||||||
if (Creature* creatureQGiver = object->ToCreature())
|
|
||||||
creatureQGiver->AI()->QuestReward(_player, quest, packet.ItemChoiceID);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TYPEID_GAMEOBJECT:
|
|
||||||
{
|
|
||||||
// Send next quest
|
|
||||||
if (Quest const* nextQuest = _player->GetNextQuest(packet.QuestGiverGUID, quest))
|
|
||||||
{
|
|
||||||
// Only send the quest to the player if the conditions are met
|
|
||||||
if (_player->CanTakeQuest(nextQuest, false))
|
|
||||||
{
|
|
||||||
if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true))
|
|
||||||
_player->AddQuestAndCheckCompletion(nextQuest, object);
|
|
||||||
|
|
||||||
_player->SetPopupQuestId(0);
|
|
||||||
_player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, packet.QuestGiverGUID, true, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_player->PlayerTalkClass->ClearMenus();
|
|
||||||
if (GameObject* questGiver = object->ToGameObject())
|
|
||||||
questGiver->AI()->QuestReward(_player, quest, packet.ItemChoiceID);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_player->PlayerTalkClass->SendQuestGiverOfferReward(quest, packet.QuestGiverGUID, true);
|
_player->PlayerTalkClass->SendQuestGiverOfferReward(quest, packet.QuestGiverGUID, true);
|
||||||
@@ -473,49 +435,48 @@ void WorldSession::HandleQuestConfirmAccept(WorldPackets::Quest::QuestConfirmAcc
|
|||||||
{
|
{
|
||||||
TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT QuestID = %u", packet.QuestID);
|
TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT QuestID = %u", packet.QuestID);
|
||||||
|
|
||||||
if (Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID))
|
if (_player->GetSharedQuestID() != uint32(packet.QuestID))
|
||||||
{
|
return;
|
||||||
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); // nullptr, this prevent DB script from duplicate running
|
|
||||||
|
|
||||||
if (quest->GetSrcSpell() > 0)
|
|
||||||
_player->CastSpell(_player, quest->GetSrcSpell(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_player->ClearQuestSharingInfo();
|
_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)
|
void WorldSession::HandleQuestgiverCompleteQuest(WorldPackets::Quest::QuestGiverCompleteQuest& packet)
|
||||||
{
|
{
|
||||||
|
bool autoCompleteMode = packet.FromScript; // 0 - standart complete quest mode with npc, 1 - auto-complete mode
|
||||||
|
|
||||||
TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %s, questId = %u self-complete: %u", packet.QuestGiverGUID.ToString().c_str(), packet.QuestID, packet.FromScript ? 1 : 0);
|
TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %s, questId = %u self-complete: %u", packet.QuestGiverGUID.ToString().c_str(), packet.QuestID, packet.FromScript ? 1 : 0);
|
||||||
|
|
||||||
Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID);
|
Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID);
|
||||||
if (!quest)
|
if (!quest)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (packet.FromScript && !quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Object* object = nullptr;
|
Object* object = nullptr;
|
||||||
if (packet.FromScript)
|
if (autoCompleteMode)
|
||||||
object = _player;
|
object = _player;
|
||||||
else
|
else
|
||||||
object = ObjectAccessor::GetObjectByTypeMask(*_player, packet.QuestGiverGUID, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT);
|
object = ObjectAccessor::GetObjectByTypeMask(*_player, packet.QuestGiverGUID, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT);
|
||||||
@@ -523,7 +484,7 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPackets::Quest::QuestGiver
|
|||||||
if (!object)
|
if (!object)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!packet.FromScript)
|
if (!quest->HasFlag(QUEST_FLAGS_AUTO_COMPLETE))
|
||||||
{
|
{
|
||||||
if (!object->hasInvolvedQuest(packet.QuestID))
|
if (!object->hasInvolvedQuest(packet.QuestID))
|
||||||
return;
|
return;
|
||||||
@@ -641,7 +602,7 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket)
|
|||||||
if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true))
|
if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true))
|
||||||
receiver->AddQuestAndCheckCompletion(quest, sender);
|
receiver->AddQuestAndCheckCompletion(quest, sender);
|
||||||
|
|
||||||
if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
|
if (quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
|
||||||
receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true);
|
receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3220,20 +3220,32 @@ enum HolidayIds : uint32
|
|||||||
HOLIDAY_ANNIVERSARY_8_YEARS = 484
|
HOLIDAY_ANNIVERSARY_8_YEARS = 484
|
||||||
};
|
};
|
||||||
|
|
||||||
// values based at QuestInfo.dbc
|
enum QuestType
|
||||||
enum QuestTypes
|
|
||||||
{
|
{
|
||||||
QUEST_TYPE_ELITE = 1,
|
QUEST_TYPE_TURNIN = 0,
|
||||||
QUEST_TYPE_LIFE = 21,
|
QUEST_TYPE_WITH_MAX_LEVEL = 1,
|
||||||
QUEST_TYPE_PVP = 41,
|
QUEST_TYPE_NORMAL = 2,
|
||||||
QUEST_TYPE_RAID = 62,
|
MAX_DB_ALLOWED_QUEST_TYPES = 3,
|
||||||
QUEST_TYPE_DUNGEON = 81,
|
|
||||||
QUEST_TYPE_WORLD_EVENT = 82,
|
// values used in quest menu packets
|
||||||
QUEST_TYPE_LEGENDARY = 83,
|
QUEST_TYPE_IN_PROGRESS = 4,
|
||||||
QUEST_TYPE_ESCORT = 84,
|
QUEST_TYPE_TASK_IN_PROGRESS = 5
|
||||||
QUEST_TYPE_HEROIC = 85,
|
};
|
||||||
QUEST_TYPE_RAID_10 = 88,
|
|
||||||
QUEST_TYPE_RAID_25 = 89
|
// values based at QuestInfo.dbc
|
||||||
|
enum QuestInfo
|
||||||
|
{
|
||||||
|
QUEST_INFO_GROUP = 1,
|
||||||
|
QUEST_INFO_CLASS = 21,
|
||||||
|
QUEST_INFO_PVP = 41,
|
||||||
|
QUEST_INFO_RAID = 62,
|
||||||
|
QUEST_INFO_DUNGEON = 81,
|
||||||
|
QUEST_INFO_WORLD_EVENT = 82,
|
||||||
|
QUEST_INFO_LEGENDARY = 83,
|
||||||
|
QUEST_INFO_ESCORT = 84,
|
||||||
|
QUEST_INFO_HEROIC = 85,
|
||||||
|
QUEST_INFO_RAID_10 = 88,
|
||||||
|
QUEST_INFO_RAID_25 = 89
|
||||||
};
|
};
|
||||||
|
|
||||||
// values based at QuestSort.dbc
|
// values based at QuestSort.dbc
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ void PhasingHandler::OnAreaChange(WorldObject* object)
|
|||||||
UpdateVisibilityIfNeeded(object, true, changed);
|
UpdateVisibilityIfNeeded(object, true, changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhasingHandler::OnConditionChange(WorldObject* object)
|
bool PhasingHandler::OnConditionChange(WorldObject* object, bool updateVisibility /*= true*/)
|
||||||
{
|
{
|
||||||
PhaseShift& phaseShift = object->GetPhaseShift();
|
PhaseShift& phaseShift = object->GetPhaseShift();
|
||||||
PhaseShift& suppressedPhaseShift = object->GetSuppressedPhaseShift();
|
PhaseShift& suppressedPhaseShift = object->GetSuppressedPhaseShift();
|
||||||
@@ -393,7 +393,8 @@ void PhasingHandler::OnConditionChange(WorldObject* object)
|
|||||||
unit->RemoveNotOwnSingleTargetAuras(true);
|
unit->RemoveNotOwnSingleTargetAuras(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateVisibilityIfNeeded(object, true, changed);
|
UpdateVisibilityIfNeeded(object, updateVisibility, changed);
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhasingHandler::SendToPlayer(Player const* player, PhaseShift const& phaseShift)
|
void PhasingHandler::SendToPlayer(Player const* player, PhaseShift const& phaseShift)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
|
|
||||||
static void OnMapChange(WorldObject* object);
|
static void OnMapChange(WorldObject* object);
|
||||||
static void OnAreaChange(WorldObject* object);
|
static void OnAreaChange(WorldObject* object);
|
||||||
static void OnConditionChange(WorldObject* object);
|
static bool OnConditionChange(WorldObject* object, bool updateVisibility = true);
|
||||||
|
|
||||||
static void SendToPlayer(Player const* player, PhaseShift const& phaseShift);
|
static void SendToPlayer(Player const* player, PhaseShift const& phaseShift);
|
||||||
static void SendToPlayer(Player const* player);
|
static void SendToPlayer(Player const* player);
|
||||||
|
|||||||
@@ -29,11 +29,11 @@
|
|||||||
Quest::Quest(Field* questRecord)
|
Quest::Quest(Field* questRecord)
|
||||||
{
|
{
|
||||||
_id = questRecord[0].GetUInt32();
|
_id = questRecord[0].GetUInt32();
|
||||||
_method = questRecord[1].GetUInt8();
|
_type = questRecord[1].GetUInt8();
|
||||||
_level = questRecord[2].GetInt16();
|
_level = questRecord[2].GetInt16();
|
||||||
_minLevel = questRecord[3].GetInt16();
|
_minLevel = questRecord[3].GetInt16();
|
||||||
_zoneOrSort = questRecord[4].GetInt16();
|
_zoneOrSort = questRecord[4].GetInt16();
|
||||||
_type = questRecord[5].GetUInt16();
|
_questInfoId = questRecord[5].GetUInt16();
|
||||||
_suggestedPlayers = questRecord[6].GetUInt8();
|
_suggestedPlayers = questRecord[6].GetUInt8();
|
||||||
_requiredFactionId1 = questRecord[7].GetUInt16();
|
_requiredFactionId1 = questRecord[7].GetUInt16();
|
||||||
_requiredFactionId2 = questRecord[8].GetUInt16();
|
_requiredFactionId2 = questRecord[8].GetUInt16();
|
||||||
@@ -339,7 +339,7 @@ void Quest::BuildQuestRewards(WorldPackets::Quest::QuestRewards& rewards, Player
|
|||||||
uint32 Quest::GetRewMoneyMaxLevel() const
|
uint32 Quest::GetRewMoneyMaxLevel() const
|
||||||
{
|
{
|
||||||
// If Quest has flag to not give money on max level, it's 0
|
// 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;
|
return 0;
|
||||||
|
|
||||||
// Else, return the rewarded copper sum modified by the rate
|
// Else, return the rewarded copper sum modified by the rate
|
||||||
@@ -351,26 +351,26 @@ bool Quest::IsAutoAccept() const
|
|||||||
return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_ACCEPT) && HasFlag(QUEST_FLAGS_AUTO_ACCEPT);
|
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) && _method == 0;
|
return !sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) && _type == QUEST_TYPE_TURNIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Quest::IsRaidQuest(Difficulty difficulty) const
|
bool Quest::IsRaidQuest(Difficulty difficulty) const
|
||||||
{
|
{
|
||||||
switch (_type)
|
switch (_questInfoId)
|
||||||
{
|
{
|
||||||
case QUEST_TYPE_RAID:
|
case QUEST_INFO_RAID:
|
||||||
return true;
|
return true;
|
||||||
case QUEST_TYPE_RAID_10:
|
case QUEST_INFO_RAID_10:
|
||||||
return !(difficulty & RAID_DIFFICULTY_MASK_25MAN);
|
return difficulty == RAID_DIFFICULTY_10MAN_NORMAL || difficulty == RAID_DIFFICULTY_10MAN_HEROIC;
|
||||||
case QUEST_TYPE_RAID_25:
|
case QUEST_INFO_RAID_25:
|
||||||
return difficulty & RAID_DIFFICULTY_MASK_25MAN;
|
return difficulty == RAID_DIFFICULTY_25MAN_NORMAL || difficulty == RAID_DIFFICULTY_25MAN_HEROIC;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((_flags & QUEST_FLAGS_RAID) != 0)
|
if ((_flags & QUEST_FLAGS_RAID_GROUP_OK) != 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -470,11 +470,11 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc) const
|
|||||||
ObjectMgr::GetLocaleString(localeData->ObjectiveText[i], loc, locQuestObjectiveText[i]);
|
ObjectMgr::GetLocaleString(localeData->ObjectiveText[i], loc, locQuestObjectiveText[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Info.QuestType = GetQuestMethod();
|
response.Info.QuestType = GetQuestType();
|
||||||
response.Info.QuestLevel = GetQuestLevel();
|
response.Info.QuestLevel = GetQuestLevel();
|
||||||
response.Info.QuestMinLevel = GetMinLevel();
|
response.Info.QuestMinLevel = GetMinLevel();
|
||||||
response.Info.QuestSortID = GetZoneOrSort();
|
response.Info.QuestSortID = GetZoneOrSort();
|
||||||
response.Info.QuestInfoID = GetType();
|
response.Info.QuestInfoID = GetQuestInfoId();
|
||||||
|
|
||||||
response.Info.SuggestedGroupNum = GetSuggestedPlayers();
|
response.Info.SuggestedGroupNum = GetSuggestedPlayers();
|
||||||
|
|
||||||
|
|||||||
@@ -131,40 +131,40 @@ enum QuestGiverStatus
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum QuestFlags
|
enum QuestFlags : uint32
|
||||||
{
|
{
|
||||||
QUEST_FLAGS_NONE = 0x00000000,
|
QUEST_FLAGS_NONE = 0x00000000,
|
||||||
QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently
|
QUEST_FLAGS_COMPLETION_NO_DEATH = 0x00000001,
|
||||||
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_COMPLETION_EVENT = 0x00000002,
|
||||||
QUEST_FLAGS_EXPLORATION = 0x00000004, // Not used currently
|
QUEST_FLAGS_COMPLETION_AREA_TRIGGER = 0x00000004,
|
||||||
QUEST_FLAGS_SHARABLE = 0x00000008, // Can be shared: Player::CanShareQuest()
|
QUEST_FLAGS_SHARABLE = 0x00000008, // Can be shared: Player::CanShareQuest()
|
||||||
QUEST_FLAGS_HAS_CONDITION = 0x00000010, // Not used currently
|
QUEST_FLAGS_HAS_CONDITION = 0x00000010, // Not used currently
|
||||||
QUEST_FLAGS_HIDE_REWARD_POI = 0x00000020, // Not used currently: Unsure of content
|
QUEST_FLAGS_HIDE_REWARD_POI = 0x00000020, // Hides questgiver turn-in minimap icon
|
||||||
QUEST_FLAGS_RAID = 0x00000040, // Can be completed while in raid
|
QUEST_FLAGS_RAID_GROUP_OK = 0x00000040, // Can be completed while in raid
|
||||||
QUEST_FLAGS_TBC = 0x00000080, // Not used currently: Available if TBC expansion enabled only
|
QUEST_FLAGS_EXPANSION_ONLY = 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_NO_MONEY_FOR_XP = 0x00000100, // 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_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE))
|
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 = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side.
|
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_DEPRECATE_REPUTATION = 0x00000800, // Not used currently
|
||||||
QUEST_FLAGS_DAILY = 0x00001000, // Used to know quest is Daily one
|
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_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_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_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_AUTO_ACCEPT = 0x00080000, // The client recognizes this flag as auto-accept.
|
||||||
QUEST_FLAGS_PLAYER_CAST_ON_ACCEPT = 0x00100000,
|
QUEST_FLAGS_PLAYER_CAST_ACCEPT = 0x00100000,
|
||||||
QUEST_FLAGS_PLAYER_CAST_ON_COMPLETE = 0x00200000,
|
QUEST_FLAGS_PLAYER_CAST_COMPLETE = 0x00200000,
|
||||||
QUEST_FLAGS_UPDATE_PHASE_SHIFT = 0x00400000,
|
QUEST_FLAGS_UPDATE_PHASESHIFT = 0x00400000,
|
||||||
QUEST_FLAGS_SOR_WHITELIST = 0x00800000,
|
QUEST_FLAGS_SOR_WHITELIST = 0x00800000,
|
||||||
QUEST_FLAGS_LAUNCH_GOSSIP_COMPLETE = 0x01000000,
|
QUEST_FLAGS_LAUNCH_GOSSIP_COMPLETE = 0x01000000,
|
||||||
QUEST_FLAGS_REMOVE_EXTRA_GET_ITEMS = 0x02000000,
|
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_HIDE_UNTIL_DISCOVERED = 0x04000000,
|
QUEST_FLAGS_WELL_KNOWN = 0x04000000,
|
||||||
QUEST_FLAGS_PORTRAIT_IN_QUEST_LOG = 0x08000000,
|
QUEST_FLAGS_PORTRAIT_IN_QUEST_LOG = 0x08000000,
|
||||||
QUEST_FLAGS_SHOW_ITEM_WHEN_COMPLETED = 0x10000000,
|
QUEST_FLAGS_SHOW_ITEM_WHEN_COMPLETED = 0x10000000,
|
||||||
QUEST_FLAGS_LAUNCH_GOSSIP_ACCEPT = 0x20000000,
|
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
|
QUEST_FLAGS_FAIL_ON_LOGOUT = 0x80000000
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -173,14 +173,14 @@ enum QuestSpecialFlags
|
|||||||
QUEST_SPECIAL_FLAGS_NONE = 0x000,
|
QUEST_SPECIAL_FLAGS_NONE = 0x000,
|
||||||
// Trinity flags for set SpecialFlags in DB if required but used only at server
|
// 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_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_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_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_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)
|
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
|
// 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_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST,
|
||||||
|
|
||||||
QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only
|
QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only
|
||||||
QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only
|
QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only
|
||||||
@@ -242,20 +242,23 @@ class TC_GAME_API Quest
|
|||||||
bool HasFlag(uint32 flag) const { return (_flags & flag) != 0; }
|
bool HasFlag(uint32 flag) const { return (_flags & flag) != 0; }
|
||||||
void SetFlag(uint32 flag) { _flags |= flag; }
|
void SetFlag(uint32 flag) { _flags |= flag; }
|
||||||
|
|
||||||
bool HasSpecialFlag(uint32 flag) const { return (_specialFlags & flag) != 0; }
|
bool HasSpecialFlag(QuestSpecialFlags flag) const { return (_specialFlags & flag) != 0; }
|
||||||
void SetSpecialFlag(uint32 flag) { _specialFlags |= flag; }
|
void SetSpecialFlag(QuestSpecialFlags flag) { _specialFlags |= flag; }
|
||||||
|
|
||||||
|
// Possibly deprecated flag
|
||||||
|
bool IsUnavailable() const { return HasFlag(QUEST_FLAGS_DEPRECATED); }
|
||||||
|
|
||||||
// whether the quest is globally enabled (spawned by pool, game event active etc.)
|
// whether the quest is globally enabled (spawned by pool, game event active etc.)
|
||||||
static bool IsTakingQuestEnabled(uint32 questId);
|
static bool IsTakingQuestEnabled(uint32 questId);
|
||||||
|
|
||||||
// table data accessors:
|
// table data accessors:
|
||||||
uint32 GetQuestId() const { return _id; }
|
uint32 GetQuestId() const { return _id; }
|
||||||
uint32 GetQuestMethod() const { return _method; }
|
uint32 GetQuestType() const { return _type; }
|
||||||
int32 GetZoneOrSort() const { return _zoneOrSort; }
|
int32 GetZoneOrSort() const { return _zoneOrSort; }
|
||||||
uint32 GetMinLevel() const { return _minLevel; }
|
uint32 GetMinLevel() const { return _minLevel; }
|
||||||
uint32 GetMaxLevel() const { return _maxLevel; }
|
uint32 GetMaxLevel() const { return _maxLevel; }
|
||||||
int32 GetQuestLevel() const { return _level; }
|
int32 GetQuestLevel() const { return _level; }
|
||||||
uint32 GetType() const { return _type; }
|
uint32 GetQuestInfoId() const { return _questInfoId; }
|
||||||
uint32 GetAllowableClasses() const { return _allowableClasses; }
|
uint32 GetAllowableClasses() const { return _allowableClasses; }
|
||||||
uint32 GetAllowableRaces() const { return _allowableRaces; }
|
uint32 GetAllowableRaces() const { return _allowableRaces; }
|
||||||
uint32 GetRequiredSkill() const { return _requiredSkillId; }
|
uint32 GetRequiredSkill() const { return _requiredSkillId; }
|
||||||
@@ -312,9 +315,9 @@ class TC_GAME_API Quest
|
|||||||
uint32 GetSoundTurnIn() const { return _soundTurnIn; }
|
uint32 GetSoundTurnIn() const { return _soundTurnIn; }
|
||||||
uint32 GetIncompleteEmote() const { return _emoteOnIncomplete; }
|
uint32 GetIncompleteEmote() const { return _emoteOnIncomplete; }
|
||||||
uint32 GetCompleteEmote() const { return _emoteOnComplete; }
|
uint32 GetCompleteEmote() const { return _emoteOnComplete; }
|
||||||
bool IsRepeatable() const { return _specialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE; }
|
bool IsRepeatable() const { return _specialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE; }
|
||||||
bool IsAutoAccept() const;
|
bool IsAutoAccept() const;
|
||||||
bool IsAutoComplete() const;
|
bool IsTurnIn() const;
|
||||||
uint32 GetFlags() const { return _flags; }
|
uint32 GetFlags() const { return _flags; }
|
||||||
uint32 GetSpecialFlags() const { return _specialFlags; }
|
uint32 GetSpecialFlags() const { return _specialFlags; }
|
||||||
uint32 GetMinimapTargetMark() const { return _minimapTargetMark; }
|
uint32 GetMinimapTargetMark() const { return _minimapTargetMark; }
|
||||||
@@ -323,17 +326,18 @@ class TC_GAME_API Quest
|
|||||||
uint32 GetRewardReputationMask() const { return _rewardReputationMask; }
|
uint32 GetRewardReputationMask() const { return _rewardReputationMask; }
|
||||||
uint32 GetQuestGiverPortrait() const { return _questGiverPortrait; }
|
uint32 GetQuestGiverPortrait() const { return _questGiverPortrait; }
|
||||||
uint32 GetQuestTurnInPortrait() const { return _questTurnInPortrait; }
|
uint32 GetQuestTurnInPortrait() const { return _questTurnInPortrait; }
|
||||||
bool IsDaily() const { return (_flags & QUEST_FLAGS_DAILY) != 0; }
|
bool IsDaily() const { return (_flags & QUEST_FLAGS_DAILY) != 0; }
|
||||||
bool IsWeekly() const { return (_flags & QUEST_FLAGS_WEEKLY) != 0; }
|
bool IsWeekly() const { return (_flags & QUEST_FLAGS_WEEKLY) != 0; }
|
||||||
bool IsMonthly() const { return (_specialFlags & QUEST_SPECIAL_FLAGS_MONTHLY) != 0; }
|
bool IsMonthly() const { return (_specialFlags & QUEST_SPECIAL_FLAGS_MONTHLY) != 0; }
|
||||||
bool IsSeasonal() const { return (_zoneOrSort == -QUEST_SORT_SEASONAL || _zoneOrSort == -QUEST_SORT_SPECIAL || _zoneOrSort == -QUEST_SORT_LUNAR_FESTIVAL || _zoneOrSort == -QUEST_SORT_MIDSUMMER || _zoneOrSort == -QUEST_SORT_BREWFEST || _zoneOrSort == -QUEST_SORT_LOVE_IS_IN_THE_AIR || _zoneOrSort == -QUEST_SORT_NOBLEGARDEN) && !IsRepeatable(); }
|
bool IsSeasonal() const { return (_zoneOrSort == -QUEST_SORT_SEASONAL || _zoneOrSort == -QUEST_SORT_SPECIAL || _zoneOrSort == -QUEST_SORT_LUNAR_FESTIVAL || _zoneOrSort == -QUEST_SORT_MIDSUMMER || _zoneOrSort == -QUEST_SORT_BREWFEST || _zoneOrSort == -QUEST_SORT_LOVE_IS_IN_THE_AIR || _zoneOrSort == -QUEST_SORT_NOBLEGARDEN) && !IsRepeatable(); }
|
||||||
bool IsDailyOrWeekly() const { return (_flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY)) != 0; }
|
bool IsDailyOrWeekly() const { return (_flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY)) != 0; }
|
||||||
bool IsRaidQuest(Difficulty difficulty) const;
|
bool IsRaidQuest(Difficulty difficulty) const;
|
||||||
bool IsAllowedInRaid(Difficulty difficulty) const;
|
bool IsAllowedInRaid(Difficulty difficulty) const;
|
||||||
bool IsDFQuest() const { return (_specialFlags & QUEST_SPECIAL_FLAGS_DF_QUEST) != 0; }
|
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;
|
uint32 CalculateHonorGain(uint8 level) const;
|
||||||
bool CanIncreaseRewardedQuestCounters() const;
|
bool CanIncreaseRewardedQuestCounters() const;
|
||||||
bool IsStartAtAreaTrigger() const { return _startsAtAreaTrigger; }
|
bool IsStartAtAreaTrigger() const { return _startsAtAreaTrigger; }
|
||||||
|
|
||||||
// multiple values
|
// multiple values
|
||||||
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
|
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
|
||||||
@@ -395,11 +399,11 @@ class TC_GAME_API Quest
|
|||||||
|
|
||||||
// table data
|
// table data
|
||||||
uint32 _id = 0;
|
uint32 _id = 0;
|
||||||
uint32 _method = 0;
|
uint32 _type = 0;
|
||||||
int32 _zoneOrSort = 0;
|
int32 _zoneOrSort = 0;
|
||||||
uint32 _minLevel = 0;
|
uint32 _minLevel = 0;
|
||||||
int32 _level = 0;
|
int32 _level = 0;
|
||||||
uint32 _type = 0;
|
uint32 _questInfoId = 0;
|
||||||
uint32 _requiredFactionId1 = 0;
|
uint32 _requiredFactionId1 = 0;
|
||||||
int32 _requiredFactionValue1 = 0;
|
int32 _requiredFactionValue1 = 0;
|
||||||
uint32 _requiredFactionId2 = 0;
|
uint32 _requiredFactionId2 = 0;
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
|
|||||||
_worldPacket << int32(Info.RewardNextQuest);
|
_worldPacket << int32(Info.RewardNextQuest);
|
||||||
_worldPacket << uint32(Info.RewardXPDifficulty);
|
_worldPacket << uint32(Info.RewardXPDifficulty);
|
||||||
|
|
||||||
if ((Info.Flags & QUEST_FLAGS_HIDDEN_REWARDS) != 0)
|
if ((Info.Flags & QUEST_FLAGS_HIDE_REWARD) != 0)
|
||||||
_worldPacket << int32(0);
|
_worldPacket << int32(0);
|
||||||
else
|
else
|
||||||
_worldPacket << int32(Info.RewardMoney);
|
_worldPacket << int32(Info.RewardMoney);
|
||||||
@@ -339,7 +339,7 @@ WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
|
|||||||
_worldPacket << uint32(Info.PortraitGiver);
|
_worldPacket << uint32(Info.PortraitGiver);
|
||||||
_worldPacket << uint32(Info.PortraitTurnIn);
|
_worldPacket << uint32(Info.PortraitTurnIn);
|
||||||
|
|
||||||
if ((Info.Flags & QUEST_FLAGS_HIDDEN_REWARDS) != 0)
|
if ((Info.Flags & QUEST_FLAGS_HIDE_REWARD) != 0)
|
||||||
{
|
{
|
||||||
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
|
||||||
_worldPacket << int32(0) << uint32(0);
|
_worldPacket << int32(0) << uint32(0);
|
||||||
|
|||||||
@@ -609,6 +609,8 @@ void WorldSession::LogoutPlayer(bool save)
|
|||||||
///- Clear whisper whitelist
|
///- Clear whisper whitelist
|
||||||
_player->ClearWhisperWhiteList();
|
_player->ClearWhisperWhiteList();
|
||||||
|
|
||||||
|
_player->FailQuestsWithFlag(QUEST_FLAGS_FAIL_ON_LOGOUT);
|
||||||
|
|
||||||
///- empty buyback items and save the player in the database
|
///- 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)
|
// some save parts only correctly work in case player present in map/player_lists (pets, etc)
|
||||||
if (save)
|
if (save)
|
||||||
|
|||||||
@@ -4314,7 +4314,7 @@ void Spell::EffectQuestComplete(SpellEffIndex effIndex)
|
|||||||
uint16 logSlot = player->FindQuestSlot(questId);
|
uint16 logSlot = player->FindQuestSlot(questId);
|
||||||
if (logSlot < MAX_QUEST_LOG_SIZE)
|
if (logSlot < MAX_QUEST_LOG_SIZE)
|
||||||
player->AreaExploredOrEventHappens(questId);
|
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.
|
player->SetRewardedQuest(questId); // If so, set status to rewarded without broadcasting it to client.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1103,6 +1103,20 @@ bool SpellInfo::HasOnlyDamageEffects() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SpellInfo::HasTargetType(::Targets target) const
|
||||||
|
{
|
||||||
|
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
|
||||||
|
{
|
||||||
|
if (!Effects[i].IsEffect())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Effects[i].TargetA.GetTarget() == target || Effects[i].TargetB.GetTarget() == target)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool SpellInfo::CanBeInterrupted(Unit const* interruptTarget, bool ignoreImmunity /*= false*/) const
|
bool SpellInfo::CanBeInterrupted(Unit const* interruptTarget, bool ignoreImmunity /*= false*/) const
|
||||||
{
|
{
|
||||||
return HasAttribute(SPELL_ATTR7_CAN_ALWAYS_BE_INTERRUPTED)
|
return HasAttribute(SPELL_ATTR7_CAN_ALWAYS_BE_INTERRUPTED)
|
||||||
|
|||||||
@@ -474,6 +474,7 @@ class TC_GAME_API SpellInfo
|
|||||||
bool HasAura(AuraType aura) const;
|
bool HasAura(AuraType aura) const;
|
||||||
bool HasAreaAuraEffect() const;
|
bool HasAreaAuraEffect() const;
|
||||||
bool HasOnlyDamageEffects() const;
|
bool HasOnlyDamageEffects() const;
|
||||||
|
bool HasTargetType(::Targets target) const;
|
||||||
|
|
||||||
inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); }
|
inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); }
|
||||||
inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); }
|
inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); }
|
||||||
|
|||||||
Reference in new issue
Block a user