diff options
-rw-r--r-- | sql/base/world_database.sql | 47 | ||||
-rw-r--r-- | sql/updates/10801_world_creature_linked_respawn.sql | 5 | ||||
-rwxr-xr-x | src/server/game/Entities/Creature/Creature.cpp | 51 | ||||
-rwxr-xr-x | src/server/game/Entities/Creature/Creature.h | 4 | ||||
-rwxr-xr-x | src/server/game/Entities/GameObject/GameObject.cpp | 15 | ||||
-rwxr-xr-x | src/server/game/Globals/ObjectMgr.cpp | 248 | ||||
-rwxr-xr-x | src/server/game/Globals/ObjectMgr.h | 33 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_npc.cpp | 3 |
8 files changed, 271 insertions, 135 deletions
diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql index 6a9990a6f16..0e705852df0 100644 --- a/sql/base/world_database.sql +++ b/sql/base/world_database.sql @@ -1451,29 +1451,6 @@ LOCK TABLES `creature_involvedrelation` WRITE; UNLOCK TABLES; -- --- Table structure for table `creature_linked_respawn` --- - -DROP TABLE IF EXISTS `creature_linked_respawn`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `creature_linked_respawn` ( - `guid` int(10) unsigned NOT NULL COMMENT 'dependent creature', - `linkedGuid` int(10) unsigned NOT NULL COMMENT 'master creature', - PRIMARY KEY (`guid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Creature Respawn Link System'; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Dumping data for table `creature_linked_respawn` --- - -LOCK TABLES `creature_linked_respawn` WRITE; -/*!40000 ALTER TABLE `creature_linked_respawn` DISABLE KEYS */; -/*!40000 ALTER TABLE `creature_linked_respawn` ENABLE KEYS */; -UNLOCK TABLES; - --- -- Table structure for table `creature_loot_template` -- @@ -3144,6 +3121,30 @@ LOCK TABLES `lfg_dungeon_rewards` WRITE; UNLOCK TABLES; -- +-- Table structure for table `linked_respawn` +-- + +DROP TABLE IF EXISTS `linked_respawn`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `linked_respawn` ( + `guid` int(10) unsigned NOT NULL COMMENT 'slave entity', + `linkedGuid` int(10) unsigned NOT NULL COMMENT 'master entity', + `linkType` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '0: creature->creature, 1: creature->GO, 2: GO->GO, 3: GO->creature', + PRIMARY KEY (`guid`, `linkType`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Respawn Link System'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `linked_respawn` +-- + +LOCK TABLES `linked_respawn` WRITE; +/*!40000 ALTER TABLE `linked_respawn` DISABLE KEYS */; +/*!40000 ALTER TABLE `linked_respawn` ENABLE KEYS */; +UNLOCK TABLES; + +-- -- Table structure for table `locales_achievement_reward` -- diff --git a/sql/updates/10801_world_creature_linked_respawn.sql b/sql/updates/10801_world_creature_linked_respawn.sql new file mode 100644 index 00000000000..4be48e58e84 --- /dev/null +++ b/sql/updates/10801_world_creature_linked_respawn.sql @@ -0,0 +1,5 @@ +ALTER table `creature_linked_respawn` +RENAME TO `linked_respawn`, +ADD COLUMN linkType tinyint(3) UNSIGNED NOT NULL DEFAULT '0', +DROP PRIMARY KEY, +ADD PRIMARY KEY(`guid`, `linkType`); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 82498d6874c..caeba5de081 100755 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -464,20 +464,17 @@ void Creature::Update(uint32 diff) if (!allowed) // Will be rechecked on next Update call break; - if (!GetLinkedCreatureRespawnTime()) // Can respawn + time_t linkedRespawntime = sObjectMgr->GetLinkedRespawnTime(GetGUID(), GetMap()->GetInstanceId()); + if (!linkedRespawntime) // Can respawn Respawn(); else // the master is dead { - if (uint32 targetGuid = sObjectMgr->GetLinkedRespawnGuid(m_DBTableGuid)) - { - if (targetGuid == m_DBTableGuid) // if linking self, never respawn (check delayed to next day) - SetRespawnTime(DAY); - else - m_respawnTime = (now > GetLinkedCreatureRespawnTime() ? now : GetLinkedCreatureRespawnTime())+urand(5,MINUTE); // else copy time from master and add a little - SaveRespawnTime(); // also save to DB immediately - } + uint64 targetGuid = sObjectMgr->GetLinkedRespawnGuid(GetGUID()); + if (targetGuid == GetGUID()) // if linking self, never respawn (check delayed to next day) + SetRespawnTime(DAY); else - Respawn(); + m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime)+urand(5,MINUTE); // else copy time from master and add a little + SaveRespawnTime(); // also save to DB immediately } } break; @@ -2383,40 +2380,6 @@ const char* Creature::GetNameForLocaleIdx(LocaleConstant loc_idx) const return GetName(); } -const CreatureData* Creature::GetLinkedRespawnCreatureData() const -{ - if (!m_DBTableGuid) // only hard-spawned creatures from DB can have a linked master - return NULL; - - if (uint32 targetGuid = sObjectMgr->GetLinkedRespawnGuid(m_DBTableGuid)) - return sObjectMgr->GetCreatureData(targetGuid); - - return NULL; -} - -// returns master's remaining respawn time if any -time_t Creature::GetLinkedCreatureRespawnTime() const -{ - if (!m_DBTableGuid) // only hard-spawned creatures from DB can have a linked master - return 0; - - if (uint32 targetGuid = sObjectMgr->GetLinkedRespawnGuid(m_DBTableGuid)) - { - Map* targetMap = NULL; - if (const CreatureData* data = sObjectMgr->GetCreatureData(targetGuid)) - { - if (data->mapid == GetMapId()) // look up on the same map - targetMap = GetMap(); - else // it shouldn't be instanceable map here - targetMap = sMapMgr->FindMap(data->mapid); - } - if (targetMap) - return sObjectMgr->GetCreatureRespawnTime(targetGuid,targetMap->GetInstanceId()); - } - - return 0; -} - void Creature::FarTeleportTo(Map* map, float X, float Y, float Z, float O) { InterruptNonMeleeSpells(true); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 2fdf1f7e640..2a75903d6f5 100755 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -609,10 +609,6 @@ class Creature : public Unit, public GridObject<Creature> float GetRespawnRadius() const { return m_respawnradius; } void SetRespawnRadius(float dist) { m_respawnradius = dist; } - // Linked Creature Respawning System - time_t GetLinkedCreatureRespawnTime() const; - const CreatureData* GetLinkedRespawnCreatureData() const; - uint32 m_groupLootTimer; // (msecs)timer used for group loot uint32 lootingGroupLowGUID; // used to find group which is looting corpse diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 503d017281f..5e117f3d153 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -323,8 +323,21 @@ void GameObject::Update(uint32 diff) { if (m_respawnTime > 0) // timer on { - if (m_respawnTime <= time(NULL)) // timer expired + time_t now = time(NULL); + if (m_respawnTime <= now) // timer expired { + time_t linkedRespawntime = sObjectMgr->GetLinkedRespawnTime(GetGUID(), GetMap()->GetInstanceId()); + if (linkedRespawntime) // Can't respawn, the master is dead + { + uint64 targetGuid = sObjectMgr->GetLinkedRespawnGuid(GetGUID()); + if (targetGuid == GetGUID()) // if linking self, never respawn (check delayed to next day) + SetRespawnTime(DAY); + else + m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime)+urand(5,MINUTE); // else copy time from master and add a little + SaveRespawnTime(); // also save to DB immediately + return; + } + m_respawnTime = 0; m_SkillupList.clear(); m_usetimes = 0; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 26248bc38ac..956392e5d9c 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1179,92 +1179,232 @@ void ObjectMgr::LoadCreatureModelInfo() sLog->outString(); } -bool ObjectMgr::CheckCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) const -{ - const CreatureData* const slave = GetCreatureData(guid); - const CreatureData* const master = GetCreatureData(linkedGuid); - - if (!slave || !master) // they must have a corresponding entry in db - { - sLog->outErrorDb("LinkedRespawn: Creature '%u' linking to '%u' which doesn't exist",guid,linkedGuid); - return false; - } - - const MapEntry* const map = sMapStore.LookupEntry(master->mapid); - - if (master->mapid != slave->mapid // link only to same map - && (!map || map->Instanceable())) // or to unistanced world - { - sLog->outErrorDb("LinkedRespawn: Creature '%u' linking to '%u' on an unpermitted map",guid,linkedGuid); - return false; - } - - if (!(master->spawnMask & slave->spawnMask) // they must have a possibility to meet (normal/heroic difficulty) - && (!map || map->Instanceable())) - { - sLog->outErrorDb("LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask",guid,linkedGuid); - return false; - } - - return true; -} - -void ObjectMgr::LoadCreatureLinkedRespawn() +void ObjectMgr::LoadLinkedRespawn() { uint32 oldMSTime = getMSTime(); - mCreatureLinkedRespawnMap.clear(); - QueryResult result = WorldDatabase.Query("SELECT guid, linkedGuid FROM creature_linked_respawn ORDER BY guid ASC"); + mLinkedRespawnMap.clear(); + QueryResult result = WorldDatabase.Query("SELECT guid, linkedGuid, linkType FROM linked_respawn ORDER BY guid ASC"); if (!result) { - sLog->outErrorDb(">> Loaded 0 linked respawns. DB table `creature_linked_respawn` is empty."); + sLog->outErrorDb(">> Loaded 0 linked respawns. DB table `linked_respawn` is empty."); sLog->outString(); return; } - do { Field *fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - uint32 linkedGuid = fields[1].GetUInt32(); + uint32 guidLow = fields[0].GetUInt32(); + uint32 linkedGuidLow = fields[1].GetUInt32(); + uint8 linkType = fields[2].GetUInt8(); - if (CheckCreatureLinkedRespawn(guid,linkedGuid)) - mCreatureLinkedRespawnMap[guid] = linkedGuid; + uint64 guid, linkedGuid; + bool error = false; + switch (linkType) + { + case CREATURE_TO_CREATURE: + { + const CreatureData* slave = GetCreatureData(guidLow); + if (!slave) + { + sLog->outErrorDb("Couldn't get creature data for GUIDLow %u", guidLow); + error = true; + break; + } - } while (result->NextRow()); + const CreatureData* master = GetCreatureData(linkedGuidLow); + if (!master) + { + sLog->outErrorDb("Couldn't get creature data for GUIDLow %u", linkedGuidLow); + error = true; + break; + } + + const MapEntry* const map = sMapStore.LookupEntry(master->mapid); + if (!map || !map->Instanceable() || (master->mapid != slave->mapid)) + { + sLog->outErrorDb("Creature '%u' linking to '%u' on an unpermitted map.", guidLow, linkedGuidLow); + error = true; + break; + } + + if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + { + sLog->outErrorDb("LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask", guidLow, linkedGuidLow); + error = true; + break; + } + + guid = MAKE_NEW_GUID(guidLow, slave->id, HIGHGUID_UNIT); + linkedGuid = MAKE_NEW_GUID(linkedGuidLow, master->id, HIGHGUID_UNIT); + break; + } + case CREATURE_TO_GO: + { + const CreatureData* slave = GetCreatureData(guidLow); + if (!slave) + { + sLog->outErrorDb("Couldn't get creature data for GUIDLow %u", guidLow); + error = true; + break; + } + + const GameObjectData* master = GetGOData(linkedGuidLow); + if (!master) + { + sLog->outErrorDb("Couldn't get gameobject data for GUIDLow %u", linkedGuidLow); + error = true; + break; + } + + const MapEntry* const map = sMapStore.LookupEntry(master->mapid); + if (!map || !map->Instanceable() || (master->mapid != slave->mapid)) + { + sLog->outErrorDb("Creature '%u' linking to '%u' on an unpermitted map.", guidLow, linkedGuidLow); + error = true; + break; + } - sLog->outString(">> Loaded " UI64FMTD " linked respawns in %u ms", uint64(mCreatureLinkedRespawnMap.size()), GetMSTimeDiffToNow(oldMSTime)); + if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + { + sLog->outErrorDb("LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask", guidLow, linkedGuidLow); + error = true; + break; + } + + guid = MAKE_NEW_GUID(guidLow, slave->id, HIGHGUID_UNIT); + linkedGuid = MAKE_NEW_GUID(linkedGuidLow, master->id, HIGHGUID_GAMEOBJECT); + break; + } + case GO_TO_GO: + { + const GameObjectData* slave = GetGOData(guidLow); + if (!slave) + { + sLog->outErrorDb("Couldn't get gameobject data for GUIDLow %u", guidLow); + error = true; + break; + } + + const GameObjectData* master = GetGOData(linkedGuidLow); + if (!master) + { + sLog->outErrorDb("Couldn't get gameobject data for GUIDLow %u", linkedGuidLow); + error = true; + break; + } + + const MapEntry* const map = sMapStore.LookupEntry(master->mapid); + if (!map || !map->Instanceable() || (master->mapid != slave->mapid)) + { + sLog->outErrorDb("Creature '%u' linking to '%u' on an unpermitted map.", guidLow, linkedGuidLow); + error = true; + break; + } + + if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + { + sLog->outErrorDb("LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask", guidLow, linkedGuidLow); + error = true; + break; + } + + guid = MAKE_NEW_GUID(guidLow, slave->id, HIGHGUID_GAMEOBJECT); + linkedGuid = MAKE_NEW_GUID(linkedGuidLow, master->id, HIGHGUID_GAMEOBJECT); + break; + } + case GO_TO_CREATURE: + { + const GameObjectData* slave = GetGOData(guidLow); + if (!slave) + { + sLog->outErrorDb("Couldn't get gameobject data for GUIDLow %u", guidLow); + error = true; + break; + } + + const CreatureData* master = GetCreatureData(linkedGuidLow); + if (!master) + { + sLog->outErrorDb("Couldn't get creature data for GUIDLow %u", linkedGuidLow); + error = true; + break; + } + + const MapEntry* const map = sMapStore.LookupEntry(master->mapid); + if (!map || !map->Instanceable() || (master->mapid != slave->mapid)) + { + sLog->outErrorDb("Creature '%u' linking to '%u' on an unpermitted map.", guidLow, linkedGuidLow); + error = true; + break; + } + + if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + { + sLog->outErrorDb("LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask", guidLow, linkedGuidLow); + error = true; + break; + } + + guid = MAKE_NEW_GUID(guidLow, slave->id, HIGHGUID_GAMEOBJECT); + linkedGuid = MAKE_NEW_GUID(linkedGuidLow, master->id, HIGHGUID_UNIT); + break; + } + } + + if (!error) + mLinkedRespawnMap[guid] = linkedGuid; + + } + while (result->NextRow()); + + sLog->outString(">> Loaded " UI64FMTD " linked respawns in %u ms", uint64(mLinkedRespawnMap.size()), GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } -bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) +bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow) { - if (!guid) + if (!guidLow) return false; - if (!linkedGuid) // we're removing the linking + const CreatureData* master = GetCreatureData(guidLow); + uint64 guid = MAKE_NEW_GUID(guidLow, master->id, HIGHGUID_UNIT); + + if (!linkedGuidLow) // we're removing the linking { - mCreatureLinkedRespawnMap.erase(guid); + mLinkedRespawnMap.erase(guid); PreparedStatement *stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CRELINKED_RESPAWN); - stmt->setUInt32(0, guid); + stmt->setUInt32(0, guidLow); WorldDatabase.Execute(stmt); return true; } - if (CheckCreatureLinkedRespawn(guid,linkedGuid)) // we add/change linking + const CreatureData* slave = GetCreatureData(linkedGuidLow); + + const MapEntry* const map = sMapStore.LookupEntry(master->mapid); + if (!map || !map->Instanceable() || (master->mapid != slave->mapid)) { - mCreatureLinkedRespawnMap[guid] = linkedGuid; - PreparedStatement *stmt = WorldDatabase.GetPreparedStatement(WORLD_REP_CRELINKED_RESPAWN); - stmt->setUInt32(0, guid); - stmt->setUInt32(1, linkedGuid); - WorldDatabase.Execute(stmt); - return true; + sLog->outErrorDb("Creature '%u' linking to '%u' on an unpermitted map.", guidLow, linkedGuidLow); + return false; } - return false; + if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + { + sLog->outErrorDb("LinkedRespawn: Creature '%u' linking to '%u' with not corresponding spawnMask", guidLow, linkedGuidLow); + return false; + } + + uint64 linkedGuid = MAKE_NEW_GUID(linkedGuidLow, slave->id, HIGHGUID_UNIT); + + mLinkedRespawnMap[guid] = linkedGuid; + PreparedStatement *stmt = WorldDatabase.GetPreparedStatement(WORLD_REP_CRELINKED_RESPAWN); + stmt->setUInt32(0, guidLow); + stmt->setUInt32(1, linkedGuidLow); + WorldDatabase.Execute(stmt); + return true; } void ObjectMgr::LoadCreatures() diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index e45794ccc0d..ab259e8a37e 100755 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -379,7 +379,7 @@ struct TrinityStringLocale StringVector Content; }; -typedef std::map<uint32,uint32> CreatureLinkedRespawnMap; +typedef std::map<uint64,uint64> LinkedRespawnMap; typedef UNORDERED_MAP<uint32,CreatureData> CreatureDataMap; typedef UNORDERED_MAP<uint32,GameObjectData> GameObjectDataMap; typedef UNORDERED_MAP<uint32,CreatureLocale> CreatureLocaleMap; @@ -866,7 +866,6 @@ class ObjectMgr void CheckCreatureTemplate(CreatureInfo const* cInfo); void LoadCreatures(); void LoadCreatureLinkedRespawn(); - bool CheckCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid) const; bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid); void LoadCreatureRespawnTimes(); void LoadCreatureAddons(); @@ -980,10 +979,10 @@ class ObjectMgr } CreatureData& NewOrExistCreatureData(uint32 guid) { return mCreatureDataMap[guid]; } void DeleteCreatureData(uint32 guid); - uint32 GetLinkedRespawnGuid(uint32 guid) const + uint64 GetLinkedRespawnGuid(uint64 guid) const { - CreatureLinkedRespawnMap::const_iterator itr = mCreatureLinkedRespawnMap.find(guid); - if (itr == mCreatureLinkedRespawnMap.end()) return 0; + LinkedRespawnMap::const_iterator itr = mLinkedRespawnMap.find(guid); + if (itr == mLinkedRespawnMap.end()) return 0; return itr->second; } CreatureLocale const* GetCreatureLocale(uint32 entry) const @@ -1073,6 +1072,20 @@ class ObjectMgr void AddCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid, uint32 instance); void DeleteCorpseCellData(uint32 mapid, uint32 cellid, uint32 player_guid); + time_t GetLinkedRespawnTime(uint64 guid, uint32 instance) + { + uint64 linkedGuid = GetLinkedRespawnGuid(guid); + switch (GUID_HIPART(linkedGuid)) + { + case HIGHGUID_UNIT: + return GetCreatureRespawnTime(GUID_LOPART(linkedGuid), instance); + case HIGHGUID_GAMEOBJECT: + return GetGORespawnTime(GUID_LOPART(linkedGuid), instance); + default: + return 0; + } + } + time_t GetCreatureRespawnTime(uint32 loguid, uint32 instance) { ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, m_CreatureRespawnTimesMtx, 0); @@ -1319,7 +1332,7 @@ class ObjectMgr MapObjectGuids mMapObjectGuids; CreatureDataMap mCreatureDataMap; - CreatureLinkedRespawnMap mCreatureLinkedRespawnMap; + LinkedRespawnMap mLinkedRespawnMap; CreatureLocaleMap mCreatureLocaleMap; GameObjectDataMap mGameObjectDataMap; GameObjectLocaleMap mGameObjectLocaleMap; @@ -1343,6 +1356,14 @@ class ObjectMgr std::set<uint32> difficultyEntries[MAX_DIFFICULTY - 1]; // already loaded difficulty 1 value in creatures, used in CheckCreatureTemplate std::set<uint32> hasDifficultyEntries[MAX_DIFFICULTY - 1]; // already loaded creatures with difficulty 1 values, used in CheckCreatureTemplate + enum CreatureLinkedRespawnType + { + CREATURE_TO_CREATURE, + CREATURE_TO_GO, // Creature is dependant on GO + GO_TO_GO, + GO_TO_CREATURE, // GO is dependant on creature + }; + }; #define sObjectMgr ACE_Singleton<ObjectMgr, ACE_Null_Mutex>::instance() diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 3eda0b508c9..06d69acebc4 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -546,9 +546,6 @@ public: handler->PSendSysMessage(LANG_NPCINFO_PHASEMASK, target->GetPhaseMask()); handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); handler->PSendSysMessage(LANG_NPCINFO_POSITION,float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); - if (const CreatureData* const linked = target->GetLinkedRespawnCreatureData()) - if (CreatureInfo const *master = GetCreatureInfo(linked->id)) - handler->PSendSysMessage(LANG_NPCINFO_LINKGUID, sObjectMgr->GetLinkedRespawnGuid(target->GetDBTableGUIDLow()), linked->id, master->Name); if ((npcflags & UNIT_NPC_FLAG_VENDOR)) { |