mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Quests: Fixed showing quest objective completion clientside for objective types 10, 11, 12 and 14
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user