[9529] Make Player::IsValidPos const
[getmangos.git] / src / game / PoolManager.cpp
blob651252b8072339226bd7981d7878e55b65e685e4
1 /*
2 * Copyright (C) 2005-2010 MaNGOS <http://www.mangosproject.org/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "PoolManager.h"
20 #include "ObjectMgr.h"
21 #include "ObjectDefines.h"
22 #include "ProgressBar.h"
23 #include "Log.h"
24 #include "MapManager.h"
25 #include "World.h"
26 #include "Policies/SingletonImp.h"
28 INSTANTIATE_SINGLETON_1(PoolManager);
30 ////////////////////////////////////////////////////////////
31 // template class SpawnedPoolData
33 // Method that tell amount spawned objects/subpools
34 uint32 SpawnedPoolData::GetSpawnedObjects(uint32 pool_id) const
36 SpawnedPoolPools::const_iterator itr = mSpawnedPools.find(pool_id);
37 return itr != mSpawnedPools.end() ? itr->second : 0;
40 // Method that tell if a creature is spawned currently
41 template<>
42 bool SpawnedPoolData::IsSpawnedObject<Creature>(uint32 db_guid) const
44 return mSpawnedCreatures.find(db_guid) != mSpawnedCreatures.end();
47 // Method that tell if a gameobject is spawned currently
48 template<>
49 bool SpawnedPoolData::IsSpawnedObject<GameObject>(uint32 db_guid) const
51 return mSpawnedGameobjects.find(db_guid) != mSpawnedGameobjects.end();
54 // Method that tell if a pool is spawned currently
55 template<>
56 bool SpawnedPoolData::IsSpawnedObject<Pool>(uint32 sub_pool_id) const
58 return mSpawnedPools.find(sub_pool_id) != mSpawnedPools.end();
61 template<>
62 void SpawnedPoolData::AddSpawn<Creature>(uint32 db_guid, uint32 pool_id)
64 mSpawnedCreatures.insert(db_guid);
65 ++mSpawnedPools[pool_id];
68 template<>
69 void SpawnedPoolData::AddSpawn<GameObject>(uint32 db_guid, uint32 pool_id)
71 mSpawnedGameobjects.insert(db_guid);
72 ++mSpawnedPools[pool_id];
75 template<>
76 void SpawnedPoolData::AddSpawn<Pool>(uint32 sub_pool_id, uint32 pool_id)
78 mSpawnedPools[sub_pool_id] = 0;
79 ++mSpawnedPools[pool_id];
82 template<>
83 void SpawnedPoolData::RemoveSpawn<Creature>(uint32 db_guid, uint32 pool_id)
85 mSpawnedCreatures.erase(db_guid);
86 uint32& val = mSpawnedPools[pool_id];
87 if (val > 0)
88 --val;
91 template<>
92 void SpawnedPoolData::RemoveSpawn<GameObject>(uint32 db_guid, uint32 pool_id)
94 mSpawnedGameobjects.erase(db_guid);
95 uint32& val = mSpawnedPools[pool_id];
96 if (val > 0)
97 --val;
100 template<>
101 void SpawnedPoolData::RemoveSpawn<Pool>(uint32 sub_pool_id, uint32 pool_id)
103 mSpawnedPools.erase(sub_pool_id);
104 uint32& val = mSpawnedPools[pool_id];
105 if (val > 0)
106 --val;
109 ////////////////////////////////////////////////////////////
110 // Methods of template class PoolGroup
112 // Method to add a gameobject/creature guid to the proper list depending on pool type and chance value
113 template <class T>
114 void PoolGroup<T>::AddEntry(PoolObject& poolitem, uint32 maxentries)
116 if (poolitem.chance != 0 && maxentries == 1)
117 ExplicitlyChanced.push_back(poolitem);
118 else
119 EqualChanced.push_back(poolitem);
122 // Method to check the chances are proper in this object pool
123 template <class T>
124 bool PoolGroup<T>::CheckPool() const
126 if (EqualChanced.size() == 0)
128 float chance = 0;
129 for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
130 chance += ExplicitlyChanced[i].chance;
131 if (chance != 100 && chance != 0)
132 return false;
134 return true;
137 template <class T>
138 PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
140 if (!ExplicitlyChanced.empty())
142 float roll = (float)rand_chance();
144 for (uint32 i = 0; i < ExplicitlyChanced.size(); ++i)
146 roll -= ExplicitlyChanced[i].chance;
147 // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
148 // so this need explicit check for this case
149 if (roll < 0 && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid)))
150 return &ExplicitlyChanced[i];
154 if (!EqualChanced.empty())
156 int32 index = irand(0, EqualChanced.size()-1);
157 // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
158 // so this need explicit check for this case
159 if (EqualChanced[index].guid == triggerFrom || !spawns.IsSpawnedObject<T>(EqualChanced[index].guid))
160 return &EqualChanced[index];
163 return NULL;
166 // Main method to despawn a creature or gameobject in a pool
167 // If no guid is passed, the pool is just removed (event end case)
168 // If guid is filled, cache will be used and no removal will occur, it just fill the cache
169 template<class T>
170 void PoolGroup<T>::DespawnObject(SpawnedPoolData& spawns, uint32 guid)
172 for (size_t i = 0; i < EqualChanced.size(); ++i)
174 // if spawned
175 if (spawns.IsSpawnedObject<T>(EqualChanced[i].guid))
177 // any or specially requested
178 if (!guid || EqualChanced[i].guid == guid)
180 Despawn1Object(EqualChanced[i].guid);
181 spawns.RemoveSpawn<T>(EqualChanced[i].guid,poolId);
186 for (size_t i = 0; i < ExplicitlyChanced.size(); ++i)
188 // spawned
189 if (spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid))
191 // any or specially requested
192 if (!guid || ExplicitlyChanced[i].guid == guid)
194 Despawn1Object(ExplicitlyChanced[i].guid);
195 spawns.RemoveSpawn<T>(ExplicitlyChanced[i].guid,poolId);
201 // Method that is actualy doing the removal job on one creature
202 template<>
203 void PoolGroup<Creature>::Despawn1Object(uint32 guid)
205 if (CreatureData const* data = sObjectMgr.GetCreatureData(guid))
207 sObjectMgr.RemoveCreatureFromGrid(guid, data);
209 if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_UNIT)))
210 pCreature->AddObjectToRemoveList();
214 // Same on one gameobject
215 template<>
216 void PoolGroup<GameObject>::Despawn1Object(uint32 guid)
218 if (GameObjectData const* data = sObjectMgr.GetGOData(guid))
220 sObjectMgr.RemoveGameobjectFromGrid(guid, data);
222 if (GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_GAMEOBJECT)))
223 pGameobject->AddObjectToRemoveList();
227 // Same on one pool
228 template<>
229 void PoolGroup<Pool>::Despawn1Object(uint32 child_pool_id)
231 sPoolMgr.DespawnPool(child_pool_id);
234 // Method for a pool only to remove any found record causing a circular dependency loop
235 template<>
236 void PoolGroup<Pool>::RemoveOneRelation(uint16 child_pool_id)
238 for (PoolObjectList::iterator itr = ExplicitlyChanced.begin(); itr != ExplicitlyChanced.end(); ++itr)
240 if(itr->guid == child_pool_id)
242 ExplicitlyChanced.erase(itr);
243 break;
246 for (PoolObjectList::iterator itr = EqualChanced.begin(); itr != EqualChanced.end(); ++itr)
248 if(itr->guid == child_pool_id)
250 EqualChanced.erase(itr);
251 break;
256 template <class T>
257 void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom, bool instantly)
259 uint32 lastDespawned = 0;
260 int count = limit - spawns.GetSpawnedObjects(poolId);
262 // If triggered from some object respawn this object is still marked as spawned
263 // and also counted into m_SpawnedPoolAmount so we need increase count to be
264 // spawned by 1
265 if (triggerFrom)
266 ++count;
268 // This will try to spawn the rest of pool, not guaranteed
269 for (int i = 0; i < count; ++i)
271 PoolObject* obj = RollOne(spawns,triggerFrom);
272 if (!obj)
273 continue;
274 if (obj->guid == lastDespawned)
275 continue;
277 if (obj->guid == triggerFrom)
279 assert(spawns.IsSpawnedObject<T>(obj->guid));
280 assert(spawns.GetSpawnedObjects(poolId) > 0);
281 ReSpawn1Object(obj);
282 triggerFrom = 0;
283 continue;
286 spawns.AddSpawn<T>(obj->guid,poolId);
287 Spawn1Object(obj, instantly);
289 if (triggerFrom)
291 // One spawn one despawn no count increase
292 DespawnObject(spawns, triggerFrom);
293 lastDespawned = triggerFrom;
294 triggerFrom = 0;
299 // Method that is actualy doing the spawn job on 1 creature
300 template <>
301 void PoolGroup<Creature>::Spawn1Object(PoolObject* obj, bool instantly)
303 if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid))
305 sObjectMgr.AddCreatureToGrid(obj->guid, data);
307 // Spawn if necessary (loaded grids only)
308 Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid));
309 // We use spawn coords to spawn (avoid work for instances until implemented support)
310 if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
312 Creature* pCreature = new Creature;
313 //sLog.outDebug("Spawning creature %u",obj->guid);
314 if (!pCreature->LoadFromDB(obj->guid, map))
316 delete pCreature;
317 return;
319 else
321 // if new spawn replaces a just despawned creature, not instantly spawn but set respawn timer
322 if(!instantly)
324 pCreature->SetRespawnTime( pCreature->GetRespawnDelay() );
325 if (sWorld.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY) || pCreature->isWorldBoss())
326 pCreature->SaveRespawnTime();
328 map->Add(pCreature);
331 // for not loaded grid just update respawn time (avoid work for instances until implemented support)
332 else if(!map->Instanceable() && !instantly)
334 sObjectMgr.SaveCreatureRespawnTime(obj->guid,map->GetInstanceId(),time(NULL) + data->spawntimesecs);
339 // Same for 1 gameobject
340 template <>
341 void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj, bool instantly)
343 if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid))
345 sObjectMgr.AddGameobjectToGrid(obj->guid, data);
346 // Spawn if necessary (loaded grids only)
347 // this base map checked as non-instanced and then only existed
348 Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid));
349 // We use current coords to unspawn, not spawn coords since creature can have changed grid
350 // (avoid work for instances until implemented support)
351 if (!map->Instanceable() && map->IsLoaded(data->posX, data->posY))
353 GameObject* pGameobject = new GameObject;
354 //sLog.outDebug("Spawning gameobject %u", obj->guid);
355 if (!pGameobject->LoadFromDB(obj->guid, map))
357 delete pGameobject;
358 return;
360 else
362 if (pGameobject->isSpawnedByDefault())
364 // if new spawn replaces a just despawned object, not instantly spawn but set respawn timer
365 if(!instantly)
367 pGameobject->SetRespawnTime( pGameobject->GetRespawnDelay() );
368 if (sWorld.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY))
369 pGameobject->SaveRespawnTime();
371 map->Add(pGameobject);
375 // for not loaded grid just update respawn time (avoid work for instances until implemented support)
376 else if(!map->Instanceable() && !instantly)
378 // for spawned by default object only
379 if (data->spawntimesecs >= 0)
380 sObjectMgr.SaveGORespawnTime(obj->guid,map->GetInstanceId(),time(NULL) + data->spawntimesecs);
385 // Same for 1 pool
386 template <>
387 void PoolGroup<Pool>::Spawn1Object(PoolObject* obj, bool instantly)
389 sPoolMgr.SpawnPool(obj->guid, instantly);
392 // Method that does the respawn job on the specified creature
393 template <>
394 void PoolGroup<Creature>::ReSpawn1Object(PoolObject* obj)
396 if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid))
397 if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(MAKE_NEW_GUID(obj->guid, data->id, HIGHGUID_UNIT)))
398 pCreature->GetMap()->Add(pCreature);
401 // Method that does the respawn job on the specified gameobject
402 template <>
403 void PoolGroup<GameObject>::ReSpawn1Object(PoolObject* obj)
405 if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid))
406 if (GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(MAKE_NEW_GUID(obj->guid, data->id, HIGHGUID_GAMEOBJECT)))
407 pGameobject->GetMap()->Add(pGameobject);
410 // Nothing to do for a child Pool
411 template <>
412 void PoolGroup<Pool>::ReSpawn1Object(PoolObject* /*obj*/)
417 ////////////////////////////////////////////////////////////
418 // Methods of class PoolManager
420 PoolManager::PoolManager()
424 void PoolManager::LoadFromDB()
426 QueryResult *result = WorldDatabase.Query("SELECT MAX(entry) FROM pool_template");
427 if (!result)
429 sLog.outString(">> Table pool_template is empty.");
430 sLog.outString();
431 return;
433 else
435 Field *fields = result->Fetch();
436 max_pool_id = fields[0].GetUInt16();
437 delete result;
440 mPoolTemplate.resize(max_pool_id + 1);
442 result = WorldDatabase.Query("SELECT entry,max_limit FROM pool_template");
443 if (!result)
445 mPoolTemplate.clear();
446 sLog.outString(">> Table pool_template is empty:");
447 sLog.outString();
448 return;
451 uint32 count = 0;
453 barGoLink bar((int)result->GetRowCount());
456 ++count;
457 Field *fields = result->Fetch();
459 bar.step();
461 uint16 pool_id = fields[0].GetUInt16();
463 PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id];
464 pPoolTemplate.MaxLimit = fields[1].GetUInt32();
466 } while (result->NextRow());
468 sLog.outString();
469 sLog.outString( ">> Loaded %u objects pools", count );
470 delete result;
472 // Creatures
474 mPoolCreatureGroups.resize(max_pool_id + 1);
475 mCreatureSearchMap.clear();
476 // 1 2 3
477 result = WorldDatabase.Query("SELECT guid, pool_entry, chance FROM pool_creature");
479 count = 0;
480 if (!result)
482 barGoLink bar2(1);
483 bar2.step();
485 sLog.outString();
486 sLog.outString(">> Loaded %u creatures in pools", count );
488 else
491 barGoLink bar2((int)result->GetRowCount());
494 Field *fields = result->Fetch();
496 bar2.step();
498 uint32 guid = fields[0].GetUInt32();
499 uint16 pool_id = fields[1].GetUInt16();
500 float chance = fields[2].GetFloat();
502 CreatureData const* data = sObjectMgr.GetCreatureData(guid);
503 if (!data)
505 sLog.outErrorDb("`pool_creature` has a non existing creature spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id );
506 continue;
508 if (pool_id > max_pool_id)
510 sLog.outErrorDb("`pool_creature` pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",pool_id);
511 continue;
513 if (chance < 0 || chance > 100)
515 sLog.outErrorDb("`pool_creature` has an invalid chance (%f) for creature guid (%u) in pool id (%i), skipped.", chance, guid, pool_id);
516 continue;
518 PoolTemplateData *pPoolTemplate = &mPoolTemplate[pool_id];
519 ++count;
521 PoolObject plObject = PoolObject(guid, chance);
522 PoolGroup<Creature>& cregroup = mPoolCreatureGroups[pool_id];
523 cregroup.SetPoolId(pool_id);
524 cregroup.AddEntry(plObject, pPoolTemplate->MaxLimit);
525 SearchPair p(guid, pool_id);
526 mCreatureSearchMap.insert(p);
528 } while (result->NextRow());
529 sLog.outString();
530 sLog.outString( ">> Loaded %u creatures in pools", count );
531 delete result;
534 // Gameobjects
536 mPoolGameobjectGroups.resize(max_pool_id + 1);
537 mGameobjectSearchMap.clear();
538 // 1 2 3
539 result = WorldDatabase.Query("SELECT guid, pool_entry, chance FROM pool_gameobject");
541 count = 0;
542 if (!result)
544 barGoLink bar2(1);
545 bar2.step();
547 sLog.outString();
548 sLog.outString(">> Loaded %u gameobject in pools", count );
550 else
553 barGoLink bar2((int)result->GetRowCount());
556 Field *fields = result->Fetch();
558 bar2.step();
560 uint32 guid = fields[0].GetUInt32();
561 uint16 pool_id = fields[1].GetUInt16();
562 float chance = fields[2].GetFloat();
564 GameObjectData const* data = sObjectMgr.GetGOData(guid);
565 if (!data)
567 sLog.outErrorDb("`pool_gameobject` has a non existing gameobject spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id );
568 continue;
570 GameObjectInfo const* goinfo = ObjectMgr::GetGameObjectInfo(data->id);
571 if (goinfo->type != GAMEOBJECT_TYPE_CHEST &&
572 goinfo->type != GAMEOBJECT_TYPE_GOOBER &&
573 goinfo->type != GAMEOBJECT_TYPE_FISHINGHOLE)
575 sLog.outErrorDb("`pool_gameobject` has a not lootable gameobject spawn (GUID: %u, type: %u) defined for pool id (%u), skipped.", guid, goinfo->type, pool_id );
576 continue;
578 if (pool_id > max_pool_id)
580 sLog.outErrorDb("`pool_gameobject` pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",pool_id);
581 continue;
583 if (chance < 0 || chance > 100)
585 sLog.outErrorDb("`pool_gameobject` has an invalid chance (%f) for gameobject guid (%u) in pool id (%i), skipped.", chance, guid, pool_id);
586 continue;
588 PoolTemplateData *pPoolTemplate = &mPoolTemplate[pool_id];
590 ++count;
592 PoolObject plObject = PoolObject(guid, chance);
593 PoolGroup<GameObject>& gogroup = mPoolGameobjectGroups[pool_id];
594 gogroup.SetPoolId(pool_id);
595 gogroup.AddEntry(plObject, pPoolTemplate->MaxLimit);
596 SearchPair p(guid, pool_id);
597 mGameobjectSearchMap.insert(p);
599 } while( result->NextRow() );
600 sLog.outString();
601 sLog.outString( ">> Loaded %u gameobject in pools", count );
602 delete result;
605 // Pool of pools
606 mPoolPoolGroups.resize(max_pool_id + 1);
607 // 1 2 3
608 result = WorldDatabase.Query("SELECT pool_id, mother_pool, chance FROM pool_pool");
610 count = 0;
611 if( !result )
613 barGoLink bar2(1);
614 bar2.step();
616 sLog.outString();
617 sLog.outString(">> Loaded %u pools in pools", count );
619 else
622 barGoLink bar2( (int)result->GetRowCount() );
625 Field *fields = result->Fetch();
627 bar2.step();
629 uint16 child_pool_id = fields[0].GetUInt16();
630 uint16 mother_pool_id = fields[1].GetUInt16();
631 float chance = fields[2].GetFloat();
633 if (mother_pool_id > max_pool_id)
635 sLog.outErrorDb("`pool_pool` mother_pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",mother_pool_id);
636 continue;
638 if (child_pool_id > max_pool_id)
640 sLog.outErrorDb("`pool_pool` included pool_id (%i) is out of range compared to max pool id in `pool_template`, skipped.",child_pool_id);
641 continue;
643 if (mother_pool_id == child_pool_id)
645 sLog.outErrorDb("`pool_pool` pool_id (%i) includes itself, dead-lock detected, skipped.",child_pool_id);
646 continue;
648 if (chance < 0 || chance > 100)
650 sLog.outErrorDb("`pool_pool` has an invalid chance (%f) for pool id (%u) in mother pool id (%i), skipped.", chance, child_pool_id, mother_pool_id);
651 continue;
653 PoolTemplateData *pPoolTemplateMother = &mPoolTemplate[mother_pool_id];
655 ++count;
657 PoolObject plObject = PoolObject(child_pool_id, chance);
658 PoolGroup<Pool>& plgroup = mPoolPoolGroups[mother_pool_id];
659 plgroup.SetPoolId(mother_pool_id);
660 plgroup.AddEntry(plObject, pPoolTemplateMother->MaxLimit);
661 SearchPair p(child_pool_id, mother_pool_id);
662 mPoolSearchMap.insert(p);
664 } while( result->NextRow() );
666 // Now check for circular reference
667 for(uint16 i=0; i<max_pool_id; ++i)
669 std::set<uint16> checkedPools;
670 for(SearchMap::iterator poolItr = mPoolSearchMap.find(i); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second))
672 checkedPools.insert(poolItr->first);
673 if(checkedPools.find(poolItr->second) != checkedPools.end())
675 std::ostringstream ss;
676 ss<< "The pool(s) ";
677 for (std::set<uint16>::const_iterator itr=checkedPools.begin(); itr!=checkedPools.end(); ++itr)
678 ss << *itr << " ";
679 ss << "create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool "
680 << poolItr->first << " and child pool " << poolItr->second;
681 sLog.outErrorDb("%s", ss.str().c_str());
682 mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first);
683 mPoolSearchMap.erase(poolItr);
684 --count;
685 break;
689 sLog.outString();
690 sLog.outString( ">> Loaded %u pools in mother pools", count );
691 delete result;
695 // 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
696 void PoolManager::Initialize()
698 QueryResult *result = WorldDatabase.Query("SELECT DISTINCT pool_template.entry FROM pool_template LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry LEFT JOIN pool_pool ON pool_template.entry=pool_pool.pool_id WHERE game_event_pool.pool_entry IS NULL AND pool_pool.pool_id IS NULL");
699 uint32 count=0;
700 if (result)
704 Field *fields = result->Fetch();
705 uint16 pool_entry = fields[0].GetUInt16();
706 if (!CheckPool(pool_entry))
708 sLog.outErrorDb("Pool Id (%u) has all creatures or gameobjects with explicit chance sum <>100 and no equal chance defined. The pool system cannot pick one to spawn.", pool_entry);
709 continue;
711 SpawnPool(pool_entry, true);
712 count++;
713 } while (result->NextRow());
714 delete result;
717 sLog.outBasic("Pool handling system initialized, %u pools spawned.", count);
720 // Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
721 // If it's same, the creature is respawned only (added back to map)
722 template<>
723 void PoolManager::SpawnPoolGroup<Creature>(uint16 pool_id, uint32 db_guid, bool instantly)
725 if (!mPoolCreatureGroups[pool_id].isEmpty())
726 mPoolCreatureGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid, instantly);
729 // Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
730 // If it's same, the gameobject is respawned only (added back to map)
731 template<>
732 void PoolManager::SpawnPoolGroup<GameObject>(uint16 pool_id, uint32 db_guid, bool instantly)
734 if (!mPoolGameobjectGroups[pool_id].isEmpty())
735 mPoolGameobjectGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid, instantly);
738 // Call to spawn a pool, if cache if true the method will spawn only if cached entry is different
739 // If it's same, the pool is respawned only
740 template<>
741 void PoolManager::SpawnPoolGroup<Pool>(uint16 pool_id, uint32 sub_pool_id, bool instantly)
743 if (!mPoolPoolGroups[pool_id].isEmpty())
744 mPoolPoolGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id, instantly);
748 \param instantly defines if (leaf-)objects are spawned instantly or with fresh respawn timer */
749 void PoolManager::SpawnPool(uint16 pool_id, bool instantly)
751 SpawnPoolGroup<Pool>(pool_id, 0, instantly);
752 SpawnPoolGroup<GameObject>(pool_id, 0, instantly);
753 SpawnPoolGroup<Creature>(pool_id, 0, instantly);
756 // Call to despawn a pool, all gameobjects/creatures in this pool are removed
757 void PoolManager::DespawnPool(uint16 pool_id)
759 if (!mPoolCreatureGroups[pool_id].isEmpty())
760 mPoolCreatureGroups[pool_id].DespawnObject(mSpawnedData);
762 if (!mPoolGameobjectGroups[pool_id].isEmpty())
763 mPoolGameobjectGroups[pool_id].DespawnObject(mSpawnedData);
765 if (!mPoolPoolGroups[pool_id].isEmpty())
766 mPoolPoolGroups[pool_id].DespawnObject(mSpawnedData);
769 // Method that check chance integrity of the creatures and gameobjects in this pool
770 bool PoolManager::CheckPool(uint16 pool_id) const
772 return pool_id <= max_pool_id &&
773 mPoolGameobjectGroups[pool_id].CheckPool() &&
774 mPoolCreatureGroups[pool_id].CheckPool() &&
775 mPoolPoolGroups[pool_id].CheckPool();
778 // Call to update the pool when a gameobject/creature part of pool [pool_id] is ready to respawn
779 // Here we cache only the creature/gameobject whose guid is passed as parameter
780 // Then the spawn pool call will use this cache to decide
781 template<typename T>
782 void PoolManager::UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id)
784 if (uint16 motherpoolid = IsPartOfAPool<Pool>(pool_id))
785 SpawnPoolGroup<Pool>(motherpoolid, pool_id, false);
786 else
787 SpawnPoolGroup<T>(pool_id, db_guid_or_pool_id, false);
790 template void PoolManager::UpdatePool<Pool>(uint16 pool_id, uint32 db_guid_or_pool_id);
791 template void PoolManager::UpdatePool<GameObject>(uint16 pool_id, uint32 db_guid_or_pool_id);
792 template void PoolManager::UpdatePool<Creature>(uint16 pool_id, uint32 db_guid_or_pool_id);