From 2f144d9d294f4f6afed9dc1b68cfa76918ecae34 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 4 Nov 2010 23:53:23 +0300 Subject: [PATCH] [10682] New table 'item_convert' for convertion items. * Implment vendor at show replace BoA item with reputation requirement by identical item without rep. reqs for player that fit this requirements of original item. * Table also can be used for store item convertion data form one team items to similar other team items. This case not impement but added function easy used for it. * Note: strict single convert for item not created problem for both way use: item converted for same team or all, can't be original item for conversion to another team. --- sql/mangos.sql | 22 ++++++- sql/updates/10682_01_mangos_item_convert.sql | 8 +++ sql/updates/Makefile.am | 2 + src/game/Chat.cpp | 1 + src/game/Chat.h | 1 + src/game/ItemHandler.cpp | 18 +++++- src/game/Level3.cpp | 9 +++ src/game/ObjectMgr.cpp | 66 ++++++++++++++++++++ src/game/ObjectMgr.h | 13 ++++ src/game/Player.cpp | 21 ++++++- src/game/World.cpp | 3 + src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 13 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 sql/updates/10682_01_mangos_item_convert.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 79b45732e..b221ee712 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_10679_02_mangos_creature_template` bit(1) default NULL + `required_10682_01_mangos_item_convert` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -2143,6 +2143,26 @@ LOCK TABLES `instance_template` WRITE; /*!40000 ALTER TABLE `instance_template` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `item_convert` +-- + +DROP TABLE IF EXISTS `item_convert`; +CREATE TABLE `item_convert` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Npc System'; + +-- +-- Dumping data for table `item_convert` +-- + +LOCK TABLES `item_convert` WRITE; +/*!40000 ALTER TABLE `item_convert` DISABLE KEYS */; +/*!40000 ALTER TABLE `item_convert` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `item_enchantment_template` -- diff --git a/sql/updates/10682_01_mangos_item_convert.sql b/sql/updates/10682_01_mangos_item_convert.sql new file mode 100644 index 000000000..97c64f53b --- /dev/null +++ b/sql/updates/10682_01_mangos_item_convert.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_10679_02_mangos_creature_template required_10682_01_mangos_item_convert bit; + +DROP TABLE IF EXISTS `item_convert`; +CREATE TABLE `item_convert` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Npc System'; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 468c785dd..7f43ad61a 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -116,6 +116,7 @@ pkgdata_DATA = \ 10664_01_characters_arena_team_stats.sql \ 10679_01_mangos_npc_vendor_template.sql \ 10679_02_mangos_creature_template.sql \ + 10682_01_mangos_item_convert.sql \ README ## Additional files to include when running 'make dist' @@ -212,4 +213,5 @@ EXTRA_DIST = \ 10664_01_characters_arena_team_stats.sql \ 10679_01_mangos_npc_vendor_template.sql \ 10679_02_mangos_creature_template.sql \ + 10682_01_mangos_item_convert.sql \ README diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index ab91c6e76..04bec4603 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -478,6 +478,7 @@ ChatCommand * ChatHandler::getCommandTable() { "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL }, { "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuOptionCommand, "", NULL }, { "gossip_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipScriptsCommand, "", NULL }, + { "item_convert", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemConvertCommand, "", NULL }, { "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL }, { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, { "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 9950ad4c5..5b56d0bb9 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -391,6 +391,7 @@ class ChatHandler bool HandleReloadGossipScriptsCommand(char* args); bool HandleReloadGOQuestRelationsCommand(char* args); bool HandleReloadGOQuestInvRelationsCommand(char* args); + bool HandleReloadItemConvertCommand(char* args); bool HandleReloadItemEnchantementsCommand(char* args); bool HandleReloadItemRequiredTragetCommand(char* args); bool HandleReloadLocalesAchievementRewardCommand(char* args); diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 3856b7a60..e75a306e0 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -773,7 +773,9 @@ void WorldSession::SendListInventory(ObjectGuid vendorguid) if (crItem) { - if (ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(crItem->item)) + uint32 itemId = crItem->item; + ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(itemId); + if (pProto) { if (!_player->isGameMaster()) { @@ -792,13 +794,25 @@ void WorldSession::SendListInventory(ObjectGuid vendorguid) continue; } + // possible item coverting for BoA case + if (pProto->Flags & ITEM_FLAG_BOA) + { + // convert if can use and then buy + if (pProto->RequiredReputationFaction && uint32(_player->GetReputationRank(pProto->RequiredReputationFaction)) >= pProto->RequiredReputationRank) + { + itemId = sObjectMgr.GetItemConvert(itemId, _player->getRaceMask()); + // checked at convert data loading as existed + pProto = ObjectMgr::GetItemPrototype(itemId); + } + } + ++count; // reputation discount uint32 price = (crItem->ExtendedCost == 0 || pProto->Flags2 & ITEM_FLAG2_EXT_COST_REQUIRES_GOLD) ? uint32(floor(pProto->BuyPrice * discountMod)) : 0; data << uint32(vendorslot +1); // client size expected counting from 1 - data << uint32(crItem->item); + data << uint32(itemId); data << uint32(pProto->DisplayInfoID); data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem)); data << uint32(price); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 7305d6132..6b4a25f6f 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -185,6 +185,7 @@ bool ChatHandler::HandleReloadAllGossipsCommand(char* args) bool ChatHandler::HandleReloadAllItemCommand(char* /*args*/) { HandleReloadPageTextsCommand((char*)"a"); + HandleReloadItemConvertCommand((char*)"a"); HandleReloadItemEnchantementsCommand((char*)"a"); HandleReloadItemRequiredTragetCommand((char*)"a"); return true; @@ -661,6 +662,14 @@ bool ChatHandler::HandleReloadItemEnchantementsCommand(char* /*args*/) return true; } +bool ChatHandler::HandleReloadItemConvertCommand(char* /*args*/) +{ + sLog.outString( "Re-Loading Item Converts Table..." ); + sObjectMgr.LoadItemConverts(); + SendGlobalSysMessage("DB table `item_convert` reloaded."); + return true; +} + bool ChatHandler::HandleReloadItemRequiredTragetCommand(char* /*args*/) { sLog.outString( "Re-Loading Item Required Targets Table..." ); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 58df871a1..c624ca7cb 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2393,6 +2393,72 @@ void ObjectMgr::LoadItemPrototypes() sLog.outErrorDb("Item (Entry: %u) not exist in `item_template` but referenced in `CharStartOutfit.dbc`", *itr); } + +void ObjectMgr::LoadItemConverts() +{ + m_ItemRequiredTarget.clear(); // needed for reload case + + uint32 count = 0; + + QueryResult *result = WorldDatabase.Query("SELECT entry,item FROM item_convert"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded 0 Item converts . DB table `item_convert` is empty."); + return; + } + + barGoLink bar((int)result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 itemEntry = fields[0].GetUInt32(); + uint32 itemTargetId = fields[1].GetUInt32(); + + ItemPrototype const* pItemEntryProto = sItemStorage.LookupEntry(itemEntry); + if (!pItemEntryProto) + { + sLog.outErrorDb("Table `item_convert`: Item %u not exist in `item_template`.", itemEntry); + continue; + } + + ItemPrototype const* pItemTargetProto = sItemStorage.LookupEntry(itemTargetId); + if (!pItemTargetProto) + { + sLog.outErrorDb("Table `item_convert`: Item target %u for original item %u not exist in `item_template`.", itemTargetId, itemEntry); + continue; + } + + // 2 cases when item convert used + // Boa item with reputation requirement + if ((!(pItemEntryProto->Flags & ITEM_FLAG_BOA) || !pItemEntryProto->RequiredReputationFaction) && + // convertion to another team/race + (pItemTargetProto->AllowableRace & pItemEntryProto->AllowableRace)) + { + sLog.outErrorDb("Table `item_convert` not appropriate item %u conversion to %u. Table can be used for BoA items requirement drop or for conversion to another race/team use.", itemEntry, itemTargetId); + continue; + } + + m_ItemConvert[itemEntry] = itemTargetId; + + ++count; + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString(">> Loaded %u Item converts", count); +} + + void ObjectMgr::LoadItemRequiredTarget() { m_ItemRequiredTarget.clear(); // needed for reload case diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 2a7a8b838..d56654274 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -440,6 +440,7 @@ typedef UNORDERED_MAP PageTextLocaleMap; typedef UNORDERED_MAP MangosStringLocaleMap; typedef UNORDERED_MAP GossipMenuItemsLocaleMap; typedef UNORDERED_MAP PointOfInterestLocaleMap; +typedef UNORDERED_MAP ItemConvertMap; typedef std::multimap ExclusiveQuestGroupsMap; typedef std::multimap ItemRequiredTargetMap; @@ -931,6 +932,7 @@ class ObjectMgr void LoadGameObjectLocales(); void LoadGameobjects(); void LoadGameobjectRespawnTimes(); + void LoadItemConverts(); void LoadItemPrototypes(); void LoadItemRequiredTarget(); void LoadItemLocales(); @@ -1251,6 +1253,16 @@ class ObjectMgr return mSpellClickInfoMap.equal_range(creature_id); } + uint32 GetItemConvert(uint32 itemEntry, uint32 raceMask) const + { + ItemConvertMap::const_iterator iter = m_ItemConvert.find(itemEntry); + if (iter == m_ItemConvert.end()) + return itemEntry; + + ItemPrototype const* proto = GetItemPrototype(iter->second); + return (proto && proto->AllowableRace & raceMask) ? iter->second : itemEntry; + } + ItemRequiredTargetMapBounds GetItemRequiredTargetMapBounds(uint32 uiItemEntry) const { return m_ItemRequiredTarget.equal_range(uiItemEntry); @@ -1360,6 +1372,7 @@ class ObjectMgr SpellClickInfoMap mSpellClickInfoMap; + ItemConvertMap m_ItemConvert; ItemRequiredTargetMap m_ItemRequiredTarget; typedef std::vector LocalForIndex; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 8c7773cc1..56a7ae4ba 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18704,12 +18704,31 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 } VendorItem const* crItem = vendorslot < vCount ? vItems->GetItem(vendorslot) : tItems->GetItem(vendorslot - vCount); - if(!crItem || crItem->item != item) // store diff item (cheating) + if (!crItem) // store diff item (cheating) { SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); return false; } + if (crItem->item != item) // store diff item (cheating or special convert) + { + ItemPrototype const* crProto = ObjectMgr::GetItemPrototype(crItem->item); + // possible item coverting for BoA case + if (crProto->Flags & ITEM_FLAG_BOA) + { + // convert if can use and then buy + if (crProto->RequiredReputationFaction && uint32(GetReputationRank(crProto->RequiredReputationFaction)) >= crProto->RequiredReputationRank) + { + uint32 newitemid = sObjectMgr.GetItemConvert(crItem->item, getRaceMask()); + + if (newitemid != item) // store diff item (cheating or special convert) + { + SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); + return false; + } + } + } + } // check current item amount if it limited if (crItem->maxcount != 0) diff --git a/src/game/World.cpp b/src/game/World.cpp index 375d106eb..9d67dbc4d 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -998,6 +998,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Items..." ); // must be after LoadRandomEnchantmentsTable and LoadPageTexts sObjectMgr.LoadItemPrototypes(); + sLog.outString( "Loading Item converts..." ); // must be after LoadItemPrototypes + sObjectMgr.LoadItemConverts(); + sLog.outString( "Loading Creature Model Based Info Data..." ); sObjectMgr.LoadCreatureModelInfo(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 03c90bc21..d2c69d16d 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 "10681" + #define REVISION_NR "10682" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 651b7199b..43b887dd7 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_10664_01_characters_arena_team_stats" - #define REVISION_DB_MANGOS "required_10679_02_mangos_creature_template" + #define REVISION_DB_MANGOS "required_10682_01_mangos_item_convert" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #endif // __REVISION_SQL_H__