mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Maps: move pooling hand-off outside of Map::CheckRespawn (PR#25785)
fixes #25777
This commit is contained in:
@@ -3036,47 +3036,42 @@ bool Map::CheckRespawn(RespawnInfo* info)
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 poolId = info->spawnId ? sPoolMgr->IsPartOfAPool(info->type, info->spawnId) : 0;
|
||||
// Next, check if there's already an instance of this object that would block the respawn
|
||||
// Only do this for unpooled spawns
|
||||
if (!poolId)
|
||||
bool alreadyExists = false;
|
||||
switch (info->type)
|
||||
{
|
||||
bool doDelete = false;
|
||||
switch (info->type)
|
||||
case SPAWN_TYPE_CREATURE:
|
||||
{
|
||||
case SPAWN_TYPE_CREATURE:
|
||||
{
|
||||
// escort check for creatures only (if the world config boolean is set)
|
||||
bool const isEscort = (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && data->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC);
|
||||
// escort check for creatures only (if the world config boolean is set)
|
||||
bool const isEscort = (sWorld->getBoolConfig(CONFIG_RESPAWN_DYNAMIC_ESCORTNPC) && data->spawnGroupData->flags & SPAWNGROUP_FLAG_ESCORTQUESTNPC);
|
||||
|
||||
auto range = _creatureBySpawnIdStore.equal_range(info->spawnId);
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
Creature* creature = it->second;
|
||||
if (!creature->IsAlive())
|
||||
continue;
|
||||
// escort NPCs are allowed to respawn as long as all other instances are already escorting
|
||||
if (isEscort && creature->IsEscorted())
|
||||
continue;
|
||||
doDelete = true;
|
||||
break;
|
||||
}
|
||||
auto range = _creatureBySpawnIdStore.equal_range(info->spawnId);
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
Creature* creature = it->second;
|
||||
if (!creature->IsAlive())
|
||||
continue;
|
||||
// escort NPCs are allowed to respawn as long as all other instances are already escorting
|
||||
if (isEscort && creature->IsEscorted())
|
||||
continue;
|
||||
alreadyExists = true;
|
||||
break;
|
||||
}
|
||||
case SPAWN_TYPE_GAMEOBJECT:
|
||||
// gameobject check is simpler - they cannot be dead or escorting
|
||||
if (_gameobjectBySpawnIdStore.find(info->spawnId) != _gameobjectBySpawnIdStore.end())
|
||||
doDelete = true;
|
||||
break;
|
||||
default:
|
||||
ABORT_MSG("Invalid spawn type %u with spawnId %u on map %u", uint32(info->type), info->spawnId, GetId());
|
||||
return true;
|
||||
}
|
||||
if (doDelete)
|
||||
{
|
||||
info->respawnTime = 0;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case SPAWN_TYPE_GAMEOBJECT:
|
||||
// gameobject check is simpler - they cannot be dead or escorting
|
||||
if (_gameobjectBySpawnIdStore.find(info->spawnId) != _gameobjectBySpawnIdStore.end())
|
||||
alreadyExists = true;
|
||||
break;
|
||||
default:
|
||||
ABORT_MSG("Invalid spawn type %u with spawnId %u on map %u", uint32(info->type), info->spawnId, GetId());
|
||||
return true;
|
||||
}
|
||||
if (alreadyExists)
|
||||
{
|
||||
info->respawnTime = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// next, check linked respawn time
|
||||
@@ -3094,21 +3089,6 @@ bool Map::CheckRespawn(RespawnInfo* info)
|
||||
info->respawnTime = respawnTime;
|
||||
return false;
|
||||
}
|
||||
|
||||
// now, check if we're part of a pool
|
||||
if (poolId)
|
||||
{
|
||||
// ok, part of a pool - hand off to pool logic to handle this, we're just going to remove the respawn and call it a day
|
||||
if (info->type == SPAWN_TYPE_GAMEOBJECT)
|
||||
sPoolMgr->UpdatePool<GameObject>(poolId, info->spawnId);
|
||||
else if (info->type == SPAWN_TYPE_CREATURE)
|
||||
sPoolMgr->UpdatePool<Creature>(poolId, info->spawnId);
|
||||
else
|
||||
ABORT_MSG("Invalid spawn type %u (spawnid %u) on map %u", uint32(info->type), info->spawnId, GetId());
|
||||
info->respawnTime = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// everything ok, let's spawn
|
||||
return true;
|
||||
}
|
||||
@@ -3275,22 +3255,39 @@ void Map::ProcessRespawns()
|
||||
RespawnInfo* next = _respawnTimes.top();
|
||||
if (now < next->respawnTime) // done for this tick
|
||||
break;
|
||||
if (CheckRespawn(next)) // see if we're allowed to respawn
|
||||
{
|
||||
// ok, respawn
|
||||
|
||||
if (uint32 poolId = sPoolMgr->IsPartOfAPool(next->type, next->spawnId)) // is this part of a pool?
|
||||
{ // if yes, respawn will be handled by (external) pooling logic, just delete the respawn time
|
||||
// step 1: remove entry from maps to avoid it being reachable by outside logic
|
||||
_respawnTimes.pop();
|
||||
GetRespawnMapForType(next->type).erase(next->spawnId);
|
||||
|
||||
// step 2: tell pooling logic to do its thing
|
||||
sPoolMgr->UpdatePool(poolId, next->type, next->spawnId);
|
||||
|
||||
// step 3: get rid of the actual entry
|
||||
delete next;
|
||||
}
|
||||
else if (CheckRespawn(next)) // see if we're allowed to respawn
|
||||
{ // ok, respawn
|
||||
// step 1: remove entry from maps to avoid it being reachable by outside logic
|
||||
_respawnTimes.pop();
|
||||
GetRespawnMapForType(next->type).erase(next->spawnId);
|
||||
|
||||
// step 2: do the respawn, which involves external logic
|
||||
DoRespawn(next->type, next->spawnId, next->gridId);
|
||||
|
||||
// step 3: get rid of the actual entry
|
||||
delete next;
|
||||
}
|
||||
else if (!next->respawnTime) // just remove respawn entry without rescheduling
|
||||
{
|
||||
else if (!next->respawnTime)
|
||||
{ // just remove this respawn entry without rescheduling
|
||||
_respawnTimes.pop();
|
||||
GetRespawnMapForType(next->type).erase(next->spawnId);
|
||||
delete next;
|
||||
}
|
||||
else // value changed, update heap position
|
||||
{
|
||||
else
|
||||
{ // new respawn time, update heap position
|
||||
ASSERT(now < next->respawnTime); // infinite loop guard
|
||||
_respawnTimes.decrease(next->handle);
|
||||
SaveRespawnInfoDB(*next);
|
||||
|
||||
@@ -845,3 +845,18 @@ void PoolMgr::UpdatePool(uint32 pool_id, uint32 db_guid_or_pool_id)
|
||||
template void PoolMgr::UpdatePool<Pool>(uint32 pool_id, uint32 db_guid_or_pool_id);
|
||||
template void PoolMgr::UpdatePool<GameObject>(uint32 pool_id, uint32 db_guid_or_pool_id);
|
||||
template void PoolMgr::UpdatePool<Creature>(uint32 pool_id, uint32 db_guid_or_pool_id);
|
||||
|
||||
void PoolMgr::UpdatePool(uint32 pool_id, SpawnObjectType type, uint32 spawnId)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SPAWN_TYPE_CREATURE:
|
||||
UpdatePool<Creature>(pool_id, spawnId);
|
||||
break;
|
||||
case SPAWN_TYPE_GAMEOBJECT:
|
||||
UpdatePool<GameObject>(pool_id, spawnId);
|
||||
break;
|
||||
default:
|
||||
ABORT_MSG("Invalid spawn type %u passed to PoolMgr::IsPartOfPool (with spawnId %u)", uint32(type), spawnId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ class TC_GAME_API PoolMgr
|
||||
|
||||
template<typename T>
|
||||
void UpdatePool(uint32 pool_id, uint32 db_guid_or_pool_id);
|
||||
void UpdatePool(uint32 pool_id, SpawnObjectType type, ObjectGuid::LowType spawnId);
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
|
||||
Reference in New Issue
Block a user