31 ActivePoolPools::const_iterator itr =
mSpawnedPools.find(pool_id);
37 bool ActivePoolData::IsActiveObject<Creature>(
uint32 db_guid)
const 44 bool ActivePoolData::IsActiveObject<GameObject>(
uint32 db_guid)
const 51 bool ActivePoolData::IsActiveObject<Pool>(
uint32 sub_pool_id)
const 58 bool ActivePoolData::IsActiveObject<Quest>(
uint32 quest_id)
const 64 void ActivePoolData::ActivateObject<Creature>(
uint32 db_guid,
uint32 pool_id)
71 void ActivePoolData::ActivateObject<GameObject>(
uint32 db_guid,
uint32 pool_id)
78 void ActivePoolData::ActivateObject<Pool>(
uint32 sub_pool_id,
uint32 pool_id)
85 void ActivePoolData::ActivateObject<Quest>(
uint32 quest_id,
uint32 pool_id)
92 void ActivePoolData::RemoveObject<Creature>(
uint32 db_guid,
uint32 pool_id)
101 void ActivePoolData::RemoveObject<GameObject>(
uint32 db_guid,
uint32 pool_id)
110 void ActivePoolData::RemoveObject<Pool>(
uint32 sub_pool_id,
uint32 pool_id)
119 void ActivePoolData::RemoveObject<Quest>(
uint32 quest_id,
uint32 pool_id)
134 if (poolitem.
chance != 0 && maxentries == 1)
135 ExplicitlyChanced.push_back(poolitem);
137 EqualChanced.push_back(poolitem);
144 if (EqualChanced.empty())
147 for (
uint32 i = 0; i < ExplicitlyChanced.size(); ++i)
148 chance += ExplicitlyChanced[i].chance;
149 if (chance != 100 && chance != 0)
158 if (!ExplicitlyChanced.empty())
162 for (
uint32 i = 0; i < ExplicitlyChanced.size(); ++i)
164 roll -= ExplicitlyChanced[i].chance;
167 if (roll < 0 && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.
IsActiveObject<T>(ExplicitlyChanced[i].guid)))
168 return &ExplicitlyChanced[i];
171 if (!EqualChanced.empty())
176 if (EqualChanced[index].guid == triggerFrom || !spawns.
IsActiveObject<T>(EqualChanced[index].guid))
177 return &EqualChanced[index];
189 for (
size_t i = 0; i < EqualChanced.size(); ++i)
194 if (!guid || EqualChanced[i].guid == guid)
196 Despawn1Object(EqualChanced[i].guid);
202 for (
size_t i = 0; i < ExplicitlyChanced.size(); ++i)
207 if (!guid || ExplicitlyChanced[i].guid == guid)
209 Despawn1Object(ExplicitlyChanced[i].guid);
210 spawns.
RemoveObject<T>(ExplicitlyChanced[i].guid, poolId);
222 sObjectMgr.RemoveCreatureFromGrid(guid, data);
225 pCreature->AddObjectToRemoveList();
235 sObjectMgr.RemoveGameobjectFromGrid(guid, data);
238 pGameobject->AddObjectToRemoveList();
246 sPoolMgr.DespawnPool(child_pool_id);
256 for (PooledQuestRelation::iterator itr = qr.first; itr != qr.second; ++itr)
258 QuestRelations::iterator qitr = questMap->find(itr->second);
259 if (qitr == questMap->end())
261 QuestRelations::iterator lastElement = questMap->upper_bound(itr->second);
262 for (; qitr != lastElement; ++qitr)
264 if (qitr->first == itr->second && qitr->second == itr->first)
266 questMap->erase(qitr);
273 questMap =
sObjectMgr.GetGOQuestRelationMap();
274 qr =
sPoolMgr.mQuestGORelation.equal_range(quest_id);
275 for (PooledQuestRelation::iterator itr = qr.first; itr != qr.second; ++itr)
277 QuestRelations::iterator qitr = questMap->find(itr->second);
278 if (qitr == questMap->end())
280 QuestRelations::iterator lastElement = questMap->upper_bound(itr->second);
281 for (; qitr != lastElement; ++qitr)
283 if (qitr->first == itr->second && qitr->second == itr->first)
285 questMap->erase(qitr);
296 for (PoolObjectList::iterator itr = ExplicitlyChanced.begin(); itr != ExplicitlyChanced.end(); ++itr)
298 if (itr->guid == child_pool_id)
300 ExplicitlyChanced.erase(itr);
304 for (PoolObjectList::iterator itr = EqualChanced.begin(); itr != EqualChanced.end(); ++itr)
306 if (itr->guid == child_pool_id)
308 EqualChanced.erase(itr);
381 for (PooledQuestRelation::iterator itr = qr.first; itr != qr.second; ++itr)
383 sLog.outDebug(
"PoolGroup<Quest>: Adding quest %u to creature %u", itr->first, itr->second);
384 questMap->insert(QuestRelations::value_type(itr->second, itr->first));
388 questMap =
sObjectMgr.GetGOQuestRelationMap();
390 for (PooledQuestRelation::iterator itr = qr.first; itr != qr.second; ++itr)
392 sLog.outDebug(
"PoolGroup<Quest>: Adding quest %u to GO %u", itr->first, itr->second);
393 questMap->insert(QuestRelations::value_type(itr->second, itr->first));
422 sLog.outDebug(
"PoolGroup<Quest>: Spawning pool %u", poolId);
431 uint32 questId = result->Fetch()[0].GetUInt32();
434 Spawn1Object(&tempObj);
436 }
while (result->NextRow() && limit);
444 for (PoolObjectList::iterator itr = EqualChanced.begin(); itr != EqualChanced.end(); ++itr)
448 newQuests.insert(itr->guid);
452 DespawnObject(spawns);
455 if (limit > newQuests.size() && !currentQuests.empty())
460 newQuests.insert(questId);
461 currentQuests.erase(questId);
462 }
while (newQuests.size() < limit && !currentQuests.empty());
465 if (newQuests.empty())
474 Spawn1Object(&tempObj);
475 newQuests.erase(questId);
477 }
while (limit && !newQuests.empty());
498 for (
int i = 0; i < count; ++i)
500 PoolObject* obj = RollOne(spawns, triggerFrom);
503 if (obj->
guid == lastDespawned)
506 if (obj->
guid == triggerFrom)
518 DespawnObject(spawns, triggerFrom);
519 lastDespawned = triggerFrom;
535 sLog.outString(
">> Loaded 0 object pools. DB table `pool_template` is empty.");
540 Field* fields = result->Fetch();
541 max_pool_id = fields[0].GetUInt32();
544 mPoolTemplate.resize(max_pool_id + 1);
549 mPoolTemplate.clear();
550 sLog.outString(
">> Loaded 0 object pools. DB table `pool_template` is empty.");
559 Field* fields = result->Fetch();
561 uint32 pool_id = fields[0].GetUInt32();
564 pPoolTemplate.
MaxLimit = fields[1].GetUInt32();
567 while (result->NextRow());
569 sLog.outString(
">> Loaded %u objects pools", count);
572 mPoolCreatureGroups.resize(max_pool_id + 1);
573 mCreatureSearchMap.clear();
580 sLog.outString(
">> Loaded 0 creatures in pools. DB table `pool_creature` is empty.");
586 Field* fields = result->Fetch();
589 uint32 guid = fields[0].GetUInt32();
590 uint32 pool_id = fields[1].GetUInt32();
591 float chance = fields[2].GetFloat();
596 sLog.outErrorDb(
"`pool_creature` has a non existing creature spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id);
599 if (pool_id > max_pool_id)
601 sLog.outErrorDb(
"`pool_creature` pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.", pool_id);
604 if (chance < 0 || chance > 100)
606 sLog.outErrorDb(
"`pool_creature` has an invalid chance (%f) for creature guid (%u) in pool id (%i), skipped.", chance, guid, pool_id);
617 mCreatureSearchMap.insert(p);
620 while (result->NextRow());
621 sLog.outString(
">> Loaded %u creatures in pools", count);
625 mPoolGameobjectGroups.resize(max_pool_id + 1);
626 mGameobjectSearchMap.clear();
632 sLog.outString(
">> Loaded 0 gameobjects in pools. DB table `pool_gameobject` is empty.");
637 Field* fields = result->Fetch();
639 uint32 guid = fields[0].GetUInt32();
640 uint32 pool_id = fields[1].GetUInt32();
641 float chance = fields[2].GetFloat();
646 sLog.outErrorDb(
"`pool_gameobject` has a non existing gameobject spawn (GUID: %u) defined for pool id (%u), skipped.", guid, pool_id);
654 sLog.outErrorDb(
"`pool_gameobject` has a not lootable gameobject spawn (GUID: %u, type: %u) defined for pool id (%u), skipped.", guid, goinfo->
type, pool_id);
657 if (pool_id > max_pool_id)
659 sLog.outErrorDb(
"`pool_gameobject` pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.", pool_id);
662 if (chance < 0 || chance > 100)
664 sLog.outErrorDb(
"`pool_gameobject` has an invalid chance (%f) for gameobject guid (%u) in pool id (%i), skipped.", chance, guid, pool_id);
676 mGameobjectSearchMap.insert(p);
679 while (result->NextRow());
680 sLog.outString(
">> Loaded %u gameobject in pools", count);
684 mPoolPoolGroups.resize(max_pool_id + 1);
690 sLog.outString(
">> Loaded 0 pools in pools");
695 Field* fields = result->Fetch();
697 uint32 child_pool_id = fields[0].GetUInt32();
698 uint32 mother_pool_id = fields[1].GetUInt32();
699 float chance = fields[2].GetFloat();
701 if (mother_pool_id > max_pool_id)
703 sLog.outErrorDb(
"`pool_pool` mother_pool id (%i) is out of range compared to max pool id in `pool_template`, skipped.", mother_pool_id);
706 if (child_pool_id > max_pool_id)
708 sLog.outErrorDb(
"`pool_pool` included pool_id (%i) is out of range compared to max pool id in `pool_template`, skipped.", child_pool_id);
711 if (mother_pool_id == child_pool_id)
713 sLog.outErrorDb(
"`pool_pool` pool_id (%i) includes itself, dead-lock detected, skipped.", child_pool_id);
716 if (chance < 0 || chance > 100)
718 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);
730 mPoolSearchMap.insert(p);
732 }
while (result->NextRow());
735 for (
uint32 i = 0; i < max_pool_id; ++i)
737 std::set<uint32> checkedPools;
738 for (SearchMap::iterator poolItr = mPoolSearchMap.find(i); poolItr != mPoolSearchMap.end(); poolItr = mPoolSearchMap.find(poolItr->second))
740 checkedPools.insert(poolItr->first);
741 if (checkedPools.find(poolItr->second) != checkedPools.end())
743 std::ostringstream ss;
744 ss <<
"The pool(s) ";
745 for (std::set<uint32>::const_iterator itr = checkedPools.begin(); itr != checkedPools.end(); ++itr)
747 ss <<
"create(s) a circular reference, which can cause the server to freeze.\nRemoving the last link between mother pool " 748 << poolItr->first <<
" and child pool " << poolItr->second;
749 sLog.outErrorDb(
"%s", ss.str().c_str());
750 mPoolPoolGroups[poolItr->second].RemoveOneRelation(poolItr->first);
751 mPoolSearchMap.erase(poolItr);
758 sLog.outString(
">> Loaded %u pools in mother pools", count);
766 mQuestSearchMap.clear();
767 mPoolQuestGroups.resize(max_pool_id + 1);
772 sLog.outString(
">> Loaded 0 quests in pools");
785 std::map<uint32, int32> poolTypeMap;
789 Field* fields = result->Fetch();
792 uint32 entry = fields[0].GetUInt32();
793 uint32 pool_id = fields[1].GetUInt32();
798 sLog.outErrorDb(
"`pool_quest` has a non existing quest template (Entry: %u) defined for pool id (%u), skipped.", entry, pool_id);
802 if (pool_id > max_pool_id)
804 sLog.outErrorDb(
"`pool_quest` pool id (%u) is out of range compared to max pool id in `pool_template`, skipped.", pool_id);
810 sLog.outErrorDb(
"`pool_quest` has an quest (%u) which is not daily or weekly in pool id (%u), use ExclusiveGroup instead, skipped.", entry, pool_id);
814 if (poolTypeMap[pool_id] == QUEST_NONE)
815 poolTypeMap[pool_id] = pQuest->
IsDaily() ? QUEST_DAILY : QUEST_NONE;
817 int32 currType = pQuest->
IsDaily() ? QUEST_DAILY : QUEST_NONE;
819 if (poolTypeMap[pool_id] != currType)
821 sLog.outErrorDb(
"`pool_quest` quest %u is %s but pool (%u) is specified for %s, mixing not allowed, skipped.", entry, currType == QUEST_DAILY ?
"QUEST_DAILY" :
"QUEST_NONE", pool_id, poolTypeMap[pool_id] == QUEST_DAILY ?
"QUEST_DAILY" :
"QUEST_NONE");
825 creBounds = mQuestCreatureRelation.equal_range(entry);
826 goBounds = mQuestGORelation.equal_range(entry);
828 if (creBounds.first == creBounds.second && goBounds.first == goBounds.second)
830 sLog.outErrorDb(
"`pool_quest` lists entry (%u) as member of pool (%u) but is not started anywhere, skipped.", entry, pool_id);
843 mQuestSearchMap.insert(p);
845 }
while (result->NextRow());
847 sLog.outString(
">> Loaded %u quests in pools", count);
853 QueryResult_AutoPtr result =
WorldDatabase.
Query(
"SELECT DISTINCT pool_template.entry, pool_pool.pool_id, pool_pool.mother_pool 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");
859 Field* fields = result->Fetch();
860 uint32 pool_entry = fields[0].GetUInt32();
861 uint32 pool_pool_id = fields[1].GetUInt32();
862 if (!CheckPool(pool_entry))
876 SpawnPool(pool_entry);
880 while (result->NextRow());
883 sLog.outBasic(
"Pool handling system initialized, %u pools spawned.", count);
889 std::ostringstream query;
890 query <<
"DELETE FROM pool_quest_save WHERE pool_id IN (";
892 for (PoolGroupQuestMap::iterator itr = mPoolQuestGroups.begin(); itr != mPoolQuestGroups.end(); ++itr)
894 if (itr->GetPoolId() != 0)
899 query << itr->GetPoolId();
909 query.rdbuf()->str(
"");
910 query <<
"INSERT INTO pool_quest_save (pool_id, quest_id) VALUES ";
911 for (SearchMap::iterator itr = mQuestSearchMap.begin(); itr != mQuestSearchMap.end(); ++itr)
913 if (IsSpawnedObject<Quest>(itr->first))
918 query <<
"(" << itr->second <<
"," << itr->first <<
")";
930 for (PoolGroupQuestMap::iterator itr = mPoolQuestGroups.begin(); itr != mPoolQuestGroups.end(); ++itr)
932 if (
sObjectMgr.GetQuestTemplate(itr->GetFirstEqualChancedObjectId()))
934 UpdatePool<Quest>(itr->GetPoolId(), 1);
946 if (!mPoolCreatureGroups[pool_id].isEmpty())
947 mPoolCreatureGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid);
955 if (!mPoolGameobjectGroups[pool_id].isEmpty())
956 mPoolGameobjectGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, db_guid);
964 if (!mPoolPoolGroups[pool_id].isEmpty())
965 mPoolPoolGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, sub_pool_id);
972 if (!mPoolQuestGroups[pool_id].isEmpty())
973 mPoolQuestGroups[pool_id].SpawnObject(mSpawnedData, mPoolTemplate[pool_id].MaxLimit, quest_id);
978 SpawnPool<Pool>(pool_id, 0);
979 SpawnPool<GameObject>(pool_id, 0);
980 SpawnPool<Creature>(pool_id, 0);
981 SpawnPool<Quest>(pool_id, 0);
987 if (!mPoolCreatureGroups[pool_id].isEmpty())
988 mPoolCreatureGroups[pool_id].DespawnObject(mSpawnedData);
990 if (!mPoolGameobjectGroups[pool_id].isEmpty())
991 mPoolGameobjectGroups[pool_id].DespawnObject(mSpawnedData);
993 if (!mPoolPoolGroups[pool_id].isEmpty())
994 mPoolPoolGroups[pool_id].DespawnObject(mSpawnedData);
996 if (!mPoolQuestGroups[pool_id].isEmpty())
997 mPoolQuestGroups[pool_id].DespawnObject(mSpawnedData);
1003 return pool_id <= max_pool_id &&
1004 mPoolGameobjectGroups[pool_id].CheckPool() &&
1005 mPoolCreatureGroups[pool_id].CheckPool() &&
1006 mPoolPoolGroups[pool_id].CheckPool() &&
1007 mPoolQuestGroups[pool_id].CheckPool();
1013 template<
typename T>
1016 if (
uint32 motherpoolid = IsPartOfAPool<Pool>(pool_id))
1017 SpawnPool<Pool>(motherpoolid, pool_id);
1019 SpawnPool<T>(pool_id, db_guid_or_pool_id);
1022 template void PoolMgr::UpdatePool<Pool>(
uint32 pool_id,
uint32 db_guid_or_pool_id);
1023 template void PoolMgr::UpdatePool<GameObject>(
uint32 pool_id,
uint32 db_guid_or_pool_id);
1024 template void PoolMgr::UpdatePool<Creature>(
uint32 pool_id,
uint32 db_guid_or_pool_id);
1025 template void PoolMgr::UpdatePool<Quest>(
uint32 pool_id,
uint32 db_guid_or_pool_id);
void ReSpawn1Object(PoolObject *obj)
bool LoadCreatureFromDB(uint32 guid, Map *map, bool addToMap=true)
void Despawn1Object(uint32 guid)
DatabaseType WorldDatabase
Accessor to the world database.
std::pair< PooledQuestRelation::iterator, PooledQuestRelation::iterator > PooledQuestRelationBoundsNC
QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2
bool IsActiveObject(uint32 db_guid_or_pool_id) const
#define sLog
Log class singleton.
void SpawnObject(ActivePoolData &spawns, uint32 limit, uint32 triggerFrom)
QueryResult_AutoPtr Query(const char *sql)
bool IsGridLoaded(float x, float y) const
std::pair< uint32, uint32 > SearchPair
static ObjectAccessor & Instance()
Map const * CreateBaseMap(uint32 id) const
void UpdatePool(uint32 pool_id, uint32 db_guid_or_pool_id)
ActivePoolObjects mSpawnedCreatures
std::multimap< uint32, uint32 > QuestRelations
void RemoveObject(uint32 db_guid_or_pool_id, uint32 pool_id)
void Spawn1Object(PoolObject *obj)
INSTANTIATE_SINGLETON_1(PoolMgr)
#define MAKE_NEW_GUID(l, e, h)
void RemoveOneRelation(uint32 child_pool_id)
void AddEntry(PoolObject &poolitem, uint32 maxentries)
PoolObject * RollOne(ActivePoolData &spawns, uint32 triggerFrom)
bool PExecute(const char *format,...) ATTR_PRINTF(2
void DespawnObject(ActivePoolData &spawns, uint32 guid=0)
ActivePoolPools mSpawnedPools
ActivePoolObjects mSpawnedGameobjects
uint32 GetActiveObjectCount(uint32 pool_id) const
ActivePoolObjects mActiveQuests
void ActivateObject(uint32 db_guid_or_pool_id, uint32 pool_id)
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
std::pair< PooledQuestRelation::const_iterator, PooledQuestRelation::const_iterator > PooledQuestRelationBounds
bool Instanceable() const
void SpawnPool(uint32 pool_id)
void DespawnPool(uint32 pool_id)
DatabaseType CharacterDatabase
Accessor to the character database.
bool isSpawnedByDefault() const
ActivePoolObjects GetActiveQuests() const
void SetPoolId(uint32 pool_id)
bool CheckPool(uint32 pool_id) const
C::value_type const & SelectRandomContainerElement(C const &container)
std::set< uint32 > ActivePoolObjects
bool LoadGameObjectFromDB(uint32 guid, Map *map, bool addToMap=true)
uint32 urand(uint32 min, uint32 max)