diff options
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
| -rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 137 |
1 files changed, 82 insertions, 55 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 1811ac2a4f9..746782fa1ec 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1594,7 +1594,8 @@ void ObjectMgr::LoadLinkedRespawn() break; } - if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + // they must have a possibility to meet (normal/heroic difficulty) + if (!Trinity::Containers::Intersects(master->spawnDifficulties.begin(), master->spawnDifficulties.end(), slave->spawnDifficulties.begin(), slave->spawnDifficulties.end())) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Creature '" UI64FMTD "' linking to Creature '" UI64FMTD "' with not corresponding spawnMask", guidLow, linkedGuidLow); error = true; @@ -1631,7 +1632,8 @@ void ObjectMgr::LoadLinkedRespawn() break; } - if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + // they must have a possibility to meet (normal/heroic difficulty) + if (!Trinity::Containers::Intersects(master->spawnDifficulties.begin(), master->spawnDifficulties.end(), slave->spawnDifficulties.begin(), slave->spawnDifficulties.end())) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Creature '" UI64FMTD "' linking to Gameobject '" UI64FMTD "' with not corresponding spawnMask", guidLow, linkedGuidLow); error = true; @@ -1668,7 +1670,8 @@ void ObjectMgr::LoadLinkedRespawn() break; } - if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + // they must have a possibility to meet (normal/heroic difficulty) + if (!Trinity::Containers::Intersects(master->spawnDifficulties.begin(), master->spawnDifficulties.end(), slave->spawnDifficulties.begin(), slave->spawnDifficulties.end())) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject '" UI64FMTD "' linking to Gameobject '" UI64FMTD "' with not corresponding spawnMask", guidLow, linkedGuidLow); error = true; @@ -1705,7 +1708,8 @@ void ObjectMgr::LoadLinkedRespawn() break; } - if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + // they must have a possibility to meet (normal/heroic difficulty) + if (!Trinity::Containers::Intersects(master->spawnDifficulties.begin(), master->spawnDifficulties.end(), slave->spawnDifficulties.begin(), slave->spawnDifficulties.end())) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Gameobject '" UI64FMTD "' linking to Creature '" UI64FMTD "' with not corresponding spawnMask", guidLow, linkedGuidLow); error = true; @@ -1758,7 +1762,8 @@ bool ObjectMgr::SetCreatureLinkedRespawn(ObjectGuid::LowType guidLow, ObjectGuid return false; } - if (!(master->spawnMask & slave->spawnMask)) // they must have a possibility to meet (normal/heroic difficulty) + // they must have a possibility to meet (normal/heroic difficulty) + if (!Trinity::Containers::Intersects(master->spawnDifficulties.begin(), master->spawnDifficulties.end(), slave->spawnDifficulties.begin(), slave->spawnDifficulties.end())) { TC_LOG_ERROR("sql.sql", "LinkedRespawn: Creature '" UI64FMTD "' linking to '" UI64FMTD "' with not corresponding spawnMask", guidLow, linkedGuidLow); return false; @@ -1862,14 +1867,44 @@ void ObjectMgr::LoadTempSummons() TC_LOG_INFO("server.loading", ">> Loaded %u temp summons in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } +inline std::vector<Difficulty> ParseSpawnDifficulties(std::string const& difficultyString, std::string const& table, ObjectGuid::LowType spawnId, uint32 mapId, + std::set<Difficulty> const& mapDifficulties) +{ + Tokenizer tokens(difficultyString, ',', 0, false); + std::vector<Difficulty> difficulties; + bool isTransportMap = sObjectMgr->IsTransportMap(mapId); + for (char const* token : tokens) + { + Difficulty difficultyId = Difficulty(strtoul(token, nullptr, 10)); + if (difficultyId && !sDifficultyStore.LookupEntry(difficultyId)) + { + TC_LOG_ERROR("sql.sql", "Table `%s` has %s (GUID: " UI64FMTD ") with non invalid difficulty id %u, skipped.", + table.c_str(), table.c_str(), spawnId, difficultyId); + continue; + } + + if (!isTransportMap && mapDifficulties.find(difficultyId) == mapDifficulties.end()) + { + TC_LOG_ERROR("sql.sql", "Table `%s` has %s (GUID: " UI64FMTD ") has unsupported difficulty %u for map (Id: %u).", + table.c_str(), table.c_str(), spawnId, difficultyId, mapId); + continue; + } + + difficulties.push_back(difficultyId); + } + + std::sort(difficulties.begin(), difficulties.end()); + return difficulties; +} + void ObjectMgr::LoadCreatures() { uint32 oldMSTime = getMSTime(); // 0 1 2 3 4 5 6 7 8 9 10 QueryResult result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, " - // 11 12 13 14 15 16 17 18 19 20 21 - "currentwaypoint, curhealth, curmana, MovementType, spawnMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.unit_flags2, creature.unit_flags3, " + // 11 12 13 14 15 16 17 18 19 20 21 + "currentwaypoint, curhealth, curmana, MovementType, spawnDifficulties, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.unit_flags2, creature.unit_flags3, " // 22 23 24 25 26 27 "creature.dynamicflags, creature.phaseUseFlags, creature.phaseid, creature.phasegroup, creature.terrainSwapMap, creature.ScriptName " "FROM creature " @@ -1883,10 +1918,10 @@ void ObjectMgr::LoadCreatures() } // Build single time for check spawnmask - std::map<uint32, uint64> spawnMasks; + std::unordered_map<uint32, std::set<Difficulty>> spawnMasks; for (auto& mapDifficultyPair : sDB2Manager.GetMapDifficulties()) for (auto& difficultyPair : mapDifficultyPair.second) - spawnMasks[mapDifficultyPair.first] |= UI64LIT(1) << difficultyPair.first; + spawnMasks[mapDifficultyPair.first].insert(Difficulty(difficultyPair.first)); PhaseShift phaseShift; @@ -1921,7 +1956,7 @@ void ObjectMgr::LoadCreatures() data.curhealth = fields[12].GetUInt32(); data.curmana = fields[13].GetUInt32(); data.movementType = fields[14].GetUInt8(); - data.spawnMask = fields[15].GetUInt64(); + data.spawnDifficulties = ParseSpawnDifficulties(fields[15].GetString(), "creature", guid, data.mapid, spawnMasks[data.mapid]); int16 gameEvent = fields[16].GetInt8(); uint32 PoolId = fields[17].GetUInt32(); data.npcflag = fields[18].GetUInt64(); @@ -1945,6 +1980,7 @@ void ObjectMgr::LoadCreatures() } if (sWorld->getBoolConfig(CONFIG_CREATURE_CHECK_INVALID_POSITION)) + { if (VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager()) { if (vmgr->isMapLoadingEnabled() && !IsTransportMap(data.mapid)) @@ -1959,10 +1995,13 @@ void ObjectMgr::LoadCreatures() guid, data.id, data.mapid, data.posX, data.posY, data.posZ); } } + } - // Skip spawnMask check for transport maps - if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) - TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD ") that have wrong spawn mask " UI64FMTD " including unsupported difficulty modes for map (Id: %u).", guid, data.spawnMask, data.mapid); + if (data.spawnDifficulties.empty()) + { + TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD ") that is not spawned in any difficulty, skipped.", guid); + continue; + } bool ok = true; for (uint32 diff = 0; diff < MAX_CREATURE_DIFFICULTIES && ok; ++diff) @@ -2100,29 +2139,21 @@ void ObjectMgr::LoadCreatures() void ObjectMgr::AddCreatureToGrid(ObjectGuid::LowType guid, CreatureData const* data) { - uint64 mask = data->spawnMask; - for (uint8 i = 0; mask != 0; i++, mask >>= 1) + for (Difficulty difficulty : data->spawnDifficulties) { - if (mask & 1) - { - CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; - cell_guids.creatures.insert(guid); - } + CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, difficulty)][cellCoord.GetId()]; + cell_guids.creatures.insert(guid); } } void ObjectMgr::RemoveCreatureFromGrid(ObjectGuid::LowType guid, CreatureData const* data) { - uint64 mask = data->spawnMask; - for (uint8 i = 0; mask != 0; i++, mask >>= 1) + for (Difficulty difficulty : data->spawnDifficulties) { - if (mask & 1) - { - CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; - cell_guids.creatures.erase(guid); - } + CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, difficulty)][cellCoord.GetId()]; + cell_guids.creatures.erase(guid); } } @@ -2150,7 +2181,7 @@ ObjectGuid::LowType ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, fl data.rotation.w = rotation3; data.spawntimesecs = spawntimedelay; data.animprogress = 100; - data.spawnMask = SPAWNMASK_CONTINENT; + data.spawnDifficulties.push_back(DIFFICULTY_NONE); data.go_state = GO_STATE_READY; data.artKit = goinfo->type == GAMEOBJECT_TYPE_CONTROL_ZONE ? 21 : 0; data.dbData = false; @@ -2202,7 +2233,7 @@ ObjectGuid::LowType ObjectMgr::AddCreatureData(uint32 entry, uint32 mapId, float data.curhealth = stats->GenerateHealth(cInfo); data.curmana = stats->GenerateMana(cInfo); data.movementType = cInfo->MovementType; - data.spawnMask = SPAWNMASK_CONTINENT; + data.spawnDifficulties.push_back(DIFFICULTY_NONE); data.dbData = false; data.npcflag = cInfo->npcflag; data.unit_flags = cInfo->unit_flags; @@ -2230,8 +2261,8 @@ void ObjectMgr::LoadGameobjects() // 0 1 2 3 4 5 6 QueryResult result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation, " - // 7 8 9 10 11 12 13 14 15 16 - "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, eventEntry, pool_entry, " + // 7 8 9 10 11 12 13 14 15 16 + "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnDifficulties, eventEntry, pool_entry, " // 17 18 19 20 21 "phaseUseFlags, phaseid, phasegroup, terrainSwapMap, ScriptName " "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid " @@ -2244,10 +2275,10 @@ void ObjectMgr::LoadGameobjects() } // build single time for check spawnmask - std::map<uint32, uint64> spawnMasks; + std::unordered_map<uint32, std::set<Difficulty>> spawnMasks; for (auto& mapDifficultyPair : sDB2Manager.GetMapDifficulties()) for (auto& difficultyPair : mapDifficultyPair.second) - spawnMasks[mapDifficultyPair.first] |= UI64LIT(1) << difficultyPair.first; + spawnMasks[mapDifficultyPair.first].insert(Difficulty(difficultyPair.first)); PhaseShift phaseShift; @@ -2308,6 +2339,7 @@ void ObjectMgr::LoadGameobjects() } if (sWorld->getBoolConfig(CONFIG_GAME_OBJECT_CHECK_INVALID_POSITION)) + { if (VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager()) { if (vmgr->isMapLoadingEnabled() && !IsTransportMap(data.mapid)) @@ -2322,6 +2354,7 @@ void ObjectMgr::LoadGameobjects() guid, data.id, data.mapid, data.posX, data.posY, data.posZ); } } + } if (data.spawntimesecs == 0 && gInfo->IsDespawnAtAction()) { @@ -2342,10 +2375,12 @@ void ObjectMgr::LoadGameobjects() } data.go_state = GOState(go_state); - data.spawnMask = fields[14].GetUInt64(); - - if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) - TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: " UI64FMTD " Entry: %u) that has wrong spawn mask " UI64FMTD " including unsupported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid); + data.spawnDifficulties = ParseSpawnDifficulties(fields[14].GetString(), "gameobject", guid, data.mapid, spawnMasks[data.mapid]); + if (data.spawnDifficulties.empty()) + { + TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD ") that is not spawned in any difficulty, skipped.", guid); + continue; + } int16 gameEvent = fields[15].GetInt8(); uint32 PoolId = fields[16].GetUInt32(); @@ -2472,29 +2507,21 @@ void ObjectMgr::LoadGameobjects() void ObjectMgr::AddGameobjectToGrid(ObjectGuid::LowType guid, GameObjectData const* data) { - uint64 mask = data->spawnMask; - for (uint8 i = 0; mask != 0; i++, mask >>= 1) + for (Difficulty difficulty : data->spawnDifficulties) { - if (mask & 1) - { - CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; - cell_guids.gameobjects.insert(guid); - } + CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, difficulty)][cellCoord.GetId()]; + cell_guids.gameobjects.insert(guid); } } void ObjectMgr::RemoveGameobjectFromGrid(ObjectGuid::LowType guid, GameObjectData const* data) { - uint64 mask = data->spawnMask; - for (uint8 i = 0; mask != 0; i++, mask >>= 1) + for (Difficulty difficulty : data->spawnDifficulties) { - if (mask & 1) - { - CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); - CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, i)][cellCoord.GetId()]; - cell_guids.gameobjects.erase(guid); - } + CellCoord cellCoord = Trinity::ComputeCellCoord(data->posX, data->posY); + CellObjectGuids& cell_guids = _mapObjectGuidsStore[MAKE_PAIR32(data->mapid, difficulty)][cellCoord.GetId()]; + cell_guids.gameobjects.erase(guid); } } |
