[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.
This commit is contained in:
VladimirMangos 2010-11-04 23:53:23 +03:00
parent 225b4db1ca
commit 2f144d9d29
13 changed files with 162 additions and 6 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `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'; ) 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 */; /*!40000 ALTER TABLE `instance_template` ENABLE KEYS */;
UNLOCK TABLES; 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` -- Table structure for table `item_enchantment_template`
-- --

View file

@ -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';

View file

@ -116,6 +116,7 @@ pkgdata_DATA = \
10664_01_characters_arena_team_stats.sql \ 10664_01_characters_arena_team_stats.sql \
10679_01_mangos_npc_vendor_template.sql \ 10679_01_mangos_npc_vendor_template.sql \
10679_02_mangos_creature_template.sql \ 10679_02_mangos_creature_template.sql \
10682_01_mangos_item_convert.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -212,4 +213,5 @@ EXTRA_DIST = \
10664_01_characters_arena_team_stats.sql \ 10664_01_characters_arena_team_stats.sql \
10679_01_mangos_npc_vendor_template.sql \ 10679_01_mangos_npc_vendor_template.sql \
10679_02_mangos_creature_template.sql \ 10679_02_mangos_creature_template.sql \
10682_01_mangos_item_convert.sql \
README README

View file

@ -478,6 +478,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL }, { "gossip_menu", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuCommand, "", NULL },
{ "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuOptionCommand, "", NULL }, { "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuOptionCommand, "", NULL },
{ "gossip_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipScriptsCommand, "", 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_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
{ "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL }, { "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL },

View file

@ -391,6 +391,7 @@ class ChatHandler
bool HandleReloadGossipScriptsCommand(char* args); bool HandleReloadGossipScriptsCommand(char* args);
bool HandleReloadGOQuestRelationsCommand(char* args); bool HandleReloadGOQuestRelationsCommand(char* args);
bool HandleReloadGOQuestInvRelationsCommand(char* args); bool HandleReloadGOQuestInvRelationsCommand(char* args);
bool HandleReloadItemConvertCommand(char* args);
bool HandleReloadItemEnchantementsCommand(char* args); bool HandleReloadItemEnchantementsCommand(char* args);
bool HandleReloadItemRequiredTragetCommand(char* args); bool HandleReloadItemRequiredTragetCommand(char* args);
bool HandleReloadLocalesAchievementRewardCommand(char* args); bool HandleReloadLocalesAchievementRewardCommand(char* args);

View file

@ -773,7 +773,9 @@ void WorldSession::SendListInventory(ObjectGuid vendorguid)
if (crItem) 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()) if (!_player->isGameMaster())
{ {
@ -792,13 +794,25 @@ void WorldSession::SendListInventory(ObjectGuid vendorguid)
continue; 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; ++count;
// reputation discount // reputation discount
uint32 price = (crItem->ExtendedCost == 0 || pProto->Flags2 & ITEM_FLAG2_EXT_COST_REQUIRES_GOLD) ? uint32(floor(pProto->BuyPrice * discountMod)) : 0; 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(vendorslot +1); // client size expected counting from 1
data << uint32(crItem->item); data << uint32(itemId);
data << uint32(pProto->DisplayInfoID); data << uint32(pProto->DisplayInfoID);
data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem)); data << uint32(crItem->maxcount <= 0 ? 0xFFFFFFFF : pCreature->GetVendorItemCurrentCount(crItem));
data << uint32(price); data << uint32(price);

View file

@ -185,6 +185,7 @@ bool ChatHandler::HandleReloadAllGossipsCommand(char* args)
bool ChatHandler::HandleReloadAllItemCommand(char* /*args*/) bool ChatHandler::HandleReloadAllItemCommand(char* /*args*/)
{ {
HandleReloadPageTextsCommand((char*)"a"); HandleReloadPageTextsCommand((char*)"a");
HandleReloadItemConvertCommand((char*)"a");
HandleReloadItemEnchantementsCommand((char*)"a"); HandleReloadItemEnchantementsCommand((char*)"a");
HandleReloadItemRequiredTragetCommand((char*)"a"); HandleReloadItemRequiredTragetCommand((char*)"a");
return true; return true;
@ -661,6 +662,14 @@ bool ChatHandler::HandleReloadItemEnchantementsCommand(char* /*args*/)
return true; 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*/) bool ChatHandler::HandleReloadItemRequiredTragetCommand(char* /*args*/)
{ {
sLog.outString( "Re-Loading Item Required Targets Table..." ); sLog.outString( "Re-Loading Item Required Targets Table..." );

View file

@ -2393,6 +2393,72 @@ void ObjectMgr::LoadItemPrototypes()
sLog.outErrorDb("Item (Entry: %u) not exist in `item_template` but referenced in `CharStartOutfit.dbc`", *itr); 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<ItemPrototype>(itemEntry);
if (!pItemEntryProto)
{
sLog.outErrorDb("Table `item_convert`: Item %u not exist in `item_template`.", itemEntry);
continue;
}
ItemPrototype const* pItemTargetProto = sItemStorage.LookupEntry<ItemPrototype>(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() void ObjectMgr::LoadItemRequiredTarget()
{ {
m_ItemRequiredTarget.clear(); // needed for reload case m_ItemRequiredTarget.clear(); // needed for reload case

View file

@ -440,6 +440,7 @@ typedef UNORDERED_MAP<uint32,PageTextLocale> PageTextLocaleMap;
typedef UNORDERED_MAP<int32,MangosStringLocale> MangosStringLocaleMap; typedef UNORDERED_MAP<int32,MangosStringLocale> MangosStringLocaleMap;
typedef UNORDERED_MAP<uint32,GossipMenuItemsLocale> GossipMenuItemsLocaleMap; typedef UNORDERED_MAP<uint32,GossipMenuItemsLocale> GossipMenuItemsLocaleMap;
typedef UNORDERED_MAP<uint32,PointOfInterestLocale> PointOfInterestLocaleMap; typedef UNORDERED_MAP<uint32,PointOfInterestLocale> PointOfInterestLocaleMap;
typedef UNORDERED_MAP<uint32,uint32> ItemConvertMap;
typedef std::multimap<int32, uint32> ExclusiveQuestGroupsMap; typedef std::multimap<int32, uint32> ExclusiveQuestGroupsMap;
typedef std::multimap<uint32, ItemRequiredTarget> ItemRequiredTargetMap; typedef std::multimap<uint32, ItemRequiredTarget> ItemRequiredTargetMap;
@ -931,6 +932,7 @@ class ObjectMgr
void LoadGameObjectLocales(); void LoadGameObjectLocales();
void LoadGameobjects(); void LoadGameobjects();
void LoadGameobjectRespawnTimes(); void LoadGameobjectRespawnTimes();
void LoadItemConverts();
void LoadItemPrototypes(); void LoadItemPrototypes();
void LoadItemRequiredTarget(); void LoadItemRequiredTarget();
void LoadItemLocales(); void LoadItemLocales();
@ -1251,6 +1253,16 @@ class ObjectMgr
return mSpellClickInfoMap.equal_range(creature_id); 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 ItemRequiredTargetMapBounds GetItemRequiredTargetMapBounds(uint32 uiItemEntry) const
{ {
return m_ItemRequiredTarget.equal_range(uiItemEntry); return m_ItemRequiredTarget.equal_range(uiItemEntry);
@ -1360,6 +1372,7 @@ class ObjectMgr
SpellClickInfoMap mSpellClickInfoMap; SpellClickInfoMap mSpellClickInfoMap;
ItemConvertMap m_ItemConvert;
ItemRequiredTargetMap m_ItemRequiredTarget; ItemRequiredTargetMap m_ItemRequiredTarget;
typedef std::vector<LocaleConstant> LocalForIndex; typedef std::vector<LocaleConstant> LocalForIndex;

View file

@ -18704,12 +18704,31 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
} }
VendorItem const* crItem = vendorslot < vCount ? vItems->GetItem(vendorslot) : tItems->GetItem(vendorslot - vCount); 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); SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
return false; 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 // check current item amount if it limited
if (crItem->maxcount != 0) if (crItem->maxcount != 0)

View file

@ -998,6 +998,9 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Items..." ); // must be after LoadRandomEnchantmentsTable and LoadPageTexts sLog.outString( "Loading Items..." ); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
sObjectMgr.LoadItemPrototypes(); sObjectMgr.LoadItemPrototypes();
sLog.outString( "Loading Item converts..." ); // must be after LoadItemPrototypes
sObjectMgr.LoadItemConverts();
sLog.outString( "Loading Creature Model Based Info Data..." ); sLog.outString( "Loading Creature Model Based Info Data..." );
sObjectMgr.LoadCreatureModelInfo(); sObjectMgr.LoadCreatureModelInfo();

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "10681" #define REVISION_NR "10682"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_10664_01_characters_arena_team_stats" #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" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__