From 4f23fb3d29fc8f30bdcbf0c341fc5b25e731b1da Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sun, 28 Mar 2021 14:44:16 +0200 Subject: [PATCH] Core/Quests: make the player questgiver handling a bit more flexible to allow popup quest accepting at more places in the future --- .../game/AI/SmartScripts/SmartScript.cpp | 4 ++ src/server/game/Entities/Player/Player.cpp | 7 ++++ src/server/game/Entities/Player/Player.h | 5 +++ src/server/game/Handlers/QuestHandler.cpp | 37 ++++++++++++++++++- src/server/game/Spells/SpellEffects.cpp | 4 ++ 5 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 0bf3206864..497f49e73d 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -425,6 +425,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { if (pTarget->CanTakeQuest(q, true)) { + pTarget->SetPopupQuestId(0); pTarget->PlayerTalkClass->SendQuestGiverQuestDetails(q, pTarget->GetGUID(), true, false); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player guidLow %u - offered quest %u", pTarget->GetGUID().GetCounter(), e.action.questOffer.questID); @@ -434,7 +435,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { pTarget->AddQuestAndCheckCompletion(q, nullptr); if (q->IsAutoAccept()) + { + pTarget->SetPopupQuestId(0); pTarget->PlayerTalkClass->SendQuestGiverQuestDetails(q, pTarget->GetGUID(), true, true); + } TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_OFFER_QUEST: Player guidLow %u - quest %u added", pTarget->GetGUID().GetCounter(), e.action.questOffer.questID); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 8148e49a7b..8825b03100 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -155,6 +155,7 @@ Player::Player(WorldSession* session): Unit(true) m_ingametime = 0; m_sharedQuestId = 0; + m_popupQuestId = 0; m_ExtraFlags = 0; @@ -14258,7 +14259,10 @@ void Player::SendPreparedQuest(ObjectGuid guid) if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, CanCompleteRepeatableQuest(quest), true); else + { + SetPopupQuestId(0); PlayerTalkClass->SendQuestGiverQuestDetails(quest, guid, true, false); + } } } } @@ -23473,7 +23477,10 @@ void Player::SendInitialPacketsAfterAddToMap() if (GetPlayerSharingQuest()) { if (Quest const* quest = sObjectMgr->GetQuestTemplate(GetSharedQuestID())) + { + SetPopupQuestId(0); PlayerTalkClass->SendQuestGiverQuestDetails(quest, GetGUID(), true, false); + } else ClearQuestSharingInfo(); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1c8e2ab112..146b02ebeb 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1449,6 +1449,10 @@ class TC_GAME_API Player : public Unit, public GridObject void SetQuestSharingInfo(ObjectGuid guid, uint32 id) { m_playerSharingQuest = guid; m_sharedQuestId = id; } void ClearQuestSharingInfo() { m_playerSharingQuest = ObjectGuid::Empty; m_sharedQuestId = 0; } + // Returns the ID of the next available quest in chain of the most recently rewarded quest that has been rewarded via UI popup + uint32 GetPopupQuestId() const { return m_popupQuestId; } + void SetPopupQuestId(uint32 questId) { m_popupQuestId = questId; } + uint32 GetInGameTime() const { return m_ingametime; } void SetInGameTime(uint32 time) { m_ingametime = time; } @@ -2452,6 +2456,7 @@ class TC_GAME_API Player : public Unit, public GridObject ObjectGuid m_playerSharingQuest; uint32 m_sharedQuestId; + uint32 m_popupQuestId; uint32 m_ingametime; /*********************************************************/ diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index d8f1547c58..8df5870830 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -127,17 +127,35 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG if (Player* playerQuestObject = object->ToPlayer()) { - if ((!_player->GetPlayerSharingQuest().IsEmpty() && _player->GetPlayerSharingQuest() != packet.QuestGiverGUID) - || (_player != playerQuestObject && !playerQuestObject->CanShareQuest(packet.QuestID))) + // Various checks for player quest givers + if ((!_player->GetPlayerSharingQuest().IsEmpty() && _player->GetPlayerSharingQuest() != packet.QuestGiverGUID) // Player tries to accept a shared quest from a different questiver + || (_player != playerQuestObject && !playerQuestObject->CanShareQuest(packet.QuestID))) // Player tries to accept a quest that cannot be shared { CLOSE_GOSSIP_CLEAR_SHARING_INFO(); return; } + + // Player tries to accept a quest from a player questgiver that he is not in a party/raid with if (!_player->IsInSameRaidWith(playerQuestObject)) { CLOSE_GOSSIP_CLEAR_SHARING_INFO(); return; } + + // Player tries to accept a quest from himself that cannot be taken. Such quests must be provided by a quest with flag QUEST_FLAGS_AUTOCOMPLETE prior to that + if (_player->GetPopupQuestId()) + { + if (_player->GetPopupQuestId() != packet.QuestID || _player->GetGUID() != packet.QuestGiverGUID) + { + CLOSE_GOSSIP_CLEAR_SHARING_INFO(); + return; + } + } + else if (_player->GetGUID() == packet.QuestGiverGUID) // Covering all remaining poossible cheat scenarios when trying to exploit quest sharing + { + CLOSE_GOSSIP_CLEAR_SHARING_INFO(); + return; + } } else { @@ -207,6 +225,10 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG if (quest->GetSrcSpell() > 0) _player->CastSpell(_player, quest->GetSrcSpell(), true); + // A quest has been accepted, reset popup follow quest ID because the quest has either been taken or another took its place + // so the player has to take the follow quest at its corresponding creature questgiver instead. + _player->SetPopupQuestId(0); + return; } } @@ -239,7 +261,10 @@ void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPackets::Quest::QuestGi if (quest->IsAutoComplete()) _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, object->GetGUID(), _player->CanCompleteQuest(quest->GetQuestId()), true); else + { + _player->SetPopupQuestId(0); _player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, object->GetGUID(), true, false); + } } } @@ -307,6 +332,12 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest 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); } } @@ -327,6 +358,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPackets::Quest::Quest if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true)) _player->AddQuestAndCheckCompletion(nextQuest, object); + _player->SetPopupQuestId(0); _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, packet.QuestGiverGUID, true, false); } } @@ -614,6 +646,7 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true); else { + receiver->SetPopupQuestId(0); receiver->SetQuestSharingInfo(sender->GetGUID(), questId); receiver->PlayerTalkClass->SendQuestGiverQuestDetails(quest, receiver->GetGUID(), true, false); } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index f0abf5a705..72cf9cc5a0 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -5136,10 +5136,14 @@ void Spell::EffectQuestStart(SpellEffIndex effIndex) if (quest->IsAutoAccept() && player->CanAddQuest(quest, false)) { player->AddQuestAndCheckCompletion(quest, player); + player->SetPopupQuestId(0); player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, player->GetGUID(), true, true); } else + { + player->SetPopupQuestId(quest->GetQuestId()); player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, player->GetGUID(), true, false); + } } }