std::vector vendorItems = { 25, 25, 25, }; void SendListInventoryCustom(Player* player, uint64 vendorGuid, uint32 vendorEntry) { TC_LOG_DEBUG("network.opcode", "WORLD: Sent SMSG_LIST_INVENTORY"); Creature* vendor = player->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR); if (!vendor) { TC_LOG_DEBUG("network.opcode", "WORLD: SendListInventory - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(vendorGuid))); player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, 0); return; } // remove fake death if (player->HasUnitState(UNIT_STATE_DIED)) player->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // Stop the npc if moving if (vendor->HasUnitState(UNIT_STATE_MOVING)) vendor->StopMoving(); //VendorItemData const* vendorItems = vendor->GetVendorItems(); //VendorItemData const* items = vendorEntry ? sObjectMgr->GetNpcVendorItemList(vendorEntry) : vendor->GetVendorItems(); // VendorItemData const* vendorItems = vendorEntry ? sObjectMgr->GetNpcVendorItemList(vendorEntry) : vendor->GetVendorItems(); /*if (!vendorItems) { WorldPacket data(SMSG_LIST_INVENTORY, 8 + 1 + 1);*/ uint16 rawItemCount = vendorItems.size(); // vendorItems ? vendorItems->GetItemCount() : 0; ByteBuffer itemsData(32 * rawItemCount); std::vector enablers; enablers.reserve(2 * rawItemCount); SetCurrentVendor(vendorEntry, GUID_LOPART(vendorGuid), GUID_HIPART(vendorGuid)); const float discountMod = player->GetReputationPriceDiscount(vendor); uint16 count = 0; for (uint16 slot = 0; slot < rawItemCount; ++slot) { if (count == 300) { TC_LOG_ERROR("sql.sql", "Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignore", count, MAX_VENDOR_ITEMS, vendor->GetEntry()); break; } // VendorItem const* vendorItem = vendorItems->GetItem(slot); // if (!vendorItem) continue; // if (vendorItem->Type == ITEM_VENDOR_TYPE_ITEM) { ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(vendorItems[slot]); if (!itemTemplate) continue; /* uint32 leftInStock = !vendorItem->maxcount ? 0xFFFFFFFF : vendor->GetVendorItemCurrentCount(vendorItem); if (!player->isGameMaster()) // ignore conditions if GM on { // Respect allowed class if (!(itemTemplate->AllowableClass & player->getClassMask()) && 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 if (leftInStock == 0) continue; } ConditionList conditions = sConditionMgr->GetConditionsForNpcVendorEvent(vendor->GetEntry(), vendorItem->item); if (!sConditionMgr->IsObjectMeetToConditions(player, vendor, conditions)) { TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), vendorItem->item); continue; } int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->BuyPrice * discountMod)) : 0; if (int32 priceMod = player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES)) price -= CalculatePct(price, priceMod); */ ++count; itemsData << uint32(slot + 1); // client expects counting to start at 1 itemsData << uint32(itemTemplate->MaxDurability); /* if (vendorItem->ExtendedCost != 0) { enablers.push_back(0); itemsData << uint32(vendorItem->ExtendedCost); } else */ enablers.push_back(1); enablers.push_back(1); // unk bit itemsData << uint32(vendorItems[slot]); itemsData << uint32(1); // 1 is items, 2 is currency itemsData << uint32(0); itemsData << uint32(itemTemplate->DisplayInfoID); // if (!unk "enabler") data << uint32(something); itemsData << int32(0xFFFFFFFF); itemsData << uint32(itemTemplate->BuyCount); } /* else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY) { CurrencyTypesEntry const* currencyTemplate = sCurrencyTypesStore.LookupEntry(vendorItem->item); if (!currencyTemplate) continue; if (vendorItem->ExtendedCost == 0) continue; // there's no price defined for currencies, only extendedcost is used ++count; itemsData << uint32(slot + 1); // client expects counting to start at 1 itemsData << uint32(0); // max durability if (vendorItem->ExtendedCost != 0) { enablers.push_back(0); itemsData << uint32(vendorItem->ExtendedCost); } else enablers.push_back(1); enablers.push_back(1); // unk bit itemsData << uint32(vendorItem->item); itemsData << uint32(vendorItem->Type); // 1 is items, 2 is currency itemsData << uint32(0); // price, only seen currency types that have Extended cost itemsData << uint32(0); // displayId // if (!unk "enabler") data << uint32(something); itemsData << int32(-1); itemsData << uint32(vendorItem->maxcount); } */ // else error } ObjectGuid guid = vendorGuid; WorldPacket data(SMSG_LIST_INVENTORY, 12 + itemsData.size()); data.WriteBit(guid[1]); data.WriteBit(guid[0]); data.WriteBits(count, 21); // item count data.WriteBit(guid[3]); data.WriteBit(guid[6]); data.WriteBit(guid[5]); data.WriteBit(guid[2]); data.WriteBit(guid[7]); for (std::vector::const_iterator itr = enablers.begin(); itr != enablers.end(); ++itr) data.WriteBit(*itr); data.WriteBit(guid[4]); data.FlushBits(); data.append(itemsData); data.WriteByteSeq(guid[5]); data.WriteByteSeq(guid[4]); data.WriteByteSeq(guid[1]); data.WriteByteSeq(guid[0]); data.WriteByteSeq(guid[6]); data << uint8(count == 0); // unk byte, item count 0: 1, item count != 0: 0 or some "random" value below 300 data.WriteByteSeq(guid[2]); data.WriteByteSeq(guid[3]); data.WriteByteSeq(guid[7]); player->GetSession()->SendPacket(&data); }