diff options
author | Shauren <shauren.trinity@gmail.com> | 2017-08-20 14:11:51 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2017-08-20 14:12:25 +0200 |
commit | fb1fdf27b951fafbcb68c97675f75ef98aa5e3b7 (patch) | |
tree | 231abb9641515e0e75abdcf09b5f0ef7dfbc962b | |
parent | 6a296c7c91fe00144c858b8a611537da05d7e8ac (diff) |
Core/Creatures: Fixed trainers that don't use gossip but open trainer list directly from CMSG_TRAINER_LIST
-rw-r--r-- | sql/updates/world/master/2017_08_20_00_world.sql | 9 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 42 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 3 | ||||
-rw-r--r-- | src/server/game/Handlers/NPCHandler.cpp | 25 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 2 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 3 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_reload.cpp | 2 |
8 files changed, 75 insertions, 13 deletions
diff --git a/sql/updates/world/master/2017_08_20_00_world.sql b/sql/updates/world/master/2017_08_20_00_world.sql new file mode 100644 index 00000000000..d77b9d46ae3 --- /dev/null +++ b/sql/updates/world/master/2017_08_20_00_world.sql @@ -0,0 +1,9 @@ +-- +-- Table structure for table `creature_default_trainer` +-- +DROP TABLE IF EXISTS `creature_default_trainer`; +CREATE TABLE `creature_default_trainer` ( + `CreatureId` int(11) UNSIGNED NOT NULL, + `TrainerId` int(11) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`CreatureId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 3e4a4768cfe..9f5a82f96ea 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -14324,7 +14324,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men GetSession()->SendStablePet(guid); break; case GOSSIP_OPTION_TRAINER: - GetSession()->SendTrainerList(guid, menuItemData->TrainerId); + GetSession()->SendTrainerList(source->ToCreature(), menuItemData->TrainerId); break; case GOSSIP_OPTION_LEARNDUALSPEC: break; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 1db80ed6001..2d489977e79 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -8633,6 +8633,39 @@ void ObjectMgr::LoadTrainers() TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " Trainers in %u ms", _trainers.size(), GetMSTimeDiffToNow(oldMSTime)); } +void ObjectMgr::LoadCreatureDefaultTrainers() +{ + uint32 oldMSTime = getMSTime(); + + _creatureDefaultTrainers.clear(); + + if (QueryResult result = WorldDatabase.Query("SELECT CreatureId, TrainerId FROM creature_default_trainer")) + { + do + { + Field* fields = result->Fetch(); + uint32 creatureId = fields[0].GetUInt32(); + uint32 trainerId = fields[1].GetUInt32(); + + if (!GetCreatureTemplate(creatureId)) + { + TC_LOG_ERROR("sql.sql", "Table `trainer_spell` references non-existing creature template (CreatureId: %u), ignoring", creatureId); + continue; + } + + if (!GetTrainer(trainerId)) + { + TC_LOG_ERROR("sql.sql", "Table `trainer_spell` references non-existing trainer (TrainerId: %u) for CreatureId %u, ignoring", trainerId, creatureId); + continue; + } + + _creatureDefaultTrainers[creatureId] = trainerId; + } while (result->NextRow()); + } + + TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " default trainers in %u ms", _creatureDefaultTrainers.size(), GetMSTimeDiffToNow(oldMSTime)); +} + int ObjectMgr::LoadReferenceVendor(int32 vendor, int32 item, uint8 referenceType, std::set<uint32> *skip_vendors) { // find all items from the reference vendor @@ -8868,6 +8901,15 @@ Trainer::Trainer const* ObjectMgr::GetTrainer(uint32 trainerId) const return Trinity::Containers::MapGetValuePtr(_trainers, trainerId); } +uint32 ObjectMgr::GetCreatureDefaultTrainer(uint32 creatureId) const +{ + auto itr = _creatureDefaultTrainers.find(creatureId); + if (itr != _creatureDefaultTrainers.end()) + return itr->second; + + return 0; +} + void ObjectMgr::AddVendorItem(uint32 entry, uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedCost, uint8 type, bool persist /*= true*/) { VendorItemData& vList = _cacheVendorItemStore[entry]; diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index aad57743e82..ff394c9ed3d 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1166,6 +1166,7 @@ class TC_GAME_API ObjectMgr void LoadVendors(); void LoadTrainers(); + void LoadCreatureDefaultTrainers(); void LoadTerrainPhaseInfo(); void LoadTerrainSwapDefaults(); @@ -1379,6 +1380,7 @@ class TC_GAME_API ObjectMgr bool DeleteGameTele(std::string const& name); Trainer::Trainer const* GetTrainer(uint32 trainerId) const; + uint32 GetCreatureDefaultTrainer(uint32 creatureId) const; VendorItemData const* GetNpcVendorItemList(uint32 entry) const { @@ -1659,6 +1661,7 @@ class TC_GAME_API ObjectMgr CacheVendorItemContainer _cacheVendorItemStore; std::unordered_map<uint32, Trainer::Trainer> _trainers; + std::unordered_map<uint32, uint32> _creatureDefaultTrainers; std::set<uint32> _difficultyEntries[MAX_CREATURE_DIFFICULTIES]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate std::set<uint32> _hasDifficultyEntries[MAX_CREATURE_DIFFICULTIES]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index 6d16a63d81a..51c6e29776f 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -90,18 +90,21 @@ void WorldSession::SendShowMailBox(ObjectGuid guid) void WorldSession::HandleTrainerListOpcode(WorldPackets::NPC::Hello& packet) { - TC_LOG_INFO("network", "%s sent legacy gossipless trainer hello for unit %s, no trainer list available", GetPlayerInfo().c_str(), packet.Unit.ToString().c_str()); -} - -void WorldSession::SendTrainerList(ObjectGuid guid, uint32 trainerId) -{ - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); - if (!unit) + Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(packet.Unit, UNIT_NPC_FLAG_TRAINER); + if (!npc) { - TC_LOG_DEBUG("network", "WORLD: SendTrainerList - %s not found or you can not interact with him.", guid.ToString().c_str()); + TC_LOG_DEBUG("network", "WorldSession::SendTrainerList - %s not found or you can not interact with him.", packet.Unit.ToString().c_str()); return; } + if (uint32 trainerId = sObjectMgr->GetCreatureDefaultTrainer(npc->GetEntry())) + SendTrainerList(npc, trainerId); + else + TC_LOG_DEBUG("network", "WorldSession::SendTrainerList - Creature id %u has no trainer data.", npc->GetEntry()); +} + +void WorldSession::SendTrainerList(Creature* npc, uint32 trainerId) +{ // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); @@ -109,14 +112,14 @@ void WorldSession::SendTrainerList(ObjectGuid guid, uint32 trainerId) Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(trainerId); if (!trainer) { - TC_LOG_DEBUG("network", "WORLD: SendTrainerList - trainer spells not found for trainer %s id %d", guid.ToString().c_str(), trainerId); + TC_LOG_DEBUG("network", "WorldSession::SendTrainerList - trainer spells not found for trainer %s id %d", npc->GetGUID().ToString().c_str(), trainerId); return; } _player->PlayerTalkClass->GetInteractionData().Reset(); - _player->PlayerTalkClass->GetInteractionData().SourceGuid = guid; + _player->PlayerTalkClass->GetInteractionData().SourceGuid = npc->GetGUID(); _player->PlayerTalkClass->GetInteractionData().TrainerId = trainerId; - trainer->SendSpells(unit, _player, GetSessionDbLocaleIndex()); + trainer->SendSpells(npc, _player, GetSessionDbLocaleIndex()); } void WorldSession::HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpell& packet) diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 2addad0b5c2..d2e39197b10 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -972,7 +972,7 @@ class TC_GAME_API WorldSession void SendNameQueryOpcode(ObjectGuid guid); - void SendTrainerList(ObjectGuid guid, uint32 trainerId); + void SendTrainerList(Creature* npc, uint32 trainerId); void SendListInventory(ObjectGuid guid); void SendShowBank(ObjectGuid guid); bool CanOpenMailBox(ObjectGuid guid); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 4234d3720e8..1b15c75b08f 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1939,6 +1939,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Trainers..."); sObjectMgr->LoadTrainers(); // must be after load CreatureTemplate + TC_LOG_INFO("server.loading", "Loading Creature default trainers..."); + sObjectMgr->LoadCreatureDefaultTrainers(); + TC_LOG_INFO("server.loading", "Loading Gossip menu..."); sObjectMgr->LoadGossipMenu(); diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index b657e9e56fe..d1c9396af5a 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -693,9 +693,11 @@ public: { TC_LOG_INFO("misc", "Re-Loading `trainer` Table!"); sObjectMgr->LoadTrainers(); + sObjectMgr->LoadCreatureDefaultTrainers(); handler->SendGlobalGMSysMessage("DB table `trainer` reloaded."); handler->SendGlobalGMSysMessage("DB table `trainer_locale` reloaded."); handler->SendGlobalGMSysMessage("DB table `trainer_spell` reloaded."); + handler->SendGlobalGMSysMessage("DB table `creature_default_trainer` reloaded."); return true; } |