diff options
author | pete318 <pete318@users.noreply.github.com> | 2016-02-03 12:34:38 +0000 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-04-02 17:51:03 +0200 |
commit | 2fe84d7471f8f5e521ca77825e63b9cff92ba1dc (patch) | |
tree | 625360ea6e70d6d5c394d6579155c070dfe31dba | |
parent | 0a8bab885ac7c1efd5f67619998502a3a8be4c62 (diff) |
Prevent duplicate spawns for same spawn ID
If there is an alive instance of the creature upon creature spawn, skip
spawn entirely. If there are only dead instances, despawn them. A new dead
corpse in the creatures home position will be respawned.
Closes: #16462
(cherry picked from commit fe2a0fda4464effeb2fb655da84a0460328b1aeb)
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 2 |
2 files changed, 32 insertions, 2 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index d75d0ab0fd4..9a6e118351a 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1318,8 +1318,38 @@ bool Creature::CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, Creatu return true; } -bool Creature::LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap) +bool Creature::LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool allowDuplicate) { + if (!allowDuplicate) + { + // If an alive instance of this spawnId is already found, skip creation + // If only dead instance(s) exist, despawn them and spawn a new (maybe also dead) version + const auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(spawnId); + std::vector <Creature*> despawnList; + + if (creatureBounds.first != creatureBounds.second) + { + for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr) + { + if (itr->second->IsAlive()) + { + TC_LOG_DEBUG("maps", "Would have spawned %u but %s already exists", spawnId, creatureBounds.first->second->GetGUID().ToString().c_str()); + return false; + } + else + { + despawnList.push_back(itr->second); + TC_LOG_DEBUG("maps", "Despawned dead instance of spawn %u (%s)", spawnId, itr->second->GetGUID().ToString().c_str()); + } + } + + for (Creature* despawnCreature : despawnList) + { + despawnCreature->AddObjectToRemoveList(); + } + } + } + CreatureData const* data = sObjectMgr->GetCreatureData(spawnId); if (!data) { diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 54e472a56d3..9103f864e3d 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -568,7 +568,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma void setDeathState(DeathState s) override; // override virtual Unit::setDeathState bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map) { return LoadCreatureFromDB(spawnId, map, false); } - bool LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap = true); + bool LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap = true, bool allowDuplicate = false); void SaveToDB(); // overriden in Pet virtual void SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask); |