aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Globals/ObjectMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Globals/ObjectMgr.cpp')
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp137
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);
}
}