aboutsummaryrefslogtreecommitdiff
path: root/src/game/PoolHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/PoolHandler.cpp')
-rw-r--r--src/game/PoolHandler.cpp329
1 files changed, 172 insertions, 157 deletions
diff --git a/src/game/PoolHandler.cpp b/src/game/PoolHandler.cpp
index 15afb656805..6a148b58d66 100644
--- a/src/game/PoolHandler.cpp
+++ b/src/game/PoolHandler.cpp
@@ -26,6 +26,85 @@
INSTANTIATE_SINGLETON_1(PoolHandler);
////////////////////////////////////////////////////////////
+// template class SpawnedPoolData
+
+// Method that tell amount spawned objects/subpools
+uint32 SpawnedPoolData::GetSpawnedObjects(uint32 pool_id) const
+{
+ 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<>
+bool SpawnedPoolData::IsSpawnedObject<Creature>(uint32 db_guid) const
+{
+ return mSpawnedCreatures.find(db_guid) != mSpawnedCreatures.end();
+}
+
+// Method that tell if a gameobject is spawned currently
+template<>
+bool SpawnedPoolData::IsSpawnedObject<GameObject>(uint32 db_guid) const
+{
+ return mSpawnedGameobjects.find(db_guid) != mSpawnedGameobjects.end();
+}
+
+// Method that tell if a pool is spawned currently
+template<>
+bool SpawnedPoolData::IsSpawnedObject<Pool>(uint32 sub_pool_id) const
+{
+ return mSpawnedPools.find(sub_pool_id) != mSpawnedPools.end();
+}
+
+template<>
+void SpawnedPoolData::AddSpawn<Creature>(uint32 db_guid, uint32 pool_id)
+{
+ mSpawnedCreatures.insert(db_guid);
+ ++mSpawnedPools[pool_id];
+}
+
+template<>
+void SpawnedPoolData::AddSpawn<GameObject>(uint32 db_guid, uint32 pool_id)
+{
+ mSpawnedGameobjects.insert(db_guid);
+ ++mSpawnedPools[pool_id];
+}
+
+template<>
+void SpawnedPoolData::AddSpawn<Pool>(uint32 sub_pool_id, uint32 pool_id)
+{
+ mSpawnedPools[sub_pool_id] = 0;
+ ++mSpawnedPools[pool_id];
+}
+
+template<>
+void SpawnedPoolData::RemoveSpawn<Creature>(uint32 db_guid, uint32 pool_id)
+{
+ mSpawnedCreatures.erase(db_guid);
+ uint32& val = mSpawnedPools[pool_id];
+ if (val > 0)
+ --val;
+}
+
+template<>
+void SpawnedPoolData::RemoveSpawn<GameObject>(uint32 db_guid, uint32 pool_id)
+{
+ mSpawnedGameobjects.erase(db_guid);
+ uint32& val = mSpawnedPools[pool_id];
+ if (val > 0)
+ --val;
+}
+
+template<>
+void SpawnedPoolData::RemoveSpawn<Pool>(uint32 sub_pool_id, uint32 pool_id)
+{
+ mSpawnedPools.erase(sub_pool_id);
+ uint32& val = mSpawnedPools[pool_id];
+ if (val > 0)
+ --val;
+}
+
+////////////////////////////////////////////////////////////
// Methods of template class PoolGroup
// Method to add a gameobject/creature guid to the proper list depending on pool type and chance value
@@ -40,7 +119,7 @@ void PoolGroup<T>::AddEntry(PoolObject& poolitem, uint32 maxentries)
// Method to check the chances are proper in this object pool
template <class T>
-bool PoolGroup<T>::CheckPool(void)
+bool PoolGroup<T>::CheckPool() const
{
if (EqualChanced.size() == 0)
{
@@ -53,21 +132,8 @@ bool PoolGroup<T>::CheckPool(void)
return true;
}
-// Method that tell if the gameobject, creature or pool is spawned currently
template <class T>
-bool PoolGroup<T>::IsSpawnedObject(uint32 guid)
-{
- for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
- if (ExplicitlyChanced[i].guid == guid)
- return ExplicitlyChanced[i].spawned;
- for (uint32 i=0; i<EqualChanced.size(); ++i)
- if (EqualChanced[i].guid == guid)
- return EqualChanced[i].spawned;
- return false;
-}
-
-template <class T>
-void PoolGroup<T>::RollOne(int32& index, PoolObjectList** store, uint32 triggerFrom)
+PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
{
if (!ExplicitlyChanced.empty())
{
@@ -78,61 +144,50 @@ void PoolGroup<T>::RollOne(int32& index, PoolObjectList** store, uint32 triggerF
roll -= ExplicitlyChanced[i].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 && (!ExplicitlyChanced[i].spawned || ExplicitlyChanced[i].guid == triggerFrom))
- {
- index = i;
- *store = &ExplicitlyChanced;
- return;
- }
+ if (roll < 0 && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid)))
+ return &ExplicitlyChanced[i];
}
}
if (!EqualChanced.empty())
{
- index = irand(0, EqualChanced.size()-1);
+ int32 index = irand(0, EqualChanced.size()-1);
// 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 (!EqualChanced[index].spawned || EqualChanced[index].guid == triggerFrom)
- {
- *store = &EqualChanced;
- return;
- }
+ if (EqualChanced[index].guid == triggerFrom || !spawns.IsSpawnedObject<T>(EqualChanced[index].guid))
+ return &EqualChanced[index];
}
- index = -1;
+ return NULL;
}
// Main method to despawn a creature or gameobject in a pool
// 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(uint32 guid)
+void PoolGroup<T>::DespawnObject(SpawnedPoolData& spawns, uint32 guid)
{
for (size_t i=0; i<EqualChanced.size(); ++i)
{
- if (EqualChanced[i].spawned)
+ // if spawned
+ if (spawns.IsSpawnedObject<T>(EqualChanced[i].guid))
{
if (!guid || EqualChanced[i].guid == guid)
{
Despawn1Object(EqualChanced[i].guid);
-
- EqualChanced[i].spawned = false;
- if (m_SpawnedPoolAmount > 0)
- --m_SpawnedPoolAmount;
+ spawns.RemoveSpawn<T>(EqualChanced[i].guid,poolId);
}
}
}
for (size_t i = 0; i < ExplicitlyChanced.size(); ++i)
{
- if (ExplicitlyChanced[i].spawned)
+ // spawned
+ if (spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid))
{
if (!guid || ExplicitlyChanced[i].guid == guid)
{
Despawn1Object(ExplicitlyChanced[i].guid);
- ExplicitlyChanced[i].spawned = false;
-
- if (m_SpawnedPoolAmount > 0)
- --m_SpawnedPoolAmount;
+ spawns.RemoveSpawn<T>(ExplicitlyChanced[i].guid,poolId);
}
}
}
@@ -194,10 +249,10 @@ void PoolGroup<Pool>::RemoveOneRelation(uint16 child_pool_id)
}
template <class T>
-void PoolGroup<T>::SpawnObject(uint32 limit, uint32 triggerFrom)
+void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom)
{
uint32 lastDespawned = 0;
- int count = limit - m_SpawnedPoolAmount;
+ 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
@@ -208,43 +263,38 @@ void PoolGroup<T>::SpawnObject(uint32 limit, uint32 triggerFrom)
// This will try to spawn the rest of pool, not guaranteed
for (int i = 0; i < count; ++i)
{
- int index;
- PoolObjectList* store;
-
- RollOne(index, &store, triggerFrom);
- if (index == -1)
+ PoolObject* obj = RollOne(spawns,triggerFrom);
+ if (!obj)
continue;
- if ((*store)[index].guid == lastDespawned)
+ if (obj->guid == lastDespawned)
continue;
- if ((*store)[index].guid == triggerFrom)
+ if (obj->guid == triggerFrom)
{
- (*store)[index].spawned = ReSpawn1Object(triggerFrom);
+ ReSpawn1Object(obj);
triggerFrom = 0;
continue;
}
- else
- (*store)[index].spawned = Spawn1Object((*store)[index].guid);
+ spawns.AddSpawn<T>(obj->guid,poolId);
+ Spawn1Object(obj);
if (triggerFrom)
{
// One spawn one despawn no count increase
- DespawnObject(triggerFrom);
+ DespawnObject(spawns, triggerFrom);
lastDespawned = triggerFrom;
triggerFrom = 0;
}
- else
- ++m_SpawnedPoolAmount;
}
}
// Method that is actualy doing the spawn job on 1 creature
template <>
-bool PoolGroup<Creature>::Spawn1Object(uint32 guid)
+void PoolGroup<Creature>::Spawn1Object(PoolObject* obj)
{
- if (CreatureData const* data = objmgr.GetCreatureData(guid))
+ if (CreatureData const* data = objmgr.GetCreatureData(obj->guid))
{
- objmgr.AddCreatureToGrid(guid, data);
+ objmgr.AddCreatureToGrid(obj->guid, data);
// Spawn if necessary (loaded grids only)
Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid));
@@ -253,26 +303,24 @@ bool PoolGroup<Creature>::Spawn1Object(uint32 guid)
{
Creature* pCreature = new Creature;
//sLog.outDebug("Spawning creature %u",guid);
- if (!pCreature->LoadFromDB(guid, map))
+ if (!pCreature->LoadFromDB(obj->guid, map))
{
delete pCreature;
- return false;
+ return;
}
else
map->Add(pCreature);
}
- return true;
}
- return false;
}
// Same for 1 gameobject
template <>
-bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
+void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj)
{
- if (GameObjectData const* data = objmgr.GetGOData(guid))
+ if (GameObjectData const* data = objmgr.GetGOData(obj->guid))
{
- objmgr.AddGameobjectToGrid(guid, data);
+ objmgr.AddGameobjectToGrid(obj->guid, data);
// Spawn if necessary (loaded grids only)
// this base map checked as non-instanced and then only existed
Map* map = const_cast<Map*>(MapManager::Instance().CreateBaseMap(data->mapid));
@@ -281,10 +329,10 @@ bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
{
GameObject* pGameobject = new GameObject;
//sLog.outDebug("Spawning gameobject %u", guid);
- if (!pGameobject->LoadFromDB(guid, map))
+ if (!pGameobject->LoadFromDB(obj->guid, map))
{
delete pGameobject;
- return false;
+ return;
}
else
{
@@ -292,52 +340,38 @@ bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
map->Add(pGameobject);
}
}
- return true;
}
- return false;
}
// Same for 1 pool
template <>
-bool PoolGroup<Pool>::Spawn1Object(uint32 child_pool_id)
+void PoolGroup<Pool>::Spawn1Object(PoolObject* obj)
{
- poolhandler.SpawnPool(child_pool_id, 0, 0);
- poolhandler.SpawnPool(child_pool_id, 0, TYPEID_GAMEOBJECT);
- poolhandler.SpawnPool(child_pool_id, 0, TYPEID_UNIT);
- return true;
+ poolhandler.SpawnPool(obj->guid);
}
// Method that does the respawn job on the specified creature
template <>
-bool PoolGroup<Creature>::ReSpawn1Object(uint32 guid)
+void PoolGroup<Creature>::ReSpawn1Object(PoolObject* obj)
{
- if (CreatureData const* data = objmgr.GetCreatureData(guid))
- {
- if (Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_UNIT), (Creature*)NULL))
+ if (CreatureData const* data = objmgr.GetCreatureData(obj->guid))
+ if (Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(obj->guid, data->id, HIGHGUID_UNIT), (Creature*)NULL))
pCreature->GetMap()->Add(pCreature);
- return true;
- }
- return false;
}
-// Same for 1 gameobject
+// Method that does the respawn job on the specified gameobject
template <>
-bool PoolGroup<GameObject>::ReSpawn1Object(uint32 guid)
+void PoolGroup<GameObject>::ReSpawn1Object(PoolObject* obj)
{
- if (GameObjectData const* data = objmgr.GetGOData(guid))
- {
- if (GameObject* pGameobject = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL))
+ if (GameObjectData const* data = objmgr.GetGOData(obj->guid))
+ if (GameObject* pGameobject = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(obj->guid, data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL))
pGameobject->GetMap()->Add(pGameobject);
- return true;
- }
- return false;
}
// Nothing to do for a child Pool
template <>
-bool PoolGroup<Pool>::ReSpawn1Object(uint32 /*guid*/)
+void PoolGroup<Pool>::ReSpawn1Object(PoolObject* /*obj*/)
{
- return true;
}
////////////////////////////////////////////////////////////
@@ -345,7 +379,6 @@ bool PoolGroup<Pool>::ReSpawn1Object(uint32 /*guid*/)
PoolHandler::PoolHandler()
{
- m_IsPoolSystemStarted = false;
}
void PoolHandler::LoadFromDB()
@@ -448,6 +481,7 @@ void PoolHandler::LoadFromDB()
PoolObject plObject = PoolObject(guid, chance);
PoolGroup<Creature>& cregroup = mPoolCreatureGroups[pool_id];
+ cregroup.SetPoolId(pool_id);
cregroup.AddEntry(plObject, pPoolTemplate->MaxLimit);
SearchPair p(guid, pool_id);
mCreatureSearchMap.insert(p);
@@ -519,6 +553,7 @@ void PoolHandler::LoadFromDB()
PoolObject plObject = PoolObject(guid, chance);
PoolGroup<GameObject>& gogroup = mPoolGameobjectGroups[pool_id];
+ gogroup.SetPoolId(pool_id);
gogroup.AddEntry(plObject, pPoolTemplate->MaxLimit);
SearchPair p(guid, pool_id);
mGameobjectSearchMap.insert(p);
@@ -585,6 +620,7 @@ void PoolHandler::LoadFromDB()
PoolObject plObject = PoolObject(child_pool_id, chance);
PoolGroup<Pool>& plgroup = mPoolPoolGroups[mother_pool_id];
+ plgroup.SetPoolId(mother_pool_id);
plgroup.AddEntry(plObject, pPoolTemplateMother->MaxLimit);
SearchPair p(child_pool_id, mother_pool_id);
mPoolSearchMap.insert(p);
@@ -636,87 +672,63 @@ void PoolHandler::Initialize()
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);
continue;
}
- SpawnPool(pool_entry, 0, 0);
- SpawnPool(pool_entry, 0, TYPEID_GAMEOBJECT);
- SpawnPool(pool_entry, 0, TYPEID_UNIT);
+ SpawnPool(pool_entry);;
count++;
} while (result->NextRow());
}
sLog.outBasic("Pool handling system initialized, %u pools spawned.", count);
- m_IsPoolSystemStarted = true;
}
// 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/creature is respawned only (added back to map)
-void PoolHandler::SpawnPool(uint16 pool_id, uint32 guid, uint32 type)
+// If it's same, the creature is respawned only (added back to map)
+template<>
+void PoolHandler::SpawnPool<Creature>(uint16 pool_id, uint32 db_guid)
{
- switch (type)
- {
- case TYPEID_UNIT:
- if (!mPoolCreatureGroups[pool_id].isEmpty())
- mPoolCreatureGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, guid);
- break;
- case TYPEID_GAMEOBJECT:
- if (!mPoolGameobjectGroups[pool_id].isEmpty())
- mPoolGameobjectGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, guid);
- break;
- default:
- if (!mPoolPoolGroups[pool_id].isEmpty())
- mPoolPoolGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, guid);
- }
+ if (!mPoolCreatureGroups[pool_id].isEmpty())
+ mPoolCreatureGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid);
}
-// Call to despawn a pool, all gameobjects/creatures in this pool are removed
-void PoolHandler::DespawnPool(uint16 pool_id)
+// 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 PoolHandler::SpawnPool<GameObject>(uint16 pool_id, uint32 db_guid)
{
- if (!mPoolCreatureGroups[pool_id].isEmpty())
- mPoolCreatureGroups[pool_id].DespawnObject();
-
if (!mPoolGameobjectGroups[pool_id].isEmpty())
- mPoolGameobjectGroups[pool_id].DespawnObject();
+ mPoolGameobjectGroups[pool_id].SpawnObject(mSpawnedData, 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 PoolHandler::SpawnPool<Pool>(uint16 pool_id, uint32 sub_pool_id)
+{
if (!mPoolPoolGroups[pool_id].isEmpty())
- mPoolPoolGroups[pool_id].DespawnObject();
+ mPoolPoolGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id);
}
-// Call to update the pool when a gameobject/creature part of pool [pool_id] is ready to respawn
-// Here we cache only the creature/gameobject whose guid is passed as parameter
-// Then the spawn pool call will use this cache to decide
-void PoolHandler::UpdatePool(uint16 pool_id, uint32 guid, uint32 type)
+void PoolHandler::SpawnPool( uint16 pool_id )
{
- if (uint16 motherpoolid = IsPartOfAPool(pool_id, 0))
- SpawnPool(motherpoolid, 0, 0);
- else
- SpawnPool(pool_id, guid, type);
+ SpawnPool<Pool>(pool_id, 0);
+ SpawnPool<GameObject>(pool_id, 0);
+ SpawnPool<Creature>(pool_id, 0);
}
-// Method that tell if the gameobject/creature is part of a pool and return the pool id if yes
-uint16 PoolHandler::IsPartOfAPool(uint32 guid, uint32 type)
+// Call to despawn a pool, all gameobjects/creatures in this pool are removed
+void PoolHandler::DespawnPool(uint16 pool_id)
{
- if (type == 0) // pool of pool
- {
- SearchMap::const_iterator itr = mPoolSearchMap.find(guid);
- if (itr != mPoolSearchMap.end())
- return itr->second;
- }
- else if (type == TYPEID_GAMEOBJECT)
- {
- SearchMap::const_iterator itr = mGameobjectSearchMap.find(guid);
- if (itr != mGameobjectSearchMap.end())
- return itr->second;
- }
- else // creature
- {
- SearchMap::const_iterator itr = mCreatureSearchMap.find(guid);
- if (itr != mCreatureSearchMap.end())
- return itr->second;
- }
- return 0;
+ if (!mPoolCreatureGroups[pool_id].isEmpty())
+ mPoolCreatureGroups[pool_id].DespawnObject(mSpawnedData);
+
+ if (!mPoolGameobjectGroups[pool_id].isEmpty())
+ mPoolGameobjectGroups[pool_id].DespawnObject(mSpawnedData);
+
+ if (!mPoolPoolGroups[pool_id].isEmpty())
+ mPoolPoolGroups[pool_id].DespawnObject(mSpawnedData);
}
// Method that check chance integrity of the creatures and gameobjects in this pool
-bool PoolHandler::CheckPool(uint16 pool_id)
+bool PoolHandler::CheckPool(uint16 pool_id) const
{
return pool_id <= max_pool_id &&
mPoolGameobjectGroups[pool_id].CheckPool() &&
@@ -724,15 +736,18 @@ bool PoolHandler::CheckPool(uint16 pool_id)
mPoolPoolGroups[pool_id].CheckPool();
}
-// Method that tell if a creature or gameobject in pool_id is spawned currently
-bool PoolHandler::IsSpawnedObject(uint16 pool_id, uint32 guid, uint32 type)
+// Call to update the pool when a gameobject/creature part of pool [pool_id] is ready to respawn
+// 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 PoolHandler::UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id)
{
- if (pool_id > max_pool_id)
- return false;
- if (type == 0)
- return mPoolPoolGroups[pool_id].IsSpawnedObject(guid);
- else if (type == TYPEID_GAMEOBJECT)
- return mPoolGameobjectGroups[pool_id].IsSpawnedObject(guid);
+ if (uint16 motherpoolid = IsPartOfAPool<Pool>(pool_id))
+ SpawnPool<Pool>(motherpoolid, pool_id);
else
- return mPoolCreatureGroups[pool_id].IsSpawnedObject(guid);
+ SpawnPool<T>(pool_id, db_guid_or_pool_id);
}
+
+template void PoolHandler::UpdatePool<Pool>(uint16 pool_id, uint32 db_guid_or_pool_id);
+template void PoolHandler::UpdatePool<GameObject>(uint16 pool_id, uint32 db_guid_or_pool_id);
+template void PoolHandler::UpdatePool<Creature>(uint16 pool_id, uint32 db_guid_or_pool_id); \ No newline at end of file