From 1d8f222621c3befa917aad8c6c2f9c6ae3b36bc0 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 13 Dec 2010 15:10:16 +0300 Subject: [PATCH] [10867] Implement templates for trainer spell data in `npc_trainer_template`. New table let avoid duplication similar trainer spells for different trainers. --- sql/mangos.sql | 27 ++++- .../10867_01_mangos_npc_trainer_template.sql | 12 ++ .../10867_02_mangos_creature_template.sql | 4 + sql/updates/Makefile.am | 4 + src/game/Creature.cpp | 14 ++- src/game/Creature.h | 2 + src/game/Level3.cpp | 6 +- src/game/NPCHandler.cpp | 95 ++++++++++----- src/game/ObjectMgr.cpp | 114 ++++++++++++------ src/game/ObjectMgr.h | 16 ++- src/game/SQLStorages.cpp | 4 +- src/game/World.cpp | 3 +- src/game/WorldSession.h | 1 + src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 15 files changed, 229 insertions(+), 77 deletions(-) create mode 100644 sql/updates/10867_01_mangos_npc_trainer_template.sql create mode 100644 sql/updates/10867_02_mangos_creature_template.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index d8b66348f..69ba73b5a 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_10864_01_mangos_spell_proc_event` bit(1) default NULL + `required_10867_02_mangos_creature_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -1252,6 +1252,7 @@ CREATE TABLE `creature_template` ( `movementId` int(11) UNSIGNED DEFAULT '0' NOT NULL, `RegenHealth` tinyint(3) unsigned NOT NULL default '1', `equipment_id` mediumint(8) unsigned NOT NULL default '0', + `trainer_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', `flags_extra` int(10) unsigned NOT NULL default '0', @@ -3990,6 +3991,30 @@ LOCK TABLES `npc_trainer` WRITE; /*!40000 ALTER TABLE `npc_trainer` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `npc_trainer_template` +-- + +DROP TABLE IF EXISTS `npc_trainer_template`; +CREATE TABLE `npc_trainer_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `spell` mediumint(8) unsigned NOT NULL default '0', + `spellcost` int(10) unsigned NOT NULL default '0', + `reqskill` smallint(5) unsigned NOT NULL default '0', + `reqskillvalue` smallint(5) unsigned NOT NULL default '0', + `reqlevel` tinyint(3) unsigned NOT NULL default '0', + UNIQUE KEY `entry_spell` (`entry`,`spell`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `npc_trainer_template` +-- + +LOCK TABLES `npc_trainer` WRITE; +/*!40000 ALTER TABLE `npc_trainer_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `npc_trainer_template` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `npc_vendor` -- diff --git a/sql/updates/10867_01_mangos_npc_trainer_template.sql b/sql/updates/10867_01_mangos_npc_trainer_template.sql new file mode 100644 index 000000000..3e439c9a7 --- /dev/null +++ b/sql/updates/10867_01_mangos_npc_trainer_template.sql @@ -0,0 +1,12 @@ +ALTER TABLE db_version CHANGE COLUMN required_10864_01_mangos_spell_proc_event required_10867_01_mangos_npc_trainer_template bit; + +DROP TABLE IF EXISTS `npc_trainer_template`; +CREATE TABLE `npc_trainer_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `spell` mediumint(8) unsigned NOT NULL default '0', + `spellcost` int(10) unsigned NOT NULL default '0', + `reqskill` smallint(5) unsigned NOT NULL default '0', + `reqskillvalue` smallint(5) unsigned NOT NULL default '0', + `reqlevel` tinyint(3) unsigned NOT NULL default '0', + UNIQUE KEY `entry_spell` (`entry`,`spell`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/10867_02_mangos_creature_template.sql b/sql/updates/10867_02_mangos_creature_template.sql new file mode 100644 index 000000000..5adceb3e8 --- /dev/null +++ b/sql/updates/10867_02_mangos_creature_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_10867_01_mangos_npc_trainer_template required_10867_02_mangos_creature_template bit; + +ALTER TABLE creature_template + ADD COLUMN trainer_id mediumint(8) unsigned NOT NULL default '0' AFTER equipment_id; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 26dc74689..06fe22724 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -133,6 +133,8 @@ pkgdata_DATA = \ 10862_01_characters_mail.sql \ 10863_01_mangos_spell_proc_event.sql \ 10864_01_mangos_spell_proc_event.sql \ + 10867_01_mangos_npc_trainer_template.sql \ + 10867_02_mangos_creature_template.sql \ README ## Additional files to include when running 'make dist' @@ -246,4 +248,6 @@ EXTRA_DIST = \ 10862_01_characters_mail.sql \ 10863_01_mangos_spell_proc_event.sql \ 10864_01_mangos_spell_proc_event.sql \ + 10867_01_mangos_npc_trainer_template.sql \ + 10867_02_mangos_creature_template.sql \ README diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index ec637db18..22d63a9cb 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -730,10 +730,11 @@ bool Creature::IsTrainerOf(Player* pPlayer, bool msg) const // pet trainers not have spells in fact now if (GetCreatureInfo()->trainer_type != TRAINER_TYPE_PETS) { - TrainerSpellData const* trainer_spells = GetTrainerSpells(); + TrainerSpellData const* cSpells = GetTrainerSpells(); + TrainerSpellData const* tSpells = GetTrainerTemplateSpells(); // for not pet trainer expected not empty trainer list always - if (!trainer_spells || trainer_spells->spellList.empty()) + if ((!cSpells || cSpells->spellList.empty()) && (!tSpells || tSpells->spellList.empty())) { sLog.outErrorDb("Creature %u (Entry: %u) have UNIT_NPC_FLAG_TRAINER but have empty trainer spell list.", GetGUIDLow(),GetEntry()); @@ -2181,7 +2182,8 @@ VendorItemData const* Creature::GetVendorItems() const VendorItemData const* Creature::GetVendorTemplateItems() const { - return GetCreatureInfo()->vendorId ? sObjectMgr.GetNpcVendorItemList(GetCreatureInfo()->vendorId) : NULL; + uint32 vendorId = GetCreatureInfo()->vendorId; + return vendorId ? sObjectMgr.GetNpcVendorItemList(vendorId) : NULL; } uint32 Creature::GetVendorItemCurrentCount(VendorItem const* vItem) @@ -2256,6 +2258,12 @@ uint32 Creature::UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 us return vCount->count; } +TrainerSpellData const* Creature::GetTrainerTemplateSpells() const +{ + uint32 trainerId = GetCreatureInfo()->trainerId; + return trainerId ? sObjectMgr.GetNpcTrainerTemplateSpells(trainerId) : NULL; +} + TrainerSpellData const* Creature::GetTrainerSpells() const { return sObjectMgr.GetNpcTrainerSpells(GetEntry()); diff --git a/src/game/Creature.h b/src/game/Creature.h index 9d3118126..d9204597b 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -130,6 +130,7 @@ struct CreatureInfo uint32 movementId; bool RegenHealth; uint32 equipmentId; + uint32 trainerId; uint32 vendorId; uint32 MechanicImmuneMask; uint32 flags_extra; @@ -515,6 +516,7 @@ class MANGOS_DLL_SPEC Creature : public Unit uint32 GetVendorItemCurrentCount(VendorItem const* vItem); uint32 UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 used_count); + TrainerSpellData const* GetTrainerTemplateSpells() const; TrainerSpellData const* GetTrainerSpells() const; CreatureInfo const *GetCreatureInfo() const { return m_creatureInfo; } diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 570376112..3110f2cc0 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -467,8 +467,12 @@ bool ChatHandler::HandleReloadNpcGossipCommand(char* /*args*/) bool ChatHandler::HandleReloadNpcTrainerCommand(char* /*args*/) { + sLog.outString( "Re-Loading `npc_trainer_template` Table!" ); + sObjectMgr.LoadTrainerTemplates(); + SendGlobalSysMessage("DB table `npc_trainer_template` reloaded."); + sLog.outString( "Re-Loading `npc_trainer` Table!" ); - sObjectMgr.LoadTrainerSpell(); + sObjectMgr.LoadTrainers(); SendGlobalSysMessage("DB table `npc_trainer` reloaded."); return true; } diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index b23d030ce..e1c5092fa 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -111,6 +111,27 @@ void WorldSession::SendTrainerList(ObjectGuid guid) SendTrainerList(guid, str); } + +static void SendTrainerSpellHelper(WorldPacket& data, TrainerSpell const* tSpell, TrainerSpellState state, float fDiscountMod, bool can_learn_primary_prof) +{ + bool primary_prof_first_rank = sSpellMgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell); + SpellChainNode const* chain_node = sSpellMgr.GetSpellChainNode(tSpell->learnedSpell); + + data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) + data << uint8(state==TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); + data << uint32(floor(tSpell->spellCost * fDiscountMod)); + + data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0); + // primary prof. learn confirmation dialog + data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state + data << uint8(tSpell->reqLevel); + data << uint32(tSpell->reqSkill); + data << uint32(tSpell->reqSkillValue); + data << uint32(!tSpell->IsCastable() && chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0); + data << uint32(!tSpell->IsCastable() && chain_node && chain_node->prev ? chain_node->req : 0); + data << uint32(0); +} + void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) { DEBUG_LOG( "WORLD: SendTrainerList" ); @@ -134,57 +155,68 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) if (!ci) return; - TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); - if (!trainer_spells) + TrainerSpellData const* cSpells = unit->GetTrainerSpells(); + TrainerSpellData const* tSpells = unit->GetTrainerTemplateSpells(); + + if (!cSpells && !tSpells) { DEBUG_LOG("WORLD: SendTrainerList - Training spells not found for %s", guid.GetString().c_str()); return; } - WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1); + uint32 maxcount = (cSpells ? cSpells->spellList.size() : 0) + (tSpells ? tSpells->spellList.size() : 0); + + WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+maxcount*38 + strTitle.size()+1); data << ObjectGuid(guid); - data << uint32(trainer_spells->trainerType); + data << uint32(cSpells->trainerType ? cSpells->trainerType : tSpells->trainerType); size_t count_pos = data.wpos(); - data << uint32(trainer_spells->spellList.size()); + data << uint32(maxcount); // reputation discount float fDiscountMod = _player->GetReputationPriceDiscount(unit); bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; uint32 count = 0; - for(TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) + + if (cSpells) { - TrainerSpell const* tSpell = &itr->second; + for(TrainerSpellMap::const_iterator itr = cSpells->spellList.begin(); itr != cSpells->spellList.end(); ++itr) + { + TrainerSpell const* tSpell = &itr->second; - if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell)) - continue; + if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell)) + continue; - bool primary_prof_first_rank = sSpellMgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell); - SpellChainNode const* chain_node = sSpellMgr.GetSpellChainNode(tSpell->learnedSpell); - TrainerSpellState state = _player->GetTrainerSpellState(tSpell); + TrainerSpellState state = _player->GetTrainerSpellState(tSpell); - data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) - data << uint8(state==TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); - data << uint32(floor(tSpell->spellCost * fDiscountMod)); + SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof); - data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0); - // primary prof. learn confirmation dialog - data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state - data << uint8(tSpell->reqLevel); - data << uint32(tSpell->reqSkill); - data << uint32(tSpell->reqSkillValue); - data << uint32(!tSpell->IsCastable() && chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0); - data << uint32(!tSpell->IsCastable() && chain_node && chain_node->prev ? chain_node->req : 0); - data << uint32(0); + ++count; + } + } - ++count; + if (tSpells) + { + for(TrainerSpellMap::const_iterator itr = tSpells->spellList.begin(); itr != tSpells->spellList.end(); ++itr) + { + TrainerSpell const* tSpell = &itr->second; + + if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell)) + continue; + + TrainerSpellState state = _player->GetTrainerSpellState(tSpell); + + SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof); + + ++count; + } } data << strTitle; data.put(count_pos,count); - SendPacket( &data ); + SendPacket(&data); } void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) @@ -210,12 +242,17 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) return; // check present spell in trainer spell list - TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); - if (!trainer_spells) + TrainerSpellData const* cSpells = unit->GetTrainerSpells(); + TrainerSpellData const* tSpells = unit->GetTrainerTemplateSpells(); + + if (!cSpells && !tSpells) return; // not found, cheat? - TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); + TrainerSpell const* trainer_spell = cSpells->Find(spellId); + if (!trainer_spell) + trainer_spell = tSpells->Find(spellId); + if (!trainer_spell) return; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 322b1a6b7..850f61f20 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -8825,29 +8825,31 @@ void ObjectMgr::LoadMailLevelRewards() sLog.outString( ">> Loaded %u level dependent mail rewards,", count ); } -void ObjectMgr::LoadTrainerSpell() +void ObjectMgr::LoadTrainers(char const* tableName, bool isTemplates) { + CacheTrainerSpellMap& trainerList = isTemplates ? m_mCacheTrainerTemplateSpellMap : m_mCacheTrainerSpellMap; + // For reload case - for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr) + for (CacheTrainerSpellMap::iterator itr = trainerList.begin(); itr != trainerList.end(); ++itr) itr->second.Clear(); - m_mCacheTrainerSpellMap.clear(); + trainerList.clear(); std::set skip_trainers; - QueryResult *result = WorldDatabase.Query("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM npc_trainer"); + QueryResult *result = WorldDatabase.PQuery("SELECT entry, spell,spellcost,reqskill,reqskillvalue,reqlevel FROM %s", tableName); - if( !result ) + if (!result) { - barGoLink bar( 1 ); + barGoLink bar(1); bar.step(); sLog.outString(); - sLog.outErrorDb(">> Loaded `npc_trainer`, table is empty!"); + sLog.outErrorDb(">> Loaded `%s`, table is empty!", tableName); return; } - barGoLink bar( (int)result->GetRowCount() ); + barGoLink bar((int)result->GetRowCount()); std::set talentIds; @@ -8861,48 +8863,60 @@ void ObjectMgr::LoadTrainerSpell() uint32 entry = fields[0].GetUInt32(); uint32 spell = fields[1].GetUInt32(); - CreatureInfo const* cInfo = GetCreatureTemplate(entry); - - if(!cInfo) - { - sLog.outErrorDb("Table `npc_trainer` have entry for nonexistent creature template (Entry: %u), ignore", entry); - continue; - } - - if(!(cInfo->npcflag & UNIT_NPC_FLAG_TRAINER)) - { - if (skip_trainers.find(entry) == skip_trainers.end()) - { - sLog.outErrorDb("Table `npc_trainer` have data for creature (Entry: %u) without trainer flag, ignore", entry); - skip_trainers.insert(entry); - } - continue; - } - SpellEntry const *spellinfo = sSpellStore.LookupEntry(spell); - if(!spellinfo) + if (!spellinfo) { - sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u ) has non existing spell %u, ignore", entry,spell); + sLog.outErrorDb("Table `%s` for trainer (Entry: %u ) has non existing spell %u, ignore", tableName, entry, spell); continue; } - if(!SpellMgr::IsSpellValid(spellinfo)) + if (!SpellMgr::IsSpellValid(spellinfo)) { - sLog.outErrorDb("Table `npc_trainer` for Trainer (Entry: %u) has broken learning spell %u, ignore", entry, spell); + sLog.outErrorDb("Table `%s` for trainer (Entry: %u) has broken learning spell %u, ignore", tableName, entry, spell); continue; } - if(GetTalentSpellCost(spell)) + if (GetTalentSpellCost(spell)) { if (talentIds.find(spell) == talentIds.end()) { - sLog.outErrorDb("Table `npc_trainer` has talent as learning spell %u, ignore", spell); + sLog.outErrorDb("Table `%s` has talent as learning spell %u, ignore", tableName, spell); talentIds.insert(spell); } continue; } - TrainerSpellData& data = m_mCacheTrainerSpellMap[entry]; + if (!isTemplates) + { + CreatureInfo const* cInfo = GetCreatureTemplate(entry); + + if (!cInfo) + { + sLog.outErrorDb("Table `%s` have entry for nonexistent creature template (Entry: %u), ignore", tableName, entry); + continue; + } + + if (!(cInfo->npcflag & UNIT_NPC_FLAG_TRAINER)) + { + if (skip_trainers.find(entry) == skip_trainers.end()) + { + sLog.outErrorDb("Table `%s` have data for creature (Entry: %u) without trainer flag, ignore", tableName, entry); + skip_trainers.insert(entry); + } + continue; + } + + if (TrainerSpellData const* tSpells = cInfo->trainerId ? GetNpcTrainerTemplateSpells(cInfo->trainerId) : NULL) + { + if (tSpells->spellList.find(spell) != tSpells->spellList.end()) + { + sLog.outErrorDb("Table `%s` for trainer (Entry: %u) has spell %u listed in trainer template %u, ignore", tableName, entry, spell); + continue; + } + } + } + + TrainerSpellData& data = trainerList[entry]; TrainerSpell& trainerSpell = data.spellList[spell]; trainerSpell.spell = spell; @@ -8927,7 +8941,7 @@ void ObjectMgr::LoadTrainerSpell() } } - if(SpellMgr::IsProfessionSpell(trainerSpell.learnedSpell)) + if (SpellMgr::IsProfessionSpell(trainerSpell.learnedSpell)) data.trainerType = 2; ++count; @@ -8936,7 +8950,35 @@ void ObjectMgr::LoadTrainerSpell() delete result; sLog.outString(); - sLog.outString( ">> Loaded %d Trainers", count ); + sLog.outString( ">> Loaded %d trainer %sspells", count, isTemplates ? "template " : "" ); +} + +void ObjectMgr::LoadTrainerTemplates() +{ + LoadTrainers("npc_trainer_template", true); + + // post loading check + std::set trainer_ids; + + for(CacheTrainerSpellMap::const_iterator tItr = m_mCacheTrainerTemplateSpellMap.begin(); tItr != m_mCacheTrainerTemplateSpellMap.end(); ++tItr) + trainer_ids.insert(tItr->first); + + for(uint32 i = 1; i < sCreatureStorage.MaxEntry; ++i) + { + if (CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(i)) + { + if (cInfo->trainerId) + { + if (trainer_ids.count(cInfo->trainerId) > 0) + trainer_ids.erase(cInfo->trainerId); + else + sLog.outErrorDb("Creature (Entry: %u) has trainer_id = %u for nonexistent trainer template", cInfo->Entry, cInfo->trainerId); + } + } + } + + for(std::set::const_iterator tItr = trainer_ids.begin(); tItr != trainer_ids.end(); ++tItr) + sLog.outErrorDb("Table `npc_trainer_template` has trainer template %u not used by any trainers ", *tItr); } void ObjectMgr::LoadVendors(char const* tableName, bool isTemplates) @@ -8988,7 +9030,7 @@ void ObjectMgr::LoadVendors(char const* tableName, bool isTemplates) delete result; sLog.outString(); - sLog.outString( ">> Loaded %u vendor items", count); + sLog.outString( ">> Loaded %u vendor %sitems", count, isTemplates ? "template " : ""); } diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 7b715ecf9..3767c4876 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -972,7 +972,8 @@ class ObjectMgr void LoadVendorTemplates(); void LoadVendors() { LoadVendors("npc_vendor", false); } - void LoadTrainerSpell(); + void LoadTrainerTemplates(); + void LoadTrainers() { LoadTrainers("npc_trainer", false); } std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint32 level) const; @@ -1202,13 +1203,22 @@ class ObjectMgr TrainerSpellData const* GetNpcTrainerSpells(uint32 entry) const { - CacheTrainerSpellMap::const_iterator iter = m_mCacheTrainerSpellMap.find(entry); + CacheTrainerSpellMap::const_iterator iter = m_mCacheTrainerSpellMap.find(entry); if(iter == m_mCacheTrainerSpellMap.end()) return NULL; return &iter->second; } + TrainerSpellData const* GetNpcTrainerTemplateSpells(uint32 entry) const + { + CacheTrainerSpellMap::const_iterator iter = m_mCacheTrainerTemplateSpellMap.find(entry); + if(iter == m_mCacheTrainerTemplateSpellMap.end()) + return NULL; + + return &iter->second; + } + VendorItemData const* GetNpcVendorItemList(uint32 entry) const { CacheVendorItemMap::const_iterator iter = m_mCacheVendorItemMap.find(entry); @@ -1384,6 +1394,7 @@ class ObjectMgr void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); void LoadQuestRelationsHelper(QuestRelationsMap& map, char const* table); void LoadVendors(char const* tableName, bool isTemplates); + void LoadTrainers(char const* tableName, bool isTemplates); MailLevelRewardMap m_mailLevelRewardMap; @@ -1433,6 +1444,7 @@ class ObjectMgr CacheNpcTextIdMap m_mCacheNpcTextIdMap; CacheVendorItemMap m_mCacheVendorTemplateItemMap; CacheVendorItemMap m_mCacheVendorItemMap; + CacheTrainerSpellMap m_mCacheTrainerTemplateSpellMap; CacheTrainerSpellMap m_mCacheTrainerSpellMap; }; diff --git a/src/game/SQLStorages.cpp b/src/game/SQLStorages.cpp index c9765e026..fa0b57b4d 100644 --- a/src/game/SQLStorages.cpp +++ b/src/game/SQLStorages.cpp @@ -21,8 +21,8 @@ #include "Database/SQLStorageImpl.h" #include "Database/DatabaseEnv.h" -const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiis"; -const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiii"; +const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiis"; +const char CreatureInfodstfmt[]="iiiiiiiiiisssiiiiiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiiffliiiiiiiliiiiii"; const char CreatureDataAddonInfofmt[]="iiilliis"; const char CreatureModelfmt[]="iffbii"; const char CreatureInfoAddonInfofmt[]="iiilliis"; diff --git a/src/game/World.cpp b/src/game/World.cpp index cfb916ada..6823efe94 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1166,7 +1166,8 @@ void World::SetInitialWorldSettings() sObjectMgr.LoadVendors(); // must be after load CreatureTemplate, VendorTemplate, and ItemTemplate sLog.outString( "Loading Trainers..." ); - sObjectMgr.LoadTrainerSpell(); // must be after load CreatureTemplate + sObjectMgr.LoadTrainerTemplates(); // must be after load CreatureTemplate + sObjectMgr.LoadTrainers(); // must be after load CreatureTemplate, TrainerTemplate sLog.outString( "Loading Waypoint scripts..." ); // before loading from creature_movement sObjectMgr.LoadCreatureMovementScripts(); diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index f3c179cba..d364b51ed 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -253,6 +253,7 @@ class MANGOS_DLL_SPEC WorldSession void SendTrainerList(ObjectGuid guid); void SendTrainerList(ObjectGuid guid, const std::string& strTitle ); + void SendListInventory(ObjectGuid guid); bool CheckBanker(ObjectGuid guid); void SendShowBank(ObjectGuid guid); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 431265b06..d2c85cffc 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 "10866" + #define REVISION_NR "10867" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index feb68f90f..0d248bce8 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_10862_01_characters_mail" - #define REVISION_DB_MANGOS "required_10864_01_mangos_spell_proc_event" + #define REVISION_DB_MANGOS "required_10867_02_mangos_creature_template" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version" #endif // __REVISION_SQL_H__