diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/Creature.cpp | 19 | ||||
-rw-r--r-- | src/game/Creature.h | 4 | ||||
-rw-r--r-- | src/game/ItemHandler.cpp | 27 | ||||
-rw-r--r-- | src/game/ObjectMgr.cpp | 9 | ||||
-rw-r--r-- | src/game/Player.cpp | 21 | ||||
-rw-r--r-- | src/game/Player.h | 2 |
6 files changed, 46 insertions, 36 deletions
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 91e21805d5c..3a124b2a999 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -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; -} - -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(); + return found; } -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; } diff --git a/src/game/Creature.h b/src/game/Creature.h index b2b51785956..fd9499cd75e 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -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) diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 626b748d3c6..d65e491ea0f 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -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); } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index bc4b5cac9ec..94d735f10f0 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -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; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ba3773df262..2863068686d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -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,14 +19389,19 @@ 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); + SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); return false; } - VendorItem const* crItem = vItems->m_items[vendor_slot]; + 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; + } // 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); -}
\ No newline at end of file +} diff --git a/src/game/Player.h b/src/game/Player.h index 22af6a370ca..9cfcd2d6152 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -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; } |