aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Pools/PoolMgr.cpp97
1 files changed, 50 insertions, 47 deletions
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index 95a131a5015..b0a57206b31 100644
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -255,66 +255,69 @@ void PoolGroup<Pool>::RemoveOneRelation(uint32 child_pool_id)
template <class T>
void PoolGroup<T>::SpawnObject(ActivePoolData& spawns, uint32 limit, uint32 triggerFrom)
{
- int count = limit - spawns.GetActiveObjectCount(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
- // spawned by 1
+ // First clear the object that triggered the respawn, if any.
+ // DespawnObject is responsible for decrementing the active object counter.
if (triggerFrom)
- ++count;
+ DespawnObject(spawns, triggerFrom);
- if (count > 0)
- {
- PoolObjectList rolledObjects;
- rolledObjects.reserve(count);
+ int32 count = limit - spawns.GetActiveObjectCount(poolId);
+ if (count <= 0)
+ return;
- // roll objects to be spawned
- if (!ExplicitlyChanced.empty())
- {
- float roll = (float)rand_chance();
+ PoolObjectList candidates;
+ candidates.reserve(EqualChanced.size() + ExplicitlyChanced.size());
- for (PoolObject& obj : ExplicitlyChanced)
- {
- roll -= obj.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 && (obj.guid == triggerFrom || !spawns.IsActiveObject<T>(obj.guid)))
- {
- rolledObjects.push_back(obj);
- break;
- }
- }
- }
+ // Add all not already active candidates.
+ for (PoolObject& obj : EqualChanced)
+ if (!spawns.IsActiveObject<T>(obj.guid))
+ candidates.push_back(obj);
- if (!EqualChanced.empty() && rolledObjects.empty())
- {
- std::copy_if(EqualChanced.begin(), EqualChanced.end(), std::back_inserter(rolledObjects), [triggerFrom, &spawns](PoolObject const& object)
- {
- return object.guid == triggerFrom || !spawns.IsActiveObject<T>(object.guid);
- });
+ for (PoolObject& obj : ExplicitlyChanced)
+ if (!spawns.IsActiveObject<T>(obj.guid))
+ candidates.push_back(obj);
- Trinity::Containers::RandomResize(rolledObjects, count);
- }
+ if (candidates.empty())
+ return;
+
+ PoolObjectList rolledObjects;
+ rolledObjects.reserve(count);
- // try to spawn rolled objects
- for (PoolObject& obj : rolledObjects)
+ // Attempt to select one object based on explicit chance.
+ if (!ExplicitlyChanced.empty())
+ {
+ float roll = (float)rand_chance();
+ for (PoolObject& candidate : candidates)
{
- if (obj.guid == triggerFrom)
+ if (candidate.chance > 0)
{
- ReSpawn1Object(&obj);
- triggerFrom = 0;
- }
- else
- {
- spawns.ActivateObject<T>(obj.guid, poolId);
- Spawn1Object(&obj);
+ roll -= candidate.chance;
+ if (roll < 0)
+ {
+ rolledObjects.push_back(candidate);
+ std::swap(candidate, candidates.back());
+ candidates.pop_back();
+ break; // We only roll for one chanced object.
+ }
}
}
}
- // One spawn one despawn no count increase
- if (triggerFrom)
- DespawnObject(spawns, triggerFrom);
+ // Fill the remaining slots with random selections from the rest of the candidates.
+ uint32 remainingCount = count - rolledObjects.size();
+ if (remainingCount > 0 && !candidates.empty())
+ {
+ if (candidates.size() > remainingCount)
+ Trinity::Containers::RandomResize(candidates, remainingCount);
+
+ rolledObjects.insert(rolledObjects.end(), candidates.begin(), candidates.end());
+ }
+
+ // Spawn all the objects we've selected.
+ for (PoolObject& objToSpawn : rolledObjects)
+ {
+ spawns.ActivateObject<T>(objToSpawn.guid, poolId);
+ Spawn1Object(&objToSpawn);
+ }
}
// Method that is actualy doing the spawn job on 1 creature