diff options
Diffstat (limited to 'src/server/game/Maps/Map.cpp')
-rw-r--r-- | src/server/game/Maps/Map.cpp | 109 |
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); |