aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.cpp51
-rwxr-xr-xsrc/server/game/Entities/Creature/Creature.h4
-rwxr-xr-xsrc/server/game/Entities/GameObject/GameObject.cpp15
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp248
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h33
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp3
6 files changed, 242 insertions, 112 deletions
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))
{