Add support for vendors selling the same items with different extendedCost - original code by Vladimir (thanks mate)
Closes issue #1756 --HG-- branch : trunk
This commit is contained in:
+6
-13
@@ -62,29 +62,22 @@ TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
|
||||
|
||||
bool VendorItemData::RemoveItem(uint32 item_id)
|
||||
{
|
||||
bool found = false;
|
||||
for (VendorItemList::iterator i = m_items.begin(); i != m_items.end(); ++i)
|
||||
{
|
||||
if ((*i)->item == item_id)
|
||||
{
|
||||
m_items.erase(i);
|
||||
return true;
|
||||
i = m_items.erase(i);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return found;
|
||||
}
|
||||
|
||||
size_t VendorItemData::FindItemSlot(uint32 item_id) const
|
||||
{
|
||||
for (size_t i = 0; i < m_items.size(); ++i)
|
||||
if (m_items[i]->item == item_id)
|
||||
return i;
|
||||
return m_items.size();
|
||||
}
|
||||
|
||||
VendorItem const* VendorItemData::FindItem(uint32 item_id) const
|
||||
VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extendedCost) const
|
||||
{
|
||||
for (VendorItemList::const_iterator i = m_items.begin(); i != m_items.end(); ++i)
|
||||
if ((*i)->item == item_id)
|
||||
if((*i)->item == item_id && (*i)->ExtendedCost == extendedCost)
|
||||
return *i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+1
-3
@@ -333,9 +333,7 @@ struct VendorItemData
|
||||
m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost));
|
||||
}
|
||||
bool RemoveItem(uint32 item_id);
|
||||
VendorItem const* FindItem(uint32 item_id) const;
|
||||
size_t FindItemSlot(uint32 item_id) const;
|
||||
|
||||
VendorItem const* FindItemCostPair(uint32 item_id, uint32 extendedCost) const;
|
||||
void Clear()
|
||||
{
|
||||
for (VendorItemList::const_iterator itr = m_items.begin(); itr != m_items.end(); ++itr)
|
||||
|
||||
@@ -650,6 +650,12 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recv_data)
|
||||
|
||||
recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count;
|
||||
|
||||
// client expects count starting at 1, and we send vendorslot+1 to client already
|
||||
if (slot > 0)
|
||||
--slot;
|
||||
else
|
||||
return; // cheating
|
||||
|
||||
uint8 bag = NULL_BAG; // init for case invalid bagGUID
|
||||
|
||||
// find bag slot by bag guid
|
||||
@@ -674,7 +680,7 @@ void WorldSession::HandleBuyItemInSlotOpcode(WorldPacket & recv_data)
|
||||
if (bag == NULL_BAG)
|
||||
return;
|
||||
|
||||
GetPlayer()->BuyItemFromVendor(vendorguid,item,count,bag,bagslot);
|
||||
GetPlayer()->BuyItemFromVendorSlot(vendorguid,slot,item,count,bag,bagslot);
|
||||
}
|
||||
|
||||
void WorldSession::HandleBuyItemOpcode(WorldPacket & recv_data)
|
||||
@@ -686,7 +692,13 @@ void WorldSession::HandleBuyItemOpcode(WorldPacket & recv_data)
|
||||
|
||||
recv_data >> vendorguid >> item >> slot >> count >> unk1;
|
||||
|
||||
GetPlayer()->BuyItemFromVendor(vendorguid,item,count,NULL_BAG,NULL_SLOT);
|
||||
// client expects count starting at 1, and we send vendorslot+1 to client already
|
||||
if (slot > 0)
|
||||
--slot;
|
||||
else
|
||||
return; // cheating
|
||||
|
||||
GetPlayer()->BuyItemFromVendorSlot(vendorguid,slot,item,count,NULL_BAG,NULL_SLOT);
|
||||
}
|
||||
|
||||
void WorldSession::HandleListInventoryOpcode(WorldPacket & recv_data)
|
||||
@@ -736,11 +748,14 @@ void WorldSession::SendListInventory(uint64 vendorguid)
|
||||
data << uint64(vendorguid);
|
||||
data << uint8(numitems);
|
||||
|
||||
size_t count_pos = data.wpos();
|
||||
data << uint8(count);
|
||||
|
||||
float discountMod = _player->GetReputationPriceDiscount(pCreature);
|
||||
|
||||
for (int i = 0; i < numitems; ++i)
|
||||
for (uint8 vendorslot = 0; vendorslot < numitems; ++vendorslot )
|
||||
{
|
||||
if (VendorItem const* crItem = vItems->GetItem(i))
|
||||
if (VendorItem const* crItem = vItems->GetItem(vendorslot))
|
||||
{
|
||||
if (ItemPrototype const *pProto = objmgr.GetItemPrototype(crItem->item))
|
||||
{
|
||||
@@ -758,7 +773,7 @@ void WorldSession::SendListInventory(uint64 vendorguid)
|
||||
// reputation discount
|
||||
int32 price = uint32(floor(pProto->BuyPrice * discountMod));
|
||||
|
||||
data << uint32(count);
|
||||
data << uint32(vendorslot+1); // client expects counting to start at 1
|
||||
data << uint32(crItem->item);
|
||||
data << uint32(pProto->DisplayInfoID);
|
||||
data << int32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem));
|
||||
@@ -773,7 +788,7 @@ void WorldSession::SendListInventory(uint64 vendorguid)
|
||||
if (count == 0 || data.size() != 8 + 1 + size_t(count) * 8 * 4)
|
||||
return;
|
||||
|
||||
data.put<uint8>(8, count);
|
||||
data.put<uint8>(count_pos, count);
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
|
||||
@@ -8617,10 +8617,9 @@ bool ObjectMgr::RemoveVendorItem(uint32 entry,uint32 item, bool savetodb)
|
||||
if (iter == m_mCacheVendorItemMap.end())
|
||||
return false;
|
||||
|
||||
if (!iter->second.FindItem(item))
|
||||
if(!iter->second.RemoveItem(item))
|
||||
return false;
|
||||
|
||||
iter->second.RemoveItem(item);
|
||||
if (savetodb) WorldDatabase.PExecuteLog("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",entry, item);
|
||||
return true;
|
||||
}
|
||||
@@ -8691,12 +8690,12 @@ bool ObjectMgr::IsVendorItemValid(uint32 vendor_entry, uint32 item_id, int32 max
|
||||
if (!vItems)
|
||||
return true; // later checks for non-empty lists
|
||||
|
||||
if (vItems->FindItem(item_id))
|
||||
if(vItems->FindItemCostPair(item_id,ExtendedCost))
|
||||
{
|
||||
if (pl)
|
||||
ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST,item_id);
|
||||
ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost);
|
||||
else
|
||||
sLog.outErrorDb("Table `(game_event_)npc_vendor` has duplicate items %u for vendor (Entry: %u), ignore", item_id, vendor_entry);
|
||||
sLog.outErrorDb( "Table `npc_vendor` has duplicate items %u (with extended cost %u) for vendor (Entry: %u), ignoring", item_id, ExtendedCost, vendor_entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+13
-8
@@ -19355,7 +19355,7 @@ void Player::InitDisplayIds()
|
||||
}
|
||||
|
||||
// Return true is the bought item has a max count to force refresh of window by caller
|
||||
bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint8 bag, uint8 slot)
|
||||
bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot)
|
||||
{
|
||||
// cheating attempt
|
||||
if (count < 1) count = 1;
|
||||
@@ -19389,15 +19389,20 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t vendor_slot = vItems->FindItemSlot(item);
|
||||
if (vendor_slot >= vItems->GetItemCount())
|
||||
if (vendorslot >= vItems->GetItemCount())
|
||||
{
|
||||
SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
VendorItem const* crItem = vItems->GetItem(vendorslot);
|
||||
// store diff item (cheating)
|
||||
if(!crItem || crItem->item != item)
|
||||
{
|
||||
SendBuyError(BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
VendorItem const* crItem = vItems->m_items[vendor_slot];
|
||||
|
||||
// check current item amount if it limited
|
||||
if (crItem->maxcount != 0)
|
||||
{
|
||||
@@ -19509,7 +19514,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||
|
||||
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
|
||||
data << uint64(pCreature->GetGUID());
|
||||
data << uint32(vendor_slot+1); // numbered from 1 at client
|
||||
data << uint32(vendorslot+1); // numbered from 1 at client
|
||||
data << int32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
|
||||
data << uint32(count);
|
||||
GetSession()->SendPacket(&data);
|
||||
@@ -19564,7 +19569,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint
|
||||
|
||||
WorldPacket data(SMSG_BUY_ITEM, (8+4+4+4));
|
||||
data << uint64(pCreature->GetGUID());
|
||||
data << uint32(vendor_slot + 1); // numbered from 1 at client
|
||||
data << uint32(vendorslot + 1); // numbered from 1 at client
|
||||
data << int32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF);
|
||||
data << uint32(count);
|
||||
GetSession()->SendPacket(&data);
|
||||
@@ -23755,4 +23760,4 @@ void Player::RefundItem(Item *item)
|
||||
if (arenaRefund)
|
||||
ModifyArenaPoints(arenaRefund);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1251,7 +1251,7 @@ class Player : public Unit, public GridObject<Player>
|
||||
return mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip();
|
||||
}
|
||||
void SendNewItem(Item *item, uint32 count, bool received, bool created, bool broadcast = false);
|
||||
bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint8 bag, uint8 slot);
|
||||
bool BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 item, uint8 count, uint8 bag, uint8 slot);
|
||||
|
||||
float GetReputationPriceDiscount(Creature const* pCreature) const;
|
||||
Player* GetTrader() const { return pTrader; }
|
||||
|
||||
Reference in New Issue
Block a user