Added support for pools in pools

Pools inside another pool cannot have a number of spawned objects <> 1 (maxlimit value)

Note: pools in a pool in a pool in a pool... is possible and working,
but circulare inclusion is not detected and will cause a core infinit loop

Signed-off-by: Neo2003 <neo.2003@hotmail.fr>
This commit is contained in:
Neo2003 2008-12-07 16:59:37 +01:00
parent 7d8dc0eeef
commit 5da8bdf16e
3 changed files with 121 additions and 5 deletions

View file

@ -12,6 +12,13 @@ CREATE TABLE `pool_gameobject` (
PRIMARY KEY (`guid`,`pool_entry`) PRIMARY KEY (`guid`,`pool_entry`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8; ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `pool_pool` (
`pool_id` mediumint(8) unsigned NOT NULL default '0',
`mother_pool` mediumint(8) unsigned NOT NULL default '0',
`chance` float NOT NULL default '0',
PRIMARY KEY (`pool_id`,`mother_pool`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `pool_template` ( CREATE TABLE `pool_template` (
`entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Pool entry', `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Pool entry',
`max_limit` int(10) unsigned NOT NULL default '0' COMMENT 'Max number of objects (0) is no limit', `max_limit` int(10) unsigned NOT NULL default '0' COMMENT 'Max number of objects (0) is no limit',

View file

@ -210,6 +210,70 @@ void PoolHandler::LoadFromDB()
sLog.outString( ">> Loaded %u gameobject in pools", count ); sLog.outString( ">> Loaded %u gameobject in pools", count );
delete result; delete result;
} }
// Pool of pools
mPoolPoolGroups.resize(max_pool_id + 1);
// 1 2 3
result = WorldDatabase.Query("SELECT pool_id, mother_pool, chance FROM pool_pool");
count = 0;
if( !result )
{
barGoLink bar2(1);
bar2.step();
sLog.outString();
sLog.outString(">> Loaded %u pools in pools", count );
}
else
{
barGoLink bar2( result->GetRowCount() );
do
{
Field *fields = result->Fetch();
bar2.step();
uint16 child_pool_id = fields[0].GetUInt16();
uint16 mother_pool_id = fields[1].GetUInt16();
float chance = fields[2].GetFloat();
if (mother_pool_id > max_pool_id)
{
sLog.outErrorDb("`pool_pool` mother_pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.",mother_pool_id);
continue;
}
if (child_pool_id > max_pool_id)
{
sLog.outErrorDb("`pool_pool` included pool_id (%i) is out of range compared to max pool id in `pool_template`, skipped.",child_pool_id);
continue;
}
if (mother_pool_id == child_pool_id)
{
sLog.outErrorDb("`pool_pool` pool_id (%i) includes itself, dead-lock detected, skipped.",child_pool_id);
continue;
}
if (chance < 0 || chance > 100)
{
sLog.outErrorDb("`pool_pool` has an invalid chance (%f) for pool id (%u) in mother pool id (%i), skipped.", chance, child_pool_id, mother_pool_id);
continue;
}
PoolTemplateData *pPoolTemplateMother = &mPoolTemplate[mother_pool_id];
++count;
PoolObject plObject = PoolObject(child_pool_id, chance);
PoolGroup<Pool>& plgroup = mPoolPoolGroups[mother_pool_id];
plgroup.AddEntry(plObject, pPoolTemplateMother->MaxLimit);
SearchPair p(child_pool_id, mother_pool_id);
mPoolSearchMap.insert(p);
} while( result->NextRow() );
sLog.outString();
sLog.outString( ">> Loaded %u pools in mother pools", count );
delete result;
}
} }
// The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks // The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks
@ -241,6 +305,8 @@ void PoolHandler::Initialize()
// If it's same, the gameobject/creature is respawned only (added back to map) // 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, bool cache)
{ {
if (!mPoolPoolGroups[pool_id].isEmpty())
mPoolPoolGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache);
if (!mPoolGameobjectGroups[pool_id].isEmpty()) if (!mPoolGameobjectGroups[pool_id].isEmpty())
mPoolGameobjectGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache); mPoolGameobjectGroups[pool_id].SpawnObject(mPoolTemplate[pool_id].MaxLimit, cache);
if (!mPoolCreatureGroups[pool_id].isEmpty()) if (!mPoolCreatureGroups[pool_id].isEmpty())
@ -250,6 +316,8 @@ void PoolHandler::SpawnPool(uint16 pool_id, bool cache)
// Call to despawn a pool, all gameobjects/creatures in this pool are removed // Call to despawn a pool, all gameobjects/creatures in this pool are removed
void PoolHandler::DespawnPool(uint16 pool_id) void PoolHandler::DespawnPool(uint16 pool_id)
{ {
if (!mPoolPoolGroups[pool_id].isEmpty())
mPoolPoolGroups[pool_id].DespawnObject();
if (!mPoolGameobjectGroups[pool_id].isEmpty()) if (!mPoolGameobjectGroups[pool_id].isEmpty())
mPoolGameobjectGroups[pool_id].DespawnObject(); mPoolGameobjectGroups[pool_id].DespawnObject();
if (!mPoolCreatureGroups[pool_id].isEmpty()) if (!mPoolCreatureGroups[pool_id].isEmpty())
@ -261,18 +329,31 @@ void PoolHandler::DespawnPool(uint16 pool_id)
// Then the spawn pool call will use this cache to decide // Then the spawn pool call will use this cache to decide
void PoolHandler::UpdatePool(uint16 pool_id, uint32 guid, uint32 type) void PoolHandler::UpdatePool(uint16 pool_id, uint32 guid, uint32 type)
{ {
if (type == TYPEID_GAMEOBJECT && !mPoolGameobjectGroups[pool_id].isEmpty()) 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); mPoolGameobjectGroups[pool_id].DespawnObject(guid);
else if (type != TYPEID_GAMEOBJECT && !mPoolCreatureGroups[pool_id].isEmpty()) else if (type != TYPEID_GAMEOBJECT && !mPoolCreatureGroups[pool_id].isEmpty())
mPoolCreatureGroups[pool_id].DespawnObject(guid); mPoolCreatureGroups[pool_id].DespawnObject(guid);
SpawnPool(pool_id, true); if (motherpoolid)
SpawnPool(motherpoolid, true);
else
SpawnPool(pool_id, true);
} }
// Method that tell if the gameobject/creature is part of a pool and return the pool id if yes // 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) uint16 PoolHandler::IsPartOfAPool(uint32 guid, uint32 type)
{ {
if (type == TYPEID_GAMEOBJECT) 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); SearchMap::const_iterator itr = mGameobjectSearchMap.find(guid);
if (itr != mGameobjectSearchMap.end()) if (itr != mGameobjectSearchMap.end())
@ -290,7 +371,9 @@ uint16 PoolHandler::IsPartOfAPool(uint32 guid, uint32 type)
// Method that check chance integrity of the creatures and gameobjects in this pool // 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)
{ {
return mPoolCreatureGroups[pool_id].CheckPool() && mPoolGameobjectGroups[pool_id].CheckPool(); return mPoolGameobjectGroups[pool_id].CheckPool() &&
mPoolCreatureGroups[pool_id].CheckPool() &&
mPoolPoolGroups[pool_id].CheckPool();
} }
// Method that tell if a creature or gameobject in pool_id is spawned currently // Method that tell if a creature or gameobject in pool_id is spawned currently
@ -298,7 +381,9 @@ bool PoolHandler::IsSpawnedObject(uint16 pool_id, uint32 guid, uint32 type)
{ {
if (pool_id > max_pool_id) if (pool_id > max_pool_id)
return false; return false;
if (type == TYPEID_GAMEOBJECT) if (type == 0)
return mPoolPoolGroups[pool_id].IsSpawnedObject(guid);
else if (type == TYPEID_GAMEOBJECT)
return mPoolGameobjectGroups[pool_id].IsSpawnedObject(guid); return mPoolGameobjectGroups[pool_id].IsSpawnedObject(guid);
else else
return mPoolCreatureGroups[pool_id].IsSpawnedObject(guid); return mPoolCreatureGroups[pool_id].IsSpawnedObject(guid);
@ -426,6 +511,13 @@ void PoolHandler::PoolGroup<GameObject>::Despawn1Object(uint32 guid)
} }
} }
// Same on one pool
template<>
void PoolHandler::PoolGroup<PoolHandler::Pool>::Despawn1Object(uint32 child_pool_id)
{
poolhandler.DespawnPool(child_pool_id);
}
// Method that Spawn 1+ creatures or gameobject // 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 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) // if cache is true, this means only one has to be spawned (or respawned if the rolled one is same as cached one)
@ -534,6 +626,14 @@ bool PoolHandler::PoolGroup<GameObject>::Spawn1Object(uint32 guid)
return false; return false;
} }
// Same for 1 pool
template <>
bool PoolHandler::PoolGroup<PoolHandler::Pool>::Spawn1Object(uint32 child_pool_id)
{
poolhandler.SpawnPool(child_pool_id);
return true;
}
// Method that does the respawn job on the specified creature // Method that does the respawn job on the specified creature
template <> template <>
bool PoolHandler::PoolGroup<Creature>::ReSpawn1Object(uint32 guid) bool PoolHandler::PoolGroup<Creature>::ReSpawn1Object(uint32 guid)
@ -561,3 +661,10 @@ bool PoolHandler::PoolGroup<GameObject>::ReSpawn1Object(uint32 guid)
} }
return false; return false;
} }
// Nothing to do for a child Pool
template <>
bool PoolHandler::PoolGroup<PoolHandler::Pool>::ReSpawn1Object(uint32 guid)
{
return true;
}

View file

@ -68,8 +68,10 @@ class PoolHandler
PoolTemplateDataMap mPoolTemplate; PoolTemplateDataMap mPoolTemplate;
PoolGroupCreatureMap mPoolCreatureGroups; PoolGroupCreatureMap mPoolCreatureGroups;
PoolGroupGameObjectMap mPoolGameobjectGroups; PoolGroupGameObjectMap mPoolGameobjectGroups;
PoolGroupPoolMap mPoolPoolGroups;
SearchMap mCreatureSearchMap; SearchMap mCreatureSearchMap;
SearchMap mGameobjectSearchMap; SearchMap mGameobjectSearchMap;
SearchMap mPoolSearchMap;
}; };