[10089] Change in event system work with pool system.

* `game_event_pool` dropped and related in momory data generated
  based by another pool tables content.

* Pool work with spawed at event and despawned at event object now different.
  - If object listed in `game_event_*` as spawned at event start and it's part of some pool
    then all other pool object must be listed as spawned with this event start, and more,
    if pool has mother pool, then all mother pool members must have objects spawned at this
    event start. More short: all object of some top (not have mother pool) mitbe or listed for some event start spawn,
    or not listed for any event start spawn.
  - If object listed in `game_event_*` as DEspawned at event start and it's part of some pool
    then nothing special required for other pool objects. Event systemwil command to pool system exclude for spawning and despawn referenced
    object until event end.

* Many checks has been added at event/pool data loading.
* Changes fix crashes related to event/pool common work.

Thanks to NoFantasy for help in research original problems and ways for improve code.
This commit is contained in:
VladimirMangos 2010-06-21 05:23:13 +04:00
parent 407156cbaf
commit 8e6410d639
10 changed files with 290 additions and 109 deletions

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0',
`required_10086_01_mangos_command` bit(1) default NULL
`required_10089_01_mangos_game_event_pool` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
--
@ -1572,7 +1572,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `game_event_creature`;
CREATE TABLE `game_event_creature` (
`guid` int(10) unsigned NOT NULL,
`event` smallint(6) NOT NULL default '0' COMMENT 'Put negatives values to remove during event',
`event` smallint(6) NOT NULL default '0' COMMENT 'Negatives value to remove during event and ignore pool grouping, positive value for spawn during event and if guid is part of pool then al pool memebers must be listed as part of event spawn.',
PRIMARY KEY (`guid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@ -1613,7 +1613,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `game_event_gameobject`;
CREATE TABLE `game_event_gameobject` (
`guid` int(10) unsigned NOT NULL,
`event` smallint(6) NOT NULL default '0' COMMENT 'Put negatives values to remove during event',
`event` smallint(6) NOT NULL default '0' COMMENT 'Negatives value to remove during event and ignore pool grouping, positive value for spawn during event and if guid is part of pool then al pool memebers must be listed as part of event spawn.',
PRIMARY KEY (`guid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@ -1648,26 +1648,6 @@ LOCK TABLES `game_event_model_equip` WRITE;
/*!40000 ALTER TABLE `game_event_model_equip` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `game_event_pool`
--
DROP TABLE IF EXISTS `game_event_pool`;
CREATE TABLE `game_event_pool` (
`pool_entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Id of the pool',
`event` smallint(6) NOT NULL default '0' COMMENT 'Put negatives values to remove during event',
PRIMARY KEY (`pool_entry`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Dumping data for table `game_event_pool`
--
LOCK TABLES `game_event_pool` WRITE;
/*!40000 ALTER TABLE `game_event_pool` DISABLE KEYS */;
/*!40000 ALTER TABLE `game_event_pool` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `game_graveyard_zone`
--

View file

@ -0,0 +1,3 @@
ALTER TABLE db_version CHANGE COLUMN required_10086_01_mangos_command required_10089_01_mangos_game_event_pool bit;
DROP TABLE IF EXISTS `game_event_pool`;

View file

@ -90,6 +90,7 @@ pkgdata_DATA = \
10051_01_characters_character_aura.sql \
10056_01_mangos_spell_proc_event.sql \
10086_01_mangos_command.sql \
10089_01_mangos_game_event_pool.sql \
README
## Additional files to include when running 'make dist'
@ -160,4 +161,5 @@ EXTRA_DIST = \
10051_01_characters_character_aura.sql \
10056_01_mangos_spell_proc_event.sql \
10086_01_mangos_command.sql \
10089_01_mangos_game_event_pool.sql \
README

View file

@ -171,6 +171,13 @@ void GameEventMgr::LoadFromDB()
sLog.outString( ">> Loaded %u game events", count );
}
std::map<uint16,int16> pool2event; // for check unique spawn event associated with pool
std::map<uint32,int16> creature2event; // for check unique spawn event associated with creature
std::map<uint32,int16> go2event; // for check unique spawn event associated with gameobject
// list only positive event top pools, filled at creature/gameobject loading
mGameEventSpawnPoolIds.resize(mGameEvent.size());
mGameEventCreatureGuids.resize(mGameEvent.size()*2-1);
// 1 2
result = WorldDatabase.Query("SELECT creature.guid, game_event_creature.event "
@ -198,6 +205,12 @@ void GameEventMgr::LoadFromDB()
uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16();
if (event_id == 0)
{
sLog.outErrorDb("`game_event_creature` game event id (%i) not allowed",event_id);
continue;
}
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventCreatureGuids.size())
@ -207,6 +220,32 @@ void GameEventMgr::LoadFromDB()
}
++count;
// spawn objects at event can be grouped in pools and then affected pools have stricter requirements for this case
if (event_id > 0)
{
creature2event[guid] = event_id;
// not list explicitly creatures from pools in event creature list
if (uint16 topPoolId = sPoolMgr.IsPartOfTopPool<Creature>(guid))
{
int16& eventRef = pool2event[topPoolId];
if (eventRef != 0)
{
if (eventRef != event_id)
sLog.outErrorDb("`game_event_creature` have creature (GUID: %u) for event %i from pool or subpool of pool (ID: %u) but pool have already content from event %i. Pool don't must have content for different events!", guid, event_id, topPoolId, eventRef);
}
else
{
eventRef = event_id;
mGameEventSpawnPoolIds[event_id].push_back(topPoolId);
sPoolMgr.RemoveAutoSpawnForPool(topPoolId);
}
continue;
}
}
GuidList& crelist = mGameEventCreatureGuids[internal_event_id];
crelist.push_back(guid);
@ -244,6 +283,12 @@ void GameEventMgr::LoadFromDB()
uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16();
if (event_id == 0)
{
sLog.outErrorDb("`game_event_gameobject` game event id (%i) not allowed",event_id);
continue;
}
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventGameobjectGuids.size())
@ -253,6 +298,32 @@ void GameEventMgr::LoadFromDB()
}
++count;
// spawn objects at event can be grouped in pools and then affected pools have stricter requirements for this case
if (event_id > 0)
{
go2event[guid] = event_id;
// not list explicitly gameobjects from pools in event gameobject list
if (uint16 topPoolId = sPoolMgr.IsPartOfTopPool<GameObject>(guid))
{
int16& eventRef = pool2event[topPoolId];
if (eventRef != 0)
{
if (eventRef != event_id)
sLog.outErrorDb("`game_event_gameobject` have gameobject (GUID: %u) for event %i from pool or subpool of pool (ID: %u) but pool have already content from event %i. Pool don't must have content for different events!", guid, event_id, topPoolId, eventRef);
}
else
{
eventRef = event_id;
mGameEventSpawnPoolIds[event_id].push_back(topPoolId);
sPoolMgr.RemoveAutoSpawnForPool(topPoolId);
}
continue;
}
}
GuidList& golist = mGameEventGameobjectGuids[internal_event_id];
golist.push_back(guid);
@ -263,6 +334,15 @@ void GameEventMgr::LoadFromDB()
sLog.outString( ">> Loaded %u gameobjects in game events", count );
}
// now recheck that all eventPools linked with events after our skip pools with parents
for(std::map<uint16,int16>::const_iterator itr = pool2event.begin(); itr != pool2event.end(); ++itr)
{
uint16 pool_id = itr->first;
int16 event_id = itr->second;
sPoolMgr.CheckEventLinkAndReport(pool_id, event_id, creature2event, go2event);
}
mGameEventModelEquip.resize(mGameEvent.size());
// 0 1 2
result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid,"
@ -365,57 +445,6 @@ void GameEventMgr::LoadFromDB()
sLog.outString();
sLog.outString( ">> Loaded %u quests additions in game events", count );
}
mGameEventPoolIds.resize(mGameEvent.size()*2-1);
// 1 2
result = WorldDatabase.Query("SELECT pool_template.entry, game_event_pool.event "
"FROM pool_template JOIN game_event_pool ON pool_template.entry = game_event_pool.pool_entry");
count = 0;
if( !result )
{
barGoLink bar2(1);
bar2.step();
sLog.outString();
sLog.outString(">> Loaded %u pools in game events", count );
}
else
{
barGoLink bar2( (int)result->GetRowCount() );
do
{
Field *fields = result->Fetch();
bar2.step();
uint32 entry = fields[0].GetUInt16();
int16 event_id = fields[1].GetInt16();
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size())
{
sLog.outErrorDb("`game_event_pool` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
continue;
}
if (!sPoolMgr.CheckPool(entry))
{
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.", entry);
continue;
}
++count;
IdList& poollist = mGameEventPoolIds[internal_event_id];
poollist.push_back(entry);
} while( result->NextRow() );
sLog.outString();
sLog.outString( ">> Loaded %u pools in game events", count );
delete result;
}
}
uint32 GameEventMgr::Initialize() // return the next event delay in ms
@ -516,6 +545,18 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
CreatureData const* data = sObjectMgr.GetCreatureData(*itr);
if (data)
{
// negative event id for pool element meaning allow be used in next pool spawn
if (event_id < 0)
{
if (uint16 pool_id = sPoolMgr.IsPartOfAPool<Creature>(*itr))
{
// will have chance at next pool update
sPoolMgr.SetExcludeObject<Creature>(pool_id, *itr, false);
sPoolMgr.UpdatePool<Creature>(pool_id);
continue;
}
}
sObjectMgr.AddCreatureToGrid(*itr, data);
// Spawn if necessary (loaded grids only)
@ -549,7 +590,20 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
GameObjectData const* data = sObjectMgr.GetGOData(*itr);
if (data)
{
// negative event id for pool element meaning allow be used in next pool spawn
if (event_id < 0)
{
if (uint16 pool_id = sPoolMgr.IsPartOfAPool<GameObject>(*itr))
{
// will have chance at next pool update
sPoolMgr.SetExcludeObject<GameObject>(pool_id, *itr, false);
sPoolMgr.UpdatePool<GameObject>(pool_id);
continue;
}
}
sObjectMgr.AddGameobjectToGrid(*itr, data);
// Spawn if necessary (loaded grids only)
// this base map checked as non-instanced and then only existed
Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid));
@ -571,14 +625,17 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
}
}
if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size())
if (event_id > 0)
{
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventPoolIds.size());
return;
}
if((size_t)event_id >= mGameEventSpawnPoolIds.size())
{
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventSpawnPoolIds element %i (size: " SIZEFMTD ")", event_id, mGameEventSpawnPoolIds.size());
return;
}
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
sPoolMgr.SpawnPool(*itr, true);
for (IdList::iterator itr = mGameEventSpawnPoolIds[event_id].begin();itr != mGameEventSpawnPoolIds[event_id].end();++itr)
sPoolMgr.SpawnPool(*itr, true);
}
}
void GameEventMgr::GameEventUnspawn(int16 event_id)
@ -596,6 +653,17 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
// Remove the creature from grid
if( CreatureData const* data = sObjectMgr.GetCreatureData(*itr) )
{
// negative event id for pool element meaning unspawn in pool and exclude for next spawns
if (event_id < 0)
{
if (uint16 poolid = sPoolMgr.IsPartOfAPool<Creature>(*itr))
{
sPoolMgr.SetExcludeObject<Creature>(poolid, *itr, true);
sPoolMgr.UpdatePool<Creature>(poolid, *itr);
continue;
}
}
sObjectMgr.RemoveCreatureFromGrid(*itr, data);
if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, *itr)))
@ -614,21 +682,36 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
// Remove the gameobject from grid
if(GameObjectData const* data = sObjectMgr.GetGOData(*itr))
{
// negative event id for pool element meaning unspawn in pool and exclude for next spawns
if (event_id < 0)
{
if (uint16 poolid = sPoolMgr.IsPartOfAPool<GameObject>(*itr))
{
sPoolMgr.SetExcludeObject<GameObject>(poolid, *itr, true);
sPoolMgr.UpdatePool<GameObject>(poolid, *itr);
continue;
}
}
sObjectMgr.RemoveGameobjectFromGrid(*itr, data);
if( GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, *itr)) )
pGameobject->AddObjectToRemoveList();
}
}
if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size())
{
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventPoolIds.size());
return;
}
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
if (event_id > 0)
{
sPoolMgr.DespawnPool(*itr);
if ((size_t)event_id >= mGameEventSpawnPoolIds.size())
{
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventSpawnPoolIds element %i (size: " SIZEFMTD ")", event_id, mGameEventSpawnPoolIds.size());
return;
}
for (IdList::iterator itr = mGameEventSpawnPoolIds[event_id].begin();itr != mGameEventSpawnPoolIds[event_id].end();++itr)
{
sPoolMgr.DespawnPool(*itr);
}
}
}

View file

@ -88,11 +88,11 @@ class GameEventMgr
typedef std::pair<uint32, uint32> QuestRelation;
typedef std::list<QuestRelation> QuestRelList;
typedef std::vector<QuestRelList> GameEventQuestMap;
GameEventQuestMap mGameEventQuests;
GameEventModelEquipMap mGameEventModelEquip;
GameEventGuidMap mGameEventCreatureGuids;
GameEventGuidMap mGameEventGameobjectGuids;
GameEventIdMap mGameEventPoolIds;
GameEventQuestMap mGameEventQuests; // events*2-1
GameEventModelEquipMap mGameEventModelEquip; // events*2-1
GameEventGuidMap mGameEventCreatureGuids; // events*2-1
GameEventGuidMap mGameEventGameobjectGuids; // events*2-1
GameEventIdMap mGameEventSpawnPoolIds; // events size, only positive event case
GameEventDataMap mGameEvent;
ActiveEvents m_ActiveEvents;
bool m_IsGameEventsInit;

View file

@ -106,6 +106,30 @@ void SpawnedPoolData::RemoveSpawn<Pool>(uint32 sub_pool_id, uint32 pool_id)
--val;
}
////////////////////////////////////////////////////////////
// Methods of class PoolObject
template<>
void PoolObject::CheckEventLinkAndReport<Creature>(uint32 poolId, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& /*go2event*/) const
{
std::map<uint32, int16>::const_iterator itr = creature2event.find(guid);
if (itr == creature2event.end() || itr->second != event_id)
sLog.outErrorDb("Creature (GUID: %u) expected to be listed in `game_event_creature` for event %u as part pool %u", guid, event_id, poolId);
}
template<>
void PoolObject::CheckEventLinkAndReport<GameObject>(uint32 poolId, int16 event_id, std::map<uint32, int16> const& /*creature2event*/, std::map<uint32, int16> const& go2event) const
{
std::map<uint32, int16>::const_iterator itr = go2event.find(guid);
if (itr == go2event.end() || itr->second != event_id)
sLog.outErrorDb("Gameobject (GUID: %u) expected to be listed in `game_event_gameobject` for event %u as part pool %u", guid, event_id, poolId);
}
template<>
void PoolObject::CheckEventLinkAndReport<Pool>(uint32 poolId, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const
{
sPoolMgr.CheckEventLinkAndReport(guid, event_id, creature2event, go2event);
}
////////////////////////////////////////////////////////////
// Methods of template class PoolGroup
@ -134,6 +158,40 @@ bool PoolGroup<T>::CheckPool() const
return true;
}
// Method to check event linking
template <class T>
void PoolGroup<T>::CheckEventLinkAndReport(int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const
{
for (uint32 i=0; i < EqualChanced.size(); ++i)
EqualChanced[i].CheckEventLinkAndReport<T>(poolId, event_id, creature2event, go2event);
for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
ExplicitlyChanced[i].CheckEventLinkAndReport<T>(poolId, event_id, creature2event, go2event);
}
template <class T>
void PoolGroup<T>::SetExcludeObject(uint32 guid, bool state)
{
for (uint32 i=0; i < EqualChanced.size(); ++i)
{
if (EqualChanced[i].guid == guid)
{
EqualChanced[i].exclude = state;
return;
}
}
for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
{
if (ExplicitlyChanced[i].guid == guid)
{
ExplicitlyChanced[i].exclude = state;
return;
}
}
}
template <class T>
PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
{
@ -146,7 +204,7 @@ PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, 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].guid == triggerFrom || !spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid)))
if (roll < 0 && !ExplicitlyChanced[i].exclude && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid)))
return &ExplicitlyChanced[i];
}
}
@ -156,7 +214,7 @@ PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, 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].guid == triggerFrom || !spawns.IsSpawnedObject<T>(EqualChanced[index].guid))
if (!EqualChanced[index].exclude && (EqualChanced[index].guid == triggerFrom || !spawns.IsSpawnedObject<T>(EqualChanced[index].guid)))
return &EqualChanced[index];
}
@ -263,7 +321,12 @@ void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 tri
// and also counted into m_SpawnedPoolAmount so we need increase count to be
// spawned by 1
if (triggerFrom)
++count;
{
if (spawns.IsSpawnedObject<T>(triggerFrom))
++count;
else
triggerFrom = 0;
}
// This will try to spawn the rest of pool, not guaranteed
for (int i = 0; i < count; ++i)
@ -462,6 +525,7 @@ void PoolManager::LoadFromDB()
PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id];
pPoolTemplate.MaxLimit = fields[1].GetUInt32();
pPoolTemplate.AutoSpawn = true; // will update and later data loading
} while (result->NextRow());
@ -661,6 +725,9 @@ void PoolManager::LoadFromDB()
SearchPair p(child_pool_id, mother_pool_id);
mPoolSearchMap.insert(p);
// update top independent pool flag
mPoolTemplate[child_pool_id].AutoSpawn = false;
} while( result->NextRow() );
// Now check for circular reference
@ -692,17 +759,15 @@ void PoolManager::LoadFromDB()
}
}
// 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
void PoolManager::Initialize()
{
QueryResult *result = WorldDatabase.Query("SELECT DISTINCT pool_template.entry FROM pool_template LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry LEFT JOIN pool_pool ON pool_template.entry=pool_pool.pool_id WHERE game_event_pool.pool_entry IS NULL AND pool_pool.pool_id IS NULL");
uint32 count=0;
if (result)
uint32 count = 0;
for(uint16 pool_entry = 0; pool_entry < mPoolTemplate.size(); ++pool_entry)
{
do
if (mPoolTemplate[pool_entry].AutoSpawn)
{
Field *fields = result->Fetch();
uint16 pool_entry = fields[0].GetUInt16();
if (!CheckPool(pool_entry))
{
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);
@ -710,8 +775,7 @@ void PoolManager::Initialize()
}
SpawnPool(pool_entry, true);
count++;
} while (result->NextRow());
delete result;
}
}
BASIC_LOG("Pool handling system initialized, %u pools spawned.", count);
@ -775,6 +839,27 @@ bool PoolManager::CheckPool(uint16 pool_id) const
mPoolPoolGroups[pool_id].CheckPool();
}
// Method that check linking all elements to event
void PoolManager::CheckEventLinkAndReport(uint16 pool_id, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const
{
mPoolGameobjectGroups[pool_id].CheckEventLinkAndReport(event_id, creature2event, go2event);
mPoolCreatureGroups[pool_id].CheckEventLinkAndReport(event_id, creature2event, go2event);
mPoolPoolGroups[pool_id].CheckEventLinkAndReport(event_id, creature2event, go2event);
}
// Method that exclude some elements from next spawn
template<>
void PoolManager::SetExcludeObject<Creature>(uint16 pool_id, uint32 db_guid_or_pool_id, bool state)
{
mPoolCreatureGroups[pool_id].SetExcludeObject(db_guid_or_pool_id, state);
}
template<>
void PoolManager::SetExcludeObject<GameObject>(uint16 pool_id, uint32 db_guid_or_pool_id, bool state)
{
mPoolGameobjectGroups[pool_id].SetExcludeObject(db_guid_or_pool_id, state);
}
// 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

View file

@ -27,13 +27,19 @@
struct PoolTemplateData
{
uint32 MaxLimit;
bool AutoSpawn; // spawn at pool system start (not part of another pool and not part of event spawn)
};
struct PoolObject
{
uint32 guid;
float chance;
PoolObject(uint32 _guid, float _chance): guid(_guid), chance(fabs(_chance)) {}
bool exclude;
PoolObject(uint32 _guid, float _chance): guid(_guid), chance(fabs(_chance)), exclude(false) {}
template<typename T>
void CheckEventLinkAndReport(uint32 poolId, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const;
};
class Pool // for Pool of Pool case
@ -73,10 +79,12 @@ class PoolGroup
bool isEmpty() const { return ExplicitlyChanced.empty() && EqualChanced.empty(); }
void AddEntry(PoolObject& poolitem, uint32 maxentries);
bool CheckPool() const;
void CheckEventLinkAndReport(int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const;
PoolObject* RollOne(SpawnedPoolData& spawns, uint32 triggerFrom);
void DespawnObject(SpawnedPoolData& spawns, uint32 guid=0);
void Despawn1Object(uint32 guid);
void SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom, bool instantly);
void SetExcludeObject(uint32 guid, bool state);
void Spawn1Object(PoolObject* obj, bool instantly);
void ReSpawn1Object(PoolObject* obj);
@ -99,17 +107,37 @@ class PoolManager
template<typename T>
uint16 IsPartOfAPool(uint32 db_guid_or_pool_id) const;
// Method that tell if the creature/gameobject/pool is part of top level pool and return the pool id if yes
template<typename T>
uint16 IsPartOfTopPool(uint32 db_guid_or_pool_id) const
{
if (uint16 pool_id = IsPartOfAPool<T>(db_guid_or_pool_id))
{
if (uint16 top_pool_id = IsPartOfTopPool<Pool>(pool_id))
return top_pool_id;
return pool_id;
}
return 0;
}
template<typename T>
bool IsSpawnedObject(uint32 db_guid_or_pool_id) const { return mSpawnedData.IsSpawnedObject<T>(db_guid_or_pool_id); }
template<typename T>
void SetExcludeObject(uint16 pool_id, uint32 db_guid_or_pool_id, bool state);
bool CheckPool(uint16 pool_id) const;
void CheckEventLinkAndReport(uint16 pool_id, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const;
void SpawnPool(uint16 pool_id, bool instantly);
void DespawnPool(uint16 pool_id);
template<typename T>
void UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id);
void UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id = 0);
void RemoveAutoSpawnForPool(uint16 pool_id) { mPoolTemplate[pool_id].AutoSpawn = false; }
protected:
template<typename T>
void SpawnPoolGroup(uint16 pool_id, uint32 db_guid_or_pool_id, bool instantly);

View file

@ -1032,7 +1032,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Objects Pooling Data...");
sPoolMgr.LoadFromDB();
sLog.outString( "Loading Game Event Data...");
sLog.outString( "Loading Game Event Data..."); // must be after sPoolMgr.LoadFromDB for proper load pool events
sLog.outString();
sGameEventMgr.LoadFromDB();
sLog.outString( ">>> Game Event Data loaded" );

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10088"
#define REVISION_NR "10089"
#endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_10051_01_characters_character_aura"
#define REVISION_DB_MANGOS "required_10086_01_mangos_command"
#define REVISION_DB_MANGOS "required_10089_01_mangos_game_event_pool"
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__