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 "ObjectGuid.h"
22 #include "ProgressBar.h"
24 #include "MapManager.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
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
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
56 bool SpawnedPoolData::IsSpawnedObject
<Pool
>(uint32 sub_pool_id
) const
58 return mSpawnedPools
.find(sub_pool_id
) != mSpawnedPools
.end();
62 void SpawnedPoolData::AddSpawn
<Creature
>(uint32 db_guid
, uint32 pool_id
)
64 mSpawnedCreatures
.insert(db_guid
);
65 ++mSpawnedPools
[pool_id
];
69 void SpawnedPoolData::AddSpawn
<GameObject
>(uint32 db_guid
, uint32 pool_id
)
71 mSpawnedGameobjects
.insert(db_guid
);
72 ++mSpawnedPools
[pool_id
];
76 void SpawnedPoolData::AddSpawn
<Pool
>(uint32 sub_pool_id
, uint32 pool_id
)
78 mSpawnedPools
[sub_pool_id
] = 0;
79 ++mSpawnedPools
[pool_id
];
83 void SpawnedPoolData::RemoveSpawn
<Creature
>(uint32 db_guid
, uint32 pool_id
)
85 mSpawnedCreatures
.erase(db_guid
);
86 uint32
& val
= mSpawnedPools
[pool_id
];
92 void SpawnedPoolData::RemoveSpawn
<GameObject
>(uint32 db_guid
, uint32 pool_id
)
94 mSpawnedGameobjects
.erase(db_guid
);
95 uint32
& val
= mSpawnedPools
[pool_id
];
101 void SpawnedPoolData::RemoveSpawn
<Pool
>(uint32 sub_pool_id
, uint32 pool_id
)
103 mSpawnedPools
.erase(sub_pool_id
);
104 uint32
& val
= mSpawnedPools
[pool_id
];
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
114 void PoolGroup
<T
>::AddEntry(PoolObject
& poolitem
, uint32 maxentries
)
116 if (poolitem
.chance
!= 0 && maxentries
== 1)
117 ExplicitlyChanced
.push_back(poolitem
);
119 EqualChanced
.push_back(poolitem
);
122 // Method to check the chances are proper in this object pool
124 bool PoolGroup
<T
>::CheckPool() const
126 if (EqualChanced
.size() == 0)
129 for (uint32 i
=0; i
<ExplicitlyChanced
.size(); ++i
)
130 chance
+= ExplicitlyChanced
[i
].chance
;
131 if (chance
!= 100 && chance
!= 0)
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
];
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
170 void PoolGroup
<T
>::DespawnObject(SpawnedPoolData
& spawns
, uint32 guid
)
172 for (size_t i
= 0; i
< EqualChanced
.size(); ++i
)
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
)
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
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(ObjectGuid(HIGHGUID_UNIT
, data
->id
, guid
)))
210 pCreature
->AddObjectToRemoveList();
214 // Same on one gameobject
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(ObjectGuid(HIGHGUID_GAMEOBJECT
, data
->id
, guid
)))
223 pGameobject
->AddObjectToRemoveList();
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
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
);
246 for (PoolObjectList::iterator itr
= EqualChanced
.begin(); itr
!= EqualChanced
.end(); ++itr
)
248 if(itr
->guid
== child_pool_id
)
250 EqualChanced
.erase(itr
);
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
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
);
274 if (obj
->guid
== lastDespawned
)
277 if (obj
->guid
== triggerFrom
)
279 ASSERT(spawns
.IsSpawnedObject
<T
>(obj
->guid
));
280 ASSERT(spawns
.GetSpawnedObjects(poolId
) > 0);
286 spawns
.AddSpawn
<T
>(obj
->guid
,poolId
);
287 Spawn1Object(obj
, instantly
);
291 // One spawn one despawn no count increase
292 DespawnObject(spawns
, triggerFrom
);
293 lastDespawned
= triggerFrom
;
299 // Method that is actualy doing the spawn job on 1 creature
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 //DEBUG_LOG("Spawning creature %u",obj->guid);
314 if (!pCreature
->LoadFromDB(obj
->guid
, map
))
321 // if new spawn replaces a just despawned creature, not instantly spawn but set respawn timer
324 pCreature
->SetRespawnTime( pCreature
->GetRespawnDelay() );
325 if (sWorld
.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATLY
) || pCreature
->isWorldBoss())
326 pCreature
->SaveRespawnTime();
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
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 //DEBUG_LOG("Spawning gameobject %u", obj->guid);
355 if (!pGameobject
->LoadFromDB(obj
->guid
, map
))
362 if (pGameobject
->isSpawnedByDefault())
364 // if new spawn replaces a just despawned object, not instantly spawn but set respawn timer
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
);
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
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
403 void PoolGroup
<GameObject
>::ReSpawn1Object(PoolObject
* obj
)
405 if (GameObjectData
const* data
= sObjectMgr
.GetGOData(obj
->guid
))
406 if (GameObject
* pGameobject
= ObjectAccessor::GetGameObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT
, data
->id
, obj
->guid
)))
407 pGameobject
->GetMap()->Add(pGameobject
);
410 // Nothing to do for a child Pool
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");
429 sLog
.outString(">> Table pool_template is empty.");
435 Field
*fields
= result
->Fetch();
436 max_pool_id
= fields
[0].GetUInt16();
440 mPoolTemplate
.resize(max_pool_id
+ 1);
442 result
= WorldDatabase
.Query("SELECT entry,max_limit FROM pool_template");
445 mPoolTemplate
.clear();
446 sLog
.outString(">> Table pool_template is empty:");
453 barGoLink
bar((int)result
->GetRowCount());
457 Field
*fields
= result
->Fetch();
461 uint16 pool_id
= fields
[0].GetUInt16();
463 PoolTemplateData
& pPoolTemplate
= mPoolTemplate
[pool_id
];
464 pPoolTemplate
.MaxLimit
= fields
[1].GetUInt32();
466 } while (result
->NextRow());
469 sLog
.outString( ">> Loaded %u objects pools", count
);
474 mPoolCreatureGroups
.resize(max_pool_id
+ 1);
475 mCreatureSearchMap
.clear();
477 result
= WorldDatabase
.Query("SELECT guid, pool_entry, chance FROM pool_creature");
486 sLog
.outString(">> Loaded %u creatures in pools", count
);
491 barGoLink
bar2((int)result
->GetRowCount());
494 Field
*fields
= result
->Fetch();
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
);
505 sLog
.outErrorDb("`pool_creature` has a non existing creature spawn (GUID: %u) defined for pool id (%u), skipped.", guid
, pool_id
);
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
);
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
);
518 PoolTemplateData
*pPoolTemplate
= &mPoolTemplate
[pool_id
];
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());
530 sLog
.outString( ">> Loaded %u creatures in pools", count
);
536 mPoolGameobjectGroups
.resize(max_pool_id
+ 1);
537 mGameobjectSearchMap
.clear();
539 result
= WorldDatabase
.Query("SELECT guid, pool_entry, chance FROM pool_gameobject");
548 sLog
.outString(">> Loaded %u gameobject in pools", count
);
553 barGoLink
bar2((int)result
->GetRowCount());
556 Field
*fields
= result
->Fetch();
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
);
567 sLog
.outErrorDb("`pool_gameobject` has a non existing gameobject spawn (GUID: %u) defined for pool id (%u), skipped.", guid
, pool_id
);
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
);
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
);
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
);
588 PoolTemplateData
*pPoolTemplate
= &mPoolTemplate
[pool_id
];
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() );
601 sLog
.outString( ">> Loaded %u gameobject in pools", count
);
606 mPoolPoolGroups
.resize(max_pool_id
+ 1);
608 result
= WorldDatabase
.Query("SELECT pool_id, mother_pool, chance FROM pool_pool");
617 sLog
.outString(">> Loaded %u pools in pools", count
);
622 barGoLink
bar2( (int)result
->GetRowCount() );
625 Field
*fields
= result
->Fetch();
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
);
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
);
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
);
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
);
653 PoolTemplateData
*pPoolTemplateMother
= &mPoolTemplate
[mother_pool_id
];
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
;
677 for (std::set
<uint16
>::const_iterator itr
=checkedPools
.begin(); itr
!=checkedPools
.end(); ++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
);
690 sLog
.outString( ">> Loaded %u pools in mother pools", count
);
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");
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
);
711 SpawnPool(pool_entry
, true);
713 } while (result
->NextRow());
717 BASIC_LOG("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)
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)
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
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
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);
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
);