aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2022_06_11_02_world.sql1
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp8
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp8
-rw-r--r--src/server/game/Events/GameEventMgr.cpp26
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp10
-rw-r--r--src/server/game/Maps/Map.cpp8
-rw-r--r--src/server/game/Maps/Map.h5
-rw-r--r--src/server/game/Maps/SpawnData.h1
-rw-r--r--src/server/game/Pools/PoolMgr.cpp369
-rw-r--r--src/server/game/Pools/PoolMgr.h80
-rw-r--r--src/server/scripts/Commands/cs_gobject.cpp2
11 files changed, 311 insertions, 207 deletions
diff --git a/sql/updates/world/master/2022_06_11_02_world.sql b/sql/updates/world/master/2022_06_11_02_world.sql
new file mode 100644
index 00000000000..1d813c7a588
--- /dev/null
+++ b/sql/updates/world/master/2022_06_11_02_world.sql
@@ -0,0 +1 @@
+ALTER TABLE `pool_members` MODIFY `spawnId` bigint UNSIGNED NOT NULL AFTER `type`;
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index f70b4c7e5b5..e0bd742ca5c 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -1775,7 +1775,7 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap,
if (!m_respawnCompatibilityMode)
{
// @todo pools need fixing! this is just a temporary thing, but they violate dynspawn principles
- if (!sPoolMgr->IsPartOfAPool<Creature>(spawnId))
+ if (!data->poolId)
{
TC_LOG_ERROR("entities.unit", "Creature (SpawnID " UI64FMTD ") trying to load in inactive spawn group '%s':\n%s", spawnId, data->spawnGroupData->name.c_str(), GetDebugInfo().c_str());
return false;
@@ -1790,7 +1790,7 @@ bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap,
if (!m_respawnCompatibilityMode)
{
// @todo same as above
- if (!sPoolMgr->IsPartOfAPool<Creature>(spawnId))
+ if (!data->poolId)
{
TC_LOG_ERROR("entities.unit", "Creature (SpawnID " UI64FMTD ") trying to load despite a respawn timer in progress:\n%s", spawnId, GetDebugInfo().c_str());
return false;
@@ -2235,9 +2235,9 @@ void Creature::Respawn(bool force)
m_triggerJustAppeared = true;
- uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<Creature>(GetSpawnId()) : 0;
+ uint32 poolid = GetCreatureData() ? GetCreatureData()->poolId : 0;
if (poolid)
- sPoolMgr->UpdatePool<Creature>(poolid, GetSpawnId());
+ sPoolMgr->UpdatePool<Creature>(GetMap()->GetPoolData(), poolid, GetSpawnId());
}
UpdateObjectVisibility();
}
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 1bd45f1f2ee..33f7e257a28 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1025,9 +1025,9 @@ void GameObject::Update(uint32 diff)
AI()->Reset();
// Respawn timer
- uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
+ uint32 poolid = GetGameObjectData() ? GetGameObjectData()->poolId : 0;
if (poolid)
- sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId());
+ sPoolMgr->UpdatePool<GameObject>(GetMap()->GetPoolData(), poolid, GetSpawnId());
else
GetMap()->AddToMap(this);
}
@@ -1394,9 +1394,9 @@ void GameObject::Delete()
if (GameObjectOverride const* goOverride = GetGameObjectOverride())
ReplaceAllFlags(GameObjectFlags(goOverride->Flags));
- uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
+ uint32 poolid = GetGameObjectData() ? GetGameObjectData()->poolId : 0;
if (poolid)
- sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId());
+ sPoolMgr->UpdatePool<GameObject>(GetMap()->GetPoolData(), poolid, GetSpawnId());
else
AddObjectToRemoveList();
}
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 72e12165505..3346b1625c1 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -416,8 +416,8 @@ void GameEventMgr::LoadFromDB()
}
// Log error for pooled object, but still spawn it
- if (uint32 poolId = sPoolMgr->IsPartOfAPool(SPAWN_TYPE_CREATURE, guid))
- TC_LOG_ERROR("sql.sql", "`game_event_creature`: game event id (%i) contains creature (" UI64FMTD ") which is part of a pool (%u). This should be spawned in game_event_pool", event_id, guid, poolId);
+ if (data->poolId)
+ TC_LOG_ERROR("sql.sql", "`game_event_creature`: game event id (%i) contains creature (" UI64FMTD ") which is part of a pool (%u). This should be spawned in game_event_pool", event_id, guid, data->poolId);
GuidList& crelist = mGameEventCreatureGuids[internal_event_id];
crelist.push_back(guid);
@@ -466,8 +466,8 @@ void GameEventMgr::LoadFromDB()
}
// Log error for pooled object, but still spawn it
- if (uint32 poolId = sPoolMgr->IsPartOfAPool(SPAWN_TYPE_GAMEOBJECT, guid))
- TC_LOG_ERROR("sql.sql", "`game_event_gameobject`: game event id (%i) contains game object (" UI64FMTD ") which is part of a pool (%u). This should be spawned in game_event_pool", event_id, guid, poolId);
+ if (data->poolId)
+ TC_LOG_ERROR("sql.sql", "`game_event_gameobject`: game event id (%i) contains game object (" UI64FMTD ") which is part of a pool (%u). This should be spawned in game_event_pool", event_id, guid, data->poolId);
GuidList& golist = mGameEventGameobjectGuids[internal_event_id];
golist.push_back(guid);
@@ -1288,7 +1288,15 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
}
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin(); itr != mGameEventPoolIds[internal_event_id].end(); ++itr)
- sPoolMgr->SpawnPool(*itr);
+ {
+ if (PoolTemplateData const* poolTemplate = sPoolMgr->GetPoolTemplate(*itr))
+ {
+ sMapMgr->DoForAllMapsWithMapId(poolTemplate->MapId, [&itr](Map* map)
+ {
+ sPoolMgr->SpawnPool(map->GetPoolData(), *itr);
+ });
+ }
+ }
}
void GameEventMgr::GameEventUnspawn(int16 event_id)
@@ -1365,7 +1373,13 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin(); itr != mGameEventPoolIds[internal_event_id].end(); ++itr)
{
- sPoolMgr->DespawnPool(*itr, true);
+ if (PoolTemplateData const* poolTemplate = sPoolMgr->GetPoolTemplate(*itr))
+ {
+ sMapMgr->DoForAllMapsWithMapId(poolTemplate->MapId, [&itr](Map* map)
+ {
+ sPoolMgr->DespawnPool(map->GetPoolData(), *itr, true);
+ });
+ }
}
}
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 0a6050ef26a..7324e9e05b1 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -2177,7 +2177,7 @@ void ObjectMgr::LoadCreatures()
data.movementType = fields[14].GetUInt8();
data.spawnDifficulties = ParseSpawnDifficulties(fields[15].GetString(), "creature", guid, data.mapId, spawnMasks[data.mapId]);
int16 gameEvent = fields[16].GetInt8();
- uint32 PoolId = fields[17].GetUInt32();
+ data.poolId = fields[17].GetUInt32();
data.npcflag = fields[18].GetUInt64();
data.unit_flags = fields[19].GetUInt32();
data.unit_flags2 = fields[20].GetUInt32();
@@ -2370,8 +2370,8 @@ void ObjectMgr::LoadCreatures()
WorldDatabase.Execute(stmt);
}
- // Add to grid if not managed by the game event or pool system
- if (gameEvent == 0 && PoolId == 0)
+ // Add to grid if not managed by the game event
+ if (gameEvent == 0)
AddCreatureToGrid(&data);
}
while (result->NextRow());
@@ -2659,7 +2659,7 @@ void ObjectMgr::LoadGameObjects()
}
int16 gameEvent = fields[15].GetInt8();
- uint32 PoolId = fields[16].GetUInt32();
+ data.poolId = fields[16].GetUInt32();
data.phaseUseFlags = fields[17].GetUInt8();
data.phaseId = fields[18].GetUInt32();
data.phaseGroup = fields[19].GetUInt32();
@@ -2771,7 +2771,7 @@ void ObjectMgr::LoadGameObjects()
WorldDatabase.Execute(stmt);
}
- if (gameEvent == 0 && PoolId == 0) // if not this is to be managed by GameEvent System or Pool system
+ if (gameEvent == 0) // if not this is to be managed by GameEvent System
AddGameobjectToGrid(&data);
}
while (result->NextRow());
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 738d0d296c8..41d3d2a9abc 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -365,6 +365,8 @@ i_scriptLock(false), _respawnCheckTimer(0)
GetGuidSequenceGenerator<HighGuid::Transport>().Set(sObjectMgr->GetGenerator<HighGuid::Transport>().GetNextAfterMaxUsed());
+ _poolData = sPoolMgr->InitPoolsForMap(this);
+
MMAP::MMapFactory::createOrGetMMapManager()->loadMapInstance(sWorld->GetDataPath(), GetId(), i_InstanceId);
sScriptMgr->OnCreateMap(this);
@@ -3392,7 +3394,7 @@ void Map::ProcessRespawns()
ASSERT_NOTNULL(GetRespawnMapForType(next->type))->erase(next->spawnId);
// step 2: tell pooling logic to do its thing
- sPoolMgr->UpdatePool(poolId, next->type, next->spawnId);
+ sPoolMgr->UpdatePool(GetPoolData(), poolId, next->type, next->spawnId);
// step 3: get rid of the actual entry
RemoveRespawnTime(next->type, next->spawnId, nullptr, true);
@@ -3485,6 +3487,10 @@ bool Map::ShouldBeSpawnedOnGridLoad(SpawnObjectType type, ObjectGuid::LowType sp
if (!IsSpawnGroupActive(spawnGroup->groupId))
return false;
+ if (spawnData->ToSpawnData()->poolId)
+ if (!GetPoolData().IsSpawnedObject(type, spawnId))
+ return false;
+
return true;
}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 87dfda99b7a..d4b7b5c1c10 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -57,6 +57,7 @@ class MapInstanced;
class Object;
class PhaseShift;
class Player;
+class SpawnedPoolData;
class TempSummon;
class Unit;
class Weather;
@@ -807,6 +808,9 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
// This will not affect any already-present creatures in the group
void SetSpawnGroupInactive(uint32 groupId) { SetSpawnGroupActive(groupId, false); }
+ SpawnedPoolData& GetPoolData() { return *_poolData; }
+ SpawnedPoolData const& GetPoolData() const { return *_poolData; }
+
typedef std::function<void(Map*)> FarSpellCallback;
void AddFarSpellCallback(FarSpellCallback&& callback);
@@ -891,6 +895,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
}
std::map<HighGuid, std::unique_ptr<ObjectGuidGeneratorBase>> _guidGenerators;
+ std::unique_ptr<SpawnedPoolData> _poolData;
MapStoredObjectTypesContainer _objectsStore;
CreatureBySpawnIdContainer _creatureBySpawnIdStore;
GameObjectBySpawnIdContainer _gameobjectBySpawnIdStore;
diff --git a/src/server/game/Maps/SpawnData.h b/src/server/game/Maps/SpawnData.h
index 1b96a70ecc1..c672ec528ad 100644
--- a/src/server/game/Maps/SpawnData.h
+++ b/src/server/game/Maps/SpawnData.h
@@ -105,6 +105,7 @@ struct SpawnData : public SpawnMetadata
uint32 phaseId = 0;
uint32 phaseGroup = 0;
int32 terrainSwapMap = -1;
+ uint32 poolId = 0;
int32 spawntimesecs = 0;
std::vector<Difficulty> spawnDifficulties;
uint32 scriptId = 0;
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index 4bfc918b2af..b7b28e139c3 100644
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -21,7 +21,7 @@
#include "DatabaseEnv.h"
#include "GameObject.h"
#include "Log.h"
-#include "MapManager.h"
+#include "Map.h"
#include "ObjectMgr.h"
#include <sstream>
@@ -30,62 +30,75 @@ PoolObject::PoolObject(uint64 _guid, float _chance) : guid(_guid), chance(std::f
}
////////////////////////////////////////////////////////////
-// template class ActivePoolData
+// template class SpawnedPoolData
-ActivePoolData::ActivePoolData() = default;
-ActivePoolData::~ActivePoolData() = default;
+SpawnedPoolData::SpawnedPoolData(Map* owner) : mOwner(owner) { }
+SpawnedPoolData::~SpawnedPoolData() = default;
// Method that tell amount spawned objects/subpools
-uint32 ActivePoolData::GetActiveObjectCount(uint32 pool_id) const
+uint32 SpawnedPoolData::GetSpawnedObjects(uint32 pool_id) const
{
- ActivePoolPools::const_iterator itr = mSpawnedPools.find(pool_id);
+ SpawnedPoolPools::const_iterator itr = mSpawnedPools.find(pool_id);
return itr != mSpawnedPools.end() ? itr->second : 0;
}
// Method that tell if a creature is spawned currently
template<>
-TC_GAME_API bool ActivePoolData::IsActiveObject<Creature>(uint64 db_guid) const
+TC_GAME_API bool SpawnedPoolData::IsSpawnedObject<Creature>(uint64 db_guid) const
{
return mSpawnedCreatures.find(db_guid) != mSpawnedCreatures.end();
}
// Method that tell if a gameobject is spawned currently
template<>
-TC_GAME_API bool ActivePoolData::IsActiveObject<GameObject>(uint64 db_guid) const
+TC_GAME_API bool SpawnedPoolData::IsSpawnedObject<GameObject>(uint64 db_guid) const
{
return mSpawnedGameobjects.find(db_guid) != mSpawnedGameobjects.end();
}
// Method that tell if a pool is spawned currently
template<>
-TC_GAME_API bool ActivePoolData::IsActiveObject<Pool>(uint64 sub_pool_id) const
+TC_GAME_API bool SpawnedPoolData::IsSpawnedObject<Pool>(uint64 sub_pool_id) const
{
return mSpawnedPools.find(sub_pool_id) != mSpawnedPools.end();
}
+bool SpawnedPoolData::IsSpawnedObject(SpawnObjectType type, uint64 db_guid_or_pool_id) const
+{
+ switch (type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ return IsSpawnedObject<Creature>(db_guid_or_pool_id);
+ case SPAWN_TYPE_GAMEOBJECT:
+ return IsSpawnedObject<GameObject>(db_guid_or_pool_id);
+ default:
+ ABORT_MSG("Invalid spawn type %u passed to SpawnedPoolData::IsSpawnedObject (with spawnId " UI64FMTD ")", uint32(type), db_guid_or_pool_id);
+ }
+}
+
template<>
-void ActivePoolData::ActivateObject<Creature>(uint64 db_guid, uint32 pool_id)
+void SpawnedPoolData::AddSpawn<Creature>(uint64 db_guid, uint32 pool_id)
{
mSpawnedCreatures.insert(db_guid);
++mSpawnedPools[pool_id];
}
template<>
-void ActivePoolData::ActivateObject<GameObject>(uint64 db_guid, uint32 pool_id)
+void SpawnedPoolData::AddSpawn<GameObject>(uint64 db_guid, uint32 pool_id)
{
mSpawnedGameobjects.insert(db_guid);
++mSpawnedPools[pool_id];
}
template<>
-void ActivePoolData::ActivateObject<Pool>(uint64 sub_pool_id, uint32 pool_id)
+void SpawnedPoolData::AddSpawn<Pool>(uint64 sub_pool_id, uint32 pool_id)
{
mSpawnedPools[sub_pool_id] = 0;
++mSpawnedPools[pool_id];
}
template<>
-void ActivePoolData::RemoveObject<Creature>(uint64 db_guid, uint32 pool_id)
+void SpawnedPoolData::RemoveSpawn<Creature>(uint64 db_guid, uint32 pool_id)
{
mSpawnedCreatures.erase(db_guid);
uint32& val = mSpawnedPools[pool_id];
@@ -94,7 +107,7 @@ void ActivePoolData::RemoveObject<Creature>(uint64 db_guid, uint32 pool_id)
}
template<>
-void ActivePoolData::RemoveObject<GameObject>(uint64 db_guid, uint32 pool_id)
+void SpawnedPoolData::RemoveSpawn<GameObject>(uint64 db_guid, uint32 pool_id)
{
mSpawnedGameobjects.erase(db_guid);
uint32& val = mSpawnedPools[pool_id];
@@ -103,7 +116,7 @@ void ActivePoolData::RemoveObject<GameObject>(uint64 db_guid, uint32 pool_id)
}
template<>
-void ActivePoolData::RemoveObject<Pool>(uint64 sub_pool_id, uint32 pool_id)
+void SpawnedPoolData::RemoveSpawn<Pool>(uint64 sub_pool_id, uint32 pool_id)
{
mSpawnedPools.erase(sub_pool_id);
uint32& val = mSpawnedPools[pool_id];
@@ -122,6 +135,26 @@ PoolGroup<T>::PoolGroup(): poolId(0)
template <class T>
PoolGroup<T>::~PoolGroup() = default;
+template <class T>
+bool PoolGroup<T>::isEmptyDeepCheck() const
+{
+ return isEmpty();
+}
+
+template <>
+bool PoolGroup<Pool>::isEmptyDeepCheck() const
+{
+ for (PoolObject const& explicitlyChanced : ExplicitlyChanced)
+ if (!sPoolMgr->IsEmpty(explicitlyChanced.guid))
+ return false;
+
+ for (PoolObject const& equalChanced : EqualChanced)
+ if (!sPoolMgr->IsEmpty(equalChanced.guid))
+ return false;
+
+ return true;
+}
+
// Method to add a gameobject/creature guid to the proper list depending on pool type and chance value
template <class T>
void PoolGroup<T>::AddEntry(PoolObject& poolitem, uint32 maxentries)
@@ -151,101 +184,83 @@ bool PoolGroup<T>::CheckPool() const
// If no guid is passed, the pool is just removed (event end case)
// If guid is filled, cache will be used and no removal will occur, it just fill the cache
template<class T>
-void PoolGroup<T>::DespawnObject(ActivePoolData& spawns, uint64 guid, bool alwaysDeleteRespawnTime)
+void PoolGroup<T>::DespawnObject(SpawnedPoolData& spawns, uint64 guid, bool alwaysDeleteRespawnTime)
{
for (size_t i=0; i < EqualChanced.size(); ++i)
{
// if spawned
- if (spawns.IsActiveObject<T>(EqualChanced[i].guid))
+ if (spawns.IsSpawnedObject<T>(EqualChanced[i].guid))
{
if (!guid || EqualChanced[i].guid == guid)
{
- Despawn1Object(EqualChanced[i].guid, alwaysDeleteRespawnTime);
- spawns.RemoveObject<T>(EqualChanced[i].guid, poolId);
+ Despawn1Object(spawns, EqualChanced[i].guid, alwaysDeleteRespawnTime);
+ spawns.RemoveSpawn<T>(EqualChanced[i].guid, poolId);
}
}
else if (alwaysDeleteRespawnTime)
- RemoveRespawnTimeFromDB(EqualChanced[i].guid);
+ RemoveRespawnTimeFromDB(spawns, EqualChanced[i].guid);
}
for (size_t i = 0; i < ExplicitlyChanced.size(); ++i)
{
// spawned
- if (spawns.IsActiveObject<T>(ExplicitlyChanced[i].guid))
+ if (spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid))
{
if (!guid || ExplicitlyChanced[i].guid == guid)
{
- Despawn1Object(ExplicitlyChanced[i].guid, alwaysDeleteRespawnTime);
- spawns.RemoveObject<T>(ExplicitlyChanced[i].guid, poolId);
+ Despawn1Object(spawns, ExplicitlyChanced[i].guid, alwaysDeleteRespawnTime);
+ spawns.RemoveSpawn<T>(ExplicitlyChanced[i].guid, poolId);
}
}
else if (alwaysDeleteRespawnTime)
- RemoveRespawnTimeFromDB(ExplicitlyChanced[i].guid);
+ RemoveRespawnTimeFromDB(spawns, ExplicitlyChanced[i].guid);
}
}
// Method that is actualy doing the removal job on one creature
template<>
-void PoolGroup<Creature>::Despawn1Object(uint64 guid, bool alwaysDeleteRespawnTime, bool saveRespawnTime)
+void PoolGroup<Creature>::Despawn1Object(SpawnedPoolData& spawns, uint64 guid, bool alwaysDeleteRespawnTime, bool saveRespawnTime)
{
- if (CreatureData const* data = sObjectMgr->GetCreatureData(guid))
+ auto creatureBounds = spawns.GetMap()->GetCreatureBySpawnIdStore().equal_range(guid);
+ for (auto itr = creatureBounds.first; itr != creatureBounds.second;)
{
- sObjectMgr->RemoveCreatureFromGrid(data);
-
- Map* map = sMapMgr->FindMap(data->mapId, 0);
- if (map && !map->Instanceable())
- {
- auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(guid);
- for (auto itr = creatureBounds.first; itr != creatureBounds.second;)
- {
- Creature* creature = itr->second;
- ++itr;
- // For dynamic spawns, save respawn time here
- if (saveRespawnTime && !creature->GetRespawnCompatibilityMode())
- creature->SaveRespawnTime();
- creature->AddObjectToRemoveList();
- }
-
- if (alwaysDeleteRespawnTime)
- map->RemoveRespawnTime(SpawnObjectType::SPAWN_TYPE_CREATURE, guid, nullptr, true);
- }
+ Creature* creature = itr->second;
+ ++itr;
+ // For dynamic spawns, save respawn time here
+ if (saveRespawnTime && !creature->GetRespawnCompatibilityMode())
+ creature->SaveRespawnTime();
+ creature->AddObjectToRemoveList();
}
+
+ if (alwaysDeleteRespawnTime)
+ spawns.GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, guid, nullptr, true);
}
// Same on one gameobject
template<>
-void PoolGroup<GameObject>::Despawn1Object(uint64 guid, bool alwaysDeleteRespawnTime, bool saveRespawnTime)
+void PoolGroup<GameObject>::Despawn1Object(SpawnedPoolData& spawns, uint64 guid, bool alwaysDeleteRespawnTime, bool saveRespawnTime)
{
- if (GameObjectData const* data = sObjectMgr->GetGameObjectData(guid))
+ auto gameobjectBounds = spawns.GetMap()->GetGameObjectBySpawnIdStore().equal_range(guid);
+ for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second;)
{
- sObjectMgr->RemoveGameobjectFromGrid(data);
-
- Map* map = sMapMgr->FindMap(data->mapId, 0);
- if (map && !map->Instanceable())
- {
- auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(guid);
- for (auto itr = gameobjectBounds.first; itr != gameobjectBounds.second;)
- {
- GameObject* go = itr->second;
- ++itr;
-
- // For dynamic spawns, save respawn time here
- if (saveRespawnTime && !go->GetRespawnCompatibilityMode())
- go->SaveRespawnTime();
- go->AddObjectToRemoveList();
- }
+ GameObject* go = itr->second;
+ ++itr;
- if (alwaysDeleteRespawnTime)
- map->RemoveRespawnTime(SpawnObjectType::SPAWN_TYPE_GAMEOBJECT, guid, nullptr, true);
- }
+ // For dynamic spawns, save respawn time here
+ if (saveRespawnTime && !go->GetRespawnCompatibilityMode())
+ go->SaveRespawnTime();
+ go->AddObjectToRemoveList();
}
+
+ if (alwaysDeleteRespawnTime)
+ spawns.GetMap()->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, guid, nullptr, true);
}
// Same on one pool
template<>
-void PoolGroup<Pool>::Despawn1Object(uint64 child_pool_id, bool alwaysDeleteRespawnTime, bool /*saveRespawnTime*/)
+void PoolGroup<Pool>::Despawn1Object(SpawnedPoolData& spawns, uint64 child_pool_id, bool alwaysDeleteRespawnTime, bool /*saveRespawnTime*/)
{
- sPoolMgr->DespawnPool(child_pool_id, alwaysDeleteRespawnTime);
+ sPoolMgr->DespawnPool(spawns, child_pool_id, alwaysDeleteRespawnTime);
}
// Method for a pool only to remove any found record causing a circular dependency loop
@@ -271,9 +286,9 @@ void PoolGroup<Pool>::RemoveOneRelation(uint32 child_pool_id)
}
template <class T>
-void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint64 triggerFrom)
+void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint64 triggerFrom)
{
- int count = limit - spawns.GetActiveObjectCount(poolId);
+ int count = limit - spawns.GetSpawnedObjects(poolId);
// If triggered from some object respawn this object is still marked as spawned
// and also counted into m_SpawnedPoolAmount so we need increase count to be
@@ -296,7 +311,7 @@ void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint64 trig
roll -= obj.chance;
// Triggering object is marked as spawned at this time and can be also rolled (respawn case)
// so this need explicit check for this case
- if (roll < 0 && (obj.guid == triggerFrom || !spawns.IsActiveObject<T>(obj.guid)))
+ if (roll < 0 && (obj.guid == triggerFrom || !spawns.IsSpawnedObject<T>(obj.guid)))
{
rolledObjects.push_back(obj);
break;
@@ -308,7 +323,7 @@ void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint64 trig
{
std::copy_if(EqualChanced.begin(), EqualChanced.end(), std::back_inserter(rolledObjects), [triggerFrom, &spawns](PoolObject const& object)
{
- return object.guid == triggerFrom || !spawns.IsActiveObject<T>(object.guid);
+ return object.guid == triggerFrom || !spawns.IsSpawnedObject<T>(object.guid);
});
Trinity::Containers::RandomResize(rolledObjects, count);
@@ -319,13 +334,13 @@ void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint64 trig
{
if (obj.guid == triggerFrom)
{
- ReSpawn1Object(&obj);
+ ReSpawn1Object(spawns, &obj);
triggerFrom = 0;
}
else
{
- spawns.ActivateObject<T>(obj.guid, poolId);
- Spawn1Object(&obj);
+ spawns.AddSpawn<T>(obj.guid, poolId);
+ Spawn1Object(spawns, &obj);
}
}
}
@@ -337,100 +352,74 @@ void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint64 trig
// Method that is actualy doing the spawn job on 1 creature
template <>
-void PoolGroup<Creature>::Spawn1Object(PoolObject* obj)
+void PoolGroup<Creature>::Spawn1Object(SpawnedPoolData& spawns, PoolObject* obj)
{
if (CreatureData const* data = sObjectMgr->GetCreatureData(obj->guid))
{
- sObjectMgr->AddCreatureToGrid(data);
-
// Spawn if necessary (loaded grids only)
- Map* map = sMapMgr->FindMap(data->mapId, 0);
// We use spawn coords to spawn
- if (map && !map->Instanceable() && map->IsGridLoaded(data->spawnPoint))
- Creature::CreateCreatureFromDB(obj->guid, map);
+ if (spawns.GetMap()->IsGridLoaded(data->spawnPoint))
+ Creature::CreateCreatureFromDB(obj->guid, spawns.GetMap());
}
}
// Same for 1 gameobject
template <>
-void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj)
+void PoolGroup<GameObject>::Spawn1Object(SpawnedPoolData& spawns, PoolObject* obj)
{
if (GameObjectData const* data = sObjectMgr->GetGameObjectData(obj->guid))
{
- sObjectMgr->AddGameobjectToGrid(data);
// Spawn if necessary (loaded grids only)
- // this base map checked as non-instanced and then only existed
- Map* map = sMapMgr->FindMap(data->mapId, 0);
// We use current coords to unspawn, not spawn coords since creature can have changed grid
- if (map && !map->Instanceable() && map->IsGridLoaded(data->spawnPoint))
- {
- if (GameObject* go = GameObject::CreateGameObjectFromDB(obj->guid, map, false))
- {
+ if (spawns.GetMap()->IsGridLoaded(data->spawnPoint))
+ if (GameObject* go = GameObject::CreateGameObjectFromDB(obj->guid, spawns.GetMap(), false))
if (go->isSpawnedByDefault())
- {
- if (!map->AddToMap(go))
+ if (!spawns.GetMap()->AddToMap(go))
delete go;
- }
- }
- }
}
}
// Same for 1 pool
template <>
-void PoolGroup<Pool>::Spawn1Object(PoolObject* obj)
+void PoolGroup<Pool>::Spawn1Object(SpawnedPoolData& spawns, PoolObject* obj)
{
- sPoolMgr->SpawnPool(obj->guid);
+ sPoolMgr->SpawnPool(spawns, obj->guid);
}
// Method that does the respawn job on the specified creature
template <>
-void PoolGroup<Creature>::ReSpawn1Object(PoolObject* obj)
+void PoolGroup<Creature>::ReSpawn1Object(SpawnedPoolData& spawns, PoolObject* obj)
{
- Despawn1Object(obj->guid, false, false);
- Spawn1Object(obj);
+ Despawn1Object(spawns, obj->guid, false, false);
+ Spawn1Object(spawns, obj);
}
// Method that does the respawn job on the specified gameobject
template <>
-void PoolGroup<GameObject>::ReSpawn1Object(PoolObject* obj)
+void PoolGroup<GameObject>::ReSpawn1Object(SpawnedPoolData& spawns, PoolObject* obj)
{
- Despawn1Object(obj->guid, false, false);
- Spawn1Object(obj);
+ Despawn1Object(spawns, obj->guid, false, false);
+ Spawn1Object(spawns, obj);
}
// Nothing to do for a child Pool
template <>
-void PoolGroup<Pool>::ReSpawn1Object(PoolObject* /*obj*/) { }
+void PoolGroup<Pool>::ReSpawn1Object(SpawnedPoolData& /*spawns*/, PoolObject* /*obj*/) { }
template <>
-void PoolGroup<Creature>::RemoveRespawnTimeFromDB(uint64 guid)
+void PoolGroup<Creature>::RemoveRespawnTimeFromDB(SpawnedPoolData& spawns, uint64 guid)
{
- if (CreatureData const* data = sObjectMgr->GetCreatureData(guid))
- {
- Map* map = sMapMgr->CreateBaseMap(data->mapId);
- if (!map->Instanceable())
- {
- map->RemoveRespawnTime(SPAWN_TYPE_CREATURE, guid, nullptr, true);
- }
- }
+ spawns.GetMap()->RemoveRespawnTime(SPAWN_TYPE_CREATURE, guid, nullptr, true);
}
template <>
-void PoolGroup<GameObject>::RemoveRespawnTimeFromDB(uint64 guid)
+void PoolGroup<GameObject>::RemoveRespawnTimeFromDB(SpawnedPoolData& spawns, uint64 guid)
{
- if (GameObjectData const* data = sObjectMgr->GetGameObjectData(guid))
- {
- Map* map = sMapMgr->CreateBaseMap(data->mapId);
- if (!map->Instanceable())
- {
- map->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, guid, nullptr, true);
- }
- }
+ spawns.GetMap()->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, guid, nullptr, true);
}
template <>
-void PoolGroup<Pool>::RemoveRespawnTimeFromDB(uint64 /*guid*/) { }
+void PoolGroup<Pool>::RemoveRespawnTimeFromDB(SpawnedPoolData& /*spawns*/, uint64 /*guid*/) { }
////////////////////////////////////////////////////////////
// Methods of class PoolMgr
@@ -473,6 +462,7 @@ void PoolMgr::LoadFromDB()
PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id];
pPoolTemplate.MaxLimit = fields[1].GetUInt32();
+ pPoolTemplate.MapId = -1;
++count;
}
@@ -523,6 +513,15 @@ void PoolMgr::LoadFromDB()
continue;
}
PoolTemplateData* pPoolTemplate = &mPoolTemplate[pool_id];
+ if (pPoolTemplate->MapId == -1)
+ pPoolTemplate->MapId = int32(data->mapId);
+
+ if (pPoolTemplate->MapId != int32(data->mapId))
+ {
+ TC_LOG_ERROR("sql.sql", "`pool_creature` has creature spawns on multiple different maps for creature guid (" UI64FMTD ") in pool id (%u), skipped.", guid, pool_id);
+ continue;
+ }
+
PoolObject plObject = PoolObject(guid, chance);
PoolGroup<Creature>& cregroup = mPoolCreatureGroups[pool_id];
cregroup.SetPoolId(pool_id);
@@ -594,6 +593,15 @@ void PoolMgr::LoadFromDB()
}
PoolTemplateData* pPoolTemplate = &mPoolTemplate[pool_id];
+ if (pPoolTemplate->MapId == -1)
+ pPoolTemplate->MapId = int32(data->mapId);
+
+ if (pPoolTemplate->MapId != int32(data->mapId))
+ {
+ TC_LOG_ERROR("sql.sql", "`pool_gameobject` has gameobject spawns on multiple different maps for gameobject guid (" UI64FMTD ") in pool id (%u), skipped.", guid, pool_id);
+ continue;
+ }
+
PoolObject plObject = PoolObject(guid, chance);
PoolGroup<GameObject>& gogroup = mPoolGameobjectGroups[pool_id];
gogroup.SetPoolId(pool_id);
@@ -629,7 +637,7 @@ void PoolMgr::LoadFromDB()
{
Field* fields = result->Fetch();
- uint32 child_pool_id = fields[0].GetUInt32();
+ uint32 child_pool_id = fields[0].GetUInt64();
uint32 mother_pool_id = fields[1].GetUInt32();
float chance = fields[2].GetFloat();
@@ -678,6 +686,21 @@ void PoolMgr::LoadFromDB()
std::set<uint32> checkedPools;
for (SearchMap::iterator poolItr = mPoolSearchMap.find(it.first); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second))
{
+ if (mPoolTemplate[poolItr->first].MapId != -1)
+ {
+ if (mPoolTemplate[poolItr->second].MapId == -1)
+ mPoolTemplate[poolItr->second].MapId = mPoolTemplate[poolItr->first].MapId;
+
+ if (mPoolTemplate[poolItr->second].MapId != mPoolTemplate[poolItr->first].MapId)
+ {
+ TC_LOG_ERROR("sql.sql", "`pool_pool` has child pools on multiple maps in pool id (%u), skipped.", poolItr->second);
+ mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first);
+ mPoolSearchMap.erase(poolItr);
+ --count;
+ break;
+ }
+ }
+
checkedPools.insert(poolItr->first);
if (checkedPools.find(poolItr->second) != checkedPools.end())
{
@@ -700,6 +723,16 @@ void PoolMgr::LoadFromDB()
}
}
+ for (auto const& [poolId, templateData] : mPoolTemplate)
+ {
+ if (IsEmpty(poolId))
+ {
+ TC_LOG_ERROR("sql.sql", "Pool Id %u is empty (has no creatures and no gameobects and either no child pools or child pools are all empty. The pool will not be spawned", poolId);
+ continue;
+ }
+ ASSERT(templateData.MapId != -1);
+ }
+
// The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks
TC_LOG_INFO("server.loading", "Starting objects pooling system...");
{
@@ -720,7 +753,10 @@ void PoolMgr::LoadFromDB()
{
Field* fields = result->Fetch();
uint32 pool_entry = fields[0].GetUInt32();
- uint32 pool_pool_id = fields[1].GetUInt32();
+ uint32 pool_pool_id = fields[1].GetUInt64();
+
+ if (IsEmpty(pool_entry))
+ continue;
if (!CheckPool(pool_entry))
{
@@ -736,13 +772,13 @@ void PoolMgr::LoadFromDB()
// Don't spawn child pools, they are spawned recursively by their parent pools
if (!pool_pool_id)
{
- SpawnPool(pool_entry);
+ mAutoSpawnPoolsPerMap[mPoolTemplate[pool_entry].MapId].push_back(pool_entry);
count++;
}
}
while (result->NextRow());
- TC_LOG_DEBUG("pool", "Pool handling system initialized, %u pools spawned in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_DEBUG("pool", "Pool handling system initialized, %u pools will be spawned by default in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
}
@@ -751,57 +787,57 @@ void PoolMgr::LoadFromDB()
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
// If it's same, the creature is respawned only (added back to map)
template<>
-void PoolMgr::SpawnPool<Creature>(uint32 pool_id, uint64 db_guid)
+void PoolMgr::SpawnPool<Creature>(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 db_guid)
{
auto it = mPoolCreatureGroups.find(pool_id);
if (it != mPoolCreatureGroups.end() && !it->second.isEmpty())
- it->second.SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid);
+ it->second.SpawnObject(spawnedPoolData, mPoolTemplate[pool_id].MaxLimit, db_guid);
}
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
// If it's same, the gameobject is respawned only (added back to map)
template<>
-void PoolMgr::SpawnPool<GameObject>(uint32 pool_id, uint64 db_guid)
+void PoolMgr::SpawnPool<GameObject>(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 db_guid)
{
auto it = mPoolGameobjectGroups.find(pool_id);
if (it != mPoolGameobjectGroups.end() && !it->second.isEmpty())
- it->second.SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid);
+ it->second.SpawnObject(spawnedPoolData, mPoolTemplate[pool_id].MaxLimit, db_guid);
}
// Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
// If it's same, the pool is respawned only
template<>
-void PoolMgr::SpawnPool<Pool>(uint32 pool_id, uint64 sub_pool_id)
+void PoolMgr::SpawnPool<Pool>(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 sub_pool_id)
{
auto it = mPoolPoolGroups.find(pool_id);
if (it != mPoolPoolGroups.end() && !it->second.isEmpty())
- it->second.SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id);
+ it->second.SpawnObject(spawnedPoolData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id);
}
-void PoolMgr::SpawnPool(uint32 pool_id)
+void PoolMgr::SpawnPool(SpawnedPoolData& spawnedPoolData, uint32 pool_id)
{
- SpawnPool<Pool>(pool_id, 0);
- SpawnPool<GameObject>(pool_id, 0);
- SpawnPool<Creature>(pool_id, 0);
+ SpawnPool<Pool>(spawnedPoolData, pool_id, 0);
+ SpawnPool<GameObject>(spawnedPoolData, pool_id, 0);
+ SpawnPool<Creature>(spawnedPoolData, pool_id, 0);
}
// Call to despawn a pool, all gameobjects/creatures in this pool are removed
-void PoolMgr::DespawnPool(uint32 pool_id, bool alwaysDeleteRespawnTime)
+void PoolMgr::DespawnPool(SpawnedPoolData& spawnedPoolData, uint32 pool_id, bool alwaysDeleteRespawnTime)
{
{
auto it = mPoolCreatureGroups.find(pool_id);
if (it != mPoolCreatureGroups.end() && !it->second.isEmpty())
- it->second.DespawnObject(mSpawnedData, 0, alwaysDeleteRespawnTime);
+ it->second.DespawnObject(spawnedPoolData, 0, alwaysDeleteRespawnTime);
}
{
auto it = mPoolGameobjectGroups.find(pool_id);
if (it != mPoolGameobjectGroups.end() && !it->second.isEmpty())
- it->second.DespawnObject(mSpawnedData, 0, alwaysDeleteRespawnTime);
+ it->second.DespawnObject(spawnedPoolData, 0, alwaysDeleteRespawnTime);
}
{
auto it = mPoolPoolGroups.find(pool_id);
if (it != mPoolPoolGroups.end() && !it->second.isEmpty())
- it->second.DespawnObject(mSpawnedData, 0, alwaysDeleteRespawnTime);
+ it->second.DespawnObject(spawnedPoolData, 0, alwaysDeleteRespawnTime);
}
}
@@ -822,6 +858,26 @@ uint32 PoolMgr::IsPartOfAPool(SpawnObjectType type, ObjectGuid::LowType spawnId)
}
}
+bool PoolMgr::IsEmpty(uint32 pool_id) const
+{
+ {
+ auto it = mPoolGameobjectGroups.find(pool_id);
+ if (it != mPoolGameobjectGroups.end() && !it->second.isEmptyDeepCheck())
+ return false;
+ }
+ {
+ auto it = mPoolCreatureGroups.find(pool_id);
+ if (it != mPoolCreatureGroups.end() && !it->second.isEmptyDeepCheck())
+ return false;
+ }
+ {
+ auto it = mPoolPoolGroups.find(pool_id);
+ if (it != mPoolPoolGroups.end() && !it->second.isEmptyDeepCheck())
+ return false;
+ }
+ return true;
+}
+
// Method that check chance integrity of the creatures and gameobjects in this pool
bool PoolMgr::CheckPool(uint32 pool_id) const
{
@@ -847,29 +903,44 @@ bool PoolMgr::CheckPool(uint32 pool_id) const
// Here we cache only the creature/gameobject whose guid is passed as parameter
// Then the spawn pool call will use this cache to decide
template<typename T>
-void PoolMgr::UpdatePool(uint32 pool_id, uint64 db_guid_or_pool_id)
+void PoolMgr::UpdatePool(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 db_guid_or_pool_id)
{
if (uint32 motherpoolid = IsPartOfAPool<Pool>(pool_id))
- SpawnPool<Pool>(motherpoolid, pool_id);
+ SpawnPool<Pool>(spawnedPoolData, motherpoolid, pool_id);
else
- SpawnPool<T>(pool_id, db_guid_or_pool_id);
+ SpawnPool<T>(spawnedPoolData, pool_id, db_guid_or_pool_id);
}
-template void PoolMgr::UpdatePool<Pool>(uint32 pool_id, uint64 db_guid_or_pool_id);
-template void PoolMgr::UpdatePool<GameObject>(uint32 pool_id, uint64 db_guid_or_pool_id);
-template void PoolMgr::UpdatePool<Creature>(uint32 pool_id, uint64 db_guid_or_pool_id);
+template void PoolMgr::UpdatePool<Pool>(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 db_guid_or_pool_id);
+template void PoolMgr::UpdatePool<GameObject>(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 db_guid_or_pool_id);
+template void PoolMgr::UpdatePool<Creature>(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 db_guid_or_pool_id);
-void PoolMgr::UpdatePool(uint32 pool_id, SpawnObjectType type, uint64 spawnId)
+void PoolMgr::UpdatePool(SpawnedPoolData& spawnedPoolData, uint32 pool_id, SpawnObjectType type, uint64 spawnId)
{
switch (type)
{
case SPAWN_TYPE_CREATURE:
- UpdatePool<Creature>(pool_id, spawnId);
+ UpdatePool<Creature>(spawnedPoolData, pool_id, spawnId);
break;
case SPAWN_TYPE_GAMEOBJECT:
- UpdatePool<GameObject>(pool_id, spawnId);
+ UpdatePool<GameObject>(spawnedPoolData, pool_id, spawnId);
break;
default:
ABORT_MSG("Invalid spawn type %u passed to PoolMgr::IsPartOfPool (with spawnId " UI64FMTD ")", uint32(type), spawnId);
}
}
+
+std::unique_ptr<SpawnedPoolData> PoolMgr::InitPoolsForMap(Map* map)
+{
+ std::unique_ptr<SpawnedPoolData> spawnedPoolData = std::make_unique<SpawnedPoolData>(map);
+ if (std::vector<uint32> const* poolIds = Trinity::Containers::MapGetValuePtr(mAutoSpawnPoolsPerMap, spawnedPoolData->GetMap()->GetId()))
+ for (uint32 poolId : *poolIds)
+ SpawnPool(*spawnedPoolData, poolId);
+
+ return spawnedPoolData;
+}
+
+PoolTemplateData const* PoolMgr::GetPoolTemplate(uint16 pool_id) const
+{
+ return Trinity::Containers::MapGetValuePtr(mPoolTemplate, pool_id);
+}
diff --git a/src/server/game/Pools/PoolMgr.h b/src/server/game/Pools/PoolMgr.h
index 5fb47f3deec..30dce09ffc8 100644
--- a/src/server/game/Pools/PoolMgr.h
+++ b/src/server/game/Pools/PoolMgr.h
@@ -21,17 +21,20 @@
#include "Define.h"
#include "SpawnData.h"
#include <map>
+#include <memory>
#include <set>
#include <unordered_map>
#include <vector>
class Creature;
class GameObject;
+class Map;
class Quest;
struct PoolTemplateData
{
uint32 MaxLimit;
+ int32 MapId;
};
struct PoolObject
@@ -45,34 +48,39 @@ class Pool // for Pool of Pool
{
};
-typedef std::set<uint64> ActivePoolObjects;
-typedef std::map<uint64, uint32> ActivePoolPools;
+typedef std::set<uint64> SpawnedPoolObjects;
+typedef std::map<uint64, uint32> SpawnedPoolPools;
-class TC_GAME_API ActivePoolData
+class TC_GAME_API SpawnedPoolData
{
public:
- explicit ActivePoolData();
- ~ActivePoolData();
+ explicit SpawnedPoolData(Map* owner);
+ ~SpawnedPoolData();
- ActivePoolData(ActivePoolData const& right) = delete;
- ActivePoolData(ActivePoolData&& right) = delete;
- ActivePoolData& operator=(ActivePoolData const& right) = delete;
- ActivePoolData& operator=(ActivePoolData&& right) = delete;
+ SpawnedPoolData(SpawnedPoolData const& right) = delete;
+ SpawnedPoolData(SpawnedPoolData&& right) = delete;
+ SpawnedPoolData& operator=(SpawnedPoolData const& right) = delete;
+ SpawnedPoolData& operator=(SpawnedPoolData&& right) = delete;
+
+ Map* GetMap() const { return mOwner; }
template<typename T>
- bool IsActiveObject(uint64 db_guid_or_pool_id) const;
+ bool IsSpawnedObject(uint64 db_guid_or_pool_id) const;
+
+ bool IsSpawnedObject(SpawnObjectType type, uint64 db_guid_or_pool_id) const;
- uint32 GetActiveObjectCount(uint32 pool_id) const;
+ uint32 GetSpawnedObjects(uint32 pool_id) const;
template<typename T>
- void ActivateObject(uint64 db_guid_or_pool_id, uint32 pool_id);
+ void AddSpawn(uint64 db_guid_or_pool_id, uint32 pool_id);
template<typename T>
- void RemoveObject(uint64 db_guid_or_pool_id, uint32 pool_id);
+ void RemoveSpawn(uint64 db_guid_or_pool_id, uint32 pool_id);
private:
- ActivePoolObjects mSpawnedCreatures;
- ActivePoolObjects mSpawnedGameobjects;
- ActivePoolPools mSpawnedPools;
+ Map* mOwner;
+ SpawnedPoolObjects mSpawnedCreatures;
+ SpawnedPoolObjects mSpawnedGameobjects;
+ SpawnedPoolPools mSpawnedPools;
};
template <class T>
@@ -90,22 +98,17 @@ class TC_GAME_API PoolGroup
void SetPoolId(uint32 pool_id) { poolId = pool_id; }
bool isEmpty() const { return ExplicitlyChanced.empty() && EqualChanced.empty(); }
+ bool isEmptyDeepCheck() const;
void AddEntry(PoolObject& poolitem, uint32 maxentries);
bool CheckPool() const;
- void DespawnObject(ActivePoolData& spawns, uint64 guid=0, bool alwaysDeleteRespawnTime = false);
- void Despawn1Object(uint64 guid, bool alwaysDeleteRespawnTime = false, bool saveRespawnTime = true);
- void SpawnObject(ActivePoolData& spawns, uint32 limit, uint64 triggerFrom);
- void RemoveRespawnTimeFromDB(uint64 guid);
+ void DespawnObject(SpawnedPoolData& spawns, uint64 guid=0, bool alwaysDeleteRespawnTime = false);
+ void Despawn1Object(SpawnedPoolData& spawns, uint64 guid, bool alwaysDeleteRespawnTime = false, bool saveRespawnTime = true);
+ void SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint64 triggerFrom);
+ void RemoveRespawnTimeFromDB(SpawnedPoolData& spawns, uint64 guid);
- void Spawn1Object(PoolObject* obj);
- void ReSpawn1Object(PoolObject* obj);
+ void Spawn1Object(SpawnedPoolData& spawns, PoolObject* obj);
+ void ReSpawn1Object(SpawnedPoolData& spawns, PoolObject* obj);
void RemoveOneRelation(uint32 child_pool_id);
- uint64 GetFirstEqualChancedObjectId()
- {
- if (EqualChanced.empty())
- return 0;
- return EqualChanced.front().guid;
- }
uint32 GetPoolId() const { return poolId; }
private:
uint32 poolId;
@@ -136,20 +139,25 @@ class TC_GAME_API PoolMgr
uint32 IsPartOfAPool(SpawnObjectType type, uint64 spawnId) const;
template<typename T>
- bool IsSpawnedObject(uint64 db_guid_or_pool_id) const { return mSpawnedData.IsActiveObject<T>(db_guid_or_pool_id); }
+ bool IsSpawnedObject(SpawnedPoolData& spawnedPoolData, uint64 db_guid_or_pool_id) const { return spawnedPoolData.IsSpawnedObject<T>(db_guid_or_pool_id); }
+ bool IsEmpty(uint32 pool_id) const;
bool CheckPool(uint32 pool_id) const;
- void SpawnPool(uint32 pool_id);
- void DespawnPool(uint32 pool_id, bool alwaysDeleteRespawnTime = false);
+ void SpawnPool(SpawnedPoolData& spawnedPoolData, uint32 pool_id);
+ void DespawnPool(SpawnedPoolData& spawnedPoolData, uint32 pool_id, bool alwaysDeleteRespawnTime = false);
template<typename T>
- void UpdatePool(uint32 pool_id, uint64 db_guid_or_pool_id);
- void UpdatePool(uint32 pool_id, SpawnObjectType type, uint64 spawnId);
+ void UpdatePool(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 db_guid_or_pool_id);
+ void UpdatePool(SpawnedPoolData& spawnedPoolData, uint32 pool_id, SpawnObjectType type, uint64 spawnId);
+
+ std::unique_ptr<SpawnedPoolData> InitPoolsForMap(Map* map);
+
+ PoolTemplateData const* GetPoolTemplate(uint16 pool_id) const;
private:
template<typename T>
- void SpawnPool(uint32 pool_id, uint64 db_guid_or_pool_id);
+ void SpawnPool(SpawnedPoolData& spawnedPoolData, uint32 pool_id, uint64 db_guid_or_pool_id);
typedef std::unordered_map<uint32, PoolTemplateData> PoolTemplateDataMap;
typedef std::unordered_map<uint32, PoolGroup<Creature>> PoolGroupCreatureMap;
@@ -165,9 +173,7 @@ class TC_GAME_API PoolMgr
SearchMap mCreatureSearchMap;
SearchMap mGameobjectSearchMap;
SearchMap mPoolSearchMap;
-
- // dynamic data
- ActivePoolData mSpawnedData;
+ std::unordered_map<uint32, std::vector<uint32>> mAutoSpawnPoolsPerMap;
};
#define sPoolMgr PoolMgr::instance()
diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp
index 203609f513f..e389f535569 100644
--- a/src/server/scripts/Commands/cs_gobject.cpp
+++ b/src/server/scripts/Commands/cs_gobject.cpp
@@ -254,7 +254,7 @@ public:
phaseId = fields[7].GetUInt32();
phaseGroup = fields[8].GetUInt32();
poolId = sPoolMgr->IsPartOfAPool<GameObject>(guidLow);
- if (!poolId || sPoolMgr->IsSpawnedObject<GameObject>(guidLow))
+ if (!poolId || sPoolMgr->IsSpawnedObject<GameObject>(player->GetMap()->GetPoolData(), guidLow))
found = true;
} while (result->NextRow() && !found);