refactor(Core/Packets): Rewrite various quest packets to modern class. (#22835)
Co-authored-by: sudlud <sudlud@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1559,9 +1559,9 @@ public:
|
|||||||
void SendQuestReward(Quest const* quest, uint32 XP);
|
void SendQuestReward(Quest const* quest, uint32 XP);
|
||||||
void SendQuestFailed(uint32 questId, InventoryResult reason = EQUIP_ERR_OK);
|
void SendQuestFailed(uint32 questId, InventoryResult reason = EQUIP_ERR_OK);
|
||||||
void SendQuestTimerFailed(uint32 quest_id);
|
void SendQuestTimerFailed(uint32 quest_id);
|
||||||
void SendCanTakeQuestResponse(uint32 msg) const;
|
void SendCanTakeQuestResponse(QuestFailedReason msg) const;
|
||||||
void SendQuestConfirmAccept(Quest const* quest, Player* pReceiver);
|
void SendQuestConfirmAccept(Quest const* quest, Player* pReceiver);
|
||||||
void SendPushToPartyResponse(Player const* player, uint8 msg) const;
|
void SendPushToPartyResponse(Player const* player, QuestShareMessages msg) const;
|
||||||
void SendQuestUpdateAddItem(Quest const* quest, uint32 item_idx, uint16 count);
|
void SendQuestUpdateAddItem(Quest const* quest, uint32 item_idx, uint16 count);
|
||||||
void SendQuestUpdateAddCreatureOrGo(Quest const* quest, ObjectGuid guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count);
|
void SendQuestUpdateAddCreatureOrGo(Quest const* quest, ObjectGuid guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count);
|
||||||
void SendQuestUpdateAddPlayer(Quest const* quest, uint16 old_count, uint16 add_count);
|
void SendQuestUpdateAddPlayer(Quest const* quest, uint16 old_count, uint16 add_count);
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "MapMgr.h"
|
#include "MapMgr.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "PoolMgr.h"
|
#include "PoolMgr.h"
|
||||||
|
#include "QuestPackets.h"
|
||||||
#include "ReputationMgr.h"
|
#include "ReputationMgr.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
#include "SpellAuraEffects.h"
|
#include "SpellAuraEffects.h"
|
||||||
@@ -991,8 +992,7 @@ bool Player::SatisfyQuestLog(bool msg)
|
|||||||
|
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_QUESTLOG_FULL, 0);
|
SendDirectMessage(WorldPackets::Quest::QuestLogFull().Write());
|
||||||
SendDirectMessage(&data);
|
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTLOG_FULL");
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTLOG_FULL");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -2381,13 +2381,13 @@ bool Player::HasQuestForItem(uint32 itemid, uint32 excludeQuestId /* 0 */, bool
|
|||||||
|
|
||||||
void Player::SendQuestComplete(uint32 quest_id)
|
void Player::SendQuestComplete(uint32 quest_id)
|
||||||
{
|
{
|
||||||
if (quest_id)
|
if (!quest_id)
|
||||||
{
|
return;
|
||||||
WorldPacket data(SMSG_QUESTUPDATE_COMPLETE, 4);
|
|
||||||
data << uint32(quest_id);
|
WorldPackets::Quest::QuestUpdateComplete questUpdateComplete;
|
||||||
SendDirectMessage(&data);
|
questUpdateComplete.QuestId = quest_id;
|
||||||
|
SendDirectMessage(questUpdateComplete.Write());
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = {}", quest_id);
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = {}", quest_id);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendQuestReward(Quest const* quest, uint32 XP)
|
void Player::SendQuestReward(Quest const* quest, uint32 XP)
|
||||||
@@ -2395,54 +2395,50 @@ void Player::SendQuestReward(Quest const* quest, uint32 XP)
|
|||||||
uint32 questid = quest->GetQuestId();
|
uint32 questid = quest->GetQuestId();
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = {}", questid);
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = {}", questid);
|
||||||
sGameEventMgr->HandleQuestComplete(questid);
|
sGameEventMgr->HandleQuestComplete(questid);
|
||||||
WorldPacket data(SMSG_QUESTGIVER_QUEST_COMPLETE, (4 + 4 + 4 + 4 + 4));
|
WorldPackets::Quest::QuestGiverQuestComplete questGiverQuestComplete;
|
||||||
data << uint32(questid);
|
questGiverQuestComplete.QuestId = questid;
|
||||||
|
uint32 rewardMoney = quest->GetRewOrReqMoney(GetLevel());
|
||||||
|
|
||||||
if (!IsMaxLevel())
|
if (!IsMaxLevel())
|
||||||
{
|
questGiverQuestComplete.Experience = XP;
|
||||||
data << uint32(XP);
|
|
||||||
data << uint32(quest->GetRewOrReqMoney(GetLevel()));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
rewardMoney += quest->GetRewMoneyMaxLevel();
|
||||||
data << uint32(0);
|
|
||||||
data << uint32(quest->GetRewOrReqMoney(GetLevel()) + quest->GetRewMoneyMaxLevel());
|
|
||||||
}
|
|
||||||
|
|
||||||
data << uint32(10 * quest->CalculateHonorGain(GetQuestLevel(quest)));
|
questGiverQuestComplete.RewardMoney = rewardMoney;
|
||||||
data << uint32(quest->GetBonusTalents()); // bonus talents
|
questGiverQuestComplete.RewardHonor = 10 * quest->CalculateHonorGain(GetQuestLevel(quest));
|
||||||
data << uint32(quest->GetRewArenaPoints());
|
questGiverQuestComplete.RewardTalents = quest->GetBonusTalents();
|
||||||
SendDirectMessage(&data);
|
questGiverQuestComplete.RewardArena = quest->GetRewArenaPoints();
|
||||||
|
SendDirectMessage(questGiverQuestComplete.Write());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendQuestFailed(uint32 questId, InventoryResult reason)
|
void Player::SendQuestFailed(uint32 questId, InventoryResult reason)
|
||||||
{
|
{
|
||||||
if (questId)
|
if (!questId)
|
||||||
{
|
return;
|
||||||
WorldPacket data(SMSG_QUESTGIVER_QUEST_FAILED, 4 + 4);
|
|
||||||
data << uint32(questId);
|
WorldPackets::Quest::QuestGiverQuestFailed questGiverQuestFailed;
|
||||||
data << uint32(reason); // failed reason (valid reasons: 4, 16, 50, 17, 74, other values show default message)
|
questGiverQuestFailed.QuestId = questId;
|
||||||
SendDirectMessage(&data);
|
questGiverQuestFailed.FailureReason = reason; // failed reason (valid reasons: 4, 16, 50, 17, 74, other values show default message)
|
||||||
|
SendDirectMessage(questGiverQuestFailed.Write());
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED");
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendQuestTimerFailed(uint32 quest_id)
|
void Player::SendQuestTimerFailed(uint32 quest_id)
|
||||||
{
|
{
|
||||||
if (quest_id)
|
if (!quest_id)
|
||||||
{
|
return;
|
||||||
WorldPacket data(SMSG_QUESTUPDATE_FAILEDTIMER, 4);
|
|
||||||
data << uint32(quest_id);
|
WorldPackets::Quest::QuestUpdateFailedTimer questUpdateFailedTimer;
|
||||||
SendDirectMessage(&data);
|
questUpdateFailedTimer.QuestId = quest_id;
|
||||||
|
SendDirectMessage(questUpdateFailedTimer.Write());
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_FAILEDTIMER");
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_FAILEDTIMER");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendCanTakeQuestResponse(uint32 msg) const
|
void Player::SendCanTakeQuestResponse(QuestFailedReason msg) const
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_QUESTGIVER_QUEST_INVALID, 4);
|
WorldPackets::Quest::QuestGiverQuestInvalid questGiverQuestInvalid;
|
||||||
data << uint32(msg);
|
questGiverQuestInvalid.FailureReason = msg;
|
||||||
SendDirectMessage(&data);
|
SendDirectMessage(questGiverQuestInvalid.Write());
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_INVALID");
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTGIVER_QUEST_INVALID");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2458,35 +2454,36 @@ void Player::SendQuestConfirmAccept(const Quest* quest, Player* pReceiver)
|
|||||||
if (const QuestLocale* pLocale = sObjectMgr->GetQuestLocale(quest->GetQuestId()))
|
if (const QuestLocale* pLocale = sObjectMgr->GetQuestLocale(quest->GetQuestId()))
|
||||||
ObjectMgr::GetLocaleString(pLocale->Title, loc_idx, strTitle);
|
ObjectMgr::GetLocaleString(pLocale->Title, loc_idx, strTitle);
|
||||||
|
|
||||||
WorldPacket data(SMSG_QUEST_CONFIRM_ACCEPT, (4 + quest->GetTitle().size() + 8));
|
WorldPackets::Quest::QuestConfirmAccept questConfirmAccept;
|
||||||
data << uint32(quest->GetQuestId());
|
questConfirmAccept.QuestId = quest->GetQuestId();
|
||||||
data << quest->GetTitle();
|
questConfirmAccept.QuestTitle = quest->GetTitle();
|
||||||
data << GetGUID();
|
questConfirmAccept.PlayerGuid = GetGUID();
|
||||||
pReceiver->SendDirectMessage(&data);
|
pReceiver->SendDirectMessage(questConfirmAccept.Write());
|
||||||
|
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUEST_CONFIRM_ACCEPT");
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUEST_CONFIRM_ACCEPT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendPushToPartyResponse(Player const* player, uint8 msg) const
|
void Player::SendPushToPartyResponse(Player const* player, QuestShareMessages msg) const
|
||||||
{
|
{
|
||||||
if (player)
|
if (!player)
|
||||||
{
|
return;
|
||||||
WorldPacket data(MSG_QUEST_PUSH_RESULT, (8 + 1));
|
|
||||||
data << player->GetGUID();
|
WorldPackets::Quest::QuestPushResult questPushResult;
|
||||||
data << uint8(msg); // valid values: 0-8
|
questPushResult.PlayerGuid = player->GetGUID();
|
||||||
SendDirectMessage(&data);
|
questPushResult.QuestShareMessage = msg;
|
||||||
|
SendDirectMessage(questPushResult.Write());
|
||||||
LOG_DEBUG("network", "WORLD: Sent MSG_QUEST_PUSH_RESULT");
|
LOG_DEBUG("network", "WORLD: Sent MSG_QUEST_PUSH_RESULT");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendQuestUpdateAddItem(Quest const* /*quest*/, uint32 /*item_idx*/, uint16 /*count*/)
|
void Player::SendQuestUpdateAddItem(Quest const* /*quest*/, uint32 /*item_idx*/, uint16 /*count*/)
|
||||||
{
|
{
|
||||||
WorldPacket data(SMSG_QUESTUPDATE_ADD_ITEM, 0);
|
// Packet is intentionally sent empty; the optional payload (item id and
|
||||||
|
// count) is not required by the 3.3.5 client:
|
||||||
|
//questUpdateAddItem.ItemId = quest->RequiredItemId[item_idx];
|
||||||
|
//questUpdateAddItem.Count = count;
|
||||||
|
SendDirectMessage(WorldPackets::Quest::QuestUpdateAddItem().Write());
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM");
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM");
|
||||||
//data << quest->RequiredItemId[item_idx];
|
|
||||||
//data << count;
|
|
||||||
SendDirectMessage(&data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendQuestUpdateAddCreatureOrGo(Quest const* quest, ObjectGuid guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count)
|
void Player::SendQuestUpdateAddCreatureOrGo(Quest const* quest, ObjectGuid guid, uint32 creatureOrGO_idx, uint16 old_count, uint16 add_count)
|
||||||
@@ -2498,14 +2495,14 @@ void Player::SendQuestUpdateAddCreatureOrGo(Quest const* quest, ObjectGuid guid,
|
|||||||
// client expected gameobject template id in form (id|0x80000000)
|
// client expected gameobject template id in form (id|0x80000000)
|
||||||
entry = (-entry) | 0x80000000;
|
entry = (-entry) | 0x80000000;
|
||||||
|
|
||||||
WorldPacket data(SMSG_QUESTUPDATE_ADD_KILL, (4 * 4 + 8));
|
WorldPackets::Quest::QuestUpdateAddKill questUpdateAddKill;
|
||||||
|
questUpdateAddKill.QuestId = quest->GetQuestId();
|
||||||
|
questUpdateAddKill.CreatureEntry = entry;
|
||||||
|
questUpdateAddKill.CurrentCount = old_count + add_count;
|
||||||
|
questUpdateAddKill.RequiredCount = quest->RequiredNpcOrGoCount[creatureOrGO_idx];
|
||||||
|
questUpdateAddKill.ObjectiveGuid = guid;
|
||||||
|
SendDirectMessage(questUpdateAddKill.Write());
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_ADD_KILL");
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_ADD_KILL");
|
||||||
data << uint32(quest->GetQuestId());
|
|
||||||
data << uint32(entry);
|
|
||||||
data << uint32(old_count + add_count);
|
|
||||||
data << uint32(quest->RequiredNpcOrGoCount[ creatureOrGO_idx ]);
|
|
||||||
data << guid;
|
|
||||||
SendDirectMessage(&data);
|
|
||||||
|
|
||||||
uint16 log_slot = FindQuestSlot(quest->GetQuestId());
|
uint16 log_slot = FindQuestSlot(quest->GetQuestId());
|
||||||
if (log_slot < MAX_QUEST_LOG_SIZE)
|
if (log_slot < MAX_QUEST_LOG_SIZE)
|
||||||
@@ -2516,12 +2513,12 @@ void Player::SendQuestUpdateAddPlayer(Quest const* quest, uint16 old_count, uint
|
|||||||
{
|
{
|
||||||
ASSERT(old_count + add_count < 65536 && "player count store in 16 bits");
|
ASSERT(old_count + add_count < 65536 && "player count store in 16 bits");
|
||||||
|
|
||||||
WorldPacket data(SMSG_QUESTUPDATE_ADD_PVP_KILL, (3 * 4));
|
WorldPackets::Quest::QuestUpdateAddPvPKill questUpdateAddPvPKill;
|
||||||
|
questUpdateAddPvPKill.QuestId = quest->GetQuestId();
|
||||||
|
questUpdateAddPvPKill.CurrentCount = old_count + add_count;
|
||||||
|
questUpdateAddPvPKill.RequiredCount = quest->GetPlayersSlain();
|
||||||
|
SendDirectMessage(questUpdateAddPvPKill.Write());
|
||||||
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_ADD_PVP_KILL");
|
LOG_DEBUG("network", "WORLD: Sent SMSG_QUESTUPDATE_ADD_PVP_KILL");
|
||||||
data << uint32(quest->GetQuestId());
|
|
||||||
data << uint32(old_count + add_count);
|
|
||||||
data << uint32(quest->GetPlayersSlain());
|
|
||||||
SendDirectMessage(&data);
|
|
||||||
|
|
||||||
uint16 log_slot = FindQuestSlot(quest->GetQuestId());
|
uint16 log_slot = FindQuestSlot(quest->GetQuestId());
|
||||||
if (log_slot < MAX_QUEST_LOG_SIZE)
|
if (log_slot < MAX_QUEST_LOG_SIZE)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include "Opcodes.h"
|
#include "Opcodes.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "QuestDef.h"
|
#include "QuestDef.h"
|
||||||
|
#include "QuestPackets.h"
|
||||||
#include "ScriptMgr.h"
|
#include "ScriptMgr.h"
|
||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "WorldPacket.h"
|
#include "WorldPacket.h"
|
||||||
@@ -382,29 +383,23 @@ void WorldSession::HandleQuestgiverCancel(WorldPacket& /*recvData*/)
|
|||||||
_player->PlayerTalkClass->SendCloseGossip();
|
_player->PlayerTalkClass->SendCloseGossip();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleQuestLogSwapQuest(WorldPacket& recvData)
|
void WorldSession::HandleQuestLogSwapQuest(WorldPackets::Quest::QuestLogSwapQuest& packet)
|
||||||
{
|
{
|
||||||
uint8 slot1, slot2;
|
if (packet.Slot1 == packet.Slot2 || packet.Slot1 >= MAX_QUEST_LOG_SIZE || packet.Slot2 >= MAX_QUEST_LOG_SIZE)
|
||||||
recvData >> slot1 >> slot2;
|
|
||||||
|
|
||||||
if (slot1 == slot2 || slot1 >= MAX_QUEST_LOG_SIZE || slot2 >= MAX_QUEST_LOG_SIZE)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LOG_DEBUG("network", "WORLD: Received CMSG_QUESTLOG_SWAP_QUEST slot 1 = {}, slot 2 = {}", slot1, slot2);
|
LOG_DEBUG("network", "WORLD: Received CMSG_QUESTLOG_SWAP_QUEST slot 1 = {}, slot 2 = {}", packet.Slot1, packet.Slot2);
|
||||||
|
|
||||||
GetPlayer()->SwapQuestSlot(slot1, slot2);
|
GetPlayer()->SwapQuestSlot(packet.Slot1, packet.Slot2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recvData)
|
void WorldSession::HandleQuestLogRemoveQuest(WorldPackets::Quest::QuestLogRemoveQuest& packet)
|
||||||
{
|
{
|
||||||
uint8 slot;
|
LOG_DEBUG("network", "WORLD: Received CMSG_QUESTLOG_REMOVE_QUEST slot = {}", packet.Slot);
|
||||||
recvData >> slot;
|
|
||||||
|
|
||||||
LOG_DEBUG("network", "WORLD: Received CMSG_QUESTLOG_REMOVE_QUEST slot = {}", slot);
|
if (packet.Slot < MAX_QUEST_LOG_SIZE)
|
||||||
|
|
||||||
if (slot < MAX_QUEST_LOG_SIZE)
|
|
||||||
{
|
{
|
||||||
if (uint32 questId = _player->GetQuestSlotQuestId(slot))
|
if (uint32 questId = _player->GetQuestSlotQuestId(packet.Slot))
|
||||||
{
|
{
|
||||||
if (!_player->TakeQuestSourceItem(questId, true))
|
if (!_player->TakeQuestSourceItem(questId, true))
|
||||||
return; // can't un-equip some items, reject quest cancel
|
return; // can't un-equip some items, reject quest cancel
|
||||||
@@ -442,20 +437,17 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recvData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_player->SetQuestSlot(slot, 0);
|
_player->SetQuestSlot(packet.Slot, 0);
|
||||||
|
|
||||||
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1);
|
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData)
|
void WorldSession::HandleQuestConfirmAccept(WorldPackets::Quest::QuestConfirmAcceptClient& packet)
|
||||||
{
|
{
|
||||||
uint32 questId;
|
LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = {}", packet.QuestId);
|
||||||
recvData >> questId;
|
|
||||||
|
|
||||||
LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_CONFIRM_ACCEPT quest = {}", questId);
|
if (Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestId))
|
||||||
|
|
||||||
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
|
|
||||||
{
|
{
|
||||||
if (!quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT))
|
if (!quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT))
|
||||||
return;
|
return;
|
||||||
@@ -530,21 +522,18 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleQuestgiverQuestAutoLaunch(WorldPacket& /*recvPacket*/)
|
void WorldSession::HandleQuestgiverQuestAutoLaunch(WorldPackets::Quest::QuestGiverQuestAutoLaunch& /*packet*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket)
|
void WorldSession::HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty& packet)
|
||||||
{
|
{
|
||||||
uint32 questId;
|
if (!_player->CanShareQuest(packet.QuestId))
|
||||||
recvPacket >> questId;
|
|
||||||
|
|
||||||
if (!_player->CanShareQuest(questId))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LOG_DEBUG("network", "WORLD: Received CMSG_PUSHQUESTTOPARTY quest = {}", questId);
|
LOG_DEBUG("network", "WORLD: Received CMSG_PUSHQUESTTOPARTY quest = {}", packet.QuestId);
|
||||||
|
|
||||||
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
|
if (Quest const* quest = sObjectMgr->GetQuestTemplate(packet.QuestId))
|
||||||
{
|
{
|
||||||
if (Group* group = _player->GetGroup())
|
if (Group* group = _player->GetGroup())
|
||||||
{
|
{
|
||||||
@@ -561,7 +550,7 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->GetQuestStatus(questId) == QUEST_STATUS_COMPLETE)
|
if (player->GetQuestStatus(packet.QuestId) == QUEST_STATUS_COMPLETE)
|
||||||
{
|
{
|
||||||
_player->SendPushToPartyResponse(player, QUEST_PARTY_MSG_FINISH_QUEST);
|
_player->SendPushToPartyResponse(player, QUEST_PARTY_MSG_FINISH_QUEST);
|
||||||
continue;
|
continue;
|
||||||
@@ -613,21 +602,16 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket)
|
void WorldSession::HandleQuestPushResult(WorldPackets::Quest::QuestPushResultClient& packet)
|
||||||
{
|
{
|
||||||
ObjectGuid guid;
|
if (_player->GetDivider() && _player->GetDivider() == packet.PlayerGuid)
|
||||||
uint32 questId;
|
|
||||||
uint8 msg;
|
|
||||||
recvPacket >> guid >> questId >> msg;
|
|
||||||
|
|
||||||
if (_player->GetDivider() && _player->GetDivider() == guid)
|
|
||||||
{
|
{
|
||||||
if (Player* player = ObjectAccessor::GetPlayer(*_player, _player->GetDivider()))
|
if (Player* player = ObjectAccessor::GetPlayer(*_player, _player->GetDivider()))
|
||||||
{
|
{
|
||||||
WorldPacket data(MSG_QUEST_PUSH_RESULT, 8 + 4 + 1);
|
WorldPackets::Quest::QuestPushResult questPushResult;
|
||||||
data << _player->GetGUID();
|
questPushResult.PlayerGuid = _player->GetGUID();
|
||||||
data << uint8(msg); // valid values: 0-8
|
questPushResult.QuestShareMessage = packet.QuestShareMessage;
|
||||||
player->SendDirectMessage(&data);
|
player->SendDirectMessage(questPushResult.Write());
|
||||||
_player->SetDivider();
|
_player->SetDivider();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "NPCPackets.h"
|
#include "NPCPackets.h"
|
||||||
#include "PetPackets.h"
|
#include "PetPackets.h"
|
||||||
#include "QueryPackets.h"
|
#include "QueryPackets.h"
|
||||||
|
#include "QuestPackets.h"
|
||||||
#include "TotemPackets.h"
|
#include "TotemPackets.h"
|
||||||
#include "WorldStatePackets.h"
|
#include "WorldStatePackets.h"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "QuestPackets.h"
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestUpdateComplete::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << QuestId;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestGiverQuestComplete::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << QuestId;
|
||||||
|
_worldPacket << Experience;
|
||||||
|
_worldPacket << RewardMoney;
|
||||||
|
_worldPacket << RewardHonor;
|
||||||
|
_worldPacket << RewardTalents;
|
||||||
|
_worldPacket << RewardArena;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestGiverQuestFailed::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << QuestId;
|
||||||
|
_worldPacket << FailureReason;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestUpdateFailedTimer::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << QuestId;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestGiverQuestInvalid::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << FailureReason;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestConfirmAccept::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << QuestId;
|
||||||
|
_worldPacket << QuestTitle;
|
||||||
|
_worldPacket << PlayerGuid;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestPushResult::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << PlayerGuid;
|
||||||
|
_worldPacket << QuestShareMessage;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestUpdateAddKill::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << QuestId;
|
||||||
|
_worldPacket << CreatureEntry;
|
||||||
|
_worldPacket << CurrentCount;
|
||||||
|
_worldPacket << RequiredCount;
|
||||||
|
_worldPacket << ObjectiveGuid;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPacket const* WorldPackets::Quest::QuestUpdateAddPvPKill::Write()
|
||||||
|
{
|
||||||
|
_worldPacket << QuestId;
|
||||||
|
_worldPacket << CurrentCount;
|
||||||
|
_worldPacket << RequiredCount;
|
||||||
|
|
||||||
|
return &_worldPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldPackets::Quest::QuestPushResultClient::Read()
|
||||||
|
{
|
||||||
|
_worldPacket >> PlayerGuid;
|
||||||
|
_worldPacket >> QuestId;
|
||||||
|
uint8 Message;
|
||||||
|
_worldPacket >> Message;
|
||||||
|
QuestShareMessage = static_cast<QuestShareMessages>(Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldPackets::Quest::QuestLogSwapQuest::Read()
|
||||||
|
{
|
||||||
|
_worldPacket >> Slot1;
|
||||||
|
_worldPacket >> Slot2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldPackets::Quest::QuestLogRemoveQuest::Read()
|
||||||
|
{
|
||||||
|
_worldPacket >> Slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldPackets::Quest::QuestConfirmAcceptClient::Read()
|
||||||
|
{
|
||||||
|
_worldPacket >> QuestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldPackets::Quest::PushQuestToParty::Read()
|
||||||
|
{
|
||||||
|
_worldPacket >> QuestId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QuestPackets_h__
|
||||||
|
#define QuestPackets_h__
|
||||||
|
|
||||||
|
#include "ObjectGuid.h"
|
||||||
|
#include "Packet.h"
|
||||||
|
#include "QuestDef.h"
|
||||||
|
|
||||||
|
namespace WorldPackets
|
||||||
|
{
|
||||||
|
namespace Quest
|
||||||
|
{
|
||||||
|
class QuestLogFull final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestLogFull() : ServerPacket(SMSG_QUESTLOG_FULL, 0) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override { return &_worldPacket; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestUpdateComplete final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestUpdateComplete() : ServerPacket(SMSG_QUESTUPDATE_COMPLETE, 4) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestGiverQuestComplete final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestGiverQuestComplete() : ServerPacket(SMSG_QUESTGIVER_QUEST_COMPLETE, 4 + 4 + 4 + 4 + 4 + 4) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
uint32 Experience = 0;
|
||||||
|
uint32 RewardMoney = 0;
|
||||||
|
uint32 RewardHonor = 0;
|
||||||
|
uint32 RewardTalents = 0;
|
||||||
|
uint32 RewardArena = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestGiverQuestFailed final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestGiverQuestFailed() : ServerPacket(SMSG_QUESTGIVER_QUEST_FAILED, 4 + 4) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
uint32 FailureReason = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestUpdateFailedTimer final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestUpdateFailedTimer() : ServerPacket(SMSG_QUESTUPDATE_FAILEDTIMER, 4) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestGiverQuestInvalid final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestGiverQuestInvalid() : ServerPacket(SMSG_QUESTGIVER_QUEST_INVALID, 4) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
QuestFailedReason FailureReason = INVALIDREASON_DONT_HAVE_REQ;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestConfirmAccept final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// 4 (QuestId) + title (variable, 16 reserved estimate) + 8 (GUID)
|
||||||
|
QuestConfirmAccept() : ServerPacket(SMSG_QUEST_CONFIRM_ACCEPT, 4 + 16 + 8) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
std::string_view QuestTitle = "";
|
||||||
|
ObjectGuid PlayerGuid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestPushResult final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestPushResult() : ServerPacket(MSG_QUEST_PUSH_RESULT, 8 + 1) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
ObjectGuid PlayerGuid;
|
||||||
|
QuestShareMessages QuestShareMessage = QUEST_PARTY_MSG_SHARING_QUEST; // valid values: 0-10
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestUpdateAddItem final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestUpdateAddItem() : ServerPacket(SMSG_QUESTUPDATE_ADD_ITEM, 0) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override { return &_worldPacket; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestUpdateAddKill final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestUpdateAddKill() : ServerPacket(SMSG_QUESTUPDATE_ADD_KILL, 4 * 4 + 8) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
uint32 CreatureEntry = 0;
|
||||||
|
uint32 CurrentCount = 0;
|
||||||
|
uint32 RequiredCount = 0;
|
||||||
|
ObjectGuid ObjectiveGuid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestUpdateAddPvPKill final : public ServerPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestUpdateAddPvPKill() : ServerPacket(SMSG_QUESTUPDATE_ADD_PVP_KILL, 3 * 4) {}
|
||||||
|
|
||||||
|
WorldPacket const* Write() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
uint32 CurrentCount = 0;
|
||||||
|
uint32 RequiredCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestPushResultClient final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestPushResultClient(WorldPacket&& packet) : ClientPacket(MSG_QUEST_PUSH_RESULT, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
ObjectGuid PlayerGuid;
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
QuestShareMessages QuestShareMessage = QUEST_PARTY_MSG_SHARING_QUEST;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestGiverQuestAutoLaunch final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestGiverQuestAutoLaunch(WorldPacket&& packet) : ClientPacket(CMSG_QUESTGIVER_QUEST_AUTOLAUNCH, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestLogSwapQuest final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestLogSwapQuest(WorldPacket&& packet) : ClientPacket(CMSG_QUESTLOG_SWAP_QUEST, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
uint8 Slot1 = 0;
|
||||||
|
uint8 Slot2 = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestLogRemoveQuest final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestLogRemoveQuest(WorldPacket&& packet) : ClientPacket(CMSG_QUESTLOG_REMOVE_QUEST, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
uint8 Slot = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class QuestConfirmAcceptClient final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QuestConfirmAcceptClient(WorldPacket&& packet) : ClientPacket(CMSG_QUEST_CONFIRM_ACCEPT, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PushQuestToParty final : public ClientPacket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PushQuestToParty(WorldPacket&& packet) : ClientPacket(CMSG_PUSHQUESTTOPARTY, std::move(packet)) {}
|
||||||
|
|
||||||
|
void Read() override;
|
||||||
|
|
||||||
|
uint32 QuestId = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QuestPackets_h__
|
||||||
@@ -192,6 +192,16 @@ namespace WorldPackets
|
|||||||
class ItemRefund;
|
class ItemRefund;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Quest
|
||||||
|
{
|
||||||
|
class QuestPushResultClient;
|
||||||
|
class QuestGiverQuestAutoLaunch;
|
||||||
|
class QuestLogSwapQuest;
|
||||||
|
class QuestLogRemoveQuest;
|
||||||
|
class QuestConfirmAcceptClient;
|
||||||
|
class PushQuestToParty;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Calendar
|
namespace Calendar
|
||||||
{
|
{
|
||||||
class GetEvent;
|
class GetEvent;
|
||||||
@@ -915,13 +925,13 @@ public: // opcodes handlers
|
|||||||
void HandleQuestgiverRequestRewardOpcode(WorldPacket& recvPacket);
|
void HandleQuestgiverRequestRewardOpcode(WorldPacket& recvPacket);
|
||||||
void HandleQuestQueryOpcode(WorldPacket& recvPacket);
|
void HandleQuestQueryOpcode(WorldPacket& recvPacket);
|
||||||
void HandleQuestgiverCancel(WorldPacket& recvData);
|
void HandleQuestgiverCancel(WorldPacket& recvData);
|
||||||
void HandleQuestLogSwapQuest(WorldPacket& recvData);
|
void HandleQuestLogSwapQuest(WorldPackets::Quest::QuestLogSwapQuest& packet);
|
||||||
void HandleQuestLogRemoveQuest(WorldPacket& recvData);
|
void HandleQuestLogRemoveQuest(WorldPackets::Quest::QuestLogRemoveQuest& packet);
|
||||||
void HandleQuestConfirmAccept(WorldPacket& recvData);
|
void HandleQuestConfirmAccept(WorldPackets::Quest::QuestConfirmAcceptClient& packet);
|
||||||
void HandleQuestgiverCompleteQuest(WorldPacket& recvData);
|
void HandleQuestgiverCompleteQuest(WorldPacket& recvData);
|
||||||
void HandleQuestgiverQuestAutoLaunch(WorldPacket& recvPacket);
|
void HandleQuestgiverQuestAutoLaunch(WorldPackets::Quest::QuestGiverQuestAutoLaunch& packet);
|
||||||
void HandlePushQuestToParty(WorldPacket& recvPacket);
|
void HandlePushQuestToParty(WorldPackets::Quest::PushQuestToParty& packet);
|
||||||
void HandleQuestPushResult(WorldPacket& recvPacket);
|
void HandleQuestPushResult(WorldPackets::Quest::QuestPushResultClient& packet);
|
||||||
|
|
||||||
void HandleMessagechatOpcode(WorldPacket& recvPacket);
|
void HandleMessagechatOpcode(WorldPacket& recvPacket);
|
||||||
void SendPlayerNotFoundNotice(std::string const& name);
|
void SendPlayerNotFoundNotice(std::string const& name);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "PlayerScript.h"
|
#include "PlayerScript.h"
|
||||||
|
#include "QuestPackets.h"
|
||||||
|
|
||||||
enum ApprenticeAnglerQuestEnum
|
enum ApprenticeAnglerQuestEnum
|
||||||
{
|
{
|
||||||
@@ -54,14 +55,10 @@ public:
|
|||||||
player->SaveToDB(false, false);
|
player->SaveToDB(false, false);
|
||||||
|
|
||||||
// Send packet with money
|
// Send packet with money
|
||||||
WorldPacket data(SMSG_QUESTGIVER_QUEST_COMPLETE, (4 + 4 + 4 + 4 + 4));
|
WorldPackets::Quest::QuestGiverQuestComplete questGiverQuestComplete;
|
||||||
data << uint32(quest->GetQuestId());
|
questGiverQuestComplete.QuestId = quest->GetQuestId();
|
||||||
data << uint32(0);
|
questGiverQuestComplete.RewardMoney = moneyRew;
|
||||||
data << uint32(moneyRew);
|
player->SendDirectMessage(questGiverQuestComplete.Write());
|
||||||
data << uint32(0);
|
|
||||||
data << uint32(0);
|
|
||||||
data << uint32(0);
|
|
||||||
player->SendDirectMessage(&data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user