diff options
Diffstat (limited to 'src/game/PoolHandler.cpp')
-rw-r--r-- | src/game/PoolHandler.cpp | 329 |
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 |