aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Handlers/ItemHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Handlers/ItemHandler.cpp')
-rwxr-xr-xsrc/server/game/Handlers/ItemHandler.cpp189
1 files changed, 102 insertions, 87 deletions
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index edd0d396e2f..2b2526ef1fd 100755
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -27,6 +27,7 @@
#include "UpdateData.h"
#include "ObjectAccessor.h"
#include "SpellInfo.h"
+#include <list>
void WorldSession::HandleSplitItemOpcode(WorldPacket & recv_data)
{
@@ -722,6 +723,19 @@ void WorldSession::HandleListInventoryOpcode(WorldPacket & recv_data)
SendListInventory(guid);
}
+struct VendorItemHelper
+{
+ uint32 Slot;
+ uint32 Type;
+ uint32 Entry;
+ uint32 DisplayId;
+ uint32 Durability;
+ uint32 ExtendedCost;
+ uint32 Price;
+ int32 LeftInStock;
+ uint32 BuyCount;
+};
+
void WorldSession::SendListInventory(uint64 vendorGuid)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent SMSG_LIST_INVENTORY");
@@ -742,111 +756,112 @@ void WorldSession::SendListInventory(uint64 vendorGuid)
if (vendor->HasUnitState(UNIT_STATE_MOVING))
vendor->StopMoving();
- uint8* bytes = (uint8*)&vendorGuid;
+ // build list of available items
+ VendorItemData const* vendorItems = vendor->GetVendorItems();
+ std::list<VendorItemHelper> items;
+ uint8 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0;
- VendorItemData const* items = vendor->GetVendorItems();
- if (!items)
- {
- WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + 1);
- data.WriteBit(bytes[5]);
- data.WriteBit(bytes[6]);
- data.WriteBit(bytes[1]);
- data.WriteBit(bytes[2]);
- data.WriteBit(bytes[3]);
- data.WriteBit(bytes[0]);
- data.WriteBit(bytes[7]);
- data.WriteBit(bytes[4]);
-
- data.WriteByteSeq(bytes[2]);
- data.WriteByteSeq(bytes[3]);
-
- data << uint8(0); // count == 0, next will be error code
- data << uint8(0xA0); // Only seen 0xA0 (160) so far ( should we send 0 here?)
-
- data.WriteByteSeq(bytes[4]);
- data.WriteByteSeq(bytes[7]);
- data.WriteByteSeq(bytes[6]);
- SendPacket(&data);
- return;
- }
+ //if (rawItemCount > 300),
+ // rawItemCount = 300; // client cap but uint8 max value is 255
- uint8 itemCount = items->GetItemCount();
+ const float discountMod = _player->GetReputationPriceDiscount(vendor);
uint8 count = 0;
+ for (uint8 slot = 0; slot < rawItemCount; ++slot)
+ {
+ VendorItem const* vendorItem = vendorItems->GetItem(slot);
+ if (!vendorItem) continue;
- WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + itemCount * 8 * 4);
+ ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(vendorItem->item);
+ if (!itemTemplate) continue;
- data.WriteBit(bytes[5]);
- data.WriteBit(bytes[6]);
- data.WriteBit(bytes[1]);
- data.WriteBit(bytes[2]);
- data.WriteBit(bytes[3]);
- data.WriteBit(bytes[0]);
- data.WriteBit(bytes[7]);
- data.WriteBit(bytes[4]);
+ if (!_player->isGameMaster()) // ignore conditions if GM on
+ {
+ // Respect allowed class
+ if (!(itemTemplate->AllowableClass & _player->getClassMask()))
+ continue;
+
+ // Do not sell BOP items
+ if (itemTemplate->Bonding == BIND_WHEN_PICKED_UP)
+ continue;
+
+ // Only display items in vendor lists for the team the player is on
+ if ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) ||
+ (itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE))
+ continue;
+
+ // Items sold out are not displayed in list
+ uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem);
+ if (leftInStock == 0)
+ continue;
+ }
+
+ int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
+ uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem);
+
+ VendorItemHelper item;
+ item.Slot = count + 1; // client expects counting to start at 1
+ item.Type = 1; // 1 is items, 2 is currency (FIXME: currency isn't implemented)
+ item.Entry = vendorItem->item;
+ item.DisplayId = itemTemplate->DisplayInfoID;
+ item.Durability = itemTemplate->MaxDurability;
+ item.ExtendedCost = vendorItem->ExtendedCost;
+ item.Price = price;
+ item.LeftInStock = leftInStock;
+ item.BuyCount = itemTemplate->BuyCount;
+
+ items.push_back(item);
+ }
- data.WriteByteSeq(bytes[2]);
- data.WriteByteSeq(bytes[3]);
+ uint8* guidBytes = (uint8*)&vendorGuid;
- size_t countPos = data.wpos();
- data << uint32(count);
+ WorldPacket data(SMSG_LIST_INVENTORY, 12 + 33 * items.size());
- data.WriteByteSeq(bytes[5]);
- data.WriteByteSeq(bytes[0]);
- data.WriteByteSeq(bytes[1]);
+ data.WriteBit(guidBytes[1]);
+ data.WriteBit(guidBytes[0]);
- data << uint8(0xA0); // Only seen 0xA0 (160) so far
+ data.WriteBits(items.size(), 21); // item count
- data.WriteByteSeq(bytes[4]);
- data.WriteByteSeq(bytes[7]);
- data.WriteByteSeq(bytes[6]);
+ data.WriteBit(guidBytes[3]);
+ data.WriteBit(guidBytes[6]);
+ data.WriteBit(guidBytes[5]);
+ data.WriteBit(guidBytes[2]);
+ data.WriteBit(guidBytes[7]);
+ for (std::list<VendorItemHelper>::const_iterator itr = items.begin(); itr != items.end(); ++itr)
+ {
+ data.WriteBit((*itr).ExtendedCost == 0);
+ data.WriteBit(1); // unk "enabler"
+ }
- float discountMod = _player->GetReputationPriceDiscount(vendor);
+ data.WriteBit(guidBytes[4]);
- for (uint8 slot = 0; slot < itemCount; ++slot)
+ for (std::list<VendorItemHelper>::const_iterator itr = items.begin(); itr != items.end(); ++itr)
{
- if (VendorItem const* item = items->GetItem(slot))
- {
- if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item->item))
- {
- if (!(itemTemplate->AllowableClass & _player->getClassMask()) && itemTemplate->Bonding == BIND_WHEN_PICKED_UP && !_player->isGameMaster())
- continue;
- // Only display items in vendor lists for the team the
- // player is on. If GM on, display all items.
- if (!_player->isGameMaster() && ((itemTemplate->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || (itemTemplate->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE)))
- continue;
+ data << uint32((*itr).Slot);
+ data << uint32((*itr).Durability);
+ if ((*itr).ExtendedCost != 0)
+ data << uint32((*itr).ExtendedCost);
+ data << uint32((*itr).Entry);
+ data << uint32((*itr).Type);
+ data << uint32((*itr).Price);
+ data << uint32((*itr).DisplayId);
+ // if (!unk "enabler") data << uint32(something);
+ data << int32((*itr).LeftInStock);
+ data << uint32((*itr).BuyCount);
+ }
- // Items sold out are not displayed in list
- uint32 leftInStock = !item->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(item);
- if (!_player->isGameMaster() && !leftInStock)
- continue;
+ data.WriteByteSeq(guidBytes[5]);
+ data.WriteByteSeq(guidBytes[4]);
+ data.WriteByteSeq(guidBytes[1]);
+ data.WriteByteSeq(guidBytes[0]);
+ data.WriteByteSeq(guidBytes[6]);
- ++count;
-
- // reputation discount
- int32 price = item->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0;
-
- data << uint32(itemTemplate->MaxDurability);
- data << uint32(slot + 1); // client expects counting to start at 1
- data << uint32(item->item);
- data << uint32(0); // Always 0?
- data << uint32(itemTemplate->DisplayInfoID);
- data << int32(leftInStock);
- data << uint32(itemTemplate->BuyCount);
- data << uint32(item->ExtendedCost);
- data << uint32(1); // Always 1?
- data << uint32(price);
- }
- }
- }
+ data << uint8(items.size() == 0); // unk byte, item count 0: 1, item count != 0: 0 or some "random" value below 300
- if (count == 0)
- {
- SendPacket(&data);
- return;
- }
+ data.WriteByteSeq(guidBytes[2]);
+ data.WriteByteSeq(guidBytes[3]);
+ data.WriteByteSeq(guidBytes[7]);
- data.put<uint32>(countPos, count);
SendPacket(&data);
}