aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Maps/Map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Maps/Map.cpp')
-rw-r--r--src/server/game/Maps/Map.cpp109
1 files changed, 53 insertions, 56 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 8e8fcbe2d55..61e5144f7e6 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -3159,47 +3159,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 " UI64FMTD " 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 " UI64FMTD " on map %u", uint32(info->type), info->spawnId, GetId());
+ return true;
+ }
+ if (alreadyExists)
+ {
+ info->respawnTime = 0;
+ return false;
}
// next, check linked respawn time
@@ -3219,21 +3214,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 " UI64FMTD ") on map %u", uint32(info->type), info->spawnId, GetId());
- info->respawnTime = 0;
- return false;
- }
-
// everything ok, let's spawn
return true;
}
@@ -3407,22 +3387,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();
ASSERT_NOTNULL(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();
+ ASSERT_NOTNULL(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();
ASSERT_NOTNULL(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);