[10679] New table npc_vendor_template for comon item data for diff vendors.

In vendor list show own vedor items + template ites if any.
Vendor template item lists selected by id stored in creature_template.vendor_id
This commit is contained in:
VladimirMangos 2010-11-04 18:27:08 +03:00
parent a0cb8494a9
commit 0bf8b0aa79
16 changed files with 217 additions and 68 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_10660_01_mangos_game_event_quest` bit(1) default NULL `required_10679_02_mangos_creature_template` 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';
-- --
@ -1251,6 +1251,7 @@ CREATE TABLE `creature_template` (
`movementId` int(11) UNSIGNED DEFAULT '0' NOT NULL, `movementId` int(11) UNSIGNED DEFAULT '0' NOT NULL,
`RegenHealth` tinyint(3) unsigned NOT NULL default '1', `RegenHealth` tinyint(3) unsigned NOT NULL default '1',
`equipment_id` mediumint(8) unsigned NOT NULL default '0', `equipment_id` mediumint(8) unsigned NOT NULL default '0',
`vendor_id` mediumint(8) unsigned NOT NULL default '0',
`mechanic_immune_mask` int(10) unsigned NOT NULL default '0', `mechanic_immune_mask` int(10) unsigned NOT NULL default '0',
`flags_extra` int(10) unsigned NOT NULL default '0', `flags_extra` int(10) unsigned NOT NULL default '0',
`ScriptName` char(64) NOT NULL default '', `ScriptName` char(64) NOT NULL default '',
@ -3990,6 +3991,29 @@ LOCK TABLES `npc_vendor` WRITE;
/*!40000 ALTER TABLE `npc_vendor` ENABLE KEYS */; /*!40000 ALTER TABLE `npc_vendor` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
--
-- Table structure for table `npc_vendor_template`
--
DROP TABLE IF EXISTS `npc_vendor_template`;
CREATE TABLE `npc_vendor_template` (
`entry` mediumint(8) unsigned NOT NULL default '0',
`item` mediumint(8) unsigned NOT NULL default '0',
`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`,`ExtendedCost`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Npc System';
--
-- Dumping data for table `npc_vendor_template`
--
LOCK TABLES `npc_vendor_template` WRITE;
/*!40000 ALTER TABLE `npc_vendor_template` DISABLE KEYS */;
/*!40000 ALTER TABLE `npc_vendor_template` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `page_text` -- Table structure for table `page_text`
-- --

View file

@ -0,0 +1,11 @@
ALTER TABLE db_version CHANGE COLUMN required_10660_01_mangos_game_event_quest required_10679_01_mangos_npc_vendor_template bit;
DROP TABLE IF EXISTS `npc_vendor_template`;
CREATE TABLE `npc_vendor_template` (
`entry` mediumint(8) unsigned NOT NULL default '0',
`item` mediumint(8) unsigned NOT NULL default '0',
`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`,`ExtendedCost`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Npc System';

View file

@ -0,0 +1,4 @@
ALTER TABLE db_version CHANGE COLUMN required_10679_01_mangos_npc_vendor_template required_10679_02_mangos_creature_template bit;
ALTER TABLE creature_template
ADD COLUMN vendor_id mediumint(8) unsigned NOT NULL default '0' AFTER equipment_id;

View file

@ -114,6 +114,8 @@ pkgdata_DATA = \
10660_01_mangos_game_event_quest.sql \ 10660_01_mangos_game_event_quest.sql \
10662_01_characters_item_loot.sql \ 10662_01_characters_item_loot.sql \
10664_01_characters_arena_team_stats.sql \ 10664_01_characters_arena_team_stats.sql \
10679_01_mangos_npc_vendor_template.sql \
10679_02_mangos_creature_template.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -208,4 +210,6 @@ EXTRA_DIST = \
10660_01_mangos_game_event_quest.sql \ 10660_01_mangos_game_event_quest.sql \
10662_01_characters_item_loot.sql \ 10662_01_characters_item_loot.sql \
10664_01_characters_arena_team_stats.sql \ 10664_01_characters_arena_team_stats.sql \
10679_01_mangos_npc_vendor_template.sql \
10679_02_mangos_creature_template.sql \
README README

View file

@ -2174,6 +2174,11 @@ VendorItemData const* Creature::GetVendorItems() const
return sObjectMgr.GetNpcVendorItemList(GetEntry()); return sObjectMgr.GetNpcVendorItemList(GetEntry());
} }
VendorItemData const* Creature::GetVendorTemplateItems() const
{
return GetCreatureInfo()->vendorId ? sObjectMgr.GetNpcVendorItemList(GetCreatureInfo()->vendorId) : NULL;
}
uint32 Creature::GetVendorItemCurrentCount(VendorItem const* vItem) uint32 Creature::GetVendorItemCurrentCount(VendorItem const* vItem)
{ {
if(!vItem->maxcount) if(!vItem->maxcount)

View file

@ -129,6 +129,7 @@ struct CreatureInfo
uint32 movementId; uint32 movementId;
bool RegenHealth; bool RegenHealth;
uint32 equipmentId; uint32 equipmentId;
uint32 vendorId;
uint32 MechanicImmuneMask; uint32 MechanicImmuneMask;
uint32 flags_extra; uint32 flags_extra;
uint32 ScriptID; uint32 ScriptID;
@ -505,6 +506,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
float GetSpellDamageMod(int32 Rank); float GetSpellDamageMod(int32 Rank);
VendorItemData const* GetVendorItems() const; VendorItemData const* GetVendorItems() const;
VendorItemData const* GetVendorTemplateItems() const;
uint32 GetVendorItemCurrentCount(VendorItem const* vItem); uint32 GetVendorItemCurrentCount(VendorItem const* vItem);
uint32 UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 used_count); uint32 UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 used_count);

View file

@ -742,8 +742,9 @@ void WorldSession::SendListInventory(ObjectGuid vendorguid)
pCreature->StopMoving(); pCreature->StopMoving();
VendorItemData const* vItems = pCreature->GetVendorItems(); VendorItemData const* vItems = pCreature->GetVendorItems();
VendorItemData const* tItems = pCreature->GetVendorTemplateItems();
if (!vItems) if (!vItems && !tItems)
{ {
WorldPacket data( SMSG_LIST_INVENTORY, (8+1+1) ); WorldPacket data( SMSG_LIST_INVENTORY, (8+1+1) );
data << ObjectGuid(vendorguid); data << ObjectGuid(vendorguid);
@ -753,7 +754,9 @@ void WorldSession::SendListInventory(ObjectGuid vendorguid)
return; return;
} }
uint8 numitems = vItems->GetItemCount(); uint8 customitems = vItems ? vItems->GetItemCount() : 0;
uint8 numitems = customitems + (tItems ? tItems->GetItemCount() : 0);
uint8 count = 0; uint8 count = 0;
WorldPacket data( SMSG_LIST_INVENTORY, (8+1+numitems*8*4) ); WorldPacket data( SMSG_LIST_INVENTORY, (8+1+numitems*8*4) );
@ -766,7 +769,9 @@ void WorldSession::SendListInventory(ObjectGuid vendorguid)
for(uint8 vendorslot = 0; vendorslot < numitems; ++vendorslot ) for(uint8 vendorslot = 0; vendorslot < numitems; ++vendorslot )
{ {
if (VendorItem const* crItem = vItems->GetItem(vendorslot)) VendorItem const* crItem = vendorslot < customitems ? vItems->GetItem(vendorslot) : tItems->GetItem(vendorslot - customitems);
if (crItem)
{ {
if (ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(crItem->item)) if (ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(crItem->item))
{ {

View file

@ -1617,7 +1617,7 @@ bool ChatHandler::HandleNpcAddVendorItemCommand(char* args)
uint32 vendor_entry = vendor ? vendor->GetEntry() : 0; uint32 vendor_entry = vendor ? vendor->GetEntry() : 0;
if (!sObjectMgr.IsVendorItemValid(vendor_entry, itemId, maxcount, incrtime, extendedcost, m_session->GetPlayer())) if (!sObjectMgr.IsVendorItemValid(false, "npc_vendor", vendor_entry, itemId, maxcount, incrtime, extendedcost, m_session->GetPlayer()))
{ {
SetSentErrorMessage(true); SetSentErrorMessage(true);
return false; return false;

View file

@ -474,6 +474,11 @@ bool ChatHandler::HandleReloadNpcTrainerCommand(char* /*args*/)
bool ChatHandler::HandleReloadNpcVendorCommand(char* /*args*/) bool ChatHandler::HandleReloadNpcVendorCommand(char* /*args*/)
{ {
// not safe reload vendor template tables independent...
sLog.outString( "Re-Loading `npc_vendor_template` Table!" );
sObjectMgr.LoadVendorTemplates();
SendGlobalSysMessage("DB table `npc_vendor_template` reloaded.");
sLog.outString( "Re-Loading `npc_vendor` Table!" ); sLog.outString( "Re-Loading `npc_vendor` Table!" );
sObjectMgr.LoadVendors(); sObjectMgr.LoadVendors();
SendGlobalSysMessage("DB table `npc_vendor` reloaded."); SendGlobalSysMessage("DB table `npc_vendor` reloaded.");

View file

@ -186,6 +186,9 @@ ObjectMgr::~ObjectMgr()
for (ArenaTeamMap::iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) for (ArenaTeamMap::iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr)
delete itr->second; delete itr->second;
for (CacheVendorItemMap::iterator itr = m_mCacheVendorTemplateItemMap.begin(); itr != m_mCacheVendorTemplateItemMap.end(); ++itr)
itr->second.Clear();
for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr)
itr->second.Clear(); itr->second.Clear();
@ -702,6 +705,12 @@ void ObjectMgr::LoadCreatureTemplates()
} }
} }
if(cInfo->vendorId > 0)
{
if(!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR))
sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with vendor_id %u but not have flag UNIT_NPC_FLAG_VENDOR (%u), vendor items will ignored.", cInfo->Entry, cInfo->vendorId, UNIT_NPC_FLAG_VENDOR);
}
/// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc /// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
if(cInfo->scale <= 0.0f) if(cInfo->scale <= 0.0f)
{ {
@ -8789,16 +8798,20 @@ void ObjectMgr::LoadTrainerSpell()
sLog.outString( ">> Loaded %d Trainers", count ); sLog.outString( ">> Loaded %d Trainers", count );
} }
void ObjectMgr::LoadVendors() void ObjectMgr::LoadVendors(char const* tableName, bool isTemplates)
{ {
CacheVendorItemMap& vendorList = isTemplates ? m_mCacheVendorTemplateItemMap : m_mCacheVendorItemMap;
CacheVendorItemMap const* parentList = isTemplates ? NULL : &m_mCacheVendorTemplateItemMap;
// For reload case // For reload case
for (CacheVendorItemMap::iterator itr = m_mCacheVendorItemMap.begin(); itr != m_mCacheVendorItemMap.end(); ++itr) for (CacheVendorItemMap::iterator itr = vendorList.begin(); itr != vendorList.end(); ++itr)
itr->second.Clear(); itr->second.Clear();
m_mCacheVendorItemMap.clear(); vendorList.clear();
std::set<uint32> skip_vendors; std::set<uint32> skip_vendors;
QueryResult *result = WorldDatabase.Query("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM npc_vendor"); QueryResult *result = WorldDatabase.PQuery("SELECT entry, item, maxcount, incrtime, ExtendedCost FROM %s", tableName);
if( !result ) if( !result )
{ {
barGoLink bar( 1 ); barGoLink bar( 1 );
@ -8806,7 +8819,7 @@ void ObjectMgr::LoadVendors()
bar.step(); bar.step();
sLog.outString(); sLog.outString();
sLog.outErrorDb(">> Loaded `npc_vendor`, table is empty!"); sLog.outString(">> Loaded `%s`, table is empty!", tableName);
return; return;
} }
@ -8824,19 +8837,48 @@ void ObjectMgr::LoadVendors()
uint32 incrtime = fields[3].GetUInt32(); uint32 incrtime = fields[3].GetUInt32();
uint32 ExtendedCost = fields[4].GetUInt32(); uint32 ExtendedCost = fields[4].GetUInt32();
if(!IsVendorItemValid(entry,item_id,maxcount,incrtime,ExtendedCost,NULL,&skip_vendors)) if (!IsVendorItemValid(isTemplates, tableName, entry, item_id, maxcount, incrtime, ExtendedCost, NULL, &skip_vendors))
continue; continue;
VendorItemData& vList = m_mCacheVendorItemMap[entry]; VendorItemData& vList = vendorList[entry];
vList.AddItem(item_id,maxcount,incrtime,ExtendedCost); vList.AddItem(item_id, maxcount, incrtime, ExtendedCost);
++count; ++count;
} while (result->NextRow()); } while (result->NextRow());
delete result; delete result;
sLog.outString(); sLog.outString();
sLog.outString( ">> Loaded %d Vendors ", count ); sLog.outString( ">> Loaded %d vendor items", count);
}
void ObjectMgr::LoadVendorTemplates()
{
LoadVendors("npc_vendor_template", true);
// post loading check
std::set<uint32> vendor_ids;
for(CacheVendorItemMap::const_iterator vItr = m_mCacheVendorTemplateItemMap.begin(); vItr != m_mCacheVendorTemplateItemMap.end(); ++vItr)
vendor_ids.insert(vItr->first);
for(uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i)
{
if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(i))
{
if (cInfo->vendorId)
{
if (vendor_ids.count(cInfo->vendorId) > 0)
vendor_ids.erase(cInfo->vendorId);
else
sLog.outErrorDb("Creature (Entry: %u) has vendor_id = %u for nonexistent vendor template", cInfo->Entry, cInfo->vendorId);
}
}
}
for(std::set<uint32>::const_iterator vItr = vendor_ids.begin(); vItr != vendor_ids.end(); ++vItr)
sLog.outErrorDb("Table `npc_vendor_template` has vendor template %u not used by any vendors ", *vItr);
} }
void ObjectMgr::LoadNpcTextId() void ObjectMgr::LoadNpcTextId()
@ -9121,91 +9163,123 @@ bool ObjectMgr::RemoveVendorItem( uint32 entry,uint32 item )
return true; return true;
} }
bool ObjectMgr::IsVendorItemValid( uint32 vendor_entry, uint32 item_id, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* pl, std::set<uint32>* skip_vendors ) const bool ObjectMgr::IsVendorItemValid(bool isTemplate, char const* tableName, uint32 vendor_entry, uint32 item_id, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost, Player* pl, std::set<uint32>* skip_vendors ) const
{ {
CreatureInfo const* cInfo = GetCreatureTemplate(vendor_entry); char const* idStr = isTemplate ? "vendor template" : "vendor";
if(!cInfo) CreatureInfo const* cInfo = NULL;
if (!isTemplate)
{
cInfo = GetCreatureTemplate(vendor_entry);
if (!cInfo)
{ {
if(pl) if(pl)
ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION); ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION);
else else
sLog.outErrorDb("Table `npc_vendor` has data for nonexistent creature (Entry: %u), ignoring", vendor_entry); sLog.outErrorDb("Table `%s` has data for nonexistent creature (Entry: %u), ignoring", tableName, vendor_entry);
return false; return false;
} }
if(!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR)) if (!(cInfo->npcflag & UNIT_NPC_FLAG_VENDOR))
{ {
if(!skip_vendors || skip_vendors->count(vendor_entry)==0) if (!skip_vendors || skip_vendors->count(vendor_entry)==0)
{ {
if(pl) if (pl)
ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION); ChatHandler(pl).SendSysMessage(LANG_COMMAND_VENDORSELECTION);
else else
sLog.outErrorDb("Table `npc_vendor` has data for creature (Entry: %u) without vendor flag, ignoring", vendor_entry); sLog.outErrorDb("Table `%s` has data for creature (Entry: %u) without vendor flag, ignoring", tableName, vendor_entry);
if(skip_vendors) if (skip_vendors)
skip_vendors->insert(vendor_entry); skip_vendors->insert(vendor_entry);
} }
return false; return false;
} }
}
if(!GetItemPrototype(item_id)) if (!GetItemPrototype(item_id))
{ {
if(pl) if (pl)
ChatHandler(pl).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id); ChatHandler(pl).PSendSysMessage(LANG_ITEM_NOT_FOUND, item_id);
else else
sLog.outErrorDb("Table `npc_vendor` for vendor (Entry: %u) contain nonexistent item (%u), ignoring", sLog.outErrorDb("Table `%s` for %s %u contain nonexistent item (%u), ignoring",
vendor_entry, item_id); tableName, idStr, vendor_entry, item_id);
return false; return false;
} }
if(ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost)) if (ExtendedCost && !sItemExtendedCostStore.LookupEntry(ExtendedCost))
{ {
if(pl) if (pl)
ChatHandler(pl).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST,ExtendedCost); ChatHandler(pl).PSendSysMessage(LANG_EXTENDED_COST_NOT_EXIST,ExtendedCost);
else else
sLog.outErrorDb("Table `npc_vendor` contain item (Entry: %u) with wrong ExtendedCost (%u) for vendor (%u), ignoring", sLog.outErrorDb("Table `%s` contain item (Entry: %u) with wrong ExtendedCost (%u) for %s %u, ignoring",
item_id, ExtendedCost, vendor_entry); tableName, item_id, ExtendedCost, idStr, vendor_entry);
return false; return false;
} }
if(maxcount > 0 && incrtime == 0) if (maxcount > 0 && incrtime == 0)
{ {
if(pl) if (pl)
ChatHandler(pl).PSendSysMessage("MaxCount!=0 (%u) but IncrTime==0", maxcount); ChatHandler(pl).PSendSysMessage("MaxCount!=0 (%u) but IncrTime==0", maxcount);
else else
sLog.outErrorDb( "Table `npc_vendor` has `maxcount` (%u) for item %u of vendor (Entry: %u) but `incrtime`=0, ignoring", sLog.outErrorDb( "Table `%s` has `maxcount` (%u) for item %u of %s %u but `incrtime`=0, ignoring",
maxcount, item_id, vendor_entry); tableName, maxcount, item_id, idStr, vendor_entry);
return false; return false;
} }
else if(maxcount==0 && incrtime > 0) else if (maxcount==0 && incrtime > 0)
{ {
if(pl) if (pl)
ChatHandler(pl).PSendSysMessage("MaxCount==0 but IncrTime<>=0"); ChatHandler(pl).PSendSysMessage("MaxCount==0 but IncrTime<>=0");
else else
sLog.outErrorDb( "Table `npc_vendor` has `maxcount`=0 for item %u of vendor (Entry: %u) but `incrtime`<>0, ignoring", sLog.outErrorDb( "Table `%s` has `maxcount`=0 for item %u of %s %u but `incrtime`<>0, ignoring",
item_id, vendor_entry); tableName, item_id, idStr, vendor_entry);
return false; return false;
} }
VendorItemData const* vItems = GetNpcVendorItemList(vendor_entry); VendorItemData const* vItems = isTemplate ? GetNpcVendorTemplateItemList(vendor_entry) : GetNpcVendorItemList(vendor_entry);
if(!vItems) VendorItemData const* tItems = isTemplate ? NULL : GetNpcVendorTemplateItemList(vendor_entry);
if (!vItems && !tItems)
return true; // later checks for non-empty lists return true; // later checks for non-empty lists
if(vItems->FindItemCostPair(item_id,ExtendedCost)) if (vItems && vItems->FindItemCostPair(item_id, ExtendedCost))
{ {
if(pl) if (pl)
ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost); ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost);
else else
sLog.outErrorDb( "Table `npc_vendor` has duplicate items %u (with extended cost %u) for vendor (Entry: %u), ignoring", item_id, ExtendedCost, vendor_entry); sLog.outErrorDb( "Table `%s` has duplicate items %u (with extended cost %u) for %s %u, ignoring",
tableName, item_id, ExtendedCost, idStr, vendor_entry);
return false; return false;
} }
if(vItems->GetItemCount() >= MAX_VENDOR_ITEMS) if (!isTemplate)
{ {
if(pl) if (tItems && tItems->FindItemCostPair(item_id, ExtendedCost))
{
if (pl)
ChatHandler(pl).PSendSysMessage(LANG_ITEM_ALREADY_IN_LIST, item_id, ExtendedCost);
else
{
if (!cInfo->vendorId)
sLog.outErrorDb( "Table `%s` has duplicate items %u (with extended cost %u) for %s %u, ignoring",
tableName, item_id, ExtendedCost, idStr, vendor_entry);
else
sLog.outErrorDb( "Table `%s` has duplicate items %u (with extended cost %u) for %s %u (or possible in vendor template %u), ignoring",
tableName, item_id, ExtendedCost, idStr, vendor_entry, cInfo->vendorId);
}
return false;
}
}
uint32 countItems = vItems ? vItems->GetItemCount() : 0;
countItems += tItems ? tItems->GetItemCount() : 0;
if (countItems >= MAX_VENDOR_ITEMS)
{
if (pl)
ChatHandler(pl).SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS); ChatHandler(pl).SendSysMessage(LANG_COMMAND_ADDVENDORITEMITEMS);
else else
sLog.outErrorDb( "Table `npc_vendor` has too many items (%u >= %i) for vendor (Entry: %u), ignoring", vItems->GetItemCount(), MAX_VENDOR_ITEMS, vendor_entry); sLog.outErrorDb( "Table `%s` has too many items (%u >= %i) for %s %u, ignoring",
tableName, countItems, MAX_VENDOR_ITEMS, idStr, vendor_entry);
return false; return false;
} }

View file

@ -978,7 +978,8 @@ class ObjectMgr
void LoadGossipMenu(); void LoadGossipMenu();
void LoadGossipMenuItems(); void LoadGossipMenuItems();
void LoadVendors(); void LoadVendorTemplates();
void LoadVendors() { LoadVendors("npc_vendor", false); }
void LoadTrainerSpell(); void LoadTrainerSpell();
std::string GeneratePetName(uint32 entry); std::string GeneratePetName(uint32 entry);
@ -1225,9 +1226,18 @@ class ObjectMgr
return &iter->second; return &iter->second;
} }
VendorItemData const* GetNpcVendorTemplateItemList(uint32 entry) const
{
CacheVendorItemMap::const_iterator iter = m_mCacheVendorTemplateItemMap.find(entry);
if(iter == m_mCacheVendorTemplateItemMap.end())
return NULL;
return &iter->second;
}
void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost); void AddVendorItem(uint32 entry,uint32 item, uint32 maxcount, uint32 incrtime, uint32 ExtendedCost);
bool RemoveVendorItem(uint32 entry,uint32 item); bool RemoveVendorItem(uint32 entry,uint32 item);
bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL ) const; bool IsVendorItemValid(bool isTemplate, char const* tableName, uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set<uint32>* skip_vendors = NULL) const;
void LoadScriptNames(); void LoadScriptNames();
ScriptNameMap &GetScriptNames() { return m_scriptNames; } ScriptNameMap &GetScriptNames() { return m_scriptNames; }
@ -1370,6 +1380,7 @@ class ObjectMgr
void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment); void LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment);
void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr);
void LoadQuestRelationsHelper(QuestRelationsMap& map, char const* table); void LoadQuestRelationsHelper(QuestRelationsMap& map, char const* table);
void LoadVendors(char const* tableName, bool isTemplates);
MailLevelRewardMap m_mailLevelRewardMap; MailLevelRewardMap m_mailLevelRewardMap;
@ -1417,6 +1428,7 @@ class ObjectMgr
CreatureModelRaceMap m_mCreatureModelRaceMap; CreatureModelRaceMap m_mCreatureModelRaceMap;
CacheNpcTextIdMap m_mCacheNpcTextIdMap; CacheNpcTextIdMap m_mCacheNpcTextIdMap;
CacheVendorItemMap m_mCacheVendorTemplateItemMap;
CacheVendorItemMap m_mCacheVendorItemMap; CacheVendorItemMap m_mCacheVendorItemMap;
CacheTrainerSpellMap m_mCacheTrainerSpellMap; CacheTrainerSpellMap m_mCacheTrainerSpellMap;
}; };

View file

@ -12728,7 +12728,8 @@ void Player::PrepareGossipMenu(WorldObject *pSource, uint32 menuId)
case GOSSIP_OPTION_VENDOR: case GOSSIP_OPTION_VENDOR:
{ {
VendorItemData const* vItems = pCreature->GetVendorItems(); VendorItemData const* vItems = pCreature->GetVendorItems();
if (!vItems || vItems->Empty()) VendorItemData const* tItems = pCreature->GetVendorTemplateItems();
if ((!vItems || vItems->Empty()) && (!tItems || tItems->Empty()))
{ {
sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", pCreature->GetGUIDLow(), pCreature->GetEntry()); sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_VENDOR but have empty trading item list.", pCreature->GetGUIDLow(), pCreature->GetEntry());
hasMenuItem = false; hasMenuItem = false;
@ -18686,7 +18687,8 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32
} }
VendorItemData const* vItems = pCreature->GetVendorItems(); VendorItemData const* vItems = pCreature->GetVendorItems();
if(!vItems || vItems->Empty()) VendorItemData const* tItems = pCreature->GetVendorTemplateItems();
if ((!vItems || vItems->Empty()) && (!tItems || tItems->Empty()))
{ {
SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0); SendBuyError( BUY_ERR_CANT_FIND_ITEM, pCreature, item, 0);
return false; return false;

View file

@ -1203,7 +1203,8 @@ void World::SetInitialWorldSettings()
sObjectMgr.LoadGossipMenuItems(); sObjectMgr.LoadGossipMenuItems();
sLog.outString( "Loading Vendors..." ); sLog.outString( "Loading Vendors..." );
sObjectMgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate sObjectMgr.LoadVendorTemplates(); // must be after load ItemTemplate
sObjectMgr.LoadVendors(); // must be after load CreatureTemplate, VendorTemplate, and ItemTemplate
sLog.outString( "Loading Trainers..." ); sLog.outString( "Loading Trainers..." );
sObjectMgr.LoadTrainerSpell(); // must be after load CreatureTemplate sObjectMgr.LoadTrainerSpell(); // must be after load CreatureTemplate

View file

@ -25,8 +25,8 @@ extern DatabasePostgre WorldDatabase;
extern DatabaseMysql WorldDatabase; extern DatabaseMysql WorldDatabase;
#endif #endif
const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiis"; const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiliiiiis";
const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiii"; const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiliiiiii";
const char CreatureDataAddonInfofmt[]="iiiiiis"; const char CreatureDataAddonInfofmt[]="iiiiiis";
const char CreatureModelfmt[]="iffbii"; const char CreatureModelfmt[]="iffbii";
const char CreatureInfoAddonInfofmt[]="iiiiiis"; const char CreatureInfoAddonInfofmt[]="iiiiiis";

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 "10678" #define REVISION_NR "10679"
#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_10660_01_mangos_game_event_quest" #define REVISION_DB_MANGOS "required_10679_02_mangos_creature_template"
#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__