diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h index 91d3651bdaa..2506b2b4ec2 100644 --- a/src/server/game/DungeonFinding/LFG.h +++ b/src/server/game/DungeonFinding/LFG.h @@ -60,7 +60,7 @@ enum LfgUpdateType LFG_UPDATETYPE_JOIN_LFG_OBJECT_FAILED = 45, }; -enum LfgState +enum LfgState : uint8 { LFG_STATE_NONE, // Not using LFG / LFR LFG_STATE_ROLECHECK, // Rolecheck active diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 5d530c25b0c..e91c54c0f13 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -549,6 +549,11 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const SetComment(guid, comment); + WorldPackets::LFG::RideTicket ticket; + ticket.RequesterGuid = guid; + ticket.Id = GetQueueId(gguid); + ticket.Type = WorldPackets::LFG::RideType::Lfg; + ticket.Time = int32(time(nullptr)); std::string debugNames = ""; if (grp) // Begin rolecheck { @@ -576,6 +581,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const ObjectGuid pguid = plrg->GetGUID(); plrg->GetSession()->SendLfgUpdateStatus(updateData, true); SetState(pguid, LFG_STATE_ROLECHECK); + SetTicket(pguid, ticket); if (!isContinue) SetSelectedDungeons(pguid, dungeons); roleCheck.roles[pguid] = 0; @@ -608,18 +614,12 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const SetCallToArmsRewardEnligible(player->GetGUID(), true); // Send update to player - player->GetSession()->SendLfgJoinResult(joinData); - if (!isRaid) - { - player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE, dungeons, comment), false); - SetState(gguid, LFG_STATE_QUEUED); - } - else - { - player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_JOIN_RAIDBROWSER, dungeons, comment), false); - SetState(gguid, LFG_STATE_RAIDBROWSER); - } + SetTicket(guid, ticket); SetRoles(guid, roles); + player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(LFG_UPDATETYPE_JOIN_QUEUE_INITIAL, dungeons, comment), false); + SetState(guid, isRaid ? LFG_STATE_RAIDBROWSER : LFG_STATE_QUEUED); + player->GetSession()->SendLfgUpdateStatus(LfgUpdateData(isRaid ? LFG_UPDATETYPE_JOIN_RAIDBROWSER : LFG_UPDATETYPE_ADDED_TO_QUEUE, dungeons, comment), false); + player->GetSession()->SendLfgJoinResult(joinData); debugNames.append(player->GetName()); } @@ -704,6 +704,15 @@ void LFGMgr::LeaveLfg(ObjectGuid guid, bool disconnected) } } +WorldPackets::LFG::RideTicket const* LFGMgr::GetTicket(ObjectGuid guid) const +{ + auto itr = PlayersStore.find(guid); + if (itr != PlayersStore.end()) + return &itr->second.GetTicket(); + + return nullptr; +} + /** Update the Role check info with the player selected role. @@ -755,11 +764,7 @@ void LFGMgr::UpdateRoleCheck(ObjectGuid gguid, ObjectGuid guid /* = ObjectGuid:: } } - LfgJoinResult joinResult = LFG_JOIN_FAILED; - if (roleCheck.state == LFG_ROLECHECK_MISSING_ROLE || roleCheck.state == LFG_ROLECHECK_WRONG_ROLES) - joinResult = LFG_JOIN_ROLE_CHECK_FAILED; - - LfgJoinResultData joinData = LfgJoinResultData(joinResult, roleCheck.state); + LfgJoinResultData joinData = LfgJoinResultData(LFG_JOIN_ROLE_CHECK_FAILED, roleCheck.state); for (LfgRolesMap::const_iterator it = roleCheck.roles.begin(); it != roleCheck.roles.end(); ++it) { ObjectGuid pguid = it->first; @@ -1363,7 +1368,7 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* { TC_LOG_DEBUG("lfg.teleport", "Player %s not in group/lfggroup or dungeon not found!", player->GetName().c_str()); - player->GetSession()->SendLfgTeleportError(uint8(LFG_TELEPORTERROR_INVALID_LOCATION)); + player->GetSession()->SendLfgTeleportError(uint8(LFG_TELEPORT_RESULT_NO_RETURN_LOCATION)); return; } @@ -1377,20 +1382,20 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* return; } - LfgTeleportError error = LFG_TELEPORTERROR_OK; + LfgTeleportResult error = LFG_TELEPORT_RESULT_NONE; if (!player->IsAlive()) - error = LFG_TELEPORTERROR_PLAYER_DEAD; + error = LFG_TELEPORT_RESULT_DEAD; else if (player->IsFalling() || player->HasUnitState(UNIT_STATE_JUMPING)) - error = LFG_TELEPORTERROR_FALLING; + error = LFG_TELEPORT_RESULT_FALLING; else if (player->IsMirrorTimerActive(FATIGUE_TIMER)) - error = LFG_TELEPORTERROR_FATIGUE; + error = LFG_TELEPORT_RESULT_EXHAUSTION; else if (player->GetVehicle()) - error = LFG_TELEPORTERROR_IN_VEHICLE; + error = LFG_TELEPORT_RESULT_ON_TRANSPORT; else if (player->GetCharmGUID()) - error = LFG_TELEPORTERROR_CHARMING; + error = LFG_TELEPORT_RESULT_IMMUNE_TO_SUMMONS; else if (player->HasAura(9454)) // check Freeze debuff - error = LFG_TELEPORTERROR_INVALID_LOCATION; + error = LFG_TELEPORT_RESULT_NO_RETURN_LOCATION; else if (player->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance { uint32 mapid = dungeon->map; @@ -1436,12 +1441,12 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* } if (!player->TeleportTo(mapid, x, y, z, orientation)) - error = LFG_TELEPORTERROR_INVALID_LOCATION; + error = LFG_TELEPORT_RESULT_NO_RETURN_LOCATION; } else { if (player->IsInCombat()) - error = LFG_TELEPORTERROR_IN_COMBAT; + error = LFG_TELEPORT_RESULT_IMMUNE_TO_SUMMONS; else if (player->GetMapId() == uint32(dungeon->map)) { player->SetLFGLeavePoint(); @@ -1449,7 +1454,7 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* } } - if (error != LFG_TELEPORTERROR_OK) + if (error != LFG_TELEPORT_RESULT_NONE) player->GetSession()->SendLfgTeleportError(uint8(error)); TC_LOG_DEBUG("lfg.teleport", "Player %s is being teleported in to map %u " @@ -1948,6 +1953,11 @@ void LFGMgr::DecreaseKicksLeft(ObjectGuid guid) TC_LOG_TRACE("lfg.data.group.kicksleft.decrease", "Group: %s, Kicks: %u", guid.ToString().c_str(), GroupsStore[guid].GetKicksLeft()); } +void LFGMgr::SetTicket(ObjectGuid guid, WorldPackets::LFG::RideTicket const& ticket) +{ + PlayersStore[guid].SetTicket(ticket); +} + void LFGMgr::RemovePlayerData(ObjectGuid guid) { TC_LOG_TRACE("lfg.data.player.remove", "Player: %s", guid.ToString().c_str()); diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 721c66940aa..115d5198979 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -33,6 +33,14 @@ class Map; struct LFGDungeonEntry; enum Difficulty : uint8; +namespace WorldPackets +{ + namespace LFG + { + struct RideTicket; + } +} + namespace lfg { @@ -82,17 +90,21 @@ enum LfgProposalState }; /// Teleport errors -enum LfgTeleportError +enum LfgTeleportResult : uint8 { // 7 = "You can't do that right now" | 5 = No client reaction - LFG_TELEPORTERROR_OK = 0, // Internal use - LFG_TELEPORTERROR_PLAYER_DEAD = 1, - LFG_TELEPORTERROR_FALLING = 2, - LFG_TELEPORTERROR_IN_VEHICLE = 3, - LFG_TELEPORTERROR_FATIGUE = 4, - LFG_TELEPORTERROR_INVALID_LOCATION = 6, - LFG_TELEPORTERROR_CHARMING = 7, - LFG_TELEPORTERROR_IN_COMBAT = 8 + LFG_TELEPORT_RESULT_NONE = 0, // Internal use + LFG_TELEPORT_RESULT_DEAD = 1, + LFG_TELEPORT_RESULT_FALLING = 2, + LFG_TELEPORT_RESULT_ON_TRANSPORT = 3, + LFG_TELEPORT_RESULT_EXHAUSTION = 4, + LFG_TELEPORT_RESULT_NO_RETURN_LOCATION = 6, + LFG_TELEPORT_RESULT_IMMUNE_TO_SUMMONS = 8 // FIXME - It can be 7 or 8 (Need proper data) + + // unknown values + //LFG_TELEPORT_RESULT_NOT_IN_DUNGEON, + //LFG_TELEPORT_RESULT_NOT_ALLOWED, + //LFG_TELEPORT_RESULT_ALREADY_IN_DUNGEON }; /// Queue join results @@ -187,14 +199,13 @@ struct LfgUpdateData // Data needed by SMSG_LFG_QUEUE_STATUS struct LfgQueueStatusData { - LfgQueueStatusData(uint8 _queueId = 0, uint32 _dungeonId = 0, time_t _joinTime = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1, + LfgQueueStatusData(uint8 _queueId = 0, uint32 _dungeonId = 0, int32 _waitTime = -1, int32 _waitTimeAvg = -1, int32 _waitTimeTank = -1, int32 _waitTimeHealer = -1, int32 _waitTimeDps = -1, uint32 _queuedTime = 0, uint8 _tanks = 0, uint8 _healers = 0, uint8 _dps = 0) : - queueId(_queueId), dungeonId(_dungeonId), joinTime(_joinTime), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank), + queueId(_queueId), dungeonId(_dungeonId), waitTime(_waitTime), waitTimeAvg(_waitTimeAvg), waitTimeTank(_waitTimeTank), waitTimeHealer(_waitTimeHealer), waitTimeDps(_waitTimeDps), queuedTime(_queuedTime), tanks(_tanks), healers(_healers), dps(_dps) { } uint8 queueId; uint32 dungeonId; - time_t joinTime; int32 waitTime; int32 waitTimeAvg; int32 waitTimeTank; @@ -435,6 +446,8 @@ class TC_GAME_API LFGMgr void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string const& comment); /// Leaves lfg void LeaveLfg(ObjectGuid guid, bool disconnected = false); + /// Gets unique join queue data + WorldPackets::LFG::RideTicket const* GetTicket(ObjectGuid guid) const; // LfgQueue /// Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON) @@ -467,6 +480,7 @@ class TC_GAME_API LFGMgr void SetDungeon(ObjectGuid guid, uint32 dungeon); void SetSelectedDungeons(ObjectGuid guid, LfgDungeonSet const& dungeons); void DecreaseKicksLeft(ObjectGuid guid); + void SetTicket(ObjectGuid guid, WorldPackets::LFG::RideTicket const& ticket); void SetState(ObjectGuid guid, LfgState state); void SetVoteKick(ObjectGuid gguid, bool active); void RemovePlayerData(ObjectGuid guid); diff --git a/src/server/game/DungeonFinding/LFGPlayerData.cpp b/src/server/game/DungeonFinding/LFGPlayerData.cpp index 386bc5aa618..971717088d3 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.cpp +++ b/src/server/game/DungeonFinding/LFGPlayerData.cpp @@ -26,6 +26,11 @@ LfgPlayerData::LfgPlayerData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NO LfgPlayerData::~LfgPlayerData() { } +void LfgPlayerData::SetTicket(WorldPackets::LFG::RideTicket const& ticket) +{ + m_Ticket = ticket; +} + void LfgPlayerData::SetState(LfgState state) { switch (state) @@ -84,6 +89,11 @@ void LfgPlayerData::SetCallToArmsRewardEnligible(bool apply) m_CallToArmsRewardEnligible = apply; } +WorldPackets::LFG::RideTicket const& LfgPlayerData::GetTicket() const +{ + return m_Ticket; +} + LfgState LfgPlayerData::GetState() const { return m_State; diff --git a/src/server/game/DungeonFinding/LFGPlayerData.h b/src/server/game/DungeonFinding/LFGPlayerData.h index 0de93f1d514..f2031904a80 100644 --- a/src/server/game/DungeonFinding/LFGPlayerData.h +++ b/src/server/game/DungeonFinding/LFGPlayerData.h @@ -19,6 +19,7 @@ #define _LFGPLAYERDATA_H #include "LFG.h" +#include "LFGPacketsCommon.h" namespace lfg { @@ -33,6 +34,7 @@ class TC_GAME_API LfgPlayerData ~LfgPlayerData(); // General + void SetTicket(WorldPackets::LFG::RideTicket const& ticket); void SetState(LfgState state); void RestoreState(); void SetTeam(uint8 team); @@ -44,6 +46,7 @@ class TC_GAME_API LfgPlayerData void SetSelectedDungeons(const LfgDungeonSet& dungeons); // General + WorldPackets::LFG::RideTicket const& GetTicket() const; LfgState GetState() const; LfgState GetOldState() const; uint8 GetTeam() const; @@ -60,6 +63,7 @@ class TC_GAME_API LfgPlayerData private: // General + WorldPackets::LFG::RideTicket m_Ticket; ///< Join ticket LfgState m_State; ///< State if group in LFG LfgState m_OldState; ///< Old State - Used to restore state after failed Rolecheck/Proposal // Player diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp index 06f5e55d592..7dd6fa46acf 100644 --- a/src/server/game/DungeonFinding/LFGQueue.cpp +++ b/src/server/game/DungeonFinding/LFGQueue.cpp @@ -657,7 +657,7 @@ void LFGQueue::UpdateQueueTimers(uint8 queueId, time_t currTime, uint32 &tankCou if (queueinfo.bestCompatible.empty()) FindBestCompatibleInQueue(itQueue); - LfgQueueStatusData queueData(queueId, dungeonId, queueinfo.joinTime, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps); + LfgQueueStatusData queueData(queueId, dungeonId, waitTime, wtAvg, wtTank, wtHealer, wtDps, queuedTime, queueinfo.tanks, queueinfo.healers, queueinfo.dps); for (LfgRolesMap::const_iterator itPlayer = queueinfo.roles.begin(); itPlayer != queueinfo.roles.end(); ++itPlayer) { ObjectGuid pguid = itPlayer->first; diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index e0a222288df..9f540e4f57a 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -42,10 +42,7 @@ void LFGPlayerScript::OnLogout(Player* player) return; if (!player->GetGroup()) - { - player->GetSession()->SendLfgLfrList(false); sLFGMgr->LeaveLfg(player->GetGUID()); - } else if (player->GetSession()->PlayerDisconnected()) sLFGMgr->LeaveLfg(player->GetGUID(), true); } diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index fd98bd74fa2..32786f68963 100644 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -27,116 +27,6 @@ #include "WorldPacket.h" #include "WorldSession.h" -void BuildPlayerLockDungeonBlock(WorldPacket& data, lfg::LfgLockMap const& lock) -{ - data << uint32(lock.size()); // Size of lock dungeons - for (lfg::LfgLockMap::const_iterator it = lock.begin(); it != lock.end(); ++it) - { - TC_LOG_TRACE("lfg", "BuildPlayerLockDungeonBlock:: DungeonID: %u Lock status: %u Required itemLevel: %u Current itemLevel: %f", - (it->first & 0x00FFFFFF), it->second.lockStatus, it->second.requiredItemLevel, it->second.currentItemLevel); - - data << uint32(it->first); // Dungeon entry (id + type) - data << uint32(it->second.lockStatus); // Lock status - data << uint32(it->second.requiredItemLevel); // Required itemLevel - data << uint32(it->second.currentItemLevel); // Current itemLevel - } -} - -void BuildPartyLockDungeonBlock(WorldPacket& data, lfg::LfgLockPartyMap const& lockMap) -{ - data << uint8(lockMap.size()); - for (lfg::LfgLockPartyMap::const_iterator it = lockMap.begin(); it != lockMap.end(); ++it) - { - data << uint64(it->first); // Player guid - BuildPlayerLockDungeonBlock(data, it->second); - } -} - -void BuildQuestReward(WorldPacket& data, Quest const* quest, Quest const* bonusQuest, Player* player) -{ - uint8 rewCount = quest->GetRewItemsCount() + quest->GetRewCurrencyCount(); - uint32 rewMoney = player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) ? quest->GetRewOrReqMoney() : quest->GetRewMoneyMaxLevel(); - uint32 rewXP = player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) ? quest->XPValue(player) : 0; - - if (bonusQuest) - { - rewCount += bonusQuest->GetRewItemsCount() + bonusQuest->GetRewCurrencyCount(); - rewMoney += player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) ? bonusQuest->GetRewOrReqMoney() : bonusQuest->GetRewMoneyMaxLevel(); - rewXP += player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) ? bonusQuest->XPValue(player) : 0; - } - - data << uint32(rewMoney); - data << uint32(rewXP); - data << uint8(rewCount); - - if (rewCount) - { - for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - { - if (uint32 currencyId = quest->RewardCurrencyId[i]) - { - uint32 rewardCurrencyCount = quest->RewardCurrencyCount[i]; - - CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(currencyId); - if (currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) - rewardCurrencyCount = rewardCurrencyCount * CURRENCY_PRECISION; - - data << uint32(currencyId); - data << uint32(0); - data << uint32(rewardCurrencyCount); - data << uint8(1); // Is currency - } - } - - if (bonusQuest) - { - for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - { - if (uint32 currencyId = bonusQuest->RewardCurrencyId[i]) - { - uint32 rewardCurrencyCount = bonusQuest->RewardCurrencyCount[i]; - - CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(currencyId); - if (currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) - rewardCurrencyCount = rewardCurrencyCount * CURRENCY_PRECISION; - - data << uint32(currencyId); - data << uint32(0); - data << uint32(rewardCurrencyCount); - data << uint8(1); // Is currency - } - } - } - - for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i) - { - if (uint32 itemId = quest->RewardItemId[i]) - { - ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId); - data << uint32(itemId); - data << uint32(item ? item->DisplayInfoID : 0); - data << uint32(quest->RewardItemIdCount[i]); - data << uint8(0); // Is currency - } - } - - if (bonusQuest) - { - for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i) - { - if (uint32 itemId = bonusQuest->RewardItemId[i]) - { - ItemTemplate const* item = sObjectMgr->GetItemTemplate(itemId); - data << uint32(itemId); - data << uint32(item ? item->DisplayInfoID : 0); - data << uint32(bonusQuest->RewardItemIdCount[i]); - data << uint8(0); // Is currency - } - } - } - } -} - void WorldSession::HandleLfgJoinOpcode(WorldPackets::LFG::LFGJoin& lfgJoin) { if (!sLFGMgr->isOptionEnabled(lfg::LFG_OPTION_ENABLE_DUNGEON_FINDER | lfg::LFG_OPTION_ENABLE_RAID_BROWSER) || @@ -236,159 +126,96 @@ void WorldSession::HandleLfgGetLockInfoOpcode(WorldPackets::LFG::LFGGetSystemInf void WorldSession::SendLfgPlayerLockInfo() { - Player* player = GetPlayer(); - ObjectGuid guid = player->GetGUID(); + TC_LOG_DEBUG("lfg", "SMSG_LFG_PLAYER_INFO %s", GetPlayerInfo().c_str()); // Get Random dungeons that can be done at a certain level and expansion - uint8 level = player->getLevel(); - lfg::LfgDungeonSet const& randomDungeons = sLFGMgr->GetRandomAndSeasonalDungeons(level, player->GetSession()->Expansion()); + uint8 level = _player->getLevel(); + lfg::LfgDungeonSet const& randomDungeons = sLFGMgr->GetRandomAndSeasonalDungeons(level, _player->GetSession()->Expansion()); + + WorldPackets::LFG::LFGPlayerInfo lfgPlayerInfo; // Get player locked Dungeons - lfg::LfgLockMap const& lock = sLFGMgr->GetLockedDungeons(guid); - uint32 rsize = uint32(randomDungeons.size()); - uint32 lsize = uint32(lock.size()); + for (auto const& lock : sLFGMgr->GetLockedDungeons(_player->GetGUID())) + lfgPlayerInfo.BlackList.Slot.emplace_back(lock.first, lock.second.lockStatus, lock.second.requiredItemLevel, lock.second.currentItemLevel); - TC_LOG_DEBUG("lfg", "SMSG_LFG_PLAYER_INFO %s", GetPlayerInfo().c_str()); - WorldPacket data(SMSG_LFG_PLAYER_INFO, 1 + rsize * (4 + 1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4) + 4 + lsize * (1 + 4 + 4 + 4 + 4 + 1 + 4 + 4 + 4)); - - data << uint8(randomDungeons.size()); // Random Dungeon count - for (lfg::LfgDungeonSet::const_iterator it = randomDungeons.begin(); it != randomDungeons.end(); ++it) + for (uint32 slot : randomDungeons) { - uint32 dungeonId = *it; - data << uint32(dungeonId); // Dungeon Entry (id + type) - lfg::LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(dungeonId, level); - bool firstCompletion = false; - Quest const* currentQuest = nullptr; - uint32 rewValorPoints = 0; + lfgPlayerInfo.Dungeon.emplace_back(); + WorldPackets::LFG::LfgPlayerDungeonInfo& playerDungeonInfo = lfgPlayerInfo.Dungeon.back(); + playerDungeonInfo.Slot = slot; - if (reward) + bool firstReward = false; + Quest const* currentQuest = nullptr; + + if (lfg::LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(slot, level)) { if (Quest const* firstQuest = sObjectMgr->GetQuestTemplate(reward->firstQuest)) { - firstCompletion = player->CanRewardQuest(firstQuest, false); + firstReward = _player->CanRewardQuest(firstQuest, false); if (reward->completionsPerPeriod) - firstCompletion = player->SatisfyFirstLFGReward(dungeonId & 0x00FFFFFF, reward->completionsPerPeriod); + firstReward = _player->SatisfyFirstLFGReward(slot & 0x00FFFFFF, reward->completionsPerPeriod); - if (firstCompletion) + if (firstReward) currentQuest = firstQuest; - - for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; i++) - if (firstQuest->RewardCurrencyId[i] == CURRENCY_TYPE_VALOR_POINTS) - rewValorPoints += firstQuest->RewardCurrencyCount[i] * CURRENCY_PRECISION; } if (Quest const* otherQuest = sObjectMgr->GetQuestTemplate(reward->otherQuest)) - { - if (!firstCompletion) + if (!firstReward) currentQuest = otherQuest; - for (uint8 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; i++) - if (otherQuest->RewardCurrencyId[i] == CURRENCY_TYPE_VALOR_POINTS) - rewValorPoints += otherQuest->RewardCurrencyCount[i] * CURRENCY_PRECISION; - } - } - - data << uint8(firstCompletion); - - CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(CURRENCY_TYPE_VALOR_POINTS); - - if (currency && rewValorPoints && !reward->completionsPerPeriod) - { - uint32 weekCap = player->GetCurrencyWeekCap(currency); - - data << uint32(rewValorPoints); // currencyQuantity (valor points from selected dungeon) - data << uint32(weekCap); // some sort of overall cap/weekly cap - data << uint32(CURRENCY_TYPE_VALOR_POINTS); // currencyID (displays name above the cap bar) - data << uint32(0); // tier1Quantity (current valor points from lfr) - data << uint32(weekCap); // tier1Limit (total valor points from lfr) - data << uint32(0); // overallQuantity (current valor points from lfg - always 0) - data << uint32(weekCap); // overallLimit (total valor points from lfg) - data << uint32(player->GetCurrencyOnWeek(CURRENCY_TYPE_VALOR_POINTS, false)); // periodPurseQuantity (valor points this week) - data << uint32(weekCap); // periodPurseLimit (weekly cap) - data << uint32(player->GetCurrency(CURRENCY_TYPE_VALOR_POINTS, false)); // purseQuantity (overall valor points) - data << uint32(0); // purseLimit - data << uint32(rewValorPoints); // some sort of reward for completion - } - else if (firstCompletion && reward && reward->completionsPerPeriod && !reward->dailyReset) - { - data << uint32(1); // currencyQuantity - data << uint32(reward->completionsPerPeriod); // some sort of overall cap/weekly cap - data << uint32(0); // currencyID - data << uint32(0); // tier1Quantity - data << uint32(reward->completionsPerPeriod); // tier1Limit - data << uint32(player->GetFirstRewardCountForDungeonId(dungeonId & 0x00FFFFFF)); // overallQuantity - data << uint32(reward->completionsPerPeriod); // overallLimit - data << uint32(0); // periodPurseQuantity - data << uint32(0); // periodPurseLimit - data << uint32(0); // purseQuantity - data << uint32(0); // purseLimit - data << uint32(1); // some sort of reward for completion - } - else - { - data << uint32(0); // currencyQuantity - data << uint32(0); // some sort of overall cap/weekly cap - data << uint32(0); // currencyID - data << uint32(0); // tier1Quantity - data << uint32(0); // tier1Limit - data << uint32(0); // overallQuantity - data << uint32(0); // overallLimit - data << uint32(0); // periodPurseQuantity - data << uint32(0); // periodPurseLimit - data << uint32(0); // purseQuantity - data << uint32(0); // purseLimit - data << uint32(0); // some sort of reward for completion - } - - data << uint32(0); // completedEncounters - - bool isCallToArmsEligible = sLFGMgr->IsCallToArmsEnabled() && sLFGMgr->IsCallToArmsEnligible(player, dungeonId & 0x00FFFFFF); - uint8 roleMask = sLFGMgr->GetCallToArmsEnligibleRoles(); - - data << uint8(isCallToArmsEligible && roleMask); // Call to Arms eligible - Quest const* ctaQuest = sObjectMgr->GetQuestTemplate(lfg::LFG_CALL_TO_ARMS_QUEST); - - if (isCallToArmsEligible && roleMask && ctaQuest) - { - if (sLFGMgr->IsCallToArmsRewardEnligible(guid)) - roleMask |= sLFGMgr->GetRoles(guid); - - bool rewardSent = false; - - for (uint8 i = 0; i < 3; i++) + if (firstReward && reward->completionsPerPeriod) { - data << uint32(roleMask); - if (!rewardSent) - { - rewardSent = true; - BuildQuestReward(data, ctaQuest, nullptr, player); - } - else - { - data << uint32(0); - data << uint32(0); - data << uint8(0); - } + playerDungeonInfo.CompletionQuantity = 1; + playerDungeonInfo.CompletionLimit = reward->completionsPerPeriod; + playerDungeonInfo.SpecificLimit = reward->completionsPerPeriod; + playerDungeonInfo.OverallQuantity = _player->GetFirstRewardCountForDungeonId(slot & 0x00FFFFFF); + playerDungeonInfo.OverallLimit = reward->completionsPerPeriod; + playerDungeonInfo.Quantity = 1; } } - else - { - for (uint32 i = 0; i < 3; ++i) - data << uint32(0); - } if (currentQuest) - BuildQuestReward(data, currentQuest, nullptr, player); - else { - data << uint32(0); // Money - data << uint32(0); // XP - data << uint8(0); // Reward count + playerDungeonInfo.Rewards.RewardMoney = _player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) ? currentQuest->GetRewOrReqMoney() : currentQuest->GetRewMoneyMaxLevel(); + playerDungeonInfo.Rewards.RewardXP = _player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) ? currentQuest->XPValue(_player) : 0; + for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i) + if (uint32 itemId = currentQuest->RewardItemId[i]) + playerDungeonInfo.Rewards.Item.emplace_back(itemId, currentQuest->RewardItemIdCount[i]); + + for (uint32 i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) + if (uint32 currencyId = currentQuest->RewardCurrencyId[i]) + if (CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(currencyId)) + { + if (currency->Flags & CURRENCY_FLAG_HIGH_PRECISION) + playerDungeonInfo.Rewards.Currency.emplace_back(currencyId, currentQuest->RewardCurrencyCount[i] * CURRENCY_PRECISION); + else + playerDungeonInfo.Rewards.Currency.emplace_back(currencyId, currentQuest->RewardCurrencyCount[i]); + } + } + + for (auto itr : playerDungeonInfo.Rewards.Currency) + { + if (itr.CurrencyID == CURRENCY_TYPE_VALOR_POINTS) + { + CurrencyTypesEntry const* currency = sCurrencyTypesStore.LookupEntry(CURRENCY_TYPE_VALOR_POINTS); + if (!currency) + continue; + + uint32 weeklyCap = _player->GetCurrencyWeekCap(currency); + playerDungeonInfo.CompletionQuantity += itr.Quantity; + playerDungeonInfo.CompletionLimit = weeklyCap; + playerDungeonInfo.CompletionCurrencyID = itr.CurrencyID; + playerDungeonInfo.SpecificLimit = weeklyCap; + playerDungeonInfo.OverallLimit = weeklyCap; + playerDungeonInfo.PurseWeeklyQuantity = _player->GetCurrencyOnWeek(CURRENCY_TYPE_VALOR_POINTS, false); + playerDungeonInfo.PurseWeeklyLimit = weeklyCap; + playerDungeonInfo.PurseQuantity = _player->GetCurrency(CURRENCY_TYPE_VALOR_POINTS, false); + playerDungeonInfo.Quantity += itr.Quantity; + } } } - BuildPlayerLockDungeonBlock(data, lock); - SendPacket(&data); + SendPacket(lfgPlayerInfo.Write()); } void WorldSession::SendLfgPartyLockInfo() @@ -398,8 +225,9 @@ void WorldSession::SendLfgPartyLockInfo() if (!group) return; + WorldPackets::LFG::LFGPartyInfo lfgPartyInfo; + // Get the locked dungeons of the other party members - lfg::LfgLockPartyMap lockMap; for (GroupReference* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* plrg = itr->GetSource(); @@ -410,17 +238,15 @@ void WorldSession::SendLfgPartyLockInfo() if (pguid == guid) continue; - lockMap[pguid] = sLFGMgr->GetLockedDungeons(pguid); + lfgPartyInfo.Player.emplace_back(); + WorldPackets::LFG::LFGBlackList& lfgBlackList = lfgPartyInfo.Player.back(); + lfgBlackList.PlayerGuid = pguid; + for (auto const& lock : sLFGMgr->GetLockedDungeons(pguid)) + lfgBlackList.Slot.emplace_back(lock.first, lock.second.lockStatus, lock.second.requiredItemLevel, lock.second.currentItemLevel); } - uint32 size = 0; - for (lfg::LfgLockPartyMap::const_iterator it = lockMap.begin(); it != lockMap.end(); ++it) - size += 8 + 4 + uint32(it->second.size()) * (4 + 4 + 4 + 4); - TC_LOG_DEBUG("lfg", "SMSG_LFG_PARTY_INFO %s", GetPlayerInfo().c_str()); - WorldPacket data(SMSG_LFG_PARTY_INFO, 1 + size); - BuildPartyLockDungeonBlock(data, lockMap); - SendPacket(&data); + SendPacket(lfgPartyInfo.Write()); } void WorldSession::HandleLfrJoinOpcode(WorldPacket& recvData) @@ -468,12 +294,8 @@ void WorldSession::HandleLfgGetStatus(WorldPacket& /*recvData*/) void WorldSession::SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, bool party) { bool join = false; - bool extraData = false; bool queued = false; - uint8 size = uint8(updateData.dungeons.size()); ObjectGuid guid = _player->GetGUID(); - time_t joinTime = sLFGMgr->GetQueueJoinTime(_player->GetGUID()); - uint32 queueId = sLFGMgr->GetQueueId(_player->GetGUID()); switch (updateData.updateType) { @@ -483,12 +305,10 @@ void WorldSession::SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, boo case lfg::LFG_UPDATETYPE_JOIN_QUEUE: case lfg::LFG_UPDATETYPE_ADDED_TO_QUEUE: // Rolecheck Success join = true; - extraData = true; queued = true; break; case lfg::LFG_UPDATETYPE_JOIN_RAIDBROWSER: join = true; - extraData = true; break; case lfg::LFG_UPDATETYPE_PROPOSAL_BEGIN: join = true; @@ -504,42 +324,24 @@ void WorldSession::SendLfgUpdateStatus(lfg::LfgUpdateData const& updateData, boo TC_LOG_DEBUG("lfg", "SMSG_LFG_UPDATE_STATUS %s updatetype: %u, party %s", GetPlayerInfo().c_str(), updateData.updateType, party ? "true" : "false"); - WorldPacket data(SMSG_LFG_UPDATE_STATUS, 1 + 8 + 3 + 2 + 1 + updateData.comment.length() + 4 + 4 + 1 + 1 + 1 + 4 + size); - data.WriteBit(guid[1]); - data.WriteBit(party); - data.WriteBits(size, 24); - data.WriteBit(guid[6]); - data.WriteBit(extraData); // Extra info - data.WriteBits(updateData.comment.length(), 9); - data.WriteBit(guid[4]); - data.WriteBit(guid[7]); - data.WriteBit(guid[2]); - data.WriteBit(join); // LFG Join - data.WriteBit(guid[0]); - data.WriteBit(guid[3]); - data.WriteBit(guid[5]); - data.WriteBit(queued); // Join the queue + WorldPackets::LFG::LFGUpdateStatus lfgUpdateStatus; + if (WorldPackets::LFG::RideTicket const* ticket = sLFGMgr->GetTicket(guid)) + lfgUpdateStatus.Ticket = *ticket; - data << uint8(updateData.updateType); // Lfg Update type - data.WriteString(updateData.comment); - data << uint32(queueId); // Queue Id - data << uint32(joinTime); // Join date - data.WriteByteSeq(guid[6]); - for (uint8 i = 0; i < 3; ++i) - data << uint8(0); // unk - Always 0 + lfgUpdateStatus.Reason = updateData.updateType; + std::transform(updateData.dungeons.begin(), updateData.dungeons.end(), std::back_inserter(lfgUpdateStatus.Slots), [](uint32 dungeonId) + { + return sLFGMgr->GetLFGDungeonEntry(dungeonId); + }); + lfgUpdateStatus.RequestedRoles = sLFGMgr->GetRoles(_player->GetGUID()); + //lfgUpdateStatus.SuspendedPlayers; + lfgUpdateStatus.IsParty = party; + lfgUpdateStatus.Joined = join; + lfgUpdateStatus.LfgJoined = updateData.updateType != lfg::LFG_UPDATETYPE_REMOVED_FROM_QUEUE; + lfgUpdateStatus.Queued = queued; + lfgUpdateStatus.Comment = updateData.comment; - data.WriteByteSeq(guid[1]); - data.WriteByteSeq(guid[2]); - data.WriteByteSeq(guid[4]); - data.WriteByteSeq(guid[3]); - data.WriteByteSeq(guid[5]); - data.WriteByteSeq(guid[0]); - data << uint32(3); - data.WriteByteSeq(guid[7]); - for (lfg::LfgDungeonSet::const_iterator it = updateData.dungeons.begin(); it != updateData.dungeons.end(); ++it) - data << uint32(*it); - - SendPacket(&data); + SendPacket(lfgUpdateStatus.Write()); } void WorldSession::SendLfgRoleChosen(ObjectGuid guid, uint8 roles) @@ -707,7 +509,7 @@ void WorldSession::SendLfgQueueStatus(lfg::LfgQueueStatusData const& queueData) data.WriteByteSeq(guid[4]); data.WriteByteSeq(guid[6]); data << int32(queueData.waitTime); // Wait Time - data << uint32(queueData.joinTime); // Join time + data << uint32(0); // Join time data << uint32(queueData.dungeonId); // Dungeon data << uint32(queueData.queuedTime); // Player wait time in queue data.WriteByteSeq(guid[5]); @@ -737,7 +539,7 @@ void WorldSession::SendLfgPlayerReward(lfg::LfgPlayerRewardData const& rewardDat WorldPacket data(SMSG_LFG_PLAYER_REWARD, 4 + 4 + 1 + 4 + 4 + 4 + 4 + 4 + 1 + itemNum * (4 + 4 + 4)); data << uint32(rewardData.rdungeonEntry); // Random Dungeon Finished data << uint32(rewardData.sdungeonEntry); // Dungeon Finished - BuildQuestReward(data, rewardData.quest, rewardData.callToArmsQuest,GetPlayer()); + //BuildQuestReward(data, rewardData.quest, rewardData.callToArmsQuest,GetPlayer()); SendPacket(&data); } diff --git a/src/server/game/Server/Packets/LFGPackets.cpp b/src/server/game/Server/Packets/LFGPackets.cpp index cc5cb90e511..eb8de85ab8b 100644 --- a/src/server/game/Server/Packets/LFGPackets.cpp +++ b/src/server/game/Server/Packets/LFGPackets.cpp @@ -135,3 +135,152 @@ void WorldPackets::LFG::LFGGetSystemInfo::Read() { Player = _worldPacket.ReadBit(); } + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGBlackListSlot const& lfgBlackListSlot) +{ + data << uint32(lfgBlackListSlot.Slot); + data << uint32(lfgBlackListSlot.Reason); + data << uint32(lfgBlackListSlot.SubReason1); + data << uint32(lfgBlackListSlot.SubReason2); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LFGBlackList const& blackList) +{ + if (blackList.PlayerGuid) + data << *blackList.PlayerGuid; + + data << uint32(blackList.Slot.size()); + for (WorldPackets::LFG::LFGBlackListSlot const& slot : blackList.Slot) + data << slot; + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerQuestRewardItem const& playerQuestRewardItem) +{ + ItemTemplate const* item = sObjectMgr->GetItemTemplate(playerQuestRewardItem.ItemID); + data << int32(playerQuestRewardItem.ItemID); + data << int32(item ? item->DisplayInfoID : 0); + data << int32(playerQuestRewardItem.Quantity); + data << uint8(0); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerQuestRewardCurrency const& playerQuestRewardCurrency) +{ + data << int32(playerQuestRewardCurrency.CurrencyID); + data << int32(0); + data << int32(playerQuestRewardCurrency.Quantity); + data << uint8(1); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerQuestReward const& playerQuestReward) +{ + data << int32(playerQuestReward.RewardMoney); + data << int32(playerQuestReward.RewardXP); + data << uint8(playerQuestReward.Item.size() + playerQuestReward.Currency.size()); + + for (WorldPackets::LFG::LfgPlayerQuestRewardCurrency const& currency : playerQuestReward.Currency) + data << currency; + + for (WorldPackets::LFG::LfgPlayerQuestRewardItem const& item : playerQuestReward.Item) + data << item; + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::LFG::LfgPlayerDungeonInfo const& playerDungeonInfo) +{ + data << uint32(playerDungeonInfo.Slot); + data << uint8(playerDungeonInfo.FirstReward); + data << uint32(playerDungeonInfo.CompletionQuantity); + data << uint32(playerDungeonInfo.CompletionLimit); + data << uint32(playerDungeonInfo.CompletionCurrencyID); + data << uint32(playerDungeonInfo.SpecificQuantity); + data << uint32(playerDungeonInfo.SpecificLimit); + data << uint32(playerDungeonInfo.OverallQuantity); + data << uint32(playerDungeonInfo.OverallLimit); + data << uint32(playerDungeonInfo.PurseWeeklyQuantity); + data << uint32(playerDungeonInfo.PurseWeeklyLimit); + data << uint32(playerDungeonInfo.PurseQuantity); + data << uint32(playerDungeonInfo.PurseLimit); + data << uint32(playerDungeonInfo.Quantity); + data << uint32(playerDungeonInfo.CompletedMask); + data << uint8(playerDungeonInfo.ShortageEligible); + + // Todo: Shortage System (Call to Arms) + for (uint8 i = 0; i < 3; i++) + data << uint32(0); + + data << playerDungeonInfo.Rewards; + + return data; +} + +WorldPacket const* WorldPackets::LFG::LFGPlayerInfo::Write() +{ + _worldPacket << uint8(Dungeon.size()); + for (LfgPlayerDungeonInfo const& playerDungeonInfo : Dungeon) + _worldPacket << playerDungeonInfo; + + _worldPacket << uint32(BlackList.Slot.size()); + for (WorldPackets::LFG::LFGBlackListSlot const& slot : BlackList.Slot) + _worldPacket << slot; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::LFG::LFGPartyInfo::Write() +{ + _worldPacket << uint8(Player.size()); + for (WorldPackets::LFG::LFGBlackList const& player : Player) + _worldPacket << player; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::LFG::LFGUpdateStatus::Write() +{ + _worldPacket.WriteBit(Ticket.RequesterGuid[1]); + _worldPacket.WriteBit(IsParty); + _worldPacket.WriteBits(Slots.size(), 24); + _worldPacket.WriteBit(Ticket.RequesterGuid[6]); + _worldPacket.WriteBit(Joined); + _worldPacket.WriteBits(Comment.length(), 9); + _worldPacket.WriteBit(Ticket.RequesterGuid[4]); + _worldPacket.WriteBit(Ticket.RequesterGuid[7]); + _worldPacket.WriteBit(Ticket.RequesterGuid[2]); + _worldPacket.WriteBit(LfgJoined); + _worldPacket.WriteBit(Ticket.RequesterGuid[0]); + _worldPacket.WriteBit(Ticket.RequesterGuid[3]); + _worldPacket.WriteBit(Ticket.RequesterGuid[5]); + _worldPacket.WriteBit(Queued); + _worldPacket << uint8(Reason); + _worldPacket.WriteString(Comment); + + _worldPacket << uint32(Ticket.Id); + _worldPacket << uint32(Ticket.Time); + _worldPacket.WriteByteSeq(Ticket.RequesterGuid[6]); + + for (uint8 i = 0; i < 3; ++i) + _worldPacket << uint8(0); // unk - Always 0 + + _worldPacket.WriteByteSeq(Ticket.RequesterGuid[1]); + _worldPacket.WriteByteSeq(Ticket.RequesterGuid[2]); + _worldPacket.WriteByteSeq(Ticket.RequesterGuid[4]); + _worldPacket.WriteByteSeq(Ticket.RequesterGuid[3]); + _worldPacket.WriteByteSeq(Ticket.RequesterGuid[5]); + _worldPacket.WriteByteSeq(Ticket.RequesterGuid[0]); + _worldPacket << uint32(Ticket.Type); + _worldPacket.WriteByteSeq(Ticket.RequesterGuid[7]); + + for (uint32 slot : Slots) + _worldPacket << uint32(slot); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/LFGPackets.h b/src/server/game/Server/Packets/LFGPackets.h index 60bd33cb3fa..1efcdae4c7a 100644 --- a/src/server/game/Server/Packets/LFGPackets.h +++ b/src/server/game/Server/Packets/LFGPackets.h @@ -115,6 +115,113 @@ namespace WorldPackets bool Player = false; }; + + struct LFGBlackListSlot + { + LFGBlackListSlot() { } + LFGBlackListSlot(uint32 slot, uint32 reason, int32 subReason1, int32 subReason2) + : Slot(slot), Reason(reason), SubReason1(subReason1), SubReason2(subReason2) { } + + uint32 Slot = 0; + uint32 Reason = 0; + int32 SubReason1 = 0; + int32 SubReason2 = 0; + }; + + struct LFGBlackList + { + Optional PlayerGuid; + std::vector Slot; + }; + + struct LfgPlayerQuestRewardItem + { + LfgPlayerQuestRewardItem() { } + LfgPlayerQuestRewardItem(int32 itemId, int32 quantity) : ItemID(itemId), Quantity(quantity) { } + + int32 ItemID = 0; + int32 Quantity = 0; + }; + + struct LfgPlayerQuestRewardCurrency + { + LfgPlayerQuestRewardCurrency() { } + LfgPlayerQuestRewardCurrency(int32 currencyID, int32 quantity) : CurrencyID(currencyID), Quantity(quantity) { } + + int32 CurrencyID = 0; + int32 Quantity = 0; + }; + + struct LfgPlayerQuestReward + { + int32 RewardMoney = 0; // Only used by SMSG_LFG_PLAYER_INFO + int32 RewardXP = 0; + std::vector Item; + std::vector Currency; // Only used by SMSG_LFG_PLAYER_INFO + Optional Honor; // Only used by SMSG_REQUEST_PVP_REWARDS_RESPONSE + }; + + struct LfgPlayerDungeonInfo + { + uint32 Slot = 0; + uint32 CompletionQuantity = 0; + uint32 CompletionLimit = 0; + uint32 CompletionCurrencyID = 0; + uint32 SpecificQuantity = 0; + uint32 SpecificLimit = 0; + uint32 OverallQuantity = 0; + uint32 OverallLimit = 0; + uint32 PurseWeeklyQuantity = 0; + uint32 PurseWeeklyLimit = 0; + uint32 PurseQuantity = 0; + uint32 PurseLimit = 0; + uint32 Quantity = 0; + uint32 CompletedMask = 0; + uint32 ShortageRoleMask = 0; + bool ShortageEligible = false; + bool FirstReward = false; + LfgPlayerQuestReward Rewards; + LfgPlayerQuestReward ShortageReward; + }; + + class LFGPlayerInfo final : public ServerPacket + { + public: + LFGPlayerInfo() : ServerPacket(SMSG_LFG_PLAYER_INFO) { } + + WorldPacket const* Write() override; + + LFGBlackList BlackList; + std::vector Dungeon; + }; + + class LFGPartyInfo final : public ServerPacket + { + public: + LFGPartyInfo() : ServerPacket(SMSG_LFG_PARTY_INFO) { } + + WorldPacket const* Write() override; + std::vector Player; + }; + + class LFGUpdateStatus final : public ServerPacket + { + public: + LFGUpdateStatus() : ServerPacket(SMSG_LFG_UPDATE_STATUS) { } + + WorldPacket const* Write() override; + + RideTicket Ticket; + uint8 Reason = 0; + std::vector Slots; + uint32 RequestedRoles = 0; + std::vector SuspendedPlayers; + std::string Comment; + bool IsParty = false; + bool Joined = false; + bool LfgJoined = false; + bool Queued = false; + }; } } diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index b167481e2a2..31d68a16411 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -67,6 +67,7 @@ struct LfgQueueStatusData; struct LfgPlayerRewardData; struct LfgRoleCheck; struct LfgUpdateData; +enum LfgTeleportResult : uint8; } namespace rbac @@ -86,6 +87,9 @@ namespace WorldPackets class LFGBootPlayerVote; class LFGTeleport; class LFGGetSystemInfo; + class LFGPlayerInfo; + class LFGPartyInfo; + class LFGUpdateStatus; } }