@@ -130,40 +130,27 @@ bool PoolGroup<T>::CheckPool() const
130130}
131131
132132// Main method to despawn a creature or gameobject in a pool
133- // If no guid is passed, the pool is just removed (event end case)
134- // If guid is filled, cache will be used and no removal will occur, it just fill the cache
135133template <class T >
136134void PoolGroup<T>::DespawnObject(ActivePoolData& spawns, ObjectGuid::LowType guid, bool alwaysDeleteRespawnTime)
137135{
138- for (size_t i=0 ; i < EqualChanced.size (); ++i)
136+ // if spawned
137+ if (spawns.IsActiveObject <T>(guid))
139138 {
140- // if spawned
141- if (spawns.IsActiveObject <T>(EqualChanced[i].guid ))
142- {
143- if (!guid || EqualChanced[i].guid == guid)
144- {
145- Despawn1Object (EqualChanced[i].guid , alwaysDeleteRespawnTime);
146- spawns.RemoveObject <T>(EqualChanced[i].guid , poolId);
147- }
148- }
149- else if (alwaysDeleteRespawnTime)
150- RemoveRespawnTimeFromDB (EqualChanced[i].guid );
139+ Despawn1Object (guid, alwaysDeleteRespawnTime);
140+ spawns.RemoveObject <T>(guid, poolId);
151141 }
142+ else if (alwaysDeleteRespawnTime)
143+ RemoveRespawnTimeFromDB (guid);
144+ }
152145
153- for (size_t i = 0 ; i < ExplicitlyChanced.size (); ++i)
154- {
155- // spawned
156- if (spawns.IsActiveObject <T>(ExplicitlyChanced[i].guid ))
157- {
158- if (!guid || ExplicitlyChanced[i].guid == guid)
159- {
160- Despawn1Object (ExplicitlyChanced[i].guid , alwaysDeleteRespawnTime);
161- spawns.RemoveObject <T>(ExplicitlyChanced[i].guid , poolId);
162- }
163- }
164- else if (alwaysDeleteRespawnTime)
165- RemoveRespawnTimeFromDB (ExplicitlyChanced[i].guid );
166- }
146+ template <class T >
147+ void PoolGroup<T>::DespawnAllObjects(ActivePoolData& spawns, bool alwaysDeleteRespawnTime)
148+ {
149+ for (PoolObject& pooledObject : EqualChanced)
150+ DespawnObject (spawns, pooledObject.guid , alwaysDeleteRespawnTime);
151+
152+ for (PoolObject& pooledObject : ExplicitlyChanced)
153+ DespawnObject (spawns, pooledObject.guid , alwaysDeleteRespawnTime);
167154}
168155
169156// Method that is actualy doing the removal job on one creature
@@ -255,66 +242,69 @@ void PoolGroup<Pool>::RemoveOneRelation(uint32 child_pool_id)
255242template <class T >
256243void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint32 triggerFrom)
257244{
258- int count = limit - spawns.GetActiveObjectCount (poolId);
259-
260- // If triggered from some object respawn this object is still marked as spawned
261- // and also counted into m_SpawnedPoolAmount so we need increase count to be
262- // spawned by 1
245+ // First clear the object that triggered the respawn, if any.
246+ // DespawnObject is responsible for decrementing the active object counter.
263247 if (triggerFrom)
264- ++count ;
248+ DespawnObject (spawns, triggerFrom) ;
265249
266- if (count > 0 )
267- {
268- PoolObjectList rolledObjects;
269- rolledObjects.reserve (count);
250+ int32 count = limit - spawns.GetActiveObjectCount (poolId);
251+ if (count <= 0 )
252+ return ;
270253
271- // roll objects to be spawned
272- if (!ExplicitlyChanced.empty ())
273- {
274- float roll = (float )rand_chance ();
254+ PoolObjectList candidates;
255+ candidates.reserve (EqualChanced.size () + ExplicitlyChanced.size ());
275256
276- for (PoolObject& obj : ExplicitlyChanced)
277- {
278- roll -= obj.chance ;
279- // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
280- // so this need explicit check for this case
281- if (roll < 0 && (obj.guid == triggerFrom || !spawns.IsActiveObject <T>(obj.guid )))
282- {
283- rolledObjects.push_back (obj);
284- break ;
285- }
286- }
287- }
257+ // Add all not already active candidates.
258+ for (PoolObject& obj : EqualChanced)
259+ if (!spawns.IsActiveObject <T>(obj.guid ))
260+ candidates.push_back (obj);
288261
289- if (!EqualChanced.empty () && rolledObjects.empty ())
290- {
291- std::copy_if (EqualChanced.begin (), EqualChanced.end (), std::back_inserter (rolledObjects), [triggerFrom, &spawns](PoolObject const & object)
292- {
293- return object.guid == triggerFrom || !spawns.IsActiveObject <T>(object.guid );
294- });
262+ for (PoolObject& obj : ExplicitlyChanced)
263+ if (!spawns.IsActiveObject <T>(obj.guid ))
264+ candidates.push_back (obj);
295265
296- Trinity::Containers::RandomResize (rolledObjects, count);
297- }
266+ if (candidates.empty ())
267+ return ;
268+
269+ PoolObjectList rolledObjects;
270+ rolledObjects.reserve (count);
298271
299- // try to spawn rolled objects
300- for (PoolObject& obj : rolledObjects)
272+ // Attempt to select one object based on explicit chance.
273+ if (!ExplicitlyChanced.empty ())
274+ {
275+ float roll = (float )rand_chance ();
276+ for (PoolObject& candidate : candidates)
301277 {
302- if (obj. guid == triggerFrom )
278+ if (candidate. chance > 0 )
303279 {
304- ReSpawn1Object (&obj);
305- triggerFrom = 0 ;
306- }
307- else
308- {
309- spawns.ActivateObject <T>(obj.guid , poolId);
310- Spawn1Object (&obj);
280+ roll -= candidate.chance ;
281+ if (roll < 0 )
282+ {
283+ rolledObjects.push_back (candidate);
284+ std::swap (candidate, candidates.back ());
285+ candidates.pop_back ();
286+ break ; // We only roll for one chanced object.
287+ }
311288 }
312289 }
313290 }
314291
315- // One spawn one despawn no count increase
316- if (triggerFrom)
317- DespawnObject (spawns, triggerFrom);
292+ // Fill the remaining slots with random selections from the rest of the candidates.
293+ uint32 remainingCount = count - rolledObjects.size ();
294+ if (remainingCount > 0 && !candidates.empty ())
295+ {
296+ if (candidates.size () > remainingCount)
297+ Trinity::Containers::RandomResize (candidates, remainingCount);
298+
299+ rolledObjects.insert (rolledObjects.end (), candidates.begin (), candidates.end ());
300+ }
301+
302+ // Spawn all the objects we've selected.
303+ for (PoolObject& objToSpawn : rolledObjects)
304+ {
305+ spawns.ActivateObject <T>(objToSpawn.guid , poolId);
306+ Spawn1Object (&objToSpawn);
307+ }
318308}
319309
320310// Method that is actualy doing the spawn job on 1 creature
@@ -377,14 +367,6 @@ void PoolGroup<Pool>::Spawn1Object(PoolObject* obj)
377367 sPoolMgr ->SpawnPool (obj->guid );
378368}
379369
380- // Method that does the respawn job on the specified object
381- template <typename T>
382- void PoolGroup<T>::ReSpawn1Object(PoolObject* obj)
383- {
384- Despawn1Object (obj->guid , false , false );
385- Spawn1Object (obj);
386- }
387-
388370template <>
389371void PoolGroup<Creature>::RemoveRespawnTimeFromDB(ObjectGuid::LowType guid)
390372{
@@ -771,17 +753,17 @@ void PoolMgr::DespawnPool(uint32 pool_id, bool alwaysDeleteRespawnTime)
771753 {
772754 auto it = mPoolCreatureGroups .find (pool_id);
773755 if (it != mPoolCreatureGroups .end () && !it->second .isEmpty ())
774- it->second .DespawnObject (mSpawnedData , 0 , alwaysDeleteRespawnTime);
756+ it->second .DespawnAllObjects (mSpawnedData , alwaysDeleteRespawnTime);
775757 }
776758 {
777759 auto it = mPoolGameobjectGroups .find (pool_id);
778760 if (it != mPoolGameobjectGroups .end () && !it->second .isEmpty ())
779- it->second .DespawnObject (mSpawnedData , 0 , alwaysDeleteRespawnTime);
761+ it->second .DespawnAllObjects (mSpawnedData , alwaysDeleteRespawnTime);
780762 }
781763 {
782764 auto it = mPoolPoolGroups .find (pool_id);
783765 if (it != mPoolPoolGroups .end () && !it->second .isEmpty ())
784- it->second .DespawnObject (mSpawnedData , 0 , alwaysDeleteRespawnTime);
766+ it->second .DespawnAllObjects (mSpawnedData , alwaysDeleteRespawnTime);
785767 }
786768}
787769
0 commit comments