diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 76 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 5 | ||||
| -rw-r--r-- | src/server/game/Handlers/QuestHandler.cpp | 113 | ||||
| -rw-r--r-- | src/server/game/Quests/QuestDef.h | 58 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/QuestPackets.cpp | 5 | ||||
| -rw-r--r-- | src/server/game/Server/Packets/QuestPackets.h | 1 |
6 files changed, 190 insertions, 68 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 150693ce2e8..2fb445583cc 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -15035,7 +15035,7 @@ bool Player::CanSeeStartQuest(Quest const* quest) SatisfyQuestSkill(quest, false) && SatisfyQuestExclusiveGroup(quest, false) && SatisfyQuestReputation(quest, false) && SatisfyQuestDependentQuests(quest, false) && SatisfyQuestDay(quest, false) && SatisfyQuestWeek(quest, false) && - SatisfyQuestMonth(quest, false) && SatisfyQuestSeasonal(quest, false)) + SatisfyQuestMonth(quest, false) && SatisfyQuestSeasonal(quest, false) && SatisfyQuestExpansion(quest, false)) { return int32(getLevel() + sWorld->getIntConfig(CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF)) >= GetQuestMinLevel(quest); } @@ -15052,7 +15052,7 @@ bool Player::CanTakeQuest(Quest const* quest, bool msg) && SatisfyQuestDependentQuests(quest, msg) && SatisfyQuestTimed(quest, msg) && SatisfyQuestDay(quest, msg) && SatisfyQuestWeek(quest, msg) && SatisfyQuestMonth(quest, msg) && SatisfyQuestSeasonal(quest, msg) - && SatisfyQuestConditions(quest, msg); + && SatisfyQuestConditions(quest, msg) && SatisfyQuestExpansion(quest, msg); } bool Player::CanAddQuest(Quest const* quest, bool msg) const @@ -15903,23 +15903,32 @@ bool Player::SatisfyQuestSkill(Quest const* qInfo, bool msg) const bool Player::SatisfyQuestLevel(Quest const* qInfo, bool msg) const { + return SatisfyQuestMinLevel(qInfo, msg) && SatisfyQuestMaxLevel(qInfo, msg); +} + +bool Player::SatisfyQuestMinLevel(Quest const* qInfo, bool msg) const +{ if (getLevel() < GetQuestMinLevel(qInfo)) { if (msg) { SendCanTakeQuestResponse(QUEST_ERR_FAILED_LOW_LEVEL); - TC_LOG_DEBUG("misc", "Player::SatisfyQuestLevel: Sent QUEST_ERR_FAILED_LOW_LEVEL (QuestID: %u) because player '%s' (%s) doesn't have the required (min) level.", + TC_LOG_DEBUG("misc", "Player::SatisfyQuestMinLevel: Sent QUEST_ERR_FAILED_LOW_LEVEL (QuestID: %u) because player '%s' (%s) doesn't have the required (min) level.", qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str()); } return false; } + return true; +} +bool Player::SatisfyQuestMaxLevel(Quest const* qInfo, bool msg) const +{ if (qInfo->GetMaxLevel() > 0 && getLevel() > qInfo->GetMaxLevel()) { if (msg) { SendCanTakeQuestResponse(QUEST_ERR_NONE); // There doesn't seem to be a specific response for too high player level - TC_LOG_DEBUG("misc", "Player::SatisfyQuestLevel: Sent QUEST_ERR_FAILED_LOW_LEVEL (QuestID: %u) because player '%s' (%s) doesn't have the required (max) level.", + TC_LOG_DEBUG("misc", "Player::SatisfyQuestMaxLevel: Sent QUEST_ERR_FAILED_LOW_LEVEL (QuestID: %u) because player '%s' (%s) doesn't have the required (max) level.", qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str()); } return false; @@ -16095,20 +16104,6 @@ bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg) return false; } - /** @todo 6.x investigate if it's still needed - // ReputationObjective2 does not seem to be an objective requirement but a requirement - // to be able to accept the quest - uint32 fIdObj = qInfo->GetRepObjectiveFaction2(); - if (fIdObj && GetReputationMgr().GetReputation(fIdObj) >= qInfo->GetRepObjectiveValue2()) - { - if (msg) - { - SendCanTakeQuestResponse(QUEST_ERR_NONE); - TC_LOG_DEBUG("misc", "SatisfyQuestReputation: Sent QUEST_ERR_NONE (questId: %u) because player does not have required reputation (ReputationObjective2).", qInfo->GetQuestId()); - } - return false; - }**/ - return true; } @@ -16252,6 +16247,20 @@ bool Player::SatisfyQuestSeasonal(Quest const* qInfo, bool /*msg*/) const return itr->second.find(qInfo->GetQuestId()) == itr->second.end(); } +bool Player::SatisfyQuestExpansion(Quest const* qInfo, bool msg) const +{ + if (GetSession()->GetExpansion() < qInfo->GetExpansion()) + { + if (msg) + SendCanTakeQuestResponse(QUEST_ERR_FAILED_EXPANSION); + + TC_LOG_DEBUG("misc", "Player::SatisfyQuestExpansion: Sent QUEST_ERR_FAILED_EXPANSION (QuestID: %u) because player '%s' (%s) does not have required expansion.", + qInfo->GetQuestId(), GetName().c_str(), GetGUID().ToString().c_str()); + return false; + } + return true; +} + bool Player::SatisfyQuestMonth(Quest const* qInfo, bool /*msg*/) const { if (!qInfo->IsMonthly() || m_monthlyquests.empty()) @@ -16368,17 +16377,7 @@ bool Player::CanShareQuest(uint32 quest_id) const if (qInfo && qInfo->HasFlag(QUEST_FLAGS_SHARABLE)) { QuestStatusMap::const_iterator itr = m_QuestStatus.find(quest_id); - if (itr != m_QuestStatus.end()) - { - // in pool and not currently available (wintergrasp weekly, dalaran weekly) - can't share - if (sPoolMgr->IsPartOfAPool<Quest>(quest_id) && !sPoolMgr->IsSpawnedObject<Quest>(quest_id)) - { - SendPushToPartyResponse(this, QUEST_PUSH_NOT_DAILY); - return false; - } - - return true; - } + return (itr != m_QuestStatus.end()); } return false; } @@ -17365,14 +17364,23 @@ void Player::SendQuestConfirmAccept(Quest const* quest, Player* receiver) const receiver->SendDirectMessage(packet.Write()); } -void Player::SendPushToPartyResponse(Player const* player, QuestPushReason reason) const +void Player::SendPushToPartyResponse(Player const* player, QuestPushReason reason, Quest const* quest /*= nullptr*/) const { if (player) { - WorldPackets::Quest::QuestPushResultResponse data; - data.SenderGUID = player->GetGUID(); - data.Result = reason; // valid values: 0-13 - SendDirectMessage(data.Write()); + WorldPackets::Quest::QuestPushResultResponse response; + response.SenderGUID = player->GetGUID(); + response.Result = AsUnderlyingType(reason); + if (quest) + { + response.QuestTitle = quest->GetLogTitle(); + LocaleConstant localeConstant = GetSession()->GetSessionDbLocaleIndex(); + if (localeConstant != LOCALE_enUS) + if (QuestTemplateLocale const* questTemplateLocale = sObjectMgr->GetQuestLocale(quest->GetQuestId())) + ObjectMgr::GetLocaleString(questTemplateLocale->LogTitle, localeConstant, response.QuestTitle); + } + + SendDirectMessage(response.Write()); } } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 988e350e8ba..252cb202ffc 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1512,6 +1512,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void FailQuest(uint32 quest_id); bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const; bool SatisfyQuestLevel(Quest const* qInfo, bool msg) const; + bool SatisfyQuestMinLevel(Quest const* qInfo, bool msg) const; + bool SatisfyQuestMaxLevel(Quest const* qInfo, bool msg) const; bool SatisfyQuestLog(bool msg) const; bool SatisfyQuestDependentQuests(Quest const* qInfo, bool msg) const; bool SatisfyQuestPreviousQuest(Quest const* qInfo, bool msg) const; @@ -1527,6 +1529,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> bool SatisfyQuestWeek(Quest const* qInfo, bool msg) const; bool SatisfyQuestMonth(Quest const* qInfo, bool msg) const; bool SatisfyQuestSeasonal(Quest const* qInfo, bool msg) const; + bool SatisfyQuestExpansion(Quest const* qInfo, bool msg) const; bool GiveQuestSourceItem(Quest const* quest); bool TakeQuestSourceItem(uint32 questId, bool msg); bool GetQuestRewardStatus(uint32 quest_id) const; @@ -1596,7 +1599,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void SendQuestTimerFailed(uint32 questID) const; void SendCanTakeQuestResponse(QuestFailedReason reason, bool sendErrorMessage = true, std::string reasonText = "") const; void SendQuestConfirmAccept(Quest const* quest, Player* receiver) const; - void SendPushToPartyResponse(Player const* player, QuestPushReason reason) const; + void SendPushToPartyResponse(Player const* player, QuestPushReason reason, Quest const* quest = nullptr) const; void SendQuestUpdateAddCredit(Quest const* quest, ObjectGuid guid, QuestObjective const& obj, uint16 count) const; void SendQuestUpdateAddCreditSimple(QuestObjective const& obj) const; void SendQuestUpdateAddPlayer(Quest const* quest, uint16 newCount) const; diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index 7e0d4832523..9018c4dd0ab 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -30,6 +30,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" +#include "PoolMgr.h" #include "QuestDef.h" #include "QuestPackets.h" #include "ReputationMgr.h" @@ -165,7 +166,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPackets::Quest::QuestG Player* player = ObjectAccessor::FindPlayer(_player->GetPlayerSharingQuest()); if (player) { - player->SendPushToPartyResponse(_player, QUEST_PUSH_ACCEPTED); + player->SendPushToPartyResponse(_player, QuestPushReason::Accepted); _player->ClearQuestSharingInfo(); } } @@ -624,19 +625,29 @@ void WorldSession::HandleQuestgiverCloseQuest(WorldPackets::Quest::QuestGiverClo void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty& packet) { - if (!_player->CanShareQuest(packet.QuestID)) - return; - Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestID); if (!quest) return; - Player * const sender = GetPlayer(); + Player* const sender = GetPlayer(); + + if (!_player->CanShareQuest(packet.QuestID)) + { + sender->SendPushToPartyResponse(sender, QuestPushReason::NotAllowed); + return; + } + + // in pool and not currently available (wintergrasp weekly, dalaran weekly) - can't share + if (sPoolMgr->IsPartOfAPool<Quest>(packet.QuestID) && !sPoolMgr->IsSpawnedObject<Quest>(packet.QuestID)) + { + sender->SendPushToPartyResponse(sender, QuestPushReason::NotDaily); + return; + } Group* group = sender->GetGroup(); if (!group) { - sender->SendPushToPartyResponse(sender, QUEST_PUSH_NOT_IN_PARTY); + sender->SendPushToPartyResponse(sender, QuestPushReason::NotInParty); return; } @@ -647,43 +658,109 @@ void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty& if (!receiver || receiver == sender) continue; - if (!receiver->SatisfyQuestStatus(quest, false)) + if (!receiver->GetPlayerSharingQuest().IsEmpty()) { - sender->SendPushToPartyResponse(receiver, QUEST_PUSH_ONQUEST); + sender->SendPushToPartyResponse(receiver, QuestPushReason::Busy); continue; } - if (receiver->GetQuestStatus(packet.QuestID) == QUEST_STATUS_COMPLETE) + if (!receiver->IsAlive()) { - sender->SendPushToPartyResponse(receiver, QUEST_PUSH_ALREADY_DONE); + sender->SendPushToPartyResponse(receiver, QuestPushReason::Dead); + receiver->SendPushToPartyResponse(sender, QuestPushReason::DeadToRecipient, quest); + continue; + } + + switch (receiver->GetQuestStatus(packet.QuestID)) + { + case QUEST_STATUS_REWARDED: + { + sender->SendPushToPartyResponse(receiver, QuestPushReason::AlreadyDone); + receiver->SendPushToPartyResponse(sender, QuestPushReason::AlreadyDoneToRecipient, quest); + continue; + } + case QUEST_STATUS_INCOMPLETE: + case QUEST_STATUS_COMPLETE: + { + sender->SendPushToPartyResponse(receiver, QuestPushReason::OnQuest); + receiver->SendPushToPartyResponse(sender, QuestPushReason::OnQuestToRecipient, quest); + continue; + } + default: + break; + } + + if (!receiver->SatisfyQuestLog(false)) + { + sender->SendPushToPartyResponse(receiver, QuestPushReason::LogFull); + receiver->SendPushToPartyResponse(sender, QuestPushReason::LogFullToRecipient, quest); continue; } if (!receiver->SatisfyQuestDay(quest, false)) { - sender->SendPushToPartyResponse(receiver, QUEST_PUSH_DIFFERENT_SERVER_DAILY); + sender->SendPushToPartyResponse(receiver, QuestPushReason::AlreadyDone); + receiver->SendPushToPartyResponse(sender, QuestPushReason::AlreadyDoneToRecipient, quest); continue; } - if (!receiver->CanTakeQuest(quest, false)) + if (!receiver->SatisfyQuestMinLevel(quest, false)) { - sender->SendPushToPartyResponse(receiver, QUEST_PUSH_INVALID); + sender->SendPushToPartyResponse(receiver, QuestPushReason::LowLevel); + receiver->SendPushToPartyResponse(sender, QuestPushReason::LowLevelToRecipient, quest); continue; } - if (!receiver->SatisfyQuestLog(false)) + if (!receiver->SatisfyQuestMaxLevel(quest, false)) { - sender->SendPushToPartyResponse(receiver, QUEST_PUSH_LOG_FULL); + sender->SendPushToPartyResponse(receiver, QuestPushReason::HighLevel); + receiver->SendPushToPartyResponse(sender, QuestPushReason::HighLevelToRecipient, quest); continue; } - if (!receiver->GetPlayerSharingQuest().IsEmpty()) + if (!receiver->SatisfyQuestClass(quest, false)) + { + sender->SendPushToPartyResponse(receiver, QuestPushReason::Class); + receiver->SendPushToPartyResponse(sender, QuestPushReason::ClassToRecipient, quest); + continue; + } + + if (!receiver->SatisfyQuestRace(quest, false)) + { + sender->SendPushToPartyResponse(receiver, QuestPushReason::Race); + receiver->SendPushToPartyResponse(sender, QuestPushReason::RaceToRecipient, quest); + continue; + } + + if (!receiver->SatisfyQuestReputation(quest, false)) + { + sender->SendPushToPartyResponse(receiver, QuestPushReason::LowFaction); + receiver->SendPushToPartyResponse(sender, QuestPushReason::LowFactionToRecipient, quest); + continue; + } + + if (!receiver->SatisfyQuestDependentQuests(quest, false)) + { + sender->SendPushToPartyResponse(receiver, QuestPushReason::Prerequisite); + receiver->SendPushToPartyResponse(sender, QuestPushReason::PrerequisiteToRecipient, quest); + continue; + } + + if (!receiver->SatisfyQuestExpansion(quest, false)) + { + sender->SendPushToPartyResponse(receiver, QuestPushReason::Expansion); + receiver->SendPushToPartyResponse(sender, QuestPushReason::ExpansionToRecipient, quest); + continue; + } + + if (!receiver->CanTakeQuest(quest, false)) { - sender->SendPushToPartyResponse(receiver, QUEST_PUSH_BUSY); + sender->SendPushToPartyResponse(receiver, QuestPushReason::Invalid); + receiver->SendPushToPartyResponse(sender, QuestPushReason::InvalidToRecipient, quest); continue; } - sender->SendPushToPartyResponse(receiver, QUEST_PUSH_SUCCESS); + sender->SendPushToPartyResponse(receiver, QuestPushReason::Success); if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true)) receiver->AddQuestAndCheckCompletion(quest, sender); diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 9cf40a4da89..3b0c541b3a8 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -68,22 +68,50 @@ enum QuestFailedReason QUEST_ERR_HAS_IN_PROGRESS = 30 // "Progress Bar objective not completed" }; -enum QuestPushReason : uint8 +enum class QuestPushReason : uint8 { - QUEST_PUSH_SUCCESS = 0, // "Sharing quest with %s..." - QUEST_PUSH_INVALID = 1, // "%s is not eligible for that quest" - QUEST_PUSH_ACCEPTED = 2, // "%s has accepted your quest" - QUEST_PUSH_DECLINED = 3, // "%s has declined your quest" - QUEST_PUSH_BUSY = 4, // "%s is busy" - QUEST_PUSH_DEAD = 5, // "%s is dead." - QUEST_PUSH_LOG_FULL = 6, // "%s's quest log is full" - QUEST_PUSH_ONQUEST = 7, // "%s is already on that quest" - QUEST_PUSH_ALREADY_DONE = 8, // "%s has completed that quest" - QUEST_PUSH_NOT_DAILY = 9, // "That quest cannot be shared today" - QUEST_PUSH_TIMER_EXPIRED = 10, // "Quest sharing timer has expired" - QUEST_PUSH_NOT_IN_PARTY = 11, // "You are not in a party" - QUEST_PUSH_DIFFERENT_SERVER_DAILY = 12, // "%s is not eligible for that quest today" - QUEST_PUSH_NOT_ALLOWED = 13 // "That quest cannot be shared" + Success = 0, // "Sharing quest with %s..." + Invalid = 1, // "%s is not eligible for that quest" + InvalidToRecipient = 2, // "%s's attempt to share quest "%s" failed. You are not eligible for that quest." + Accepted = 3, // "%s has accepted your quest" + Declined = 4, // "%s has declined your quest" + Busy = 5, // "%s is busy" + Dead = 6, // "%s is dead." + DeadToRecipient = 7, // "%s's attempt to share quest "%s" failed. You are dead." + LogFull = 8, // "%s's quest log is full" + LogFullToRecipient = 9, // "%s's attempt to share quest "%s" failed. Your quest log is full." + OnQuest = 10, // "%s is already on that quest" + OnQuestToRecipient = 11, // "%s's attempt to share quest "%s" failed. You are already on that quest." + AlreadyDone = 12, // "%s has completed that quest" + AlreadyDoneToRecipient = 13, // "%s's attempt to share quest "%s" failed. You have completed that quest." + NotDaily = 14, // "That quest cannot be shared today" + TimerExpired = 15, // "Quest sharing timer has expired" + NotInParty = 16, // "You are not in a party" + DifferentServerDaily = 17, // "%s is not eligible for that quest today" + DifferentServerDailyToRecipient = 18, // "%s's attempt to share quest "%s" failed. You are not eligible for that quest today." + NotAllowed = 19, // "That quest cannot be shared" + Prerequisite = 20, // "%s hasn't completed all of the prerequisite quests required for that quest." + PrerequisiteToRecipient = 21, // "%s's attempt to share quest "%s" failed. You must complete all of the prerequisite quests first." + LowLevel = 22, // "%s is too low level for that quest." + LowLevelToRecipient = 23, // "%s's attempt to share quest "%s" failed. You are too low level for that quest." + HighLevel = 24, // "%s is too high level for that quest." + HighLevelToRecipient = 25, // "%s's attempt to share quest "%s" failed. You are too high level for that quest." + Class = 26, // "%s is the wrong class for that quest." + ClassToRecipient = 27, // "%s's attempt to share quest "%s" failed. You are the wrong class for that quest." + Race = 28, // "%s is the wrong race for that quest." + RaceToRecipient = 29, // "%s's attempt to share quest "%s" failed. You are the wrong race for that quest." + LowFaction = 30, // "%s's reputation is too low for that quest." + LowFactionToRecipient = 31, // "%s's attempt to share quest "%s" failed. Your reputation is too low for that quest." + Expansion = 32, // "%s doesn't own the required expansion for that quest." + ExpansionToRecipient = 33, // "%s's attempt to share quest "%s" failed. You do not own the required expansion for that quest." + NotGarrisonOwner = 34, // "%s must own a garrison to accept that quest." + NotGarrisonOwnerToRecipient = 35, // "%s's attempt to share quest "%s" failed. You must own a garrison to accept that quest." + WrongCovenant = 36, // "%s is in the wrong covenant for that quest." + WrongCovenantToRecipient = 37, // "%s's attempt to share quest "%s" failed. You are in the wrong covenant for that quest." + NewPlayerExperience = 38, // "%s must complete Exile's Reach to accept that quest." + NewPlayerExperienceToRecipient = 39, // "%s's attempt to share quest "%s" failed. You must complete Exile's Reach to accept that quest." + WrongFaction = 40, // "%s is the wrong faction for that quest." + WrongFactionToRecipient = 41 // "%s's attempt to share quest "%s" failed. You are the wrong faction for that quest." }; enum QuestTradeSkill diff --git a/src/server/game/Server/Packets/QuestPackets.cpp b/src/server/game/Server/Packets/QuestPackets.cpp index d15eed8dc0d..f012b071713 100644 --- a/src/server/game/Server/Packets/QuestPackets.cpp +++ b/src/server/game/Server/Packets/QuestPackets.cpp @@ -569,6 +569,11 @@ WorldPacket const* QuestPushResultResponse::Write() _worldPacket << SenderGUID; _worldPacket << uint8(Result); + _worldPacket.WriteBits(QuestTitle.size(), 9); + _worldPacket.FlushBits(); + + _worldPacket.WriteString(QuestTitle); + return &_worldPacket; } diff --git a/src/server/game/Server/Packets/QuestPackets.h b/src/server/game/Server/Packets/QuestPackets.h index 1b049cc0703..22d5d79acc7 100644 --- a/src/server/game/Server/Packets/QuestPackets.h +++ b/src/server/game/Server/Packets/QuestPackets.h @@ -545,6 +545,7 @@ namespace WorldPackets ObjectGuid SenderGUID; uint8 Result = 0; + std::string QuestTitle; }; class QuestLogFull final : public ServerPacket |
