diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 79f76177d3..962cc376b7 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -8554,11 +8554,11 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type) { SetLootGUID(guid); - WorldPacket data(SMSG_LOOT_RESPONSE, 8 + 1 + 50 + 1 + 1); // we guess size - data << uint64(guid); - data << uint8(loot_type); - data << LootView(*loot, this, permission); - SendDirectMessage(&data); + WorldPackets::Loot::LootResponse packet; + packet.Owner = guid; + packet.AcquireReason = loot_type; + loot->BuildLootResponse(packet, this, permission); + SendDirectMessage(packet.Write()); // add 'this' player as one of the players that are looting 'loot' loot->AddLooter(GetGUID()); @@ -8572,11 +8572,11 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type) void Player::SendLootError(ObjectGuid guid, LootError error) const { - WorldPacket data(SMSG_LOOT_RESPONSE, 10); - data << uint64(guid); - data << uint8(LOOT_NONE); - data << uint8(error); - SendDirectMessage(&data); + WorldPackets::Loot::LootResponse lootResponse; + lootResponse.Owner = guid; + lootResponse.AcquireReason = LOOT_NONE; + lootResponse.FailureReason = error; + SendDirectMessage(lootResponse.Write()); } void Player::SendNotifyLootMoneyRemoved() const diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 6bd3110d2b..3e8ded560b 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1561,7 +1561,7 @@ void Group::CountTheRoll(Rolls::iterator rollI, Map* allowedMap) WorldPackets::Loot::DisenchantCredit disenchantCredit; disenchantCredit.Disenchanter = m_disenchantInfo.DisenchanterGUID; disenchantCredit.Item.ItemID = item->itemid; - disenchantCredit.Item.RandomPropertiesID = item->randomPropertyId.Type == ItemRandomEnchantmentType::Property ? item->randomPropertyId.Id : -item->randomPropertyId.Id; + disenchantCredit.Item.RandomPropertiesID = item->randomPropertyId.Type == ItemRandomEnchantmentType::Property ? item->randomPropertyId.Id : -int32(item->randomPropertyId.Id); disenchantCredit.Item.RandomPropertiesSeed = item->randomSuffix; BroadcastPacket(disenchantCredit.Write(), false); diff --git a/src/server/game/Loot/Loot.cpp b/src/server/game/Loot/Loot.cpp index a21505a9ad..369a073017 100644 --- a/src/server/game/Loot/Loot.cpp +++ b/src/server/game/Loot/Loot.cpp @@ -22,6 +22,7 @@ #include "ItemTemplate.h" #include "Log.h" #include "LootMgr.h" +#include "LootPackets.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Player.h" @@ -70,6 +71,9 @@ bool LootItem::AllowedForPlayer(Player const* player) const if (!sConditionMgr->IsObjectMeetToConditions(const_cast(player), conditions)) return false; + if (is_currency) + return true; + ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(itemid); if (!pProto) return false; @@ -610,40 +614,14 @@ bool Loot::hasOverThresholdItem() const return false; } -ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li) +void Loot::BuildLootResponse(WorldPackets::Loot::LootResponse& packet, Player* viewer, PermissionTypes permission) const { - b << uint32(li.itemid); - b << uint32(li.count); // nr of items of this type - b << uint32(ASSERT_NOTNULL(sObjectMgr->GetItemTemplate(li.itemid))->GetDisplayID()); - b << int32(li.randomSuffix); - b << int32(li.randomPropertyId.Type == ItemRandomEnchantmentType::Property ? li.randomPropertyId.Id : -int32(li.randomPropertyId.Id)); - //b << uint8(0); // slot type - will send after this function call - return b; -} + if (permission == NONE_PERMISSION) + return; -ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) -{ - if (lv.permission == NONE_PERMISSION) - { - b << uint32(0); // gold - b << uint8(0); // item count - b << uint8(0); // currency count - return b; - } + packet.Coins = gold; - Loot &l = lv.loot; - - uint8 itemsShown = 0; - uint8 currenciesShown = 0; - - b << uint32(l.gold); //gold - - size_t count_pos = b.wpos(); // pos of item count byte - b << uint8(0); // item count placeholder - size_t currency_count_pos = b.wpos(); // pos of currency count byte - b << uint8(0); // currency count placeholder - - switch (lv.permission) + switch (permission) { case GROUP_PERMISSION: case MASTER_PERMISSION: @@ -651,22 +629,22 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { // if you are not the round-robin group looter, you can only see // blocked rolled items and quest items, and !ffa items - for (uint8 i = 0; i < l.items.size(); ++i) + for (uint8 i = 0; i < items.size(); ++i) { - if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer) && !l.items[i].is_currency) + if (!items[i].is_looted && !items[i].freeforall && items[i].conditions.empty() && items[i].AllowedForPlayer(viewer)) { uint8 slot_type; - if (l.items[i].is_blocked) // for ML & restricted is_blocked = !is_underthreshold + if (items[i].is_blocked) // for ML & restricted is_blocked = !is_underthreshold { - switch (lv.permission) + switch (permission) { case GROUP_PERMISSION: slot_type = LOOT_SLOT_TYPE_ROLL_ONGOING; break; case MASTER_PERMISSION: { - if (lv.viewer->GetGroup() && lv.viewer->GetGroup()->GetMasterLooterGuid() == lv.viewer->GetGUID()) + if (viewer->GetGroup() && viewer->GetGroup()->GetMasterLooterGuid() == viewer->GetGUID()) slot_type = LOOT_SLOT_TYPE_MASTER; else slot_type = LOOT_SLOT_TYPE_LOCKED; @@ -679,44 +657,72 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) continue; } } - else if (!l.items[i].rollWinnerGUID.IsEmpty()) - { - if (l.items[i].rollWinnerGUID == lv.viewer->GetGUID()) - slot_type = LOOT_SLOT_TYPE_OWNER; - else - continue; - } - else if (l.roundRobinPlayer.IsEmpty() || lv.viewer->GetGUID() == l.roundRobinPlayer || !l.items[i].is_underthreshold) + else if (roundRobinPlayer.IsEmpty() || viewer->GetGUID() == roundRobinPlayer || !items[i].is_underthreshold) { // no round robin owner or he has released the loot // or it IS the round robin group owner // => item is lootable slot_type = LOOT_SLOT_TYPE_ALLOW_LOOT; } + else if (!items[i].rollWinnerGUID.IsEmpty()) + { + if (items[i].rollWinnerGUID == viewer->GetGUID()) + slot_type = LOOT_SLOT_TYPE_OWNER; + else + continue; + } else // item shall not be displayed. continue; - b << uint8(i) << l.items[i]; - b << uint8(slot_type); - ++itemsShown; + if (!items[i].is_currency) + { + WorldPackets::Loot::LootItemData lootItem; + lootItem.LootListID = i; + lootItem.UIType = slot_type; + lootItem.Quantity = items[i].count; + lootItem.Loot.Initialize(items[i]); + packet.Items.push_back(lootItem); + } + else + { + WorldPackets::Loot::LootCurrency lootCurrency; + lootCurrency.LootListID = i; + lootCurrency.CurrencyID = items[i].itemid; + lootCurrency.Quantity = items[i].count; + packet.Currencies.push_back(lootCurrency); + } } } break; } case ROUND_ROBIN_PERMISSION: { - for (uint8 i = 0; i < l.items.size(); ++i) + for (uint8 i = 0; i < items.size(); ++i) { - if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer) && !!l.items[i].is_currency) + if (!items[i].is_looted && !items[i].freeforall && items[i].conditions.empty() && items[i].AllowedForPlayer(viewer)) { - if (!l.roundRobinPlayer.IsEmpty() && lv.viewer->GetGUID() != l.roundRobinPlayer) + if (!roundRobinPlayer.IsEmpty() && viewer->GetGUID() != roundRobinPlayer) // item shall not be displayed. continue; - b << uint8(i) << l.items[i]; - b << uint8(LOOT_SLOT_TYPE_ALLOW_LOOT); - ++itemsShown; + if (!items[i].is_currency) + { + WorldPackets::Loot::LootItemData lootItem; + lootItem.LootListID = i; + lootItem.UIType = LOOT_SLOT_TYPE_ALLOW_LOOT; + lootItem.Quantity = items[i].count; + lootItem.Loot.Initialize(items[i]); + packet.Items.push_back(lootItem); + } + else + { + WorldPackets::Loot::LootCurrency lootCurrency; + lootCurrency.LootListID = i; + lootCurrency.CurrencyID = items[i].itemid; + lootCurrency.Quantity = items[i].count; + packet.Currencies.push_back(lootCurrency); + } } } break; @@ -724,132 +730,170 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) case ALL_PERMISSION: case OWNER_PERMISSION: { - uint8 slot_type = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT; - for (uint8 i = 0; i < l.items.size(); ++i) + for (uint8 i = 0; i < items.size(); ++i) { - if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer) && !l.items[i].is_currency) + if (!items[i].is_looted && !items[i].freeforall && items[i].conditions.empty() && items[i].AllowedForPlayer(viewer)) { - b << uint8(i) << l.items[i]; - b << uint8(slot_type); - ++itemsShown; + if (!items[i].is_currency) + { + WorldPackets::Loot::LootItemData lootItem; + lootItem.LootListID = i; + lootItem.UIType = permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT; + lootItem.Quantity = items[i].count; + lootItem.Loot.Initialize(items[i]); + packet.Items.push_back(lootItem); + } + else + { + WorldPackets::Loot::LootCurrency lootCurrency; + lootCurrency.LootListID = i; + lootCurrency.CurrencyID = items[i].itemid; + lootCurrency.Quantity = items[i].count; + packet.Currencies.push_back(lootCurrency); + } } } break; } default: - return b; + return; } - LootSlotType slotType = lv.permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT; - NotNormalLootItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems(); - NotNormalLootItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUID()); + LootSlotType slotType = permission == OWNER_PERMISSION ? LOOT_SLOT_TYPE_OWNER : LOOT_SLOT_TYPE_ALLOW_LOOT; + NotNormalLootItemMap const& lootPlayerQuestItems = GetPlayerQuestItems(); + NotNormalLootItemMap::const_iterator q_itr = lootPlayerQuestItems.find(viewer->GetGUID()); if (q_itr != lootPlayerQuestItems.end()) { - NotNormalLootItemList* q_list = q_itr->second; - for (NotNormalLootItemList::const_iterator qi = q_list->begin(); qi != q_list->end(); ++qi) + NotNormalLootItemList const& q_list = *q_itr->second; + for (std::size_t i = 0; i < q_list.size(); ++i) { - LootItem &item = l.quest_items[qi->index]; - if (!qi->is_looted && !item.is_looted) + NotNormalLootItem const& qi = q_list[i]; + LootItem const& item = quest_items[qi.index]; + if (!qi.is_looted && !item.is_looted) { - b << uint8(l.items.size() + (qi - q_list->begin())); - b << item; - if (item.follow_loot_rules) + if (!item.is_currency) { - switch (lv.permission) + WorldPackets::Loot::LootItemData lootItem; + lootItem.LootListID = items.size() + i; + lootItem.Quantity = item.count; + lootItem.Loot.Initialize(item); + + if (item.follow_loot_rules) { - case MASTER_PERMISSION: - b << uint8(LOOT_SLOT_TYPE_MASTER); - break; - case RESTRICTED_PERMISSION: - b << (item.is_blocked ? uint8(LOOT_SLOT_TYPE_LOCKED) : uint8(slotType)); - break; - case GROUP_PERMISSION: - case ROUND_ROBIN_PERMISSION: - if (!item.is_blocked) - b << uint8(LOOT_SLOT_TYPE_ALLOW_LOOT); - else - b << uint8(LOOT_SLOT_TYPE_ROLL_ONGOING); - break; - default: - b << uint8(slotType); - break; + switch (permission) + { + case MASTER_PERMISSION: + lootItem.UIType = LOOT_SLOT_TYPE_MASTER; + break; + case RESTRICTED_PERMISSION: + lootItem.UIType = item.is_blocked ? LOOT_SLOT_TYPE_LOCKED : LOOT_SLOT_TYPE_ALLOW_LOOT; + break; + case GROUP_PERMISSION: + if (!item.is_blocked) + lootItem.UIType = LOOT_SLOT_TYPE_ALLOW_LOOT; + else + lootItem.UIType = LOOT_SLOT_TYPE_ROLL_ONGOING; + break; + default: + lootItem.UIType = slotType; + break; + } } + else + lootItem.UIType = slotType; + + packet.Items.push_back(lootItem); } else - b << uint8(slotType); - ++itemsShown; + { + WorldPackets::Loot::LootCurrency lootCurrency; + lootCurrency.LootListID = items.size() + i; + lootCurrency.CurrencyID = item.itemid; + lootCurrency.Quantity = item.count; + packet.Currencies.push_back(lootCurrency); + } } } } - NotNormalLootItemMap const& lootPlayerFFAItems = l.GetPlayerFFAItems(); - NotNormalLootItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(lv.viewer->GetGUID()); + NotNormalLootItemMap const& lootPlayerFFAItems = GetPlayerFFAItems(); + NotNormalLootItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(viewer->GetGUID()); if (ffa_itr != lootPlayerFFAItems.end()) { NotNormalLootItemList* ffa_list = ffa_itr->second; for (NotNormalLootItemList::const_iterator fi = ffa_list->begin(); fi != ffa_list->end(); ++fi) { - LootItem &item = l.items[fi->index]; + LootItem const& item = items[fi->index]; if (!fi->is_looted && !item.is_looted) { - b << uint8(fi->index); - b << item; - b << uint8(slotType); - ++itemsShown; + if (!item.is_currency) + { + WorldPackets::Loot::LootItemData lootItem; + lootItem.LootListID = fi->index; + lootItem.UIType = slotType; + lootItem.Quantity = item.count; + lootItem.Loot.Initialize(item); + packet.Items.push_back(lootItem); + } + else + { + WorldPackets::Loot::LootCurrency lootCurrency; + lootCurrency.LootListID = fi->index; + lootCurrency.CurrencyID = item.itemid; + lootCurrency.Quantity = item.count; + packet.Currencies.push_back(lootCurrency); + } } } } - NotNormalLootItemMap const& lootPlayerNonQuestNonFFAConditionalItems = l.GetPlayerNonQuestNonFFAConditionalItems(); - NotNormalLootItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(lv.viewer->GetGUID()); + NotNormalLootItemMap const& lootPlayerNonQuestNonFFAConditionalItems = GetPlayerNonQuestNonFFAConditionalItems(); + NotNormalLootItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(viewer->GetGUID()); if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end()) { NotNormalLootItemList* conditional_list = nn_itr->second; for (NotNormalLootItemList::const_iterator ci = conditional_list->begin(); ci != conditional_list->end(); ++ci) { - LootItem &item = l.items[ci->index]; + LootItem const& item = items[ci->index]; if (!ci->is_looted && !item.is_looted) { - b << uint8(ci->index); - b << item; - switch (lv.permission) + if (!item.is_currency) { - case MASTER_PERMISSION: - b << uint8(LOOT_SLOT_TYPE_MASTER); - break; - case RESTRICTED_PERMISSION: - b << (item.is_blocked ? uint8(LOOT_SLOT_TYPE_LOCKED) : uint8(slotType)); - break; - case GROUP_PERMISSION: - case ROUND_ROBIN_PERMISSION: - if (!item.is_blocked) - b << uint8(LOOT_SLOT_TYPE_ALLOW_LOOT); - else - b << uint8(LOOT_SLOT_TYPE_ROLL_ONGOING); - break; - default: - b << uint8(slotType); - break; + WorldPackets::Loot::LootItemData lootItem; + lootItem.LootListID = ci->index; + lootItem.Quantity = item.count; + lootItem.Loot.Initialize(item); + + switch (permission) + { + case MASTER_PERMISSION: + lootItem.UIType = LOOT_SLOT_TYPE_MASTER; + break; + case RESTRICTED_PERMISSION: + lootItem.UIType = item.is_blocked ? LOOT_SLOT_TYPE_LOCKED : LOOT_SLOT_TYPE_ALLOW_LOOT; + break; + case GROUP_PERMISSION: + if (!item.is_blocked) + lootItem.UIType = LOOT_SLOT_TYPE_ALLOW_LOOT; + else + lootItem.UIType = LOOT_SLOT_TYPE_ROLL_ONGOING; + break; + default: + lootItem.UIType = slotType; + break; + } + + packet.Items.push_back(lootItem); + } + else + { + WorldPackets::Loot::LootCurrency lootCurrency; + lootCurrency.LootListID = ci->index; + lootCurrency.CurrencyID = item.itemid; + lootCurrency.Quantity = item.count; + packet.Currencies.push_back(lootCurrency); } - ++itemsShown; } } } - - for (uint8 i = 0; i < l.items.size(); ++i) - { - if (!l.items[i].is_currency || l.items[i].count == 0 || l.items[i].is_looted) - continue; - - b << uint8(i); - b << uint32(l.items[i].itemid); - b << uint32(l.items[i].count); - ++currenciesShown; - } - - //update number of items and currencies shown - b.put(count_pos, itemsShown); - b.put(currency_count_pos, currenciesShown); - - return b; } diff --git a/src/server/game/Loot/Loot.h b/src/server/game/Loot/Loot.h index f0a629f45f..dcb65ff86f 100644 --- a/src/server/game/Loot/Loot.h +++ b/src/server/game/Loot/Loot.h @@ -33,6 +33,14 @@ class Player; struct Loot; struct LootStoreItem; +namespace WorldPackets +{ + namespace Loot + { + class LootResponse; + } +} + enum RollType { ROLL_PASS = 0, @@ -286,6 +294,9 @@ struct TC_GAME_API Loot bool hasItemFor(Player* player) const; bool hasOverThresholdItem() const; + // Builds data for SMSG_LOOT_RESPONSE + void BuildLootResponse(WorldPackets::Loot::LootResponse& packet, Player* viewer, PermissionTypes permission = ALL_PERMISSION) const; + private: void FillNotNormalLootFor(Player* player, bool presentAtLooting); NotNormalLootItemList* FillFFALoot(Player* player); diff --git a/src/server/game/Server/Packets/ItemPacketsCommon.cpp b/src/server/game/Server/Packets/ItemPacketsCommon.cpp index 96b6c6bb4a..c1b85fb3d6 100644 --- a/src/server/game/Server/Packets/ItemPacketsCommon.cpp +++ b/src/server/game/Server/Packets/ItemPacketsCommon.cpp @@ -17,16 +17,26 @@ #include "ItemPacketsCommon.h" #include "Item.h" +#include "ObjectMgr.h" #include "Player.h" #include "Loot.h" void WorldPackets::Item::ItemInstance::Initialize(::Item const* item) { ItemID = item->GetEntry(); + ItemDisplayID = item->GetDisplayId(); RandomPropertiesID = item->GetItemRandomPropertyId(); RandomPropertiesSeed = item->GetItemSuffixFactor(); } +void WorldPackets::Item::ItemInstance::Initialize(::LootItem const& lootItem) +{ + ItemID = lootItem.itemid; + ItemDisplayID = ASSERT_NOTNULL(sObjectMgr->GetItemTemplate(lootItem.itemid))->GetDisplayID(); + RandomPropertiesID = lootItem.randomPropertyId.Type == ItemRandomEnchantmentType::Property ? lootItem.randomPropertyId.Id : -int32(lootItem.randomPropertyId.Id); + RandomPropertiesSeed = lootItem.randomSuffix; +} + bool WorldPackets::Item::ItemInstance::operator==(ItemInstance const& r) const { if (ItemID != r.ItemID || RandomPropertiesID != r.RandomPropertiesID || RandomPropertiesSeed != r.RandomPropertiesSeed) diff --git a/src/server/game/Server/Packets/ItemPacketsCommon.h b/src/server/game/Server/Packets/ItemPacketsCommon.h index 81cf37a878..d16f034fb4 100644 --- a/src/server/game/Server/Packets/ItemPacketsCommon.h +++ b/src/server/game/Server/Packets/ItemPacketsCommon.h @@ -33,8 +33,10 @@ namespace WorldPackets struct ItemInstance { void Initialize(::Item const* item); + void Initialize(::LootItem const& lootItem); uint32 ItemID = 0; + int32 ItemDisplayID = 0; int32 RandomPropertiesSeed = 0; int32 RandomPropertiesID = 0; diff --git a/src/server/game/Server/Packets/LootPackets.cpp b/src/server/game/Server/Packets/LootPackets.cpp index bcecaa919d..bcd65de37c 100644 --- a/src/server/game/Server/Packets/LootPackets.cpp +++ b/src/server/game/Server/Packets/LootPackets.cpp @@ -16,6 +16,7 @@ */ #include "LootPackets.h" +#include "ItemPacketsCommon.h" WorldPacket const* WorldPackets::Loot::LootMoneyNotify::Write() { @@ -77,3 +78,48 @@ WorldPacket const* WorldPackets::Loot::DisenchantCredit::Write() return &_worldPacket; } + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Loot::LootItemData const& lootItemData) +{ + data << uint8(lootItemData.LootListID); + data << uint32(lootItemData.Loot.ItemID); + data << uint32(lootItemData.Quantity); + data << int32(lootItemData.Loot.ItemDisplayID); + data << int32(lootItemData.Loot.RandomPropertiesSeed); + data << int32(lootItemData.Loot.RandomPropertiesID); + data << uint8(lootItemData.UIType); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Loot::LootCurrency const& lootCurrency) +{ + data << uint8(lootCurrency.LootListID); + data << uint32(lootCurrency.CurrencyID); + data << uint32(lootCurrency.Quantity); + + return data; +} + +WorldPacket const* WorldPackets::Loot::LootResponse::Write() +{ + _worldPacket << Owner; + _worldPacket << uint8(AcquireReason); + if (!AcquireReason) + { + _worldPacket << uint8(FailureReason); + return &_worldPacket; + } + + _worldPacket << uint32(Coins); + _worldPacket << uint8(Items.size()); + _worldPacket << uint8(Currencies.size()); + + for (LootItemData const& lootItemData : Items) + _worldPacket << lootItemData; + + for (LootCurrency const& lootCurrency : Currencies) + _worldPacket << lootCurrency; + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/LootPackets.h b/src/server/game/Server/Packets/LootPackets.h index 0e6e680938..e6e3b5ad25 100644 --- a/src/server/game/Server/Packets/LootPackets.h +++ b/src/server/game/Server/Packets/LootPackets.h @@ -88,6 +88,39 @@ namespace WorldPackets ObjectGuid Disenchanter; WorldPackets::Item::ItemInstance Item; }; + + struct LootItemData + { + uint8 Type = 0; + uint8 UIType = 0; + uint32 Quantity = 0; + uint8 LootItemType = 0; + uint8 LootListID = 0; + WorldPackets::Item::ItemInstance Loot; + }; + + struct LootCurrency + { + uint32 CurrencyID = 0; + uint32 Quantity = 0; + uint8 LootListID = 0; + }; + + class LootResponse final : public ServerPacket + { + public: + LootResponse() : ServerPacket(SMSG_LOOT_RESPONSE, 100) { } + + WorldPacket const* Write() override; + + ObjectGuid Owner; + uint8 Threshold = 2; // Most common value, 2 = Uncommon + uint8 AcquireReason = 0; + uint8 FailureReason = 17; // Most common value + uint32 Coins = 0; + std::vector Items; + std::vector Currencies; + }; } }