From 8e6410d6392cd61d5b51e2654d133d9c7344a176 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 21 Jun 2010 05:23:13 +0400 Subject: [PATCH] [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. --- sql/mangos.sql | 26 +-- .../10089_01_mangos_game_event_pool.sql | 3 + sql/updates/Makefile.am | 2 + src/game/GameEventMgr.cpp | 211 ++++++++++++------ src/game/GameEventMgr.h | 10 +- src/game/PoolManager.cpp | 109 ++++++++- src/game/PoolManager.h | 32 ++- src/game/World.cpp | 2 +- src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 2 +- 10 files changed, 290 insertions(+), 109 deletions(-) create mode 100644 sql/updates/10089_01_mangos_game_event_pool.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 0a33b4e7b..098d2bb8a 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -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` -- diff --git a/sql/updates/10089_01_mangos_game_event_pool.sql b/sql/updates/10089_01_mangos_game_event_pool.sql new file mode 100644 index 000000000..f51d71e37 --- /dev/null +++ b/sql/updates/10089_01_mangos_game_event_pool.sql @@ -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`; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index ff1c377bc..0703cd7eb 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -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 diff --git a/src/game/GameEventMgr.cpp b/src/game/GameEventMgr.cpp index 04275c311..2bcbbd1a8 100644 --- a/src/game/GameEventMgr.cpp +++ b/src/game/GameEventMgr.cpp @@ -171,6 +171,13 @@ void GameEventMgr::LoadFromDB() sLog.outString( ">> Loaded %u game events", count ); } + std::map pool2event; // for check unique spawn event associated with pool + std::map creature2event; // for check unique spawn event associated with creature + std::map 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(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(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::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(*itr)) + { + // will have chance at next pool update + sPoolMgr.SetExcludeObject(pool_id, *itr, false); + sPoolMgr.UpdatePool(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(*itr)) + { + // will have chance at next pool update + sPoolMgr.SetExcludeObject(pool_id, *itr, false); + sPoolMgr.UpdatePool(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(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(*itr)) + { + sPoolMgr.SetExcludeObject(poolid, *itr, true); + sPoolMgr.UpdatePool(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(*itr)) + { + sPoolMgr.SetExcludeObject(poolid, *itr, true); + sPoolMgr.UpdatePool(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); + } } } diff --git a/src/game/GameEventMgr.h b/src/game/GameEventMgr.h index 39480a9f4..e236768bb 100644 --- a/src/game/GameEventMgr.h +++ b/src/game/GameEventMgr.h @@ -88,11 +88,11 @@ class GameEventMgr typedef std::pair QuestRelation; typedef std::list QuestRelList; typedef std::vector 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; diff --git a/src/game/PoolManager.cpp b/src/game/PoolManager.cpp index b0b30308b..ba8c76897 100644 --- a/src/game/PoolManager.cpp +++ b/src/game/PoolManager.cpp @@ -106,6 +106,30 @@ void SpawnedPoolData::RemoveSpawn(uint32 sub_pool_id, uint32 pool_id) --val; } +//////////////////////////////////////////////////////////// +// Methods of class PoolObject +template<> +void PoolObject::CheckEventLinkAndReport(uint32 poolId, int16 event_id, std::map const& creature2event, std::map const& /*go2event*/) const +{ + std::map::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(uint32 poolId, int16 event_id, std::map const& /*creature2event*/, std::map const& go2event) const +{ + std::map::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(uint32 poolId, int16 event_id, std::map const& creature2event, std::map const& go2event) const +{ + sPoolMgr.CheckEventLinkAndReport(guid, event_id, creature2event, go2event); +} + //////////////////////////////////////////////////////////// // Methods of template class PoolGroup @@ -134,6 +158,40 @@ bool PoolGroup::CheckPool() const return true; } +// Method to check event linking +template +void PoolGroup::CheckEventLinkAndReport(int16 event_id, std::map const& creature2event, std::map const& go2event) const +{ + for (uint32 i=0; i < EqualChanced.size(); ++i) + EqualChanced[i].CheckEventLinkAndReport(poolId, event_id, creature2event, go2event); + + for (uint32 i=0; i(poolId, event_id, creature2event, go2event); +} + +template +void PoolGroup::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 PoolObject* PoolGroup::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom) { @@ -146,7 +204,7 @@ PoolObject* PoolGroup::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(ExplicitlyChanced[i].guid))) + if (roll < 0 && !ExplicitlyChanced[i].exclude && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.IsSpawnedObject(ExplicitlyChanced[i].guid))) return &ExplicitlyChanced[i]; } } @@ -156,7 +214,7 @@ PoolObject* PoolGroup::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(EqualChanced[index].guid)) + if (!EqualChanced[index].exclude && (EqualChanced[index].guid == triggerFrom || !spawns.IsSpawnedObject(EqualChanced[index].guid))) return &EqualChanced[index]; } @@ -263,7 +321,12 @@ void PoolGroup::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(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 const& creature2event, std::map 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(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(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 diff --git a/src/game/PoolManager.h b/src/game/PoolManager.h index 5cdeeda7d..278cdd701 100644 --- a/src/game/PoolManager.h +++ b/src/game/PoolManager.h @@ -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 + void CheckEventLinkAndReport(uint32 poolId, int16 event_id, std::map const& creature2event, std::map 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 const& creature2event, std::map 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 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 + uint16 IsPartOfTopPool(uint32 db_guid_or_pool_id) const + { + if (uint16 pool_id = IsPartOfAPool(db_guid_or_pool_id)) + { + if (uint16 top_pool_id = IsPartOfTopPool(pool_id)) + return top_pool_id; + + return pool_id; + } + + return 0; + } + template bool IsSpawnedObject(uint32 db_guid_or_pool_id) const { return mSpawnedData.IsSpawnedObject(db_guid_or_pool_id); } + template + 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 const& creature2event, std::map const& go2event) const; void SpawnPool(uint16 pool_id, bool instantly); void DespawnPool(uint16 pool_id); template - 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 void SpawnPoolGroup(uint16 pool_id, uint32 db_guid_or_pool_id, bool instantly); diff --git a/src/game/World.cpp b/src/game/World.cpp index 0d0a4c682..9a0071b8c 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -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" ); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c3210f870..2b429896a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "10088" + #define REVISION_NR "10089" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index 8c440e80e..eb8a6c0c2 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -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__