diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index ff82b8c42..8bed3e9f9 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -473,7 +473,7 @@ bool ChatHandler::HandleGameObjectTargetCommand(const char* args) o = fields[5].GetFloat(); mapid = fields[6].GetUInt16(); pool_id = sPoolMgr.IsPartOfAPool(lowguid); - if (!pool_id || (pool_id && sPoolMgr.IsSpawnedObject(pool_id, lowguid))) + if (!pool_id || sPoolMgr.IsSpawnedObject(lowguid)) found = true; } while( result->NextRow() && (!found) ); diff --git a/src/game/PoolManager.cpp b/src/game/PoolManager.cpp index 97fc3f5c7..7c92bc39e 100644 --- a/src/game/PoolManager.cpp +++ b/src/game/PoolManager.cpp @@ -26,6 +26,85 @@ INSTANTIATE_SINGLETON_1(PoolManager); +//////////////////////////////////////////////////////////// +// 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(uint32 db_guid) const +{ + return mSpawnedCreatures.find(db_guid) != mSpawnedCreatures.end(); +} + +// Method that tell if a gameobject is spawned currently +template<> +bool SpawnedPoolData::IsSpawnedObject(uint32 db_guid) const +{ + return mSpawnedGameobjects.find(db_guid) != mSpawnedGameobjects.end(); +} + +// Method that tell if a pool is spawned currently +template<> +bool SpawnedPoolData::IsSpawnedObject(uint32 sub_pool_id) const +{ + return mSpawnedPools.find(sub_pool_id) != mSpawnedPools.end(); +} + +template<> +void SpawnedPoolData::AddSpawn(uint32 db_guid, uint32 pool_id) +{ + mSpawnedCreatures.insert(db_guid); + ++mSpawnedPools[pool_id]; +} + +template<> +void SpawnedPoolData::AddSpawn(uint32 db_guid, uint32 pool_id) +{ + mSpawnedGameobjects.insert(db_guid); + ++mSpawnedPools[pool_id]; +} + +template<> +void SpawnedPoolData::AddSpawn(uint32 sub_pool_id, uint32 pool_id) +{ + mSpawnedPools[sub_pool_id] = 0; + ++mSpawnedPools[pool_id]; +} + +template<> +void SpawnedPoolData::RemoveSpawn(uint32 db_guid, uint32 pool_id) +{ + mSpawnedCreatures.erase(db_guid); + uint32& val = mSpawnedPools[pool_id]; + if (val > 0) + --val; +} + +template<> +void SpawnedPoolData::RemoveSpawn(uint32 db_guid, uint32 pool_id) +{ + mSpawnedGameobjects.erase(db_guid); + uint32& val = mSpawnedPools[pool_id]; + if (val > 0) + --val; +} + +template<> +void SpawnedPoolData::RemoveSpawn(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 @@ -54,21 +133,8 @@ bool PoolGroup::CheckPool() const return true; } -// Method that tell if the gameobject, creature or pool is spawned currently template -bool PoolGroup::IsSpawnedObject(uint32 guid) const -{ - 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 -PoolObject* PoolGroup::RollOne(uint32 triggerFrom) +PoolObject* PoolGroup::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom) { if (!ExplicitlyChanced.empty()) { @@ -79,7 +145,7 @@ PoolObject* PoolGroup::RollOne(uint32 triggerFrom) 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)) + if (roll < 0 && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.IsSpawnedObject(ExplicitlyChanced[i].guid))) return &ExplicitlyChanced[i]; } } @@ -89,7 +155,7 @@ PoolObject* PoolGroup::RollOne(uint32 triggerFrom) 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) + if (EqualChanced[index].guid == triggerFrom || !spawns.IsSpawnedObject(EqualChanced[index].guid)) return &EqualChanced[index]; } @@ -100,34 +166,32 @@ PoolObject* PoolGroup::RollOne(uint32 triggerFrom) // 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 -void PoolGroup::DespawnObject(uint32 guid) +void PoolGroup::DespawnObject(SpawnedPoolData& spawns, uint32 guid) { for (size_t i = 0; i < EqualChanced.size(); ++i) { - if (EqualChanced[i].spawned) + // if spawned + if (spawns.IsSpawnedObject(EqualChanced[i].guid)) { + // any or specially requested if (!guid || EqualChanced[i].guid == guid) { Despawn1Object(EqualChanced[i].guid); - EqualChanced[i].spawned = false; - - if (m_SpawnedPoolAmount > 0) - --m_SpawnedPoolAmount; + spawns.RemoveSpawn(EqualChanced[i].guid,poolId); } } } for (size_t i = 0; i < ExplicitlyChanced.size(); ++i) { - if (ExplicitlyChanced[i].spawned) + // spawned + if (spawns.IsSpawnedObject(ExplicitlyChanced[i].guid)) { + // any or specially requested if (!guid || ExplicitlyChanced[i].guid == guid) { Despawn1Object(ExplicitlyChanced[i].guid); - ExplicitlyChanced[i].spawned = false; - - if (m_SpawnedPoolAmount > 0) - --m_SpawnedPoolAmount; + spawns.RemoveSpawn(ExplicitlyChanced[i].guid,poolId); } } } @@ -189,10 +253,10 @@ void PoolGroup::RemoveOneRelation(uint16 child_pool_id) } template -void PoolGroup::SpawnObject(uint32 limit, uint32 triggerFrom) +void PoolGroup::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 @@ -203,7 +267,7 @@ void PoolGroup::SpawnObject(uint32 limit, uint32 triggerFrom) // This will try to spawn the rest of pool, not guaranteed for (int i = 0; i < count; ++i) { - PoolObject* obj = RollOne(triggerFrom); + PoolObject* obj = RollOne(spawns,triggerFrom); if (!obj) continue; if (obj->guid == lastDespawned) @@ -211,22 +275,23 @@ void PoolGroup::SpawnObject(uint32 limit, uint32 triggerFrom) if (obj->guid == triggerFrom) { + assert(spawns.IsSpawnedObject(obj->guid)); + assert(spawns.GetSpawnedObjects(poolId) > 0); ReSpawn1Object(obj); triggerFrom = 0; continue; } - else - Spawn1Object(obj); + + spawns.AddSpawn(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; } } @@ -248,16 +313,12 @@ void PoolGroup::Spawn1Object(PoolObject* obj) if (!pCreature->LoadFromDB(obj->guid, map)) { delete pCreature; - obj->spawned = false; return; } else map->Add(pCreature); } - obj->spawned = true; - return; } - obj->spawned = false; } // Same for 1 gameobject @@ -278,7 +339,6 @@ void PoolGroup::Spawn1Object(PoolObject* obj) if (!pGameobject->LoadFromDB(obj->guid, map)) { delete pGameobject; - obj->spawned = false; return; } else @@ -287,10 +347,7 @@ void PoolGroup::Spawn1Object(PoolObject* obj) map->Add(pGameobject); } } - obj->spawned = true; - return; } - obj->spawned = false; } // Same for 1 pool @@ -298,7 +355,6 @@ template <> void PoolGroup::Spawn1Object(PoolObject* obj) { sPoolMgr.SpawnPool(obj->guid); - obj->spawned = true; } // Method that does the respawn job on the specified creature @@ -306,36 +362,23 @@ template <> void PoolGroup::ReSpawn1Object(PoolObject* obj) { if (CreatureData const* data = sObjectMgr.GetCreatureData(obj->guid)) - { if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(MAKE_NEW_GUID(obj->guid, data->id, HIGHGUID_UNIT))) pCreature->GetMap()->Add(pCreature); - obj->spawned = true; - return; - } - - obj->spawned = false; } -// Same for 1 gameobject +// Method that does the respawn job on the specified gameobject template <> void PoolGroup::ReSpawn1Object(PoolObject* obj) { if (GameObjectData const* data = sObjectMgr.GetGOData(obj->guid)) - { if (GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(MAKE_NEW_GUID(obj->guid, data->id, HIGHGUID_GAMEOBJECT))) pGameobject->GetMap()->Add(pGameobject); - obj->spawned = true; - return; - } - - obj->spawned = false; } // Nothing to do for a child Pool template <> -void PoolGroup::ReSpawn1Object(PoolObject* obj) +void PoolGroup::ReSpawn1Object(PoolObject* /*obj*/) { - obj->spawned = true; } @@ -445,6 +488,7 @@ void PoolManager::LoadFromDB() PoolObject plObject = PoolObject(guid, chance); PoolGroup& cregroup = mPoolCreatureGroups[pool_id]; + cregroup.SetPoolId(pool_id); cregroup.AddEntry(plObject, pPoolTemplate->MaxLimit); SearchPair p(guid, pool_id); mCreatureSearchMap.insert(p); @@ -515,6 +559,7 @@ void PoolManager::LoadFromDB() PoolObject plObject = PoolObject(guid, chance); PoolGroup& gogroup = mPoolGameobjectGroups[pool_id]; + gogroup.SetPoolId(pool_id); gogroup.AddEntry(plObject, pPoolTemplate->MaxLimit); SearchPair p(guid, pool_id); mGameobjectSearchMap.insert(p); @@ -579,6 +624,7 @@ void PoolManager::LoadFromDB() PoolObject plObject = PoolObject(child_pool_id, chance); PoolGroup& 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); @@ -645,7 +691,7 @@ template<> void PoolManager::SpawnPool(uint16 pool_id, uint32 db_guid) { if (!mPoolCreatureGroups[pool_id].isEmpty()) - mPoolCreatureGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, db_guid); + mPoolCreatureGroups[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 @@ -654,7 +700,7 @@ template<> void PoolManager::SpawnPool(uint16 pool_id, uint32 db_guid) { if (!mPoolGameobjectGroups[pool_id].isEmpty()) - mPoolGameobjectGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, db_guid); + 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 @@ -663,7 +709,7 @@ template<> void PoolManager::SpawnPool(uint16 pool_id, uint32 sub_pool_id) { if (!mPoolPoolGroups[pool_id].isEmpty()) - mPoolPoolGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, sub_pool_id); + mPoolPoolGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id); } void PoolManager::SpawnPool( uint16 pool_id ) @@ -677,13 +723,13 @@ void PoolManager::SpawnPool( uint16 pool_id ) void PoolManager::DespawnPool(uint16 pool_id) { if (!mPoolCreatureGroups[pool_id].isEmpty()) - mPoolCreatureGroups[pool_id].DespawnObject(); + mPoolCreatureGroups[pool_id].DespawnObject(mSpawnedData); if (!mPoolGameobjectGroups[pool_id].isEmpty()) - mPoolGameobjectGroups[pool_id].DespawnObject(); + mPoolGameobjectGroups[pool_id].DespawnObject(mSpawnedData); if (!mPoolPoolGroups[pool_id].isEmpty()) - mPoolPoolGroups[pool_id].DespawnObject(); + mPoolPoolGroups[pool_id].DespawnObject(mSpawnedData); } // Method that check chance integrity of the creatures and gameobjects in this pool @@ -695,33 +741,6 @@ bool PoolManager::CheckPool(uint16 pool_id) const mPoolPoolGroups[pool_id].CheckPool(); } -// Method that tell if a creature in pool_id is spawned currently -template<> -bool PoolManager::IsSpawnedObject(uint16 pool_id, uint32 db_guid) const -{ - if (pool_id > max_pool_id) - return false; - return mPoolCreatureGroups[pool_id].IsSpawnedObject(db_guid); -} - -// Method that tell if a gameobject in pool_id is spawned currently -template<> -bool PoolManager::IsSpawnedObject(uint16 pool_id, uint32 db_guid) const -{ - if (pool_id > max_pool_id) - return false; - return mPoolGameobjectGroups[pool_id].IsSpawnedObject(db_guid); -} - -// Method that tell if a pool in pool_id is spawned currently -template<> -bool PoolManager::IsSpawnedObject(uint16 pool_id, uint32 sub_pool_id) const -{ - if (pool_id > max_pool_id) - return false; - return mPoolPoolGroups[pool_id].IsSpawnedObject(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 @@ -729,7 +748,7 @@ template void PoolManager::UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id) { if (uint16 motherpoolid = IsPartOfAPool(pool_id)) - SpawnPool(motherpoolid, 0); + SpawnPool(motherpoolid, pool_id); else SpawnPool(pool_id, db_guid_or_pool_id); } diff --git a/src/game/PoolManager.h b/src/game/PoolManager.h index 2da420e1e..fa1f28543 100644 --- a/src/game/PoolManager.h +++ b/src/game/PoolManager.h @@ -33,8 +33,33 @@ struct PoolObject { uint32 guid; float chance; - bool spawned; - PoolObject(uint32 _guid, float _chance): guid(_guid), chance(fabs(_chance)), spawned(false) {} + PoolObject(uint32 _guid, float _chance): guid(_guid), chance(fabs(_chance)) {} +}; + +class Pool // for Pool of Pool case +{ +}; + +typedef std::set SpawnedPoolObjects; +typedef std::map SpawnedPoolPools; + +class SpawnedPoolData +{ + public: + template + bool IsSpawnedObject(uint32 db_guid_or_pool_id) const; + + uint32 GetSpawnedObjects(uint32 pool_id) const; + + template + void AddSpawn(uint32 db_guid_or_pool_id, uint32 pool_id); + + template + void RemoveSpawn(uint32 db_guid_or_pool_id, uint32 pool_id); + private: + SpawnedPoolObjects mSpawnedCreatures; + SpawnedPoolObjects mSpawnedGameobjects; + SpawnedPoolPools mSpawnedPools; }; template @@ -42,27 +67,24 @@ class PoolGroup { typedef std::vector PoolObjectList; public: - PoolGroup() : m_SpawnedPoolAmount(0) { } + explicit PoolGroup() : poolId(0) { } + void SetPoolId(uint32 pool_id) { poolId = pool_id; } ~PoolGroup() {}; bool isEmpty() const { return ExplicitlyChanced.empty() && EqualChanced.empty(); } void AddEntry(PoolObject& poolitem, uint32 maxentries); bool CheckPool() const; - PoolObject* RollOne(uint32 triggerFrom); - bool IsSpawnedObject(uint32 guid) const; - void DespawnObject(uint32 guid=0); + PoolObject* RollOne(SpawnedPoolData& spawns, uint32 triggerFrom); + void DespawnObject(SpawnedPoolData& spawns, uint32 guid=0); void Despawn1Object(uint32 guid); - void SpawnObject(uint32 limit, uint32 triggerFrom); + void SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom); + void Spawn1Object(PoolObject* obj); void ReSpawn1Object(PoolObject* obj); void RemoveOneRelation(uint16 child_pool_id); private: + uint32 poolId; PoolObjectList ExplicitlyChanced; PoolObjectList EqualChanced; - uint32 m_SpawnedPoolAmount; // Used to know the number of spawned objects -}; - -class Pool // for Pool of Pool case -{ }; class PoolManager @@ -78,7 +100,7 @@ class PoolManager uint16 IsPartOfAPool(uint32 db_guid_or_pool_id) const; template - bool IsSpawnedObject(uint16 pool_id, uint32 db_guid_or_pool_id) const; + bool IsSpawnedObject(uint32 db_guid_or_pool_id) const { return mSpawnedData.IsSpawnedObject(db_guid_or_pool_id); } bool CheckPool(uint16 pool_id) const; @@ -94,6 +116,7 @@ class PoolManager uint16 max_pool_id; typedef std::vector PoolTemplateDataMap; + typedef std::vector > PoolGroupCreatureMap; typedef std::vector > PoolGroupGameObjectMap; typedef std::vector > PoolGroupPoolMap; @@ -110,6 +133,8 @@ class PoolManager SearchMap mGameobjectSearchMap; SearchMap mPoolSearchMap; + // dynamic data + SpawnedPoolData mSpawnedData; }; #define sPoolMgr MaNGOS::Singleton::Instance() diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b24566adf..1462ed698 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9259" + #define REVISION_NR "9260" #endif // __REVISION_NR_H__