Core/PacketIO: Updated SMSG_QUEST_PUSH_RESPONSE to 9.1.5

This commit is contained in:
Shauren
2021-11-02 22:51:05 +01:00
parent 78e627e413
commit 122fe7549d
6 changed files with 197 additions and 75 deletions

View File

@@ -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
@@ -15902,24 +15902,33 @@ 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());
}
}

View File

@@ -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;

View File

@@ -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->SatisfyQuestMinLevel(quest, false))
{
sender->SendPushToPartyResponse(receiver, QuestPushReason::LowLevel);
receiver->SendPushToPartyResponse(sender, QuestPushReason::LowLevelToRecipient, quest);
continue;
}
if (!receiver->SatisfyQuestMaxLevel(quest, false))
{
sender->SendPushToPartyResponse(receiver, QuestPushReason::HighLevel);
receiver->SendPushToPartyResponse(sender, QuestPushReason::HighLevelToRecipient, quest);
continue;
}
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_INVALID);
sender->SendPushToPartyResponse(receiver, QuestPushReason::Invalid);
receiver->SendPushToPartyResponse(sender, QuestPushReason::InvalidToRecipient, quest);
continue;
}
if (!receiver->SatisfyQuestLog(false))
{
sender->SendPushToPartyResponse(receiver, QUEST_PUSH_LOG_FULL);
continue;
}
if (!receiver->GetPlayerSharingQuest().IsEmpty())
{
sender->SendPushToPartyResponse(receiver, QUEST_PUSH_BUSY);
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);

View File

@@ -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

View File

@@ -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;
}

View File

@@ -545,6 +545,7 @@ namespace WorldPackets
ObjectGuid SenderGUID;
uint8 Result = 0;
std::string QuestTitle;
};
class QuestLogFull final : public ServerPacket