aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
authorjoschiwald <joschiwald.trinity@gmail.com>2014-02-06 21:23:18 +0100
committerjoschiwald <joschiwald.trinity@gmail.com>2014-02-06 21:23:18 +0100
commitb000fdca70547a3e1963292e39ff9ebb596e099a (patch)
treeb5cdd9faaee7a8a41c5f2b02ae2fe7274d932dcc /src/server/game/Entities
parent59e14b2b9b2bd545d0ade660a973374829905e67 (diff)
Core/Entities: allow interaction with gameobject questgivers if player can take or return quests
Closes #11269 Closes #8898 Closes #10204 Closes #11410 Closes #7053 Closes #6189 Closes #9474
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp14
-rw-r--r--src/server/game/Entities/Player/Player.cpp163
-rw-r--r--src/server/game/Entities/Player/Player.h8
3 files changed, 158 insertions, 27 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index e326e0155c1..e3c8c9c8136 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -986,9 +986,17 @@ bool GameObject::ActivateToQuest(Player* target) const
switch (GetGoType())
{
- // scan GO chest with loot including quest items
+ case GAMEOBJECT_TYPE_QUESTGIVER:
+ {
+ GameObject* go = const_cast<GameObject*>(this);
+ QuestGiverStatus questStatus = target->GetQuestDialogStatus(go);
+ if (questStatus > DIALOG_STATUS_UNAVAILABLE)
+ return true;
+ break;
+ }
case GAMEOBJECT_TYPE_CHEST:
{
+ // scan GO chest with loot including quest items
if (LootTemplates_Gameobject.HaveQuestLootForPlayer(GetGOInfo()->GetLootId(), target))
{
if (Battleground const* bg = target->GetBattleground())
@@ -2148,6 +2156,10 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t
int16 pathProgress = -1;
switch (GetGoType())
{
+ case GAMEOBJECT_TYPE_QUESTGIVER:
+ if (ActivateToQuest(target))
+ dynFlags |= GO_DYNFLAG_LO_ACTIVATE;
+ break;
case GAMEOBJECT_TYPE_CHEST:
case GAMEOBJECT_TYPE_GOOBER:
if (ActivateToQuest(target))
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 603a4654697..09a0d033c68 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -15034,7 +15034,7 @@ void Player::AddQuestAndCheckCompletion(Quest const* quest, Object* questGiver)
switch (questGiver->GetTypeId())
{
case TYPEID_UNIT:
- sScriptMgr->OnQuestAccept(this, (questGiver->ToCreature()), quest);
+ sScriptMgr->OnQuestAccept(this, questGiver->ToCreature(), quest);
questGiver->ToCreature()->AI()->sQuestAccept(this, quest);
break;
case TYPEID_ITEM:
@@ -15177,7 +15177,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest_id);
- UpdateForQuestWorldObjects();
+ SendQuestUpdate(quest_id);
}
void Player::CompleteQuest(uint32 quest_id)
@@ -15343,7 +15343,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
else if (quest->IsSeasonal())
SetSeasonalQuestStatus(quest_id);
- RemoveActiveQuest(quest_id);
+ RemoveActiveQuest(quest_id, false);
m_RewardedQuests.insert(quest_id);
m_RewardedQuestsSave[quest_id] = true;
@@ -15391,6 +15391,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
UpdatePvPState();
}
+ SendQuestUpdate(quest_id);
+
//lets remove flag for delayed teleports
SetCanDelayTeleport(false);
}
@@ -15984,17 +15986,49 @@ bool Player::CanShareQuest(uint32 quest_id) const
return false;
}
-void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
+void Player::SetQuestStatus(uint32 questId, QuestStatus status, bool update /*= true*/)
+{
+ if (sObjectMgr->GetQuestTemplate(questId))
+ {
+ m_QuestStatus[questId].Status = status;
+ m_QuestStatusSave[questId] = true;
+ }
+
+ if (update)
+ SendQuestUpdate(questId);
+}
+
+void Player::RemoveActiveQuest(uint32 questId, bool update /*= true*/)
+{
+ QuestStatusMap::iterator itr = m_QuestStatus.find(questId);
+ if (itr != m_QuestStatus.end())
+ {
+ m_QuestStatus.erase(itr);
+ m_QuestStatusSave[questId] = false;
+ }
+
+ if (update)
+ SendQuestUpdate(questId);
+}
+
+void Player::RemoveRewardedQuest(uint32 questId, bool update /*= true*/)
{
- if (sObjectMgr->GetQuestTemplate(quest_id))
+ RewardedQuestSet::iterator rewItr = m_RewardedQuests.find(questId);
+ if (rewItr != m_RewardedQuests.end())
{
- m_QuestStatus[quest_id].Status = status;
- m_QuestStatusSave[quest_id] = true;
+ m_RewardedQuests.erase(rewItr);
+ m_RewardedQuestsSave[questId] = false;
}
+ if (update)
+ SendQuestUpdate(questId);
+}
+
+void Player::SendQuestUpdate(uint32 questId)
+{
uint32 zone = 0, area = 0;
- SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id);
+ SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(questId);
if (saBounds.first != saBounds.second)
{
GetZoneAndAreaId(zone, area);
@@ -16005,7 +16039,7 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
CastSpell(this, itr->second->spellId, true);
}
- saBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id);
+ saBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(questId);
if (saBounds.first != saBounds.second)
{
if (!zone || !area)
@@ -16019,25 +16053,108 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
UpdateForQuestWorldObjects();
}
-void Player::RemoveActiveQuest(uint32 quest_id)
+QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
{
- QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id);
- if (itr != m_QuestStatus.end())
+ QuestRelationBounds qr;
+ QuestRelationBounds qir;
+
+ switch (questgiver->GetTypeId())
{
- m_QuestStatus.erase(itr);
- m_QuestStatusSave[quest_id] = false;
- return;
+ case TYPEID_GAMEOBJECT:
+ {
+ QuestGiverStatus questStatus = QuestGiverStatus(sScriptMgr->GetDialogStatus(this, questgiver->ToGameObject()));
+ if (questStatus != DIALOG_STATUS_SCRIPTED_NO_STATUS)
+ return questStatus;
+ qr = sObjectMgr->GetGOQuestRelationBounds(questgiver->GetEntry());
+ qir = sObjectMgr->GetGOQuestInvolvedRelationBounds(questgiver->GetEntry());
+ break;
+ }
+ case TYPEID_UNIT:
+ {
+ QuestGiverStatus questStatus = QuestGiverStatus(sScriptMgr->GetDialogStatus(this, questgiver->ToCreature()));
+ if (questStatus != DIALOG_STATUS_SCRIPTED_NO_STATUS)
+ return questStatus;
+ qr = sObjectMgr->GetCreatureQuestRelationBounds(questgiver->GetEntry());
+ qir = sObjectMgr->GetCreatureQuestInvolvedRelationBounds(questgiver->GetEntry());
+ break;
+ }
+ default:
+ // it's impossible, but check
+ TC_LOG_ERROR("entities.player.quest", "GetQuestDialogStatus called for unexpected type %u", questgiver->GetTypeId());
+ return DIALOG_STATUS_NONE;
}
-}
-void Player::RemoveRewardedQuest(uint32 quest_id)
-{
- RewardedQuestSet::iterator rewItr = m_RewardedQuests.find(quest_id);
- if (rewItr != m_RewardedQuests.end())
+ QuestGiverStatus result = DIALOG_STATUS_NONE;
+
+ for (QuestRelations::const_iterator i = qir.first; i != qir.second; ++i)
{
- m_RewardedQuests.erase(rewItr);
- m_RewardedQuestsSave[quest_id] = false;
+ QuestGiverStatus result2 = DIALOG_STATUS_NONE;
+ uint32 questId = i->second;
+ Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
+ if (!quest)
+ continue;
+
+ ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId());
+ if (!sConditionMgr->IsObjectMeetToConditions(this, conditions))
+ continue;
+
+ QuestStatus status = GetQuestStatus(questId);
+ if ((status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(questId)) ||
+ (quest->IsAutoComplete() && CanTakeQuest(quest, false)))
+ {
+ if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
+ result2 = DIALOG_STATUS_REWARD_REP;
+ else
+ result2 = DIALOG_STATUS_REWARD;
+ }
+ else if (status == QUEST_STATUS_INCOMPLETE)
+ result2 = DIALOG_STATUS_INCOMPLETE;
+
+ if (result2 > result)
+ result = result2;
+ }
+
+ for (QuestRelations::const_iterator i = qr.first; i != qr.second; ++i)
+ {
+ QuestGiverStatus result2 = DIALOG_STATUS_NONE;
+ uint32 questId = i->second;
+ Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
+ if (!quest)
+ continue;
+
+ ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK, quest->GetQuestId());
+ if (!sConditionMgr->IsObjectMeetToConditions(this, conditions))
+ continue;
+
+ QuestStatus status = GetQuestStatus(questId);
+ if (status == QUEST_STATUS_NONE)
+ {
+ if (CanSeeStartQuest(quest))
+ {
+ if (SatisfyQuestLevel(quest, false))
+ {
+ if (quest->IsAutoComplete())
+ result2 = DIALOG_STATUS_REWARD_REP;
+ else if (getLevel() <= (GetQuestLevel(quest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF)))
+ {
+ if (quest->IsDaily())
+ result2 = DIALOG_STATUS_AVAILABLE_REP;
+ else
+ result2 = DIALOG_STATUS_AVAILABLE;
+ }
+ else
+ result2 = DIALOG_STATUS_LOW_LEVEL_AVAILABLE;
+ }
+ else
+ result2 = DIALOG_STATUS_UNAVAILABLE;
+ }
+ }
+
+ if (result2 > result)
+ result = result2;
}
+
+ return result;
}
// not used in Trinity, but used in scripting code
@@ -23356,7 +23473,7 @@ void Player::UpdateForQuestWorldObjects()
UpdateData udata;
WorldPacket packet;
- for (ClientGUIDs::iterator itr=m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
+ for (ClientGUIDs::iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
{
if (IS_GAMEOBJECT_GUID(*itr))
{
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 5026489daff..2eb740f0a82 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1383,9 +1383,11 @@ class Player : public Unit, public GridObject<Player>
bool TakeQuestSourceItem(uint32 questId, bool msg);
bool GetQuestRewardStatus(uint32 quest_id) const;
QuestStatus GetQuestStatus(uint32 quest_id) const;
- void SetQuestStatus(uint32 quest_id, QuestStatus status);
- void RemoveActiveQuest(uint32 quest_id);
- void RemoveRewardedQuest(uint32 quest_id);
+ void SetQuestStatus(uint32 questId, QuestStatus status, bool update = true);
+ void RemoveActiveQuest(uint32 questId, bool update = true);
+ void RemoveRewardedQuest(uint32 questId, bool update = true);
+ void SendQuestUpdate(uint32 questId);
+ QuestGiverStatus GetQuestDialogStatus(Object* questGiver);
void SetDailyQuestStatus(uint32 quest_id);
void SetWeeklyQuestStatus(uint32 quest_id);