mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
[8701] Fixes and inprovements in pool system.
* Fixed object is removed from guid->object map but still spawned in world under some conditions * Fixed possibility to spawn already spawned object * Fixed objects despawning (missing part for explicitly chanced objects added) Signed-off-by: ApoC <apoc@nymfe.net>
This commit is contained in:
parent
f59f7d2a2e
commit
b4ea5a6d19
5 changed files with 123 additions and 113 deletions
|
|
@ -369,7 +369,7 @@ void Creature::Update(uint32 diff)
|
|||
|
||||
uint16 poolid = poolhandler.IsPartOfAPool(GetGUIDLow(), GetTypeId());
|
||||
if (poolid)
|
||||
poolhandler.UpdatePool(poolid, GetGUIDLow(), GetTypeId());
|
||||
poolhandler.UpdatePool(poolid, GetGUIDLow(), TYPEID_UNIT);
|
||||
else
|
||||
GetMap()->Add(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -580,7 +580,9 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
|
|||
|
||||
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
|
||||
{
|
||||
poolhandler.SpawnPool(*itr);
|
||||
poolhandler.SpawnPool(*itr, 0, 0);
|
||||
poolhandler.SpawnPool(*itr, 0, TYPEID_GAMEOBJECT);
|
||||
poolhandler.SpawnPool(*itr, 0, TYPEID_UNIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,13 +28,6 @@ INSTANTIATE_SINGLETON_1(PoolHandler);
|
|||
////////////////////////////////////////////////////////////
|
||||
// Methods of template class PoolGroup
|
||||
|
||||
template <class T>
|
||||
PoolGroup<T>::PoolGroup()
|
||||
{
|
||||
m_SpawnedPoolAmount = 0;
|
||||
m_LastDespawnedNode = 0;
|
||||
}
|
||||
|
||||
// Method to add a gameobject/creature guid to the proper list depending on pool type and chance value
|
||||
template <class T>
|
||||
void PoolGroup<T>::AddEntry(PoolObject& poolitem, uint32 maxentries)
|
||||
|
|
@ -64,35 +57,49 @@ bool PoolGroup<T>::CheckPool(void)
|
|||
template <class T>
|
||||
bool PoolGroup<T>::IsSpawnedObject(uint32 guid)
|
||||
{
|
||||
for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
|
||||
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)
|
||||
for (uint32 i = 0; i < EqualChanced.size(); ++i)
|
||||
if (EqualChanced[i].guid == guid)
|
||||
return EqualChanced[i].spawned;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Method that return a guid of a rolled creature or gameobject
|
||||
// Note: Copy from loot system because it's very similar and only few things change
|
||||
template <class T>
|
||||
uint32 PoolGroup<T>::RollOne(void)
|
||||
void PoolGroup<T>::RollOne(int32& index, PoolObjectList** store, uint32 triggerFrom)
|
||||
{
|
||||
if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked
|
||||
if (!ExplicitlyChanced.empty())
|
||||
{
|
||||
float roll = rand_chance();
|
||||
float roll = (float)rand_chance();
|
||||
|
||||
for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
|
||||
for (uint32 i = 0; i < ExplicitlyChanced.size(); ++i)
|
||||
{
|
||||
roll -= ExplicitlyChanced[i].chance;
|
||||
if (roll < 0)
|
||||
return ExplicitlyChanced[i].guid;
|
||||
// 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 (!EqualChanced.empty())
|
||||
return EqualChanced[irand(0, EqualChanced.size()-1)].guid;
|
||||
|
||||
return 0; // None found
|
||||
if (!EqualChanced.empty())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
index = -1;
|
||||
}
|
||||
|
||||
// Main method to despawn a creature or gameobject in a pool
|
||||
|
|
@ -101,17 +108,13 @@ uint32 PoolGroup<T>::RollOne(void)
|
|||
template<class T>
|
||||
void PoolGroup<T>::DespawnObject(uint32 guid)
|
||||
{
|
||||
for (size_t i=0; i < EqualChanced.size(); ++i)
|
||||
for (size_t i = 0; i < EqualChanced.size(); ++i)
|
||||
{
|
||||
if (EqualChanced[i].spawned)
|
||||
{
|
||||
if (!guid || EqualChanced[i].guid == guid)
|
||||
{
|
||||
if (guid)
|
||||
m_LastDespawnedNode = EqualChanced[i].guid;
|
||||
else
|
||||
Despawn1Object(EqualChanced[i].guid);
|
||||
|
||||
Despawn1Object(EqualChanced[i].guid);
|
||||
EqualChanced[i].spawned = false;
|
||||
|
||||
if (m_SpawnedPoolAmount > 0)
|
||||
|
|
@ -119,6 +122,21 @@ void PoolGroup<T>::DespawnObject(uint32 guid)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ExplicitlyChanced.size(); ++i)
|
||||
{
|
||||
if (ExplicitlyChanced[i].spawned)
|
||||
{
|
||||
if (!guid || ExplicitlyChanced[i].guid == guid)
|
||||
{
|
||||
Despawn1Object(ExplicitlyChanced[i].guid);
|
||||
ExplicitlyChanced[i].spawned = false;
|
||||
|
||||
if (m_SpawnedPoolAmount > 0)
|
||||
--m_SpawnedPoolAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method that is actualy doing the removal job on one creature
|
||||
|
|
@ -176,58 +194,48 @@ void PoolGroup<Pool>::RemoveOneRelation(uint16 child_pool_id)
|
|||
}
|
||||
}
|
||||
|
||||
// Method that Spawn 1+ creatures or gameobject
|
||||
// if cache is false (initialization or event start), X creatures are spawned with X <= limit (< if limit higher that the number of creatures in pool)
|
||||
// if cache is true, this means only one has to be spawned (or respawned if the rolled one is same as cached one)
|
||||
template <class T>
|
||||
void PoolGroup<T>::SpawnObject(uint32 limit, bool cache)
|
||||
void PoolGroup<T>::SpawnObject(uint32 limit, uint32 triggerFrom)
|
||||
{
|
||||
if (limit == 1) // This is the only case where explicit chance is used
|
||||
uint32 lastDespawned = 0;
|
||||
int count = limit - m_SpawnedPoolAmount;
|
||||
|
||||
// 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
|
||||
if (triggerFrom)
|
||||
++count;
|
||||
|
||||
// This will try to spawn the rest of pool, not guaranteed
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
uint32 roll = RollOne();
|
||||
if (!cache || (cache && m_LastDespawnedNode != roll))
|
||||
int index;
|
||||
PoolObjectList* store;
|
||||
|
||||
RollOne(index, &store, triggerFrom);
|
||||
if (index == -1)
|
||||
continue;
|
||||
if ((*store)[index].guid == lastDespawned)
|
||||
continue;
|
||||
|
||||
if ((*store)[index].guid == triggerFrom)
|
||||
{
|
||||
if (cache)
|
||||
Despawn1Object(m_LastDespawnedNode);
|
||||
Spawn1Object(roll);
|
||||
(*store)[index].spawned = ReSpawn1Object(triggerFrom);
|
||||
triggerFrom = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
ReSpawn1Object(roll);
|
||||
m_LastDespawnedNode = 0;
|
||||
}
|
||||
else if (limit < EqualChanced.size() && m_SpawnedPoolAmount < limit)
|
||||
{
|
||||
std::vector<uint32> IndexList;
|
||||
for (size_t i = 0; i < EqualChanced.size(); ++i)
|
||||
if (!EqualChanced[i].spawned)
|
||||
IndexList.push_back(i);
|
||||
(*store)[index].spawned = Spawn1Object((*store)[index].guid);
|
||||
|
||||
while (m_SpawnedPoolAmount < limit && IndexList.size() > 0)
|
||||
if (triggerFrom)
|
||||
{
|
||||
uint32 roll = urand(1, IndexList.size()) - 1;
|
||||
uint32 index = IndexList[roll];
|
||||
if (!cache || (cache && EqualChanced[index].guid != m_LastDespawnedNode))
|
||||
{
|
||||
if (cache)
|
||||
Despawn1Object(m_LastDespawnedNode);
|
||||
|
||||
EqualChanced[index].spawned = Spawn1Object(EqualChanced[index].guid);
|
||||
}
|
||||
else
|
||||
EqualChanced[index].spawned = ReSpawn1Object(EqualChanced[index].guid);
|
||||
|
||||
if (EqualChanced[index].spawned)
|
||||
++m_SpawnedPoolAmount; // limited group use the Spawned variable to store the number of actualy spawned creatures
|
||||
|
||||
std::vector<uint32>::iterator itr = IndexList.begin()+roll;
|
||||
IndexList.erase(itr);
|
||||
// One spawn one despawn no count increase
|
||||
DespawnObject(triggerFrom);
|
||||
lastDespawned = triggerFrom;
|
||||
triggerFrom = 0;
|
||||
}
|
||||
m_LastDespawnedNode = 0;
|
||||
}
|
||||
else // Not enough objects in pool, so spawn all
|
||||
{
|
||||
for (size_t i = 0; i < EqualChanced.size(); ++i)
|
||||
EqualChanced[i].spawned = Spawn1Object(EqualChanced[i].guid);
|
||||
else
|
||||
++m_SpawnedPoolAmount;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -235,8 +243,7 @@ void PoolGroup<T>::SpawnObject(uint32 limit, bool cache)
|
|||
template <>
|
||||
bool PoolGroup<Creature>::Spawn1Object(uint32 guid)
|
||||
{
|
||||
CreatureData const* data = objmgr.GetCreatureData(guid);
|
||||
if (data)
|
||||
if (CreatureData const* data = objmgr.GetCreatureData(guid))
|
||||
{
|
||||
objmgr.AddCreatureToGrid(guid, data);
|
||||
|
||||
|
|
@ -250,11 +257,10 @@ bool PoolGroup<Creature>::Spawn1Object(uint32 guid)
|
|||
if (!pCreature->LoadFromDB(guid, map))
|
||||
{
|
||||
delete pCreature;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
map->Add(pCreature);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -265,8 +271,7 @@ bool PoolGroup<Creature>::Spawn1Object(uint32 guid)
|
|||
template <>
|
||||
bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
|
||||
{
|
||||
GameObjectData const* data = objmgr.GetGOData(guid);
|
||||
if (data)
|
||||
if (GameObjectData const* data = objmgr.GetGOData(guid))
|
||||
{
|
||||
objmgr.AddGameobjectToGrid(guid, data);
|
||||
// Spawn if necessary (loaded grids only)
|
||||
|
|
@ -280,6 +285,7 @@ bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
|
|||
if (!pGameobject->LoadFromDB(guid, map))
|
||||
{
|
||||
delete pGameobject;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -296,7 +302,9 @@ bool PoolGroup<GameObject>::Spawn1Object(uint32 guid)
|
|||
template <>
|
||||
bool PoolGroup<Pool>::Spawn1Object(uint32 child_pool_id)
|
||||
{
|
||||
poolhandler.SpawnPool(child_pool_id);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -304,8 +312,7 @@ bool PoolGroup<Pool>::Spawn1Object(uint32 child_pool_id)
|
|||
template <>
|
||||
bool PoolGroup<Creature>::ReSpawn1Object(uint32 guid)
|
||||
{
|
||||
CreatureData const* data = objmgr.GetCreatureData(guid);
|
||||
if (data)
|
||||
if (CreatureData const* data = objmgr.GetCreatureData(guid))
|
||||
{
|
||||
if (Creature* pCreature = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_UNIT), (Creature*)NULL))
|
||||
pCreature->GetMap()->Add(pCreature);
|
||||
|
|
@ -318,8 +325,7 @@ bool PoolGroup<Creature>::ReSpawn1Object(uint32 guid)
|
|||
template <>
|
||||
bool PoolGroup<GameObject>::ReSpawn1Object(uint32 guid)
|
||||
{
|
||||
GameObjectData const* data = objmgr.GetGOData(guid);
|
||||
if (data)
|
||||
if (GameObjectData const* data = objmgr.GetGOData(guid))
|
||||
{
|
||||
if (GameObject* pGameobject = ObjectAccessor::Instance().GetObjectInWorld(MAKE_NEW_GUID(guid, data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL))
|
||||
pGameobject->GetMap()->Add(pGameobject);
|
||||
|
|
@ -628,7 +634,9 @@ 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);
|
||||
SpawnPool(pool_entry, 0, 0);
|
||||
SpawnPool(pool_entry, 0, TYPEID_GAMEOBJECT);
|
||||
SpawnPool(pool_entry, 0, TYPEID_UNIT);
|
||||
count++;
|
||||
} while (result->NextRow());
|
||||
delete result;
|
||||
|
|
@ -640,25 +648,35 @@ void PoolHandler::Initialize()
|
|||
|
||||
// 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, bool cache)
|
||||
void PoolHandler::SpawnPool(uint16 pool_id, uint32 guid, uint32 type)
|
||||
{
|
||||
if (!mPoolPoolGroups[pool_id].isEmpty())
|
||||
mPoolPoolGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache);
|
||||
if (!mPoolGameobjectGroups[pool_id].isEmpty())
|
||||
mPoolGameobjectGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache);
|
||||
if (!mPoolCreatureGroups[pool_id].isEmpty())
|
||||
mPoolCreatureGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Call to despawn a pool, all gameobjects/creatures in this pool are removed
|
||||
void PoolHandler::DespawnPool(uint16 pool_id)
|
||||
{
|
||||
if (!mPoolPoolGroups[pool_id].isEmpty())
|
||||
mPoolPoolGroups[pool_id].DespawnObject();
|
||||
if (!mPoolGameobjectGroups[pool_id].isEmpty())
|
||||
mPoolGameobjectGroups[pool_id].DespawnObject();
|
||||
if (!mPoolCreatureGroups[pool_id].isEmpty())
|
||||
mPoolCreatureGroups[pool_id].DespawnObject();
|
||||
|
||||
if (!mPoolGameobjectGroups[pool_id].isEmpty())
|
||||
mPoolGameobjectGroups[pool_id].DespawnObject();
|
||||
|
||||
if (!mPoolPoolGroups[pool_id].isEmpty())
|
||||
mPoolPoolGroups[pool_id].DespawnObject();
|
||||
}
|
||||
|
||||
// Call to update the pool when a gameobject/creature part of pool [pool_id] is ready to respawn
|
||||
|
|
@ -666,19 +684,10 @@ void PoolHandler::DespawnPool(uint16 pool_id)
|
|||
// Then the spawn pool call will use this cache to decide
|
||||
void PoolHandler::UpdatePool(uint16 pool_id, uint32 guid, uint32 type)
|
||||
{
|
||||
uint16 motherpoolid = IsPartOfAPool(pool_id, 0);
|
||||
|
||||
if (motherpoolid)
|
||||
mPoolPoolGroups[motherpoolid].DespawnObject(pool_id);
|
||||
else if (type == TYPEID_GAMEOBJECT && !mPoolGameobjectGroups[pool_id].isEmpty())
|
||||
mPoolGameobjectGroups[pool_id].DespawnObject(guid);
|
||||
else if (type != TYPEID_GAMEOBJECT && !mPoolCreatureGroups[pool_id].isEmpty())
|
||||
mPoolCreatureGroups[pool_id].DespawnObject(guid);
|
||||
|
||||
if (motherpoolid)
|
||||
SpawnPool(motherpoolid, true);
|
||||
if (uint16 motherpoolid = IsPartOfAPool(pool_id, 0))
|
||||
SpawnPool(motherpoolid, 0, 0);
|
||||
else
|
||||
SpawnPool(pool_id, true);
|
||||
SpawnPool(pool_id, guid, type);
|
||||
}
|
||||
|
||||
// Method that tell if the gameobject/creature is part of a pool and return the pool id if yes
|
||||
|
|
|
|||
|
|
@ -40,25 +40,24 @@ struct PoolObject
|
|||
template <class T>
|
||||
class PoolGroup
|
||||
{
|
||||
typedef std::vector<PoolObject> PoolObjectList;
|
||||
public:
|
||||
PoolGroup();
|
||||
PoolGroup() : m_SpawnedPoolAmount(0) { }
|
||||
~PoolGroup() {};
|
||||
bool isEmpty() { return ExplicitlyChanced.empty() && EqualChanced.empty(); }
|
||||
void AddEntry(PoolObject& poolitem, uint32 maxentries);
|
||||
bool CheckPool(void);
|
||||
uint32 RollOne(void);
|
||||
void RollOne(int32& index, PoolObjectList** store, uint32 triggerFrom);
|
||||
bool IsSpawnedObject(uint32 guid);
|
||||
void DespawnObject(uint32 guid=0);
|
||||
void Despawn1Object(uint32 guid);
|
||||
void SpawnObject(uint32 limit, bool cache=false);
|
||||
void SpawnObject(uint32 limit, uint32 triggerFrom);
|
||||
bool Spawn1Object(uint32 guid);
|
||||
bool ReSpawn1Object(uint32 guid);
|
||||
void RemoveOneRelation(uint16 child_pool_id);
|
||||
private:
|
||||
typedef std::vector<PoolObject> PoolObjectList;
|
||||
PoolObjectList ExplicitlyChanced;
|
||||
PoolObjectList EqualChanced;
|
||||
uint32 m_LastDespawnedNode; // Store the guid of the removed creature/gameobject during a pool update
|
||||
uint32 m_SpawnedPoolAmount; // Used to know the number of spawned objects
|
||||
};
|
||||
|
||||
|
|
@ -75,7 +74,7 @@ class PoolHandler
|
|||
uint16 IsPartOfAPool(uint32 guid, uint32 type);
|
||||
bool IsSpawnedObject(uint16 pool_id, uint32 guid, uint32 type);
|
||||
bool CheckPool(uint16 pool_id);
|
||||
void SpawnPool(uint16 pool_id, bool cache=false);
|
||||
void SpawnPool(uint16 pool_id, uint32 guid, uint32 type);
|
||||
void DespawnPool(uint16 pool_id);
|
||||
void UpdatePool(uint16 pool_id, uint32 guid, uint32 type);
|
||||
void Initialize();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8700"
|
||||
#define REVISION_NR "8701"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue