diff options
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 2 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Events/GameEventMgr.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 98 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 52 | ||||
-rw-r--r-- | src/server/game/Grids/ObjectGridLoader.cpp | 50 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 229 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 11 | ||||
-rw-r--r-- | src/server/game/Maps/MapManager.h | 7 | ||||
-rw-r--r-- | src/server/game/Maps/SpawnData.h | 46 | ||||
-rw-r--r-- | src/server/game/Pools/PoolMgr.cpp | 8 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_go.cpp | 34 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_list.cpp | 30 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_npc.cpp | 2 | ||||
-rw-r--r-- | src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp | 4 |
16 files changed, 331 insertions, 271 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 0e76a98d8a0..0cc0c86eca1 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1324,9 +1324,15 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) data.displayid = displayId; data.equipmentId = GetCurrentEquipmentId(); if (!GetTransport()) - data.spawnPoint.WorldRelocate(this); + { + data.mapId = GetMapId(); + data.spawnPoint.Relocate(this); + } else - data.spawnPoint.WorldRelocate(mapid, GetTransOffsetX(), GetTransOffsetY(), GetTransOffsetZ(), GetTransOffsetO()); + { + data.mapId = mapid; + data.spawnPoint.Relocate(GetTransOffsetX(), GetTransOffsetY(), GetTransOffsetZ(), GetTransOffsetO()); + } data.spawntimesecs = m_respawnDelay; // prevent add data integrity problems data.spawndist = GetDefaultMovementType() == IDLE_MOTION_TYPE ? 0.0f : m_respawnradius; @@ -1733,7 +1739,7 @@ bool Creature::hasInvolvedQuest(uint32 quest_id) const SQLTransaction trans = CharacterDatabase.BeginTransaction(); - sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), + sMapMgr->DoForAllMapsWithMapId(data->mapId, [spawnId, trans](Map* map) -> void { // despawn all active creatures, and remove their respawns diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 5d485774f20..84aea18e5b3 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -82,7 +82,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma void Update(uint32 time) override; // overwrited Unit::Update void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr, float* dist = nullptr) const; - bool IsSpawnedOnTransport() const { return m_creatureData && m_creatureData->spawnPoint.GetMapId() != GetMapId(); } + bool IsSpawnedOnTransport() const { return m_creatureData && m_creatureData->mapId != GetMapId(); } void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } uint32 GetCorpseDelay() const { return m_corpseDelay; } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index c5f41bae2e6..610c1730964 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -998,7 +998,8 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) data.spawnId = m_spawnId; ASSERT(data.spawnId == m_spawnId); data.id = GetEntry(); - data.spawnPoint.WorldRelocate(this); + data.mapId = GetMapId(); + data.spawnPoint.Relocate(this); data.phaseMask = phaseMask; data.rotation = m_localRotation; data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime; @@ -1115,7 +1116,7 @@ bool GameObject::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap SQLTransaction trans = CharacterDatabase.BeginTransaction(); - sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), + sMapMgr->DoForAllMapsWithMapId(data->mapId, [spawnId, trans](Map* map) -> void { // despawn all active objects, and remove their respawns diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index 910f740341a..544e8f9bf5f 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -1205,7 +1205,7 @@ void GameEventMgr::UpdateEventNPCFlags(uint16 event_id) for (NPCFlagList::iterator itr = mGameEventNPCFlags[event_id].begin(); itr != mGameEventNPCFlags[event_id].end(); ++itr) // get the creature data from the low guid to get the entry, to be able to find out the whole guid if (CreatureData const* data = sObjectMgr->GetCreatureData(itr->first)) - creaturesByMap[data->spawnPoint.GetMapId()].insert(itr->first); + creaturesByMap[data->mapId].insert(itr->first); for (auto const& p : creaturesByMap) { @@ -1268,7 +1268,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) sObjectMgr->AddCreatureToGrid(*itr, data); // Spawn if necessary (loaded grids only) - Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId()); + Map* map = sMapMgr->CreateBaseMap(data->mapId); map->RemoveRespawnTime(SPAWN_TYPE_CREATURE, *itr); // We use spawn coords to spawn if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint)) @@ -1296,7 +1296,7 @@ void GameEventMgr::GameEventSpawn(int16 event_id) sObjectMgr->AddGameobjectToGrid(*itr, data); // Spawn if necessary (loaded grids only) // this base map checked as non-instanced and then only existed - Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId()); + Map* map = sMapMgr->CreateBaseMap(data->mapId); map->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, *itr); // We use current coords to unspawn, not spawn coords since creature can have changed grid if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint)) @@ -1347,7 +1347,7 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) { sObjectMgr->RemoveCreatureFromGrid(*itr, data); - sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), [&itr](Map* map) + sMapMgr->DoForAllMapsWithMapId(data->mapId, [&itr](Map* map) { map->RemoveRespawnTime(SPAWN_TYPE_CREATURE, *itr); auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(*itr); @@ -1378,7 +1378,7 @@ void GameEventMgr::GameEventUnspawn(int16 event_id) { sObjectMgr->RemoveGameobjectFromGrid(*itr, data); - sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), [&itr](Map* map) + sMapMgr->DoForAllMapsWithMapId(data->mapId, [&itr](Map* map) { map->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, *itr); auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(*itr); @@ -1413,7 +1413,7 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate) continue; // Update if spawned - sMapMgr->DoForAllMapsWithMapId(data->spawnPoint.GetMapId(), [&itr, activate](Map* map) + sMapMgr->DoForAllMapsWithMapId(data->mapId, [&itr, activate](Map* map) { auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(itr->first); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 3ba31cda2cb..5ce5e3bb12f 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1787,8 +1787,8 @@ void ObjectMgr::LoadLinkedRespawn() break; } - MapEntry const* const map = sMapStore.LookupEntry(master->spawnPoint.GetMapId()); - if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId())) + MapEntry const* const map = sMapStore.LookupEntry(master->mapId); + if (!map || !map->Instanceable() || (master->mapId != slave->mapId)) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Creature '%u' linking to Creature '%u' on an unpermitted map.", guidLow, linkedGuidLow); error = true; @@ -1824,8 +1824,8 @@ void ObjectMgr::LoadLinkedRespawn() break; } - MapEntry const* const map = sMapStore.LookupEntry(master->spawnPoint.GetMapId()); - if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId())) + MapEntry const* const map = sMapStore.LookupEntry(master->mapId); + if (!map || !map->Instanceable() || (master->mapId != slave->mapId)) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Creature '%u' linking to Gameobject '%u' on an unpermitted map.", guidLow, linkedGuidLow); error = true; @@ -1861,8 +1861,8 @@ void ObjectMgr::LoadLinkedRespawn() break; } - MapEntry const* const map = sMapStore.LookupEntry(master->spawnPoint.GetMapId()); - if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId())) + MapEntry const* const map = sMapStore.LookupEntry(master->mapId); + if (!map || !map->Instanceable() || (master->mapId != slave->mapId)) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject '%u' linking to Gameobject '%u' on an unpermitted map.", guidLow, linkedGuidLow); error = true; @@ -1898,8 +1898,8 @@ void ObjectMgr::LoadLinkedRespawn() break; } - MapEntry const* const map = sMapStore.LookupEntry(master->spawnPoint.GetMapId()); - if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId())) + MapEntry const* const map = sMapStore.LookupEntry(master->mapId); + if (!map || !map->Instanceable() || (master->mapId != slave->mapId)) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject '%u' linking to Creature '%u' on an unpermitted map.", guidLow, linkedGuidLow); error = true; @@ -1953,8 +1953,8 @@ bool ObjectMgr::SetCreatureLinkedRespawn(ObjectGuid::LowType guidLow, ObjectGuid return false; } - MapEntry const* map = sMapStore.LookupEntry(master->spawnPoint.GetMapId()); - if (!map || !map->Instanceable() || (master->spawnPoint.GetMapId() != slave->spawnPoint.GetMapId())) + MapEntry const* map = sMapStore.LookupEntry(master->mapId); + if (!map || !map->Instanceable() || (master->mapId != slave->mapId)) { TC_LOG_ERROR("sql.sql", "Creature '%u' linking to '%u' on an unpermitted map.", guidLow, linkedGuidLow); return false; @@ -2112,7 +2112,8 @@ void ObjectMgr::LoadCreatures() CreatureData& data = _creatureDataStore[guid]; data.spawnId = guid; data.id = entry; - data.spawnPoint.WorldRelocate(fields[2].GetUInt16(), fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat()); + data.mapId = fields[2].GetUInt16(); + data.spawnPoint.Relocate(fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat()); data.displayid = fields[7].GetUInt32(); data.equipmentId = fields[8].GetInt8(); data.spawntimesecs = fields[9].GetUInt32(); @@ -2129,23 +2130,23 @@ void ObjectMgr::LoadCreatures() data.unit_flags = fields[20].GetUInt32(); data.dynamicflags = fields[21].GetUInt32(); data.scriptId = GetScriptId(fields[22].GetString()); - data.spawnGroupData = &_spawnGroupDataStore[0]; + data.spawnGroupData = GetDefaultSpawnGroup(); - MapEntry const* mapEntry = sMapStore.LookupEntry(data.spawnPoint.GetMapId()); + MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapId); if (!mapEntry) { - TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u) that spawned at nonexistent map (Id: %u), skipped.", guid, data.spawnPoint.GetMapId()); + TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u) that spawned at nonexistent map (Id: %u), skipped.", guid, data.mapId); continue; } // Skip spawnMask check for transport maps - if (!IsTransportMap(data.spawnPoint.GetMapId())) + if (!IsTransportMap(data.mapId)) { - if (data.spawnMask & ~spawnMasks[data.spawnPoint.GetMapId()]) - TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u) that have wrong spawn mask %u including unsupported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.spawnPoint.GetMapId()); + if (data.spawnMask & ~spawnMasks[data.mapId]) + TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u) that have wrong spawn mask %u including unsupported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapId); } else - data.spawnGroupData = &_spawnGroupDataStore[1]; // force compatibility group for transport spawns + data.spawnGroupData = GetLegacySpawnGroup(); // force compatibility group for transport spawns bool ok = true; for (uint32 diff = 0; diff < MAX_DIFFICULTY - 1 && ok; ++diff) @@ -2214,7 +2215,7 @@ void ObjectMgr::LoadCreatures() { uint32 zoneId = 0; uint32 areaId = 0; - sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.spawnPoint); + sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapId, data.spawnPoint); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA); @@ -2242,7 +2243,7 @@ void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* if (mask & 1) { CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->spawnPoint.GetMapId(), i)][cellCoord.GetId()]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapId, i)][cellCoord.GetId()]; cell_guids.creatures.insert(guid); } } @@ -2256,7 +2257,7 @@ void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData co if (mask & 1) { CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->spawnPoint.GetMapId(), i)][cellCoord.GetId()]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapId, i)][cellCoord.GetId()]; cell_guids.creatures.erase(guid); } } @@ -2277,7 +2278,8 @@ ObjectGuid::LowType ObjectMgr::AddGameObjectData(uint32 entry, uint32 mapId, Pos GameObjectData& data = NewOrExistGameObjectData(spawnId); data.spawnId = spawnId; data.id = entry; - data.spawnPoint.WorldRelocate(mapId,pos); + data.mapId = mapId; + data.spawnPoint.Relocate(pos); data.rotation = rot; data.spawntimesecs = spawntimedelay; data.animprogress = 100; @@ -2325,7 +2327,8 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, Posit CreatureData& data = NewOrExistCreatureData(spawnId); data.spawnId = spawnId; data.id = entry; - data.spawnPoint.WorldRelocate(mapId, pos); + data.mapId = mapId; + data.spawnPoint.Relocate(pos); data.displayid = 0; data.equipmentId = 0; data.spawntimesecs = spawntimedelay; @@ -2425,18 +2428,19 @@ void ObjectMgr::LoadGameObjects() data.spawnId = guid; data.id = entry; - data.spawnPoint.WorldRelocate(fields[2].GetUInt16(), fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat()); + data.mapId = fields[2].GetUInt16(); + data.spawnPoint.Relocate(fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat(), fields[6].GetFloat()); data.rotation.x = fields[7].GetFloat(); data.rotation.y = fields[8].GetFloat(); data.rotation.z = fields[9].GetFloat(); data.rotation.w = fields[10].GetFloat(); data.spawntimesecs = fields[11].GetInt32(); - data.spawnGroupData = &_spawnGroupDataStore[0]; + data.spawnGroupData = GetDefaultSpawnGroup(); - MapEntry const* mapEntry = sMapStore.LookupEntry(data.spawnPoint.GetMapId()); + MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapId); if (!mapEntry) { - TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) spawned on a non-existed map (Id: %u), skip", guid, data.id, data.spawnPoint.GetMapId()); + TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) spawned on a non-existed map (Id: %u), skip", guid, data.id, data.mapId); continue; } @@ -2458,13 +2462,13 @@ void ObjectMgr::LoadGameObjects() data.spawnMask = fields[14].GetUInt8(); - if (!IsTransportMap(data.spawnPoint.GetMapId())) + if (!IsTransportMap(data.mapId)) { - if (data.spawnMask & ~spawnMasks[data.spawnPoint.GetMapId()]) - TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) that has wrong spawn mask %u including unsupported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.spawnPoint.GetMapId()); + if (data.spawnMask & ~spawnMasks[data.mapId]) + TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) that has wrong spawn mask %u including unsupported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapId); } else - data.spawnGroupData = &_spawnGroupDataStore[1]; // force compatibility group for transport spawns + data.spawnGroupData = GetLegacySpawnGroup(); // force compatibility group for transport spawns data.phaseMask = fields[15].GetUInt32(); int16 gameEvent = fields[16].GetInt8(); @@ -2496,7 +2500,7 @@ void ObjectMgr::LoadGameObjects() continue; } - if (!MapManager::IsValidMapCoord(data.spawnPoint)) + if (!MapManager::IsValidMapCoord(data.mapId, data.spawnPoint)) { TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) with invalid coordinates, skip", guid, data.id); continue; @@ -2518,7 +2522,7 @@ void ObjectMgr::LoadGameObjects() { uint32 zoneId = 0; uint32 areaId = 0; - sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.spawnPoint); + sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapId, data.spawnPoint); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA); @@ -2614,19 +2618,15 @@ void ObjectMgr::LoadSpawnGroups() { Field* fields = result->Fetch(); uint32 groupId = fields[0].GetUInt32(); - SpawnObjectType spawnType; + SpawnObjectType spawnType = SpawnObjectType(fields[1].GetUInt8()); + if (!SpawnData::TypeIsValid(spawnType)) { - uint32 type = fields[1].GetUInt8(); - if (type >= SPAWN_TYPE_MAX) - { - TC_LOG_ERROR("sql.sql", "Spawn data with invalid type %u listed for spawn group %u. Skipped.", type, groupId); - continue; - } - spawnType = SpawnObjectType(type); + TC_LOG_ERROR("sql.sql", "Spawn data with invalid type %u listed for spawn group %u. Skipped.", uint32(spawnType), groupId); + continue; } ObjectGuid::LowType spawnId = fields[2].GetUInt32(); - SpawnData const* data = GetSpawnData(spawnType, spawnId); + SpawnMetadata const* data = GetSpawnMetadata(spawnType, spawnId); if (!data) { TC_LOG_ERROR("sql.sql", "Spawn data with ID (%u,%u) not found, but is listed as a member of spawn group %u!", uint32(spawnType), spawnId, groupId); @@ -2640,20 +2640,20 @@ void ObjectMgr::LoadSpawnGroups() auto it = _spawnGroupDataStore.find(groupId); if (it == _spawnGroupDataStore.end()) { - TC_LOG_ERROR("sql.sql", "Spawn group %u assigned to spawn ID (%u,%u), but group is found!", groupId, uint32(spawnType), spawnId); + TC_LOG_ERROR("sql.sql", "Spawn group %u assigned to spawn ID (%u,%u), but group does not exist!", groupId, uint32(spawnType), spawnId); continue; } else { SpawnGroupTemplateData& groupTemplate = it->second; if (groupTemplate.mapId == SPAWNGROUP_MAP_UNSET) - groupTemplate.mapId = data->spawnPoint.GetMapId(); - else if (groupTemplate.mapId != data->spawnPoint.GetMapId() && !(groupTemplate.flags & SPAWNGROUP_FLAG_SYSTEM)) + groupTemplate.mapId = data->mapId; + else if (groupTemplate.mapId != data->mapId && !(groupTemplate.flags & SPAWNGROUP_FLAG_SYSTEM)) { - TC_LOG_ERROR("sql.sql", "Spawn group %u has map ID %u, but spawn (%u,%u) has map id %u - spawn NOT added to group!", groupId, groupTemplate.mapId, uint32(spawnType), spawnId, data->spawnPoint.GetMapId()); + TC_LOG_ERROR("sql.sql", "Spawn group %u has map ID %u, but spawn (%u,%u) has map id %u - spawn NOT added to group!", groupId, groupTemplate.mapId, uint32(spawnType), spawnId, data->mapId); continue; } - const_cast<SpawnData*>(data)->spawnGroupData = &groupTemplate; + const_cast<SpawnMetadata*>(data)->spawnGroupData = &groupTemplate; if (!(groupTemplate.flags & SPAWNGROUP_FLAG_SYSTEM)) _spawnGroupMapStore.emplace(groupId, data); ++numMembers; @@ -2746,7 +2746,7 @@ void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData con if (mask & 1) { CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->spawnPoint.GetMapId(), i)][cellCoord.GetId()]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapId, i)][cellCoord.GetId()]; cell_guids.gameobjects.insert(guid); } } @@ -2760,7 +2760,7 @@ void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectDat if (mask & 1) { CellCoord cellCoord = Trinity::ComputeCellCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->spawnPoint.GetMapId(), i)][cellCoord.GetId()]; + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapId, i)][cellCoord.GetId()]; cell_guids.gameobjects.erase(guid); } } diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 01b8ec4ece9..8f8c33962a2 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -551,7 +551,7 @@ typedef std::unordered_map<ObjectGuid::LowType, GameObjectData> GameObjectDataCo typedef std::unordered_map<ObjectGuid::LowType, GameObjectAddon> GameObjectAddonContainer; typedef std::unordered_map<uint32, std::vector<uint32>> GameObjectQuestItemMap; typedef std::unordered_map<uint32, SpawnGroupTemplateData> SpawnGroupDataContainer; -typedef std::multimap<uint32, SpawnData const*> SpawnGroupLinkContainer; +typedef std::multimap<uint32, SpawnMetadata const*> SpawnGroupLinkContainer; typedef std::unordered_map<uint16, std::vector<InstanceSpawnGroupInfo>> InstanceSpawnGroupContainer; typedef std::map<TempSummonGroupKey, std::vector<TempSummonData>> TempSummonDataContainer; typedef std::unordered_map<uint32, CreatureLocale> CreatureLocaleContainer; @@ -1267,9 +1267,10 @@ class TC_GAME_API ObjectMgr ObjectGuid::LowType GenerateGameObjectSpawnId(); SpawnGroupTemplateData const* GetSpawnGroupData(uint32 groupId) const { auto it = _spawnGroupDataStore.find(groupId); return it != _spawnGroupDataStore.end() ? &it->second : nullptr; } + SpawnGroupTemplateData const* GetSpawnGroupData(SpawnObjectType type, ObjectGuid::LowType spawnId) const { SpawnMetadata const* data = GetSpawnMetadata(type, spawnId); return data ? data->spawnGroupData : nullptr; } SpawnGroupTemplateData const* GetDefaultSpawnGroup() const { return &_spawnGroupDataStore.at(0); } SpawnGroupTemplateData const* GetLegacySpawnGroup() const { return &_spawnGroupDataStore.at(1); } - Trinity::IteratorPair<SpawnGroupLinkContainer::const_iterator> GetSpawnDataForGroup(uint32 groupId) const { return Trinity::Containers::MapEqualRange(_spawnGroupMapStore, groupId); } + Trinity::IteratorPair<SpawnGroupLinkContainer::const_iterator> GetSpawnMetadataForGroup(uint32 groupId) const { return Trinity::Containers::MapEqualRange(_spawnGroupMapStore, groupId); } std::vector<InstanceSpawnGroupInfo> const* GetSpawnGroupsForInstance(uint32 instanceId) const { auto it = _instanceSpawnGroupStore.find(instanceId); return it != _instanceSpawnGroupStore.end() ? &it->second : nullptr; } MailLevelReward const* GetMailLevelReward(uint32 level, uint32 raceMask) const @@ -1321,29 +1322,42 @@ class TC_GAME_API ObjectMgr return nullptr; } - SpawnData const* GetSpawnData(SpawnObjectType type, ObjectGuid::LowType guid) + SpawnMetadata const* GetSpawnMetadata(SpawnObjectType type, ObjectGuid::LowType spawnId) const { - if (type == SPAWN_TYPE_CREATURE) - return GetCreatureData(guid); - else if (type == SPAWN_TYPE_GAMEOBJECT) - return GetGameObjectData(guid); + if (SpawnData::TypeHasData(type)) + return GetSpawnData(type, spawnId); else - ASSERT(false, "Invalid spawn object type %u", uint32(type)); - return nullptr; + return nullptr; + } + + SpawnData const* GetSpawnData(SpawnObjectType type, ObjectGuid::LowType spawnId) const + { + if (!SpawnData::TypeHasData(type)) + return nullptr; + switch (type) + { + case SPAWN_TYPE_CREATURE: + return GetCreatureData(spawnId); + case SPAWN_TYPE_GAMEOBJECT: + return GetGameObjectData(spawnId); + default: + ASSERT(false, "Invalid spawn object type %u", uint32(type)); + return nullptr; + } } void OnDeleteSpawnData(SpawnData const* data); CreatureDataContainer const& GetAllCreatureData() const { return _creatureDataStore; } - CreatureData const* GetCreatureData(ObjectGuid::LowType guid) const + CreatureData const* GetCreatureData(ObjectGuid::LowType spawnId) const { - CreatureDataContainer::const_iterator itr = _creatureDataStore.find(guid); + CreatureDataContainer::const_iterator itr = _creatureDataStore.find(spawnId); if (itr == _creatureDataStore.end()) return nullptr; return &itr->second; } - CreatureData& NewOrExistCreatureData(ObjectGuid::LowType guid) { return _creatureDataStore[guid]; } - void DeleteCreatureData(ObjectGuid::LowType guid); - ObjectGuid GetLinkedRespawnGuid(ObjectGuid guid) const + CreatureData& NewOrExistCreatureData(ObjectGuid::LowType spawnId) { return _creatureDataStore[spawnId]; } + void DeleteCreatureData(ObjectGuid::LowType spawnId); + ObjectGuid GetLinkedRespawnGuid(ObjectGuid spawnId) const { - LinkedRespawnContainer::const_iterator itr = _linkedRespawnStore.find(guid); + LinkedRespawnContainer::const_iterator itr = _linkedRespawnStore.find(spawnId); if (itr == _linkedRespawnStore.end()) return ObjectGuid::Empty; return itr->second; } @@ -1354,14 +1368,14 @@ class TC_GAME_API ObjectMgr return &itr->second; } GameObjectDataContainer const& GetAllGameObjectData() const { return _gameObjectDataStore; } - GameObjectData const* GetGameObjectData(ObjectGuid::LowType guid) const + GameObjectData const* GetGameObjectData(ObjectGuid::LowType spawnId) const { - GameObjectDataContainer::const_iterator itr = _gameObjectDataStore.find(guid); + GameObjectDataContainer::const_iterator itr = _gameObjectDataStore.find(spawnId); if (itr == _gameObjectDataStore.end()) return nullptr; return &itr->second; } - GameObjectData& NewOrExistGameObjectData(ObjectGuid::LowType guid) { return _gameObjectDataStore[guid]; } - void DeleteGameObjectData(ObjectGuid::LowType guid); + GameObjectData& NewOrExistGameObjectData(ObjectGuid::LowType spawnId) { return _gameObjectDataStore[spawnId]; } + void DeleteGameObjectData(ObjectGuid::LowType spawnId); GameObjectLocale const* GetGameObjectLocale(uint32 entry) const { GameObjectLocaleContainer::const_iterator itr = _gameObjectLocaleStore.find(entry); diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp index 15a3f427ccd..63326d8ab84 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -119,49 +119,19 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord &cell, GridRefManager<T> { for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) { - T* obj = new T; + // Don't spawn at all if there's a respawn timer + ObjectGuid::LowType guid = *i_guid; + if (!map->ShouldBeSpawnedOnGridLoad<T>(guid)) + continue; - // Don't spawn at all if there's a respawn time - if ((obj->GetTypeId() == TYPEID_UNIT && !map->GetCreatureRespawnTime(*i_guid)) || (obj->GetTypeId() == TYPEID_GAMEOBJECT && !map->GetGORespawnTime(*i_guid))) + T* obj = new T; + //TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid); + if (!obj->LoadFromDB(guid, map, false, false)) { - ObjectGuid::LowType guid = *i_guid; - //TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid); - - if (obj->GetTypeId() == TYPEID_UNIT) - { - CreatureData const* cdata = sObjectMgr->GetCreatureData(guid); - ASSERT(cdata, "Tried to load creature with spawnId %u, but no such creature exists.", guid); - SpawnGroupTemplateData const* const group = cdata->spawnGroupData; - // If creature in manual spawn group, don't spawn here, unless group is already active. - if (!(group->flags & SPAWNGROUP_FLAG_SYSTEM)) - if (!map->IsSpawnGroupActive(group->groupId)) - { - delete obj; - continue; - } - } - else if (obj->GetTypeId() == TYPEID_GAMEOBJECT) - { - // If gameobject in manual spawn group, don't spawn here, unless group is already active. - GameObjectData const* godata = sObjectMgr->GetGameObjectData(guid); - ASSERT(godata, "Tried to load gameobject with spawnId %u, but no such object exists.", guid); - if (!(godata->spawnGroupData->flags & SPAWNGROUP_FLAG_SYSTEM)) - if (!map->IsSpawnGroupActive(godata->spawnGroupData->groupId)) - { - delete obj; - continue; - } - } - - if (!obj->LoadFromDB(guid, map, false, false)) - { - delete obj; - continue; - } - AddObjectHelper(cell, m, count, map, obj); - } - else delete obj; + continue; + } + AddObjectHelper(cell, m, count, map, obj); } } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 8001aa66412..9569b587112 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3026,75 +3026,64 @@ bool Map::CheckRespawn(RespawnInfo* info) return true; } -void Map::DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId) +void Map::Respawn(RespawnInfo* info, SQLTransaction dbTrans) { - if (!IsGridLoaded(gridId)) // if grid isn't loaded, this will be processed in grid load handler - return; + info->respawnTime = GameTime::GetGameTime(); + SaveRespawnInfoDB(*info, dbTrans); +} +size_t Map::DespawnAll(SpawnObjectType type, ObjectGuid::LowType spawnId) +{ + std::vector<WorldObject*> toUnload; switch (type) { case SPAWN_TYPE_CREATURE: - { - Creature* obj = new Creature(); - if (!obj->LoadFromDB(spawnId, this, true, true)) - delete obj; + for (auto const& pair : Trinity::Containers::MapEqualRange(GetCreatureBySpawnIdStore(), spawnId)) + toUnload.push_back(pair.second); break; - } case SPAWN_TYPE_GAMEOBJECT: - { - GameObject* obj = new GameObject(); - if (!obj->LoadFromDB(spawnId, this, true)) - delete obj; - break; - } + for (auto const& pair : Trinity::Containers::MapEqualRange(GetGameObjectBySpawnIdStore(), spawnId)) + toUnload.push_back(pair.second); default: - ASSERT(false, "Invalid spawn type %u (spawnid %u) on map %u", uint32(type), spawnId, GetId()); + break; } -} -void Map::Respawn(RespawnInfo* info, SQLTransaction dbTrans) -{ - if (!CheckRespawn(info)) - { - if (info->respawnTime) - { - _respawnTimes.decrease(info->handle); - SaveRespawnInfoDB(*info, dbTrans); - } - else - DeleteRespawnInfo(info, dbTrans); - return; - } + for (WorldObject* o : toUnload) + AddObjectToRemoveList(o); - // remove the actual respawn record first - since this deletes it, we save what we need - SpawnObjectType const type = info->type; - uint32 const gridId = info->gridId; - ObjectGuid::LowType const spawnId = info->spawnId; - DeleteRespawnInfo(info, dbTrans); - DoRespawn(type, spawnId, gridId); + return toUnload.size(); } bool Map::AddRespawnInfo(RespawnInfo const& info) { - ASSERT(info.spawnId, "Attempt to schedule respawn with zero spawnid (type %u)", uint32(info.type)); + if (!info.spawnId) + { + TC_LOG_ERROR("maps", "Attempt to insert respawn info for zero spawn id (type %u)", uint32(info.type)); + return false; + } RespawnInfoMap& bySpawnIdMap = GetRespawnMapForType(info.type); - auto it = bySpawnIdMap.find(info.spawnId); - if (it != bySpawnIdMap.end()) // spawnid already has a respawn scheduled + // check if we already have the maximum possible number of respawns scheduled + if (SpawnData::TypeHasData(info.type)) { - RespawnInfo* const existing = it->second; - if (info.respawnTime < existing->respawnTime) // delete existing in this case - DeleteRespawnInfo(existing); - else - return false; + auto it = bySpawnIdMap.find(info.spawnId); + if (it != bySpawnIdMap.end()) // spawnid already has a respawn scheduled + { + RespawnInfo* const existing = it->second; + if (info.respawnTime <= existing->respawnTime) // delete existing in this case + DeleteRespawnInfo(existing); + else + return false; + } + ASSERT(bySpawnIdMap.find(info.spawnId) == bySpawnIdMap.end(), "Insertion of respawn info with id (%u,%u) into spawn id map failed - state desync.", uint32(info.type), info.spawnId); } + else + ASSERT(false, "Invalid respawn info for spawn id (%u,%u) being inserted", uint32(info.type), info.spawnId); - // if we get to this point, we should insert the respawninfo (there either was no prior entry, or it was deleted already) RespawnInfo * ri = new RespawnInfo(info); ri->handle = _respawnTimes.push(ri); - bool success = bySpawnIdMap.emplace(ri->spawnId, ri).second; - ASSERT(success, "Insertion of respawn info with id (%u,%u) into spawn id map failed - state desync.", uint32(ri->type), ri->spawnId); + bySpawnIdMap.emplace(ri->spawnId, ri); return true; } @@ -3137,8 +3126,11 @@ void Map::DeleteRespawnInfo(RespawnInfo* info, SQLTransaction dbTrans) ASSERT(info); // spawnid store - size_t const n = GetRespawnMapForType(info->type).erase(info->spawnId); - ASSERT(n == 1, "Respawn stores inconsistent for map %u, spawnid %u (type %u)", GetId(), info->spawnId, uint32(info->type)); + auto& spawnMap = GetRespawnMapForType(info->type); + auto range = spawnMap.equal_range(info->spawnId); + auto it = std::find_if(range.first, range.second, [info](RespawnInfoMap::value_type const& pair) { return (pair.second == info); }); + ASSERT(it != range.second, "Respawn stores inconsistent for map %u, spawnid %u (type %u)", GetId(), info->spawnId, uint32(info->type)); + spawnMap.erase(it); // respawn heap _respawnTimes.erase(info->handle); @@ -3155,6 +3147,32 @@ void Map::DeleteRespawnInfo(RespawnInfo* info, SQLTransaction dbTrans) delete info; } +void Map::DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId) +{ + if (!IsGridLoaded(gridId)) // if grid isn't loaded, this will be processed in grid load handler + return; + + switch (type) + { + case SPAWN_TYPE_CREATURE: + { + Creature* obj = new Creature(); + if (!obj->LoadFromDB(spawnId, this, true, true)) + delete obj; + break; + } + case SPAWN_TYPE_GAMEOBJECT: + { + GameObject* obj = new GameObject(); + if (!obj->LoadFromDB(spawnId, this, true)) + delete obj; + break; + } + default: + ASSERT(false, "Invalid spawn type %u (spawnid %u) on map %u", uint32(type), spawnId, GetId()); + } +} + void Map::ProcessRespawns() { time_t now = GameTime::GetGameTime(); @@ -3207,8 +3225,11 @@ void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::Low return; } - SpawnData const* data = sObjectMgr->GetSpawnData(type, spawnId); - if (!data || !data->spawnGroupData || !(data->spawnGroupData->flags & SPAWNGROUP_FLAG_DYNAMIC_SPAWN_RATE)) + SpawnMetadata const* data = sObjectMgr->GetSpawnMetadata(type, spawnId); + if (!data) + return; + + if (!(data->spawnGroupData->flags & SPAWNGROUP_FLAG_DYNAMIC_SPAWN_RATE)) return; auto it = _zonePlayerCountMap.find(obj->GetZoneId()); @@ -3227,6 +3248,24 @@ void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::Low respawnDelay = std::max<uint32>(ceil(respawnDelay * adjustFactor), timeMinimum); } +bool Map::ShouldBeSpawnedOnGridLoad(SpawnObjectType type, ObjectGuid::LowType spawnId) const +{ + ASSERT(SpawnData::TypeHasData(type)); + + // check if the object is on its respawn timer + if (GetRespawnTime(type, spawnId)) + return false; + + SpawnMetadata const* spawnData = ASSERT_NOTNULL(sObjectMgr->GetSpawnMetadata(type, spawnId)); + // check if the object is part of a spawn group + SpawnGroupTemplateData const* spawnGroup = ASSERT_NOTNULL(spawnData->spawnGroupData); + if (!(spawnGroup->flags & SPAWNGROUP_FLAG_SYSTEM)) + if (!IsSpawnGroupActive(spawnGroup->groupId)) + return false; + + return true; +} + SpawnGroupTemplateData const* Map::GetSpawnGroupData(uint32 groupId) const { SpawnGroupTemplateData const* data = sObjectMgr->GetSpawnGroupData(groupId); @@ -3245,31 +3284,40 @@ bool Map::SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn, bool force, std::v } SetSpawnGroupActive(groupId, true); // start processing respawns for the group - 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) + std::vector<SpawnData const*> toSpawn; + for (auto& pair : sObjectMgr->GetSpawnMetadataForGroup(groupId)) + { + SpawnMetadata const* data = pair.second; + ASSERT(groupData->mapId == data->mapId); + + if (force || ignoreRespawn) + RemoveRespawnTime(data->type, data->spawnId); + + uint32 nRespawnTimers = GetRespawnMapForType(data->type).count(data->spawnId); + if (SpawnData::TypeHasData(data->type)) { - if (!force && !ignoreRespawn && (respawnTime > GameTime::GetGameTime())) + // has a respawn timer + if (nRespawnTimers) continue; - // we need to remove the respawn time, otherwise we'd end up double spawning - RemoveRespawnTime(data->type, data->spawnId); + // has a spawn already active + if (!force) + if (WorldObject* obj = GetWorldObjectBySpawnId(data->type, data->spawnId)) + if ((data->type != SPAWN_TYPE_CREATURE) || obj->ToCreature()->IsAlive()) + continue; + + toSpawn.push_back(ASSERT_NOTNULL(data->ToSpawnData())); } + } + for (SpawnData const* data : toSpawn) + { // 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 + // now do the actual (re)spawn switch (data->type) { case SPAWN_TYPE_CREATURE: @@ -3307,41 +3355,16 @@ bool Map::SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes, size_t* cou return false; } - std::vector<WorldObject*> toUnload; // unload after iterating, otherwise iterator invalidation - for (auto const& pair : sObjectMgr->GetSpawnDataForGroup(groupId)) + for (auto const& pair : sObjectMgr->GetSpawnMetadataForGroup(groupId)) { - SpawnData const* data = pair.second; - ASSERT(groupData->mapId == data->spawnPoint.GetMapId()); + SpawnMetadata const* data = pair.second; + ASSERT(groupData->mapId == data->mapId); 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 %u.", uint32(data->type), data->spawnId); - return false; - } + size_t c = DespawnAll(data->type, data->spawnId); + if (count) + *count += c; } - - if (count) - *count = toUnload.size(); - - // now do the actual despawning - for (WorldObject* obj : toUnload) - obj->AddObjectToRemoveList(); SetSpawnGroupActive(groupId, false); // stop processing respawns for the group, too return true; } @@ -4282,19 +4305,23 @@ void Map::UpdateIteratorBack(Player* player) void Map::SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 gridId, SQLTransaction dbTrans, bool startup) { - if (!spawnId) + SpawnMetadata const* data = sObjectMgr->GetSpawnMetadata(type, spawnId); + if (!data) + { + TC_LOG_ERROR("maps", "Map %u attempt to save respawn time for nonexistant spawnid (%u,%u).", GetId(), type, spawnId); return; + } if (!respawnTime) { // Delete only - RemoveRespawnTime(type, spawnId, dbTrans); + RemoveRespawnTime(data->type, data->spawnId, dbTrans); return; } RespawnInfo ri; - ri.type = type; - ri.spawnId = spawnId; + ri.type = data->type; + ri.spawnId = data->spawnId; ri.entry = entry; ri.respawnTime = respawnTime; ri.gridId = gridId; @@ -4334,7 +4361,7 @@ void Map::LoadRespawnTimes() ObjectGuid::LowType spawnId = fields[1].GetUInt32(); uint64 respawnTime = fields[2].GetUInt64(); - if (type < SPAWN_TYPE_MAX) + if (SpawnData::TypeHasData(type)) { if (SpawnData const* data = sObjectMgr->GetSpawnData(type, spawnId)) SaveRespawnTime(type, spawnId, data->id, time_t(respawnTime), Trinity::ComputeGridCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()).GetId(), nullptr, true); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 56a95ee96b1..ce876623d61 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -589,6 +589,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType> void SaveRespawnInfoDB(RespawnInfo const& info, SQLTransaction dbTrans = nullptr); void LoadRespawnTimes(); void DeleteRespawnTimes() { UnloadAllRespawnInfos(); DeleteRespawnTimesInDB(GetId(), GetInstanceId()); } + static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId); void LoadCorpseData(); void DeleteCorpseData(); @@ -597,8 +598,6 @@ class TC_GAME_API Map : public GridRefManager<NGridType> Corpse* ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia = false); void RemoveOldCorpses(); - static void DeleteRespawnTimesInDB(uint16 mapId, uint32 instanceId); - void SendInitTransports(Player* player); void SendRemoveTransports(Player* player); void SendZoneDynamicInfo(uint32 zoneId, Player* player) const; @@ -762,7 +761,6 @@ class TC_GAME_API Map : public GridRefManager<NGridType> // if return value is false and info->respawnTime is nonzero, it is guaranteed to be greater than time(NULL) bool CheckRespawn(RespawnInfo* info); void DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId); - void Respawn(RespawnInfo* info, SQLTransaction dbTrans = nullptr); bool AddRespawnInfo(RespawnInfo const& info); void UnloadAllRespawnInfos(); void DeleteRespawnInfo(RespawnInfo* info, SQLTransaction dbTrans = nullptr); @@ -775,11 +773,16 @@ class TC_GAME_API Map : public GridRefManager<NGridType> if (RespawnInfo* info = GetRespawnInfo(type, spawnId)) Respawn(info, dbTrans); } - void RemoveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId,SQLTransaction dbTrans = nullptr) + void Respawn(RespawnInfo* info, SQLTransaction dbTrans = nullptr); + void RemoveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, SQLTransaction dbTrans = nullptr) { if (RespawnInfo* info = GetRespawnInfo(type, spawnId)) DeleteRespawnInfo(info, dbTrans); } + size_t DespawnAll(SpawnObjectType type, ObjectGuid::LowType spawnId); + + bool ShouldBeSpawnedOnGridLoad(SpawnObjectType type, ObjectGuid::LowType spawnId) const; + template <typename T> bool ShouldBeSpawnedOnGridLoad(ObjectGuid::LowType spawnId) const { return ShouldBeSpawnedOnGridLoad(SpawnData::TypeFor<T>, spawnId); } SpawnGroupTemplateData const* GetSpawnGroupData(uint32 groupId) const; diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index 04811de991e..9d3b1a1746b 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -101,9 +101,14 @@ class TC_GAME_API MapManager return IsValidMAP(mapid, false) && Trinity::IsValidMapCoord(x, y, z, o); } + static bool IsValidMapCoord(uint32 mapid, Position const& pos) + { + return IsValidMapCoord(mapid, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); + } + static bool IsValidMapCoord(WorldLocation const& loc) { - return IsValidMapCoord(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ(), loc.GetOrientation()); + return IsValidMapCoord(loc.GetMapId(), loc); } void DoDelayedMovesAndRemoves(); diff --git a/src/server/game/Maps/SpawnData.h b/src/server/game/Maps/SpawnData.h index 594377f4d7e..863fa13f4bc 100644 --- a/src/server/game/Maps/SpawnData.h +++ b/src/server/game/Maps/SpawnData.h @@ -20,13 +20,18 @@ #include "Position.h" +class Creature; +class GameObject; +class Pool; +struct PoolTemplate; + // EnumUtils: DESCRIBE THIS enum SpawnObjectType { SPAWN_TYPE_CREATURE = 0, // TITLE Creature SPAWN_TYPE_GAMEOBJECT = 1, // TITLE Gameobject - - SPAWN_TYPE_MAX // SKIP + NUM_SPAWN_TYPES_WITH_DATA, // SKIP + NUM_SPAWN_TYPES = NUM_SPAWN_TYPES_WITH_DATA // SKIP }; enum SpawnObjectTypeMask @@ -34,7 +39,8 @@ enum SpawnObjectTypeMask SPAWN_TYPEMASK_CREATURE = (1 << SPAWN_TYPE_CREATURE), SPAWN_TYPEMASK_GAMEOBJECT = (1 << SPAWN_TYPE_GAMEOBJECT), - SPAWN_TYPEMASK_ALL = (1 << SPAWN_TYPE_MAX)-1 + SPAWN_TYPEMASK_WITH_DATA = (1 << NUM_SPAWN_TYPES_WITH_DATA)-1, + SPAWN_TYPEMASK_ALL = (1 << NUM_SPAWN_TYPES)-1 }; enum SpawnGroupFlags @@ -57,21 +63,45 @@ struct SpawnGroupTemplateData SpawnGroupFlags flags; }; -struct SpawnData +namespace Trinity { namespace Impl { + template <typename T> + struct SpawnObjectTypeForImpl { static_assert(!std::is_same<T,T>::value, "This type does not have an associated spawn type!"); }; + template <> struct SpawnObjectTypeForImpl<Creature> { static constexpr SpawnObjectType value = SPAWN_TYPE_CREATURE; }; + template <> struct SpawnObjectTypeForImpl<GameObject> { static constexpr SpawnObjectType value = SPAWN_TYPE_GAMEOBJECT; }; +}} + +struct SpawnData; +struct SpawnMetadata { + static constexpr bool TypeInMask(SpawnObjectType type, SpawnObjectTypeMask mask) { return ((1 << type) & mask); } + static constexpr bool TypeHasData(SpawnObjectType type) { return (type < NUM_SPAWN_TYPES_WITH_DATA); } + static constexpr bool TypeIsValid(SpawnObjectType type) { return (type < NUM_SPAWN_TYPES); } + template <typename T> + static constexpr SpawnObjectType TypeFor = Trinity::Impl::SpawnObjectTypeForImpl<T>::value; + + SpawnData const* ToSpawnData() const { return TypeHasData(type) ? reinterpret_cast<SpawnData const*>(this) : nullptr; } + SpawnObjectType const type; uint32 spawnId = 0; + uint32 mapId = MAPID_INVALID; + bool dbData = true; + SpawnGroupTemplateData const* spawnGroupData = nullptr; + + protected: + SpawnMetadata(SpawnObjectType t) : type(t) {} +}; + +struct SpawnData : public SpawnMetadata +{ uint32 id = 0; // entry in respective _template table - WorldLocation spawnPoint; + Position spawnPoint; uint32 phaseMask = 0; int32 spawntimesecs = 0; uint8 spawnMask = 0; - SpawnGroupTemplateData const* spawnGroupData = nullptr; uint32 scriptId = 0; - bool dbData = true; protected: - SpawnData(SpawnObjectType t) : type(t) {} + SpawnData(SpawnObjectType t) : SpawnMetadata(t) {} }; enum LinkedRespawnType diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index 83be9b7990b..45407c4c5aa 100644 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -170,7 +170,7 @@ void PoolGroup<Creature>::Despawn1Object(ObjectGuid::LowType guid) { sObjectMgr->RemoveCreatureFromGrid(guid, data); - Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId()); + Map* map = sMapMgr->CreateBaseMap(data->mapId); if (!map->Instanceable()) { auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(guid); @@ -195,7 +195,7 @@ void PoolGroup<GameObject>::Despawn1Object(ObjectGuid::LowType guid) { sObjectMgr->RemoveGameobjectFromGrid(guid, data); - Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId()); + Map* map = sMapMgr->CreateBaseMap(data->mapId); if (!map->Instanceable()) { auto gameobjectBounds = map->GetGameObjectBySpawnIdStore().equal_range(guid); @@ -316,7 +316,7 @@ void PoolGroup<Creature>::Spawn1Object(PoolObject* obj) sObjectMgr->AddCreatureToGrid(obj->guid, data); // Spawn if necessary (loaded grids only) - Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId()); + Map* map = sMapMgr->CreateBaseMap(data->mapId); // We use spawn coords to spawn if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint)) { @@ -340,7 +340,7 @@ void PoolGroup<GameObject>::Spawn1Object(PoolObject* obj) sObjectMgr->AddGameobjectToGrid(obj->guid, data); // Spawn if necessary (loaded grids only) // this base map checked as non-instanced and then only existed - Map* map = sMapMgr->CreateBaseMap(data->spawnPoint.GetMapId()); + Map* map = sMapMgr->CreateBaseMap(data->mapId); // We use current coords to unspawn, not spawn coords since creature can have changed grid if (!map->Instanceable() && map->IsGridLoaded(data->spawnPoint)) { diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 9122099ff92..171185428cb 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -79,13 +79,15 @@ public: return commandTable; } - static bool DoTeleport(ChatHandler* handler, WorldLocation loc) + static bool DoTeleport(ChatHandler* handler, Position pos, uint32 mapId = MAPID_INVALID) { Player* player = handler->GetSession()->GetPlayer(); - if (!MapManager::IsValidMapCoord(loc) || sObjectMgr->IsTransportMap(loc.GetMapId())) + if (mapId == MAPID_INVALID) + mapId = player->GetMapId(); + if (!MapManager::IsValidMapCoord(mapId, pos) || sObjectMgr->IsTransportMap(mapId)) { - handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, loc.GetPositionX(), loc.GetPositionY(), loc.GetMapId()); + handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, pos.GetPositionX(), pos.GetPositionY(), mapId); handler->SetSentErrorMessage(true); return false; } @@ -96,7 +98,7 @@ public: else player->SaveRecallPosition(); // save only in non-flight case - player->TeleportTo(loc); + player->TeleportTo({ mapId, pos }); return true; } @@ -110,7 +112,7 @@ public: return false; } - return DoTeleport(handler, spawnpoint->spawnPoint); + return DoTeleport(handler, spawnpoint->spawnPoint, spawnpoint->mapId); } static bool HandleGoCreatureCIdCommand(ChatHandler* handler, Variant<Hyperlink<creature_entry>, uint32> cId) @@ -137,7 +139,7 @@ public: return false; } - return DoTeleport(handler, spawnpoint->spawnPoint); + return DoTeleport(handler, spawnpoint->spawnPoint, spawnpoint->mapId); } static bool HandleGoGameObjectSpawnIdCommand(ChatHandler* handler, uint32 spawnId) @@ -150,7 +152,7 @@ public: return false; } - return DoTeleport(handler, spawnpoint->spawnPoint); + return DoTeleport(handler, spawnpoint->spawnPoint, spawnpoint->mapId); } static bool HandleGoGameObjectGOIdCommand(ChatHandler* handler, uint32 goId) @@ -177,7 +179,7 @@ public: return false; } - return DoTeleport(handler, spawnpoint->spawnPoint); + return DoTeleport(handler, spawnpoint->spawnPoint, spawnpoint->mapId); } static bool HandleGoGraveyardCommand(ChatHandler* handler, uint32 gyId) @@ -247,7 +249,7 @@ public: handler->SetSentErrorMessage(true); return false; } - return DoTeleport(handler, { node->map_id, { node->x, node->y, node->z } }); + return DoTeleport(handler, { node->x, node->y, node->z }, node->map_id); } static bool HandleGoAreaTriggerCommand(ChatHandler* handler, Variant<Hyperlink<areatrigger>, uint32> areaTriggerId) @@ -259,7 +261,7 @@ public: handler->SetSentErrorMessage(true); return false; } - return DoTeleport(handler, { at->mapid, { at->x, at->y, at->z } }); + return DoTeleport(handler, { at->x, at->y, at->z }, at->mapid); } //teleport at coordinates @@ -357,7 +359,7 @@ public: z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); } - return DoTeleport(handler, { mapId, { x, y, *z, o.get_value_or(0.0f) } }); + return DoTeleport(handler, { x, y, *z, o.get_value_or(0.0f) }, mapId); } static bool HandleGoTicketCommand(ChatHandler* handler, uint32 ticketId) @@ -383,7 +385,7 @@ public: static bool HandleGoOffsetCommand(ChatHandler* handler, float dX, Optional<float> dY, Optional<float> dZ, Optional<float> dO) { - WorldLocation loc = handler->GetSession()->GetPlayer()->GetWorldLocation(); + Position loc = handler->GetSession()->GetPlayer()->GetPosition(); loc.RelocateOffset({ dX, dY.get_value_or(0.0f), dZ.get_value_or(0.0f), dO.get_value_or(0.0f) }); return DoTeleport(handler, loc); @@ -548,9 +550,9 @@ public: handler->PSendSysMessage(LANG_COMMAND_BOSS_MULTIPLE_SPAWNS, boss->Name.c_str(), boss->Entry); for (CreatureData const* spawn : spawns) { - uint32 const mapId = spawn->spawnPoint.GetMapId(); + uint32 const mapId = spawn->mapId; MapEntry const* const map = ASSERT_NOTNULL(sMapStore.LookupEntry(mapId)); - handler->PSendSysMessage(LANG_COMMAND_BOSS_MULTIPLE_SPAWN_ETY, spawn->spawnId, mapId, map->name[handler->GetSessionDbcLocale()], spawn->spawnPoint.GetPosition().ToString().c_str()); + handler->PSendSysMessage(LANG_COMMAND_BOSS_MULTIPLE_SPAWN_ETY, spawn->spawnId, mapId, map->name[handler->GetSessionDbcLocale()], spawn->spawnPoint.ToString().c_str()); } handler->SetSentErrorMessage(true); return false; @@ -563,8 +565,8 @@ public: player->SaveRecallPosition(); CreatureData const* const spawn = spawns.front(); - uint32 const mapId = spawn->spawnPoint.GetMapId(); - if (!player->TeleportTo(spawn->spawnPoint)) + uint32 const mapId = spawn->mapId; + if (!player->TeleportTo({ mapId, spawn->spawnPoint })) { char const* const mapName = ASSERT_NOTNULL(sMapStore.LookupEntry(mapId))->name[handler->GetSessionDbcLocale()]; handler->PSendSysMessage(LANG_COMMAND_GO_BOSS_FAILED, spawn->spawnId, boss->Name.c_str(), boss->Entry, mapName); diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index e264e7153c3..430a496b418 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -656,7 +656,7 @@ public: for (auto const& pair : sObjectMgr->GetAllCreatureData()) { SpawnData const& data = pair.second; - if (data.spawnPoint.GetMapId() != mapId) + if (data.mapId != mapId) continue; CreatureTemplate const* cTemp = sObjectMgr->GetCreatureTemplate(data.id); if (!cTemp) @@ -667,7 +667,7 @@ public: for (auto const& pair : sObjectMgr->GetAllGameObjectData()) { SpawnData const& data = pair.second; - if (data.spawnPoint.GetMapId() != mapId) + if (data.mapId != mapId) continue; GameObjectTemplate const* goTemp = sObjectMgr->GetGameObjectTemplate(data.id); if (!goTemp) @@ -709,25 +709,27 @@ public: map->GetRespawnInfo(respawns, SpawnObjectTypeMask(1 << type)); for (RespawnInfo const* ri : respawns) { - SpawnData const* data = sObjectMgr->GetSpawnData(ri->type, ri->spawnId); + SpawnMetadata const* data = sObjectMgr->GetSpawnMetadata(ri->type, ri->spawnId); if (!data) continue; - uint32 respawnZoneId = map->GetZoneId(data->spawnPoint); - if (range) + uint32 respawnZoneId = 0; + if (SpawnData const* edata = data->ToSpawnData()) { - if (!player->IsInDist(data->spawnPoint, range)) - continue; - } - else - { - if (zoneId != respawnZoneId) - continue; + respawnZoneId = map->GetZoneId(edata->spawnPoint); + if (range) + { + if (!player->IsInDist(edata->spawnPoint, range)) + continue; + } + else + { + if (zoneId != respawnZoneId) + continue; + } } - uint32 gridY = ri->gridId / MAX_NUMBER_OF_GRIDS; uint32 gridX = ri->gridId % MAX_NUMBER_OF_GRIDS; - std::string respawnTime = ri->respawnTime > GameTime::GetGameTime() ? secsToTimeString(uint64(ri->respawnTime - GameTime::GetGameTime()), true) : stringOverdue; handler->PSendSysMessage("%u | %u | [%02u,%02u] | %s (%u) | %s%s", ri->spawnId, ri->entry, gridX, gridY, GetZoneName(respawnZoneId, locale), respawnZoneId, respawnTime.c_str(), map->IsSpawnGroupActive(data->spawnGroupData->groupId) ? "" : " (inactive)"); } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 358be467e39..f60a0225b97 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -763,7 +763,7 @@ public: return false; } - if (player->GetMapId() != data->spawnPoint.GetMapId()) + if (player->GetMapId() != data->mapId) { handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 1b39a2eb476..abcce451423 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -380,8 +380,8 @@ class instance_icecrown_citadel : public InstanceMapScript break; case NPC_ZAFOD_BOOMBOX: if (GameObjectTemplate const* go = sObjectMgr->GetGameObjectTemplate(GO_THE_SKYBREAKER_A)) - if ((TeamInInstance == ALLIANCE && data->spawnPoint.GetMapId() == go->moTransport.mapID) || - (TeamInInstance == HORDE && data->spawnPoint.GetMapId() != go->moTransport.mapID)) + if ((TeamInInstance == ALLIANCE && data->mapId == go->moTransport.mapID) || + (TeamInInstance == HORDE && data->mapId != go->moTransport.mapID)) return entry; return 0; case NPC_IGB_MURADIN_BRONZEBEARD: |