41 SpawnedPoolPools::const_iterator itr =
mSpawnedPools.find(pool_id);
71 return IsSpawnedObject<Creature>(db_guid_or_pool_id);
73 return IsSpawnedObject<GameObject>(db_guid_or_pool_id);
75 ABORT_MSG(
"Invalid spawn type %u passed to SpawnedPoolData::IsSpawnedObject (with spawnId " UI64FMTD ")",
uint32(type), db_guid_or_pool_id);
80void SpawnedPoolData::AddSpawn<Creature>(
uint64 db_guid,
uint32 pool_id)
87void SpawnedPoolData::AddSpawn<GameObject>(
uint64 db_guid,
uint32 pool_id)
94void SpawnedPoolData::AddSpawn<Pool>(
uint64 sub_pool_id,
uint32 pool_id)
101void SpawnedPoolData::RemoveSpawn<Creature>(
uint64 db_guid,
uint32 pool_id)
110void SpawnedPoolData::RemoveSpawn<GameObject>(
uint64 db_guid,
uint32 pool_id)
119void SpawnedPoolData::RemoveSpawn<Pool>(
uint64 sub_pool_id,
uint32 pool_id)
148 if (!
sPoolMgr->IsEmpty(explicitlyChanced.guid))
152 if (!
sPoolMgr->IsEmpty(equalChanced.guid))
162 if (poolitem.
chance != 0 && maxentries == 1)
163 ExplicitlyChanced.push_back(poolitem);
165 EqualChanced.push_back(poolitem);
172 if (EqualChanced.empty())
175 for (
uint32 i = 0; i < ExplicitlyChanced.size(); ++i)
176 chance += ExplicitlyChanced[i].chance;
177 if (chance != 100 && chance != 0)
189 for (
size_t i=0; i < EqualChanced.size(); ++i)
194 if (!guid || EqualChanced[i].guid == guid)
196 Despawn1Object(spawns, EqualChanced[i].guid, alwaysDeleteRespawnTime);
197 spawns.
RemoveSpawn<T>(EqualChanced[i].guid, poolId);
200 else if (alwaysDeleteRespawnTime)
201 RemoveRespawnTimeFromDB(spawns, EqualChanced[i].guid);
204 for (
size_t i = 0; i < ExplicitlyChanced.size(); ++i)
209 if (!guid || ExplicitlyChanced[i].guid == guid)
211 Despawn1Object(spawns, ExplicitlyChanced[i].guid, alwaysDeleteRespawnTime);
212 spawns.
RemoveSpawn<T>(ExplicitlyChanced[i].guid, poolId);
215 else if (alwaysDeleteRespawnTime)
216 RemoveRespawnTimeFromDB(spawns, ExplicitlyChanced[i].guid);
225 for (
auto itr = creatureBounds.first; itr != creatureBounds.second;)
235 if (alwaysDeleteRespawnTime)
244 for (
auto itr = gameobjectBounds.first; itr != gameobjectBounds.second;)
255 if (alwaysDeleteRespawnTime)
263 sPoolMgr->DespawnPool(spawns, child_pool_id, alwaysDeleteRespawnTime);
272 if (itr->guid == child_pool_id)
280 if (itr->guid == child_pool_id)
302 rolledObjects.reserve(count);
305 if (!ExplicitlyChanced.empty())
314 if (roll < 0 && (obj.guid == triggerFrom || !spawns.
IsSpawnedObject<T>(obj.guid)))
316 rolledObjects.push_back(obj);
322 if (!EqualChanced.empty() && rolledObjects.empty())
324 std::copy_if(EqualChanced.begin(), EqualChanced.end(), std::back_inserter(rolledObjects), [triggerFrom, &spawns](
PoolObject const&
object)
326 return object.guid == triggerFrom || !spawns.IsSpawnedObject<T>(object.guid);
335 if (obj.guid == triggerFrom)
337 ReSpawn1Object(spawns, &obj);
342 spawns.
AddSpawn<T>(obj.guid, poolId);
343 Spawn1Object(spawns, &obj);
350 DespawnObject(spawns, triggerFrom);
452 TC_LOG_INFO(
"server.loading",
">> Loaded 0 object pools. DB table `pool_template` is empty.");
459 Field* fields = result->Fetch();
465 pPoolTemplate.
MapId = -1;
469 while (result->NextRow());
476 TC_LOG_INFO(
"server.loading",
"Loading Creatures Pooling Data...");
485 TC_LOG_INFO(
"server.loading",
">> Loaded 0 creatures in pools. DB table `pool_creature` is empty.");
492 Field* fields = result->Fetch();
496 float chance = fields[2].
GetFloat();
501 TC_LOG_ERROR(
"sql.sql",
"`pool_creature` has a non existing creature spawn (GUID: {}) defined for pool id ({}), skipped.", guid, pool_id);
507 TC_LOG_ERROR(
"sql.sql",
"`pool_creature` pool id ({}) is not in `pool_template`, skipped.", pool_id);
510 if (chance < 0 || chance > 100)
512 TC_LOG_ERROR(
"sql.sql",
"`pool_creature` has an invalid chance ({}) for creature guid ({}) in pool id ({}), skipped.", chance, guid, pool_id);
516 if (pPoolTemplate->
MapId == -1)
521 TC_LOG_ERROR(
"sql.sql",
"`pool_creature` has creature spawns on multiple different maps for creature guid ({}) in pool id ({}), skipped.", guid, pool_id);
534 while (result->NextRow());
542 TC_LOG_INFO(
"server.loading",
"Loading Gameobject Pooling Data...");
551 TC_LOG_INFO(
"server.loading",
">> Loaded 0 gameobjects in pools. DB table `pool_gameobject` is empty.");
558 Field* fields = result->Fetch();
562 float chance = fields[2].
GetFloat();
567 TC_LOG_ERROR(
"sql.sql",
"`pool_gameobject` has a non existing gameobject spawn (GUID: {}) defined for pool id ({}), skipped.", guid, pool_id);
574 TC_LOG_ERROR(
"sql.sql",
"`pool_gameobject` pool id ({}) is not in `pool_template`, skipped.", pool_id);
578 if (chance < 0 || chance > 100)
580 TC_LOG_ERROR(
"sql.sql",
"`pool_gameobject` has an invalid chance ({}) for gameobject guid ({}) in pool id ({}), skipped.", chance, guid, pool_id);
585 if (pPoolTemplate->
MapId == -1)
590 TC_LOG_ERROR(
"sql.sql",
"`pool_gameobject` has gameobject spawns on multiple different maps for gameobject guid ({}) in pool id ({}), skipped.", guid, pool_id);
603 while (result->NextRow());
611 TC_LOG_INFO(
"server.loading",
"Loading Mother Pooling Data...");
620 TC_LOG_INFO(
"server.loading",
">> Loaded 0 pools in pools");
627 Field* fields = result->Fetch();
631 float chance = fields[2].
GetFloat();
637 TC_LOG_ERROR(
"sql.sql",
"`pool_pool` mother_pool id ({}) is not in `pool_template`, skipped.", mother_pool_id);
645 TC_LOG_ERROR(
"sql.sql",
"`pool_pool` included pool_id ({}) is not in `pool_template`, skipped.", child_pool_id);
649 if (mother_pool_id == child_pool_id)
651 TC_LOG_ERROR(
"sql.sql",
"`pool_pool` pool_id ({}) includes itself, dead-lock detected, skipped.", child_pool_id);
654 if (chance < 0 || chance > 100)
656 TC_LOG_ERROR(
"sql.sql",
"`pool_pool` has an invalid chance ({}) for pool id ({}) in mother pool id ({}), skipped.", chance, child_pool_id, mother_pool_id);
669 while (result->NextRow());
675 std::set<uint32> checkedPools;
685 TC_LOG_ERROR(
"sql.sql",
"`pool_pool` has child pools on multiple maps in pool id ({}), skipped.", poolItr->second);
693 checkedPools.insert(poolItr->first);
694 if (checkedPools.find(poolItr->second) != checkedPools.end())
696 std::ostringstream ss;
697 ss <<
"The pool(s) ";
698 for (std::set<uint32>::const_iterator itr = checkedPools.begin(); itr != checkedPools.end(); ++itr)
700 ss <<
"create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool "
701 << poolItr->first <<
" and child pool " << poolItr->second;
719 TC_LOG_ERROR(
"sql.sql",
"Pool Id {} 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);
722 ASSERT(templateData.MapId != -1);
726 TC_LOG_INFO(
"server.loading",
"Starting objects pooling system...");
730 QueryResult result =
WorldDatabase.Query(
"SELECT DISTINCT pool_template.entry, pool_members.spawnId, pool_members.poolSpawnId FROM pool_template"
731 " LEFT JOIN game_event_pool ON pool_template.entry = game_event_pool.pool_entry"
732 " LEFT JOIN pool_members ON pool_members.type = 2 AND pool_template.entry = pool_members.spawnId WHERE game_event_pool.pool_entry IS NULL");
736 TC_LOG_INFO(
"server.loading",
">> Pool handling system initialized, 0 pools spawned.");
743 Field* fields = result->Fetch();
755 TC_LOG_ERROR(
"sql.sql",
"Pool Id {} has no equal chance pooled entites defined and explicit chance sum is not 100. This broken pool is a child pool of Id {} and cannot be safely removed.", pool_entry, fields[2].GetUInt32());
757 TC_LOG_ERROR(
"sql.sql",
"Pool Id {} has no equal chance pooled entites defined and explicit chance sum is not 100. The pool will not be spawned.", pool_entry);
768 while (result->NextRow());
783 it->second.SpawnObject(spawnedPoolData,
mPoolTemplate[pool_id].MaxLimit, db_guid);
793 it->second.SpawnObject(spawnedPoolData,
mPoolTemplate[pool_id].MaxLimit, db_guid);
803 it->second.SpawnObject(spawnedPoolData,
mPoolTemplate[pool_id].MaxLimit, sub_pool_id);
808 SpawnPool<Pool>(spawnedPoolData, pool_id, 0);
809 SpawnPool<GameObject>(spawnedPoolData, pool_id, 0);
810 SpawnPool<Creature>(spawnedPoolData, pool_id, 0);
819 it->second.DespawnObject(spawnedPoolData, 0, alwaysDeleteRespawnTime);
824 it->second.DespawnObject(spawnedPoolData, 0, alwaysDeleteRespawnTime);
829 it->second.DespawnObject(spawnedPoolData, 0, alwaysDeleteRespawnTime);
839 return IsPartOfAPool<Creature>(spawnId);
841 return IsPartOfAPool<GameObject>(spawnId);
845 ABORT_MSG(
"Invalid spawn type %u passed to PoolMgr::IsPartOfPool (with spawnId " UI64FMTD ")",
uint32(type), spawnId);
897 if (
uint32 motherpoolid = IsPartOfAPool<Pool>(pool_id))
898 SpawnPool<Pool>(spawnedPoolData, motherpoolid, pool_id);
900 SpawnPool<T>(spawnedPoolData, pool_id, db_guid_or_pool_id);
912 UpdatePool<Creature>(spawnedPoolData, pool_id, spawnId);
915 UpdatePool<GameObject>(spawnedPoolData, pool_id, spawnId);
918 ABORT_MSG(
"Invalid spawn type %u passed to PoolMgr::IsPartOfPool (with spawnId " UI64FMTD ")",
uint32(type), spawnId);
924 std::unique_ptr<SpawnedPoolData> spawnedPoolData = std::make_unique<SpawnedPoolData>(map);
926 for (
uint32 poolId : *poolIds)
929 return spawnedPoolData;
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
#define TC_LOG_DEBUG(filterType__,...)
#define TC_LOG_ERROR(filterType__,...)
#define TC_LOG_INFO(filterType__,...)
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
static Creature * CreateCreatureFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap=true, bool allowDuplicate=false)
bool GetRespawnCompatibilityMode() const
void SaveRespawnTime(uint32 forceDelay=0)
Class used to access individual fields of database query result.
bool isSpawnedByDefault() const
static GameObject * CreateGameObjectFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap=true)
void SaveRespawnTime(uint32 forceDelay=0)
bool GetRespawnCompatibilityMode()
void RemoveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, CharacterDatabaseTransaction dbTrans=nullptr, bool alwaysDeleteFromDB=false)
GameObjectBySpawnIdContainer & GetGameObjectBySpawnIdStore()
bool IsGridLoaded(uint32 gridId) const
CreatureBySpawnIdContainer & GetCreatureBySpawnIdStore()
void SetPoolId(uint32 pool_id)
void ReSpawn1Object(SpawnedPoolData &spawns, PoolObject *obj)
void DespawnObject(SpawnedPoolData &spawns, uint64 guid=0, bool alwaysDeleteRespawnTime=false)
void Despawn1Object(SpawnedPoolData &spawns, uint64 guid, bool alwaysDeleteRespawnTime=false, bool saveRespawnTime=true)
void RemoveOneRelation(uint32 child_pool_id)
void Spawn1Object(SpawnedPoolData &spawns, PoolObject *obj)
PoolObjectList ExplicitlyChanced
void AddEntry(PoolObject &poolitem, uint32 maxentries)
bool isEmptyDeepCheck() const
void RemoveRespawnTimeFromDB(SpawnedPoolData &spawns, uint64 guid)
std::vector< PoolObject > PoolObjectList
PoolObjectList EqualChanced
void SpawnObject(SpawnedPoolData &spawns, uint32 limit, uint64 triggerFrom)
std::pair< uint64, uint32 > SearchPair
bool IsEmpty(uint32 pool_id) const
bool CheckPool(uint32 pool_id) const
std::unique_ptr< SpawnedPoolData > InitPoolsForMap(Map *map)
void UpdatePool(SpawnedPoolData &spawnedPoolData, uint32 pool_id, uint64 db_guid_or_pool_id)
static PoolMgr * instance()
void SpawnPool(SpawnedPoolData &spawnedPoolData, uint32 pool_id)
PoolTemplateData const * GetPoolTemplate(uint16 pool_id) const
PoolGroupCreatureMap mPoolCreatureGroups
PoolGroupPoolMap mPoolPoolGroups
SearchMap mGameobjectSearchMap
PoolTemplateDataMap mPoolTemplate
std::unordered_map< uint32, std::vector< uint32 > > mAutoSpawnPoolsPerMap
uint32 IsPartOfAPool(uint64 db_guid_or_pool_id) const
PoolGroupGameObjectMap mPoolGameobjectGroups
void DespawnPool(SpawnedPoolData &spawnedPoolData, uint32 pool_id, bool alwaysDeleteRespawnTime=false)
SearchMap mCreatureSearchMap
SpawnedPoolObjects mSpawnedCreatures
SpawnedPoolObjects mSpawnedGameobjects
SpawnedPoolData(Map *owner)
void AddSpawn(uint64 db_guid_or_pool_id, uint32 pool_id)
uint32 GetSpawnedObjects(uint32 pool_id) const
bool IsSpawnedObject(uint64 db_guid_or_pool_id) const
void RemoveSpawn(uint64 db_guid_or_pool_id, uint32 pool_id)
SpawnedPoolPools mSpawnedPools
void AddObjectToRemoveList()
auto MapGetValuePtr(M &map, typename M::key_type const &key)
void RandomResize(C &container, std::size_t requestedSize)
PoolObject(uint64 _guid, float _chance)