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.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 6c3794d16db..79136e3f663 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -3603,6 +3603,148 @@ void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::Low
respawnDelay = std::max<uint32>(ceil(respawnDelay * adjustFactor), timeMinimum);
}
+SpawnGroupTemplateData const* Map::GetSpawnGroupData(uint32 groupId) const
+{
+ SpawnGroupTemplateData const* data = sObjectMgr->GetSpawnGroupData(groupId);
+ if (data && data->mapId == GetId())
+ return data;
+ return nullptr;
+}
+
+bool Map::SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn, bool force, std::vector<WorldObject*>* spawnedObjects)
+{
+ SpawnGroupTemplateData const* groupData = GetSpawnGroupData(groupId);
+ if (!groupData || groupData->flags & SPAWNGROUP_FLAG_SYSTEM)
+ {
+ TC_LOG_ERROR("maps", "Tried to spawn non-existing (or system) spawn group %u on map %u. Blocked.", groupId, GetId());
+ return false;
+ }
+
+ for (auto& pair : sObjectMgr->GetSpawnDataForGroup(groupId))
+ {
+ SpawnData const* data = pair.second;
+ ASSERT(groupData->mapId == data->spawnPoint.GetMapId());
+ // Check if there's already an instance spawned
+ if (!force)
+ if (WorldObject* obj = GetWorldObjectBySpawnId(data->type, data->spawnId))
+ if ((data->type != SPAWN_TYPE_CREATURE) || obj->ToCreature()->IsAlive())
+ continue;
+
+ time_t respawnTime = GetRespawnTime(data->type, data->spawnId);
+ if (respawnTime && respawnTime > time(NULL))
+ {
+ if (!force && !ignoreRespawn)
+ continue;
+
+ // we need to remove the respawn time, otherwise we'd end up double spawning
+ RemoveRespawnTime(data->type, data->spawnId, false);
+ }
+
+ // don't spawn if the grid isn't loaded (will be handled in grid loader)
+ if (!IsGridLoaded(data->spawnPoint))
+ continue;
+
+ // Everything OK, now do the actual (re)spawn
+ switch (data->type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ {
+ Creature* creature = new Creature();
+ if (!creature->LoadFromDB(data->spawnId, this, true, force))
+ delete creature;
+ else if (spawnedObjects)
+ spawnedObjects->push_back(creature);
+ break;
+ }
+ case SPAWN_TYPE_GAMEOBJECT:
+ {
+ GameObject* gameobject = new GameObject();
+ if (!gameobject->LoadFromDB(data->spawnId, this, true))
+ delete gameobject;
+ else if (spawnedObjects)
+ spawnedObjects->push_back(gameobject);
+ break;
+ }
+ default:
+ ASSERT(false, "Invalid spawn type %u with spawnId " UI64FMTD, uint32(data->type), data->spawnId);
+ return false;
+ }
+ }
+ SetSpawnGroupActive(groupId, true); // start processing respawns for the group
+ return true;
+}
+
+bool Map::SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes)
+{
+ SpawnGroupTemplateData const* groupData = GetSpawnGroupData(groupId);
+ if (!groupData || groupData->flags & SPAWNGROUP_FLAG_SYSTEM)
+ {
+ TC_LOG_ERROR("maps", "Tried to despawn non-existing (or system) spawn group %u on map %u. Blocked.", groupId, GetId());
+ return false;
+ }
+
+ std::vector<WorldObject*> toUnload; // unload after iterating, otherwise iterator invalidation
+ for (auto const& pair : sObjectMgr->GetSpawnDataForGroup(groupId))
+ {
+ SpawnData const* data = pair.second;
+ ASSERT(groupData->mapId == data->spawnPoint.GetMapId());
+ if (deleteRespawnTimes)
+ RemoveRespawnTime(data->type, data->spawnId);
+ switch (data->type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ {
+ auto bounds = GetCreatureBySpawnIdStore().equal_range(data->spawnId);
+ for (auto it = bounds.first; it != bounds.second; ++it)
+ toUnload.emplace_back(it->second);
+ break;
+ }
+ case SPAWN_TYPE_GAMEOBJECT:
+ {
+ auto bounds = GetGameObjectBySpawnIdStore().equal_range(data->spawnId);
+ for (auto it = bounds.first; it != bounds.second; ++it)
+ toUnload.emplace_back(it->second);
+ break;
+ }
+ default:
+ ASSERT(false, "Invalid spawn type %u in spawn data with spawnId " UI64FMTD ".", uint32(data->type), data->spawnId);
+ return false;
+ }
+ }
+ // now do the actual despawning
+ for (WorldObject* obj : toUnload)
+ obj->AddObjectToRemoveList();
+ SetSpawnGroupActive(groupId, false); // stop processing respawns for the group, too
+ return true;
+}
+
+void Map::SetSpawnGroupActive(uint32 groupId, bool state)
+{
+ SpawnGroupTemplateData const* const data = GetSpawnGroupData(groupId);
+ if (!data || data->flags & SPAWNGROUP_FLAG_SYSTEM)
+ {
+ TC_LOG_ERROR("maps", "Tried to set non-existing (or system) spawn group %u to %s on map %u. Blocked.", groupId, state ? "active" : "inactive", GetId());
+ return;
+ }
+ if (state != !(data->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN)) // toggled
+ _toggledSpawnGroupIds.insert(groupId);
+ else
+ _toggledSpawnGroupIds.erase(groupId);
+}
+
+bool Map::IsSpawnGroupActive(uint32 groupId) const
+{
+ SpawnGroupTemplateData const* const data = GetSpawnGroupData(groupId);
+ if (!data)
+ {
+ TC_LOG_WARN("maps", "Tried to query state of non-existing spawn group %u on map %u.", groupId, GetId());
+ return false;
+ }
+ if (data->flags & SPAWNGROUP_FLAG_SYSTEM)
+ return true;
+ return (_toggledSpawnGroupIds.find(groupId) != _toggledSpawnGroupIds.end()) != !(data->flags & SPAWNGROUP_FLAG_MANUAL_SPAWN);
+}
+
void Map::DelayedUpdate(uint32 t_diff)
{
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)