From 25c2a76b63e89ea06e0736f38af23cbdb340d844 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 10 Apr 2010 04:28:34 +0400 Subject: [PATCH] [9716] Allow to vendor have same items in list with different extanded price. --- sql/mangos.sql | 6 +++--- sql/updates/9716_01_mangos_npc_vendor.sql | 5 +++++ sql/updates/9716_02_mangos_mangos_string.sql | 6 ++++++ sql/updates/Makefile.am | 4 ++++ src/game/Creature.cpp | 19 +++++++------------ src/game/Creature.h | 3 +-- src/game/ItemHandler.cpp | 14 ++++++++++++-- src/game/ObjectMgr.cpp | 9 ++++----- src/game/Player.cpp | 17 +++++++++++------ src/game/Player.h | 2 +- src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 12 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 sql/updates/9716_01_mangos_npc_vendor.sql create mode 100644 sql/updates/9716_02_mangos_mangos_string.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 10af84566..b7d52f8ba 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_9710_01_mangos_command` bit(1) default NULL + `required_9716_02_mangos_mangos_string` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -3071,7 +3071,7 @@ INSERT INTO `mangos_string` VALUES (207,'Item \'%i\' not found in database.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (208,'Item \'%i\' \'%s\' deleted from vendor list',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (209,'Item \'%i\' not found in vendor list.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(210,'Item \'%i\' already in vendor list.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(210,'Item \'%i\' (with extended cost %u) already in vendor list.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (211,'Spells of %s reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (212,'Spells of %s will reset at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (213,'Talents of %s reset.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -3827,7 +3827,7 @@ CREATE TABLE `npc_vendor` ( `maxcount` tinyint(3) unsigned NOT NULL default '0', `incrtime` int(10) unsigned NOT NULL default '0', `ExtendedCost` mediumint(8) unsigned NOT NULL default '0', - PRIMARY KEY (`entry`,`item`) + PRIMARY KEY (`entry`,`item`,`ExtendedCost`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Npc System'; -- diff --git a/sql/updates/9716_01_mangos_npc_vendor.sql b/sql/updates/9716_01_mangos_npc_vendor.sql new file mode 100644 index 000000000..ff549f567 --- /dev/null +++ b/sql/updates/9716_01_mangos_npc_vendor.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_9710_01_mangos_command required_9716_01_mangos_npc_vendor bit; + +ALTER TABLE npc_vendor + DROP PRIMARY KEY, + PRIMARY KEY (`entry`,`item`,`ExtendedCost`); diff --git a/sql/updates/9716_02_mangos_mangos_string.sql b/sql/updates/9716_02_mangos_mangos_string.sql new file mode 100644 index 000000000..5a96a24e7 --- /dev/null +++ b/sql/updates/9716_02_mangos_mangos_string.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_9716_01_mangos_npc_vendor required_9716_02_mangos_mangos_string bit; + +DELETE FROM mangos_string WHERE entry in (210); + +INSERT INTO mangos_string VALUES +(210,'Item \'%i\' (with extended cost %u) already in vendor list.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index f918bd367..483b23838 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -112,6 +112,8 @@ pkgdata_DATA = \ 9702_01_characters_item.sql \ 9704_01_mangos_achievement_reward.sql \ 9710_01_mangos_command.sql \ + 9716_01_mangos_npc_vendor.sql \ + 9716_02_mangos_mangos_string.sql \ README ## Additional files to include when running 'make dist' @@ -204,4 +206,6 @@ EXTRA_DIST = \ 9702_01_characters_item.sql \ 9704_01_mangos_achievement_reward.sql \ 9710_01_mangos_command.sql \ + 9716_01_mangos_npc_vendor.sql \ + 9716_02_mangos_mangos_string.sql \ README diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index c299d2b6b..667951824 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -58,29 +58,24 @@ 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 ) { + // can have many examples if((*i)->item == item_id) { m_items.erase(i); - return true; + 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; } diff --git a/src/game/Creature.h b/src/game/Creature.h index 0ffd48d4d..d4589563f 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -301,8 +301,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() { diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index c46551782..82572bf1c 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -643,6 +643,11 @@ void WorldSession::HandleBuyItemInSlotOpcode( WorldPacket & recv_data ) recv_data >> vendorguid >> item >> slot >> bagguid >> bagslot >> count; + if (slot < 1) + return; // client numbering slots from 1 + + --slot; + uint8 bag = NULL_BAG; // init for case invalid bagGUID // find bag slot by bag guid @@ -667,7 +672,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 ) @@ -679,7 +684,12 @@ void WorldSession::HandleBuyItemOpcode( WorldPacket & recv_data ) recv_data >> vendorguid >> item >> slot >> count >> unk1; - GetPlayer()->BuyItemFromVendor(vendorguid, item, count, NULL_BAG, NULL_SLOT); + if (slot < 1) + return; // client numbering slots from 1 + + --slot; + + GetPlayer()->BuyItemFromVendorSlot(vendorguid, slot, item, count, NULL_BAG, NULL_SLOT); } void WorldSession::HandleListInventoryOpcode( WorldPacket & recv_data ) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index b79e4102e..b5ca24cdc 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -8274,10 +8274,9 @@ bool ObjectMgr::RemoveVendorItem( uint32 entry,uint32 item ) if(iter == m_mCacheVendorItemMap.end()) return false; - if(!iter->second.FindItem(item)) + if(!iter->second.RemoveItem(item)) return false; - iter->second.RemoveItem(item); WorldDatabase.PExecuteLog("DELETE FROM npc_vendor WHERE entry='%u' AND item='%u'",entry, item); return true; } @@ -8348,12 +8347,12 @@ bool ObjectMgr::IsVendorItemValid( uint32 vendor_entry, uint32 item_id, uint32 m 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 `npc_vendor` has duplicate items %u for vendor (Entry: %u), ignoring", 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 2a1ab7909..c9d2e76c9 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18296,7 +18296,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; @@ -18326,14 +18326,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); + return false; + } + + VendorItem const* crItem = vItems->m_items[vendorslot]; + if(!crItem || crItem->item != item) // store diff item (cheating) { 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) @@ -18435,7 +18440,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 << uint32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF); data << uint32(count); GetSession()->SendPacket(&data); @@ -18480,7 +18485,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 << uint32(crItem->maxcount > 0 ? new_count : 0xFFFFFFFF); data << uint32(count); GetSession()->SendPacket(&data); diff --git a/src/game/Player.h b/src/game/Player.h index 97ebe75ac..62c6f2bea 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1276,7 +1276,7 @@ class MANGOS_DLL_SPEC Player : public Unit 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; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 48a4e39aa..a359fd97a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9715" + #define REVISION_NR "9716" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 2c85aa594..10d234aa2 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_9702_01_characters_item" - #define REVISION_DB_MANGOS "required_9710_01_mangos_command" + #define REVISION_DB_MANGOS "required_9716_02_mangos_mangos_string" #define REVISION_DB_REALMD "required_9010_01_realmd_realmlist" #endif // __REVISION_SQL_H__