Core/Quests: Fixed showing quest objective completion clientside for objective types 10, 11, 12 and 14

This commit is contained in:
Shauren
2017-06-10 00:06:07 +02:00
parent 38baf3800b
commit 01fd7d7fe9
7 changed files with 89 additions and 35 deletions

View File

@@ -16215,7 +16215,7 @@ void Player::AdjustQuestReqItemCount(Quest const* quest)
uint32 reqItemCount = obj.Amount;
uint32 curItemCount = GetItemCount(obj.ObjectID, true);
SetQuestObjectiveData(quest, obj.StorageIndex, std::min(curItemCount, reqItemCount));
SetQuestObjectiveData(obj, std::min(curItemCount, reqItemCount));
}
}
}
@@ -16370,7 +16370,7 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count)
if (curItemCount < reqItemCount)
{
uint32 newItemCount = std::min<uint32>(curItemCount + count, reqItemCount);
SetQuestObjectiveData(qInfo, obj.StorageIndex, newItemCount);
SetQuestObjectiveData(obj, newItemCount);
//SendQuestUpdateAddItem(qInfo, j, additemcount);
// FIXME: verify if there's any packet sent updating item
@@ -16419,7 +16419,7 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count)
if (newItemCount < reqItemCount)
{
SetQuestObjectiveData(qInfo, obj.StorageIndex, newItemCount);
SetQuestObjectiveData(obj, newItemCount);
IncompleteQuest(questid);
}
return;
@@ -16485,7 +16485,7 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid /*= ObjectGuid::E
uint16 curKillCount = GetQuestObjectiveData(qInfo, obj.StorageIndex);
if (curKillCount < reqKillCount)
{
SetQuestObjectiveData(qInfo, obj.StorageIndex, curKillCount + addKillCount);
SetQuestObjectiveData(obj, curKillCount + addKillCount);
SendQuestUpdateAddCredit(qInfo, guid, obj, curKillCount + addKillCount);
}
@@ -16531,7 +16531,7 @@ void Player::KilledPlayerCredit()
uint32 curKillCount = GetQuestObjectiveData(qInfo, obj.StorageIndex);
if (curKillCount < uint32(obj.Amount))
{
SetQuestObjectiveData(qInfo, obj.StorageIndex, curKillCount + addKillCount);
SetQuestObjectiveData(obj, curKillCount + addKillCount);
SendQuestUpdateAddPlayer(qInfo, curKillCount + addKillCount);
}
@@ -16579,7 +16579,7 @@ void Player::KillCreditGO(uint32 entry, ObjectGuid guid)
uint32 curCastCount = GetQuestObjectiveData(qInfo, obj.StorageIndex);
if (curCastCount < reqCastCount)
{
SetQuestObjectiveData(qInfo, obj.StorageIndex, curCastCount + addCastCount);
SetQuestObjectiveData(obj, curCastCount + addCastCount);
SendQuestUpdateAddCredit(qInfo, guid, obj, curCastCount + addCastCount);
}
@@ -16626,7 +16626,7 @@ void Player::TalkedToCreature(uint32 entry, ObjectGuid guid)
uint32 curTalkCount = GetQuestObjectiveData(qInfo, obj.StorageIndex);
if (curTalkCount < reqTalkCount)
{
SetQuestObjectiveData(qInfo, obj.StorageIndex, curTalkCount + addTalkCount);
SetQuestObjectiveData(obj, curTalkCount + addTalkCount);
SendQuestUpdateAddCredit(qInfo, guid, obj, curTalkCount + addTalkCount);
}
@@ -16744,15 +16744,12 @@ void Player::CurrencyChanged(uint32 currencyId, int32 change)
if (uint32(obj.ObjectID) != currencyId)
continue;
if (obj.Type != QUEST_OBJECTIVE_HAVE_CURRENCY)
continue;
QuestStatusData& q_status = m_QuestStatus[questid];
if (obj.Type == QUEST_OBJECTIVE_CURRENCY || obj.Type == QUEST_OBJECTIVE_HAVE_CURRENCY)
{
int64 value = GetCurrency(currencyId);
if (obj.Type == QUEST_OBJECTIVE_HAVE_CURRENCY)
SetQuestObjectiveData(qInfo, obj.StorageIndex, int32(std::min<int64>(value, obj.Amount)));
SetQuestObjectiveData(obj, int32(std::min<int64>(value, obj.Amount)));
if (q_status.Status == QUEST_STATUS_INCOMPLETE)
{
@@ -16771,7 +16768,7 @@ void Player::CurrencyChanged(uint32 currencyId, int32 change)
else if (obj.Type == QUEST_OBJECTIVE_OBTAIN_CURRENCY && change > 0) // currency losses are not accounted for in this objective type
{
int64 currentProgress = GetQuestObjectiveData(qInfo, obj.StorageIndex);
SetQuestObjectiveData(qInfo, obj.StorageIndex, int32(std::max(std::min<int64>(currentProgress + change, obj.Amount), SI64LIT(0))));
SetQuestObjectiveData(obj, int32(std::max(std::min<int64>(currentProgress + change, obj.Amount), SI64LIT(0))));
if (CanCompleteQuest(questid))
CompleteQuest(questid);
}
@@ -16919,44 +16916,51 @@ bool Player::IsQuestObjectiveComplete(QuestObjective const& objective) const
return true;
}
void Player::SetQuestObjectiveData(Quest const* quest, int8 storageIndex, int32 data)
void Player::SetQuestObjectiveData(QuestObjective const& objective, int32 data)
{
if (storageIndex < 0)
if (objective.StorageIndex < 0)
TC_LOG_ERROR("entities.player.quest", "Player::SetQuestObjectiveData: called for quest %u with invalid StorageIndex %d (objective data is not tracked)",
quest->GetQuestId(), storageIndex);
objective.QuestID, objective.StorageIndex);
auto itr = m_QuestStatus.find(quest->GetQuestId());
auto itr = m_QuestStatus.find(objective.QuestID);
if (itr == m_QuestStatus.end())
{
TC_LOG_ERROR("entities.player.quest", "Player::SetQuestObjectiveData: player '%s' (%s) doesn't have quest status data (QuestID: %u)",
GetName().c_str(), GetGUID().ToString().c_str(), quest->GetQuestId());
GetName().c_str(), GetGUID().ToString().c_str(), objective.QuestID);
return;
}
QuestStatusData& status = itr->second;
if (uint8(storageIndex) >= status.ObjectiveData.size())
if (uint8(objective.StorageIndex) >= status.ObjectiveData.size())
{
TC_LOG_ERROR("entities.player.quest", "Player::SetQuestObjectiveData: player '%s' (%s) quest %u out of range StorageIndex %u",
GetName().c_str(), GetGUID().ToString().c_str(), quest->GetQuestId(), storageIndex);
GetName().c_str(), GetGUID().ToString().c_str(), objective.QuestID, objective.StorageIndex);
return;
}
// No change
if (status.ObjectiveData[storageIndex] == data)
if (status.ObjectiveData[objective.StorageIndex] == data)
return;
// Set data
status.ObjectiveData[storageIndex] = data;
status.ObjectiveData[objective.StorageIndex] = data;
// Add to save
m_QuestStatusSave[quest->GetQuestId()] = QUEST_DEFAULT_SAVE_TYPE;
m_QuestStatusSave[objective.QuestID] = QUEST_DEFAULT_SAVE_TYPE;
// Update quest fields
uint16 log_slot = FindQuestSlot(quest->GetQuestId());
uint16 log_slot = FindQuestSlot(objective.QuestID);
if (log_slot < MAX_QUEST_LOG_SIZE)
SetQuestSlotCounter(log_slot, storageIndex, status.ObjectiveData[storageIndex]);
{
if (!objective.IsStoringFlag())
SetQuestSlotCounter(log_slot, objective.StorageIndex, status.ObjectiveData[objective.StorageIndex]);
else if (data)
SetQuestSlotState(log_slot, 256 << objective.StorageIndex);
else
RemoveQuestSlotState(log_slot, 256 << objective.StorageIndex);
}
}
void Player::SendQuestComplete(Quest const* quest) const
@@ -17080,6 +17084,15 @@ void Player::SendQuestUpdateAddCredit(Quest const* quest, ObjectGuid guid, Quest
GetSession()->SendPacket(packet.Write());
}
void Player::SendQuestUpdateAddCreditSimple(QuestObjective const& obj) const
{
WorldPackets::Quest::QuestUpdateAddCreditSimple packet;
packet.QuestID = obj.QuestID;
packet.ObjectID = obj.ObjectID;
packet.ObjectiveType = obj.Type;
SendDirectMessage(packet.Write());
}
void Player::SendQuestUpdateAddPlayer(Quest const* quest, uint16 newCount) const
{
WorldPackets::Quest::QuestUpdateAddPvPCredit questUpdateAddPvpCredit;
@@ -18956,19 +18969,22 @@ void Player::_LoadQuestStatusObjectives(PreparedQueryResult result)
Field* fields = result->Fetch();
uint32 questID = fields[0].GetUInt32();
Quest const* quest = sObjectMgr->GetQuestTemplate(questID);
uint16 slot = FindQuestSlot(questID);
auto itr = m_QuestStatus.find(questID);
if (itr != m_QuestStatus.end() && slot < MAX_QUEST_LOG_SIZE)
if (itr != m_QuestStatus.end() && slot < MAX_QUEST_LOG_SIZE && quest)
{
QuestStatusData& questStatusData = itr->second;
uint8 objectiveIndex = fields[1].GetUInt8();
if (objectiveIndex < questStatusData.ObjectiveData.size())
auto objectiveItr = std::find_if(quest->Objectives.begin(), quest->Objectives.end(), [=](QuestObjective const& objective) { return uint8(objective.StorageIndex) == objectiveIndex; });
if (objectiveIndex < questStatusData.ObjectiveData.size() && objectiveItr != quest->Objectives.end())
{
int32 data = fields[2].GetInt32();
questStatusData.ObjectiveData[objectiveIndex] = data;
SetQuestSlotCounter(slot, objectiveIndex, data);
if (!objectiveItr->IsStoringFlag())
SetQuestSlotCounter(slot, objectiveIndex, data);
else if (data)
SetQuestSlotState(slot, 256 << objectiveIndex);
}
else
TC_LOG_ERROR("entities.player", "Player::_LoadQuestStatusObjectives: Player '%s' (%s) has quest %d out of range objective index %u.", GetName().c_str(), GetGUID().ToString().c_str(), questID, objectiveIndex);

View File

@@ -1431,7 +1431,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
int32 GetQuestObjectiveData(Quest const* quest, int8 storageIndex) const;
bool IsQuestObjectiveComplete(QuestObjective const& objective) const;
void SetQuestObjectiveData(Quest const* quest, int8 storageIndex, int32 data);
void SetQuestObjectiveData(QuestObjective const& objective, int32 data);
bool IsQuestObjectiveProgressComplete(Quest const* quest) const;
void SendQuestComplete(Quest const* quest) const;
void SendQuestReward(Quest const* quest, uint32 XP) const;
@@ -1441,6 +1441,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SendQuestConfirmAccept(Quest const* quest, Player* receiver) const;
void SendPushToPartyResponse(Player* player, QuestPushReason reason) 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;
void SendQuestGiverStatusMultiple();

View File

@@ -511,11 +511,12 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPackets::AreaTrigger::AreaTrigge
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questId);
if (qInfo && player->GetQuestStatus(questId) == QUEST_STATUS_INCOMPLETE)
{
for (uint8 j = 0; j < qInfo->Objectives.size(); ++j)
for (QuestObjective const& obj : qInfo->Objectives)
{
if (qInfo->Objectives[j].Type == QUEST_OBJECTIVE_AREATRIGGER)
if (obj.Type == QUEST_OBJECTIVE_AREATRIGGER && !player->IsQuestObjectiveComplete(obj))
{
player->SetQuestObjectiveData(qInfo, j, int32(true));
player->SetQuestObjectiveData(obj, 1);
player->SendQuestUpdateAddCreditSimple(obj);
break;
}
}

View File

@@ -289,6 +289,21 @@ struct QuestObjective
float ProgressBarWeight = 0.0f;
std::string Description;
std::vector<int32> VisualEffects;
bool IsStoringFlag() const
{
switch (Type)
{
case QUEST_OBJECTIVE_AREATRIGGER:
case QUEST_OBJECTIVE_WINPETBATTLEAGAINSTNPC:
case QUEST_OBJECTIVE_DEFEATBATTLEPET:
case QUEST_OBJECTIVE_CRITERIA_TREE:
return true;
default:
break;
}
return false;
}
};
typedef std::vector<QuestObjective> QuestObjectives;

View File

@@ -201,6 +201,15 @@ WorldPacket const* WorldPackets::Quest::QuestUpdateAddCredit::Write()
return &_worldPacket;
};
WorldPacket const* WorldPackets::Quest::QuestUpdateAddCreditSimple::Write()
{
_worldPacket << int32(QuestID);
_worldPacket << int32(ObjectID);
_worldPacket << uint8(ObjectiveType);
return &_worldPacket;
}
WorldPacket const* WorldPackets::Quest::QuestUpdateAddPvPCredit::Write()
{
_worldPacket << int32(QuestID);

View File

@@ -187,7 +187,7 @@ namespace WorldPackets
class QuestUpdateAddCredit final : public ServerPacket
{
public:
QuestUpdateAddCredit() : ServerPacket(SMSG_QUEST_UPDATE_ADD_CREDIT, 16+4+4+2+2+1) { }
QuestUpdateAddCredit() : ServerPacket(SMSG_QUEST_UPDATE_ADD_CREDIT, 16 + 4 + 4 + 2 + 2 + 1) { }
WorldPacket const* Write() override;
@@ -199,6 +199,18 @@ namespace WorldPackets
uint8 ObjectiveType = 0;
};
class QuestUpdateAddCreditSimple final : public ServerPacket
{
public:
QuestUpdateAddCreditSimple() : ServerPacket(SMSG_QUEST_UPDATE_ADD_CREDIT_SIMPLE, 4 + 4 + 1) { }
WorldPacket const* Write() override;
int32 QuestID = 0;
int32 ObjectID = 0;
uint8 ObjectiveType = 0;
};
class QuestUpdateAddPvPCredit final : public ServerPacket
{
public:

View File

@@ -1594,7 +1594,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_PUSH_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_SPAWN_TRACKING_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_CREDIT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_CREDIT_SIMPLE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_CREDIT_SIMPLE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_ADD_PVP_CREDIT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_COMPLETE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUEST_UPDATE_COMPLETE_BY_SPELL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);