diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Events/GameEventMgr.cpp | 26 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 10 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 8 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 5 | ||||
-rw-r--r-- | src/server/game/Maps/SpawnData.h | 1 | ||||
-rw-r--r-- | src/server/game/Pools/PoolMgr.cpp | 369 | ||||
-rw-r--r-- | src/server/game/Pools/PoolMgr.h | 80 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_gobject.cpp | 2 |
10 files changed, 310 insertions, 207 deletions
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); |