58 std::unordered_map<AreaTriggerCreatePropertiesId, std::vector<TaggedPosition<Position::XY>>> verticesByCreateProperties;
59 std::unordered_map<AreaTriggerCreatePropertiesId, std::vector<TaggedPosition<Position::XY>>> verticesTargetByCreateProperties;
60 std::unordered_map<AreaTriggerCreatePropertiesId, std::vector<Position>> splinesByCreateProperties;
61 std::unordered_map<AreaTriggerId, std::vector<AreaTriggerAction>> actionsByAreaTrigger;
64 if (
QueryResult templateActions =
WorldDatabase.Query(
"SELECT AreaTriggerId, IsCustom, ActionType, ActionParam, TargetType FROM `areatrigger_template_actions`"))
68 Field* templateActionFields = templateActions->Fetch();
78 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_template_actions` has invalid ActionType {} for AreaTriggerId ({},{}) and Param {}",
85 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_template_actions` has invalid TargetType {} for AreaTriggerId ({},{}) and Param {}",
94 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_template_actions` has invalid entry for AreaTriggerId ({},{}) with TargetType=Teleport and Param ({}) not a valid world safe loc entry",
103 actionsByAreaTrigger[areaTriggerId].push_back(action);
105 while (templateActions->NextRow());
109 TC_LOG_INFO(
"server.loading",
">> Loaded 0 AreaTrigger templates actions. DB table `areatrigger_template_actions` is empty.");
113 if (
QueryResult vertices =
WorldDatabase.Query(
"SELECT AreaTriggerCreatePropertiesId, IsCustom, Idx, VerticeX, VerticeY, VerticeTargetX, VerticeTargetY FROM `areatrigger_create_properties_polygon_vertex` ORDER BY `AreaTriggerCreatePropertiesId`, `IsCustom`, `Idx`"))
117 Field* verticeFields = vertices->Fetch();
120 verticesByCreateProperties[createPropertiesId].emplace_back(verticeFields[3].GetFloat(), verticeFields[4].GetFloat());
122 if (!verticeFields[5].IsNull() && !verticeFields[6].IsNull())
123 verticesTargetByCreateProperties[createPropertiesId].emplace_back(verticeFields[5].GetFloat(), verticeFields[6].GetFloat());
124 else if (verticeFields[5].IsNull() != verticeFields[6].IsNull())
125 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties_polygon_vertex` has listed invalid target vertices (AreaTriggerCreatePropertiesId: (Id: {}, IsCustom: {}), Index: {}).",
128 while (vertices->NextRow());
132 TC_LOG_INFO(
"server.loading",
">> Loaded 0 AreaTrigger polygon vertices. DB table `areatrigger_create_properties_polygon_vertex` is empty.");
136 if (
QueryResult splines =
WorldDatabase.Query(
"SELECT AreaTriggerCreatePropertiesId, IsCustom, X, Y, Z FROM `areatrigger_create_properties_spline_point` ORDER BY `AreaTriggerCreatePropertiesId`, `IsCustom`, `Idx`"))
140 Field* splineFields = splines->Fetch();
142 splinesByCreateProperties[createPropertiesId].emplace_back(splineFields[2].GetFloat(), splineFields[3].GetFloat(), splineFields[4].GetFloat());
144 while (splines->NextRow());
148 TC_LOG_INFO(
"server.loading",
">> Loaded 0 AreaTrigger splines. DB table `areatrigger_create_properties_spline_point` is empty.");
152 if (
QueryResult templates =
WorldDatabase.Query(
"SELECT Id, IsCustom, Flags, ActionSetId, ActionSetFlags FROM `areatrigger_template`"))
156 Field* fields = templates->Fetch();
164 areaTriggerTemplate.
Actions = std::move(actionsByAreaTrigger[areaTriggerTemplate.
Id]);
166 _areaTriggerTemplateStore[areaTriggerTemplate.
Id] = areaTriggerTemplate;
168 while (templates->NextRow());
171 if (
QueryResult areatriggerCreateProperties =
WorldDatabase.Query(
"SELECT Id, IsCustom, AreaTriggerId, IsAreatriggerCustom, Flags, "
172 "MoveCurveId, ScaleCurveId, MorphCurveId, FacingCurveId, AnimId, AnimKitId, DecalPropertiesId, SpellForVisuals, TimeToTargetScale, Speed, SpeedIsTime, "
173 "Shape, ShapeData0, ShapeData1, ShapeData2, ShapeData3, ShapeData4, ShapeData5, ShapeData6, ShapeData7, ScriptName FROM `areatrigger_create_properties`"))
178 (MoveCurveId)(ScaleCurveId)(MorphCurveId)(FacingCurveId)(AnimId)(AnimKitId)(DecalPropertiesId)(SpellForVisuals)(TimeToTargetScale)(Speed)(SpeedIsTime)
179 (Shape)(ShapeData0)(ShapeData1)(ShapeData2)(ShapeData3)(ShapeData4)(ShapeData5)(ShapeData6)(ShapeData7)(ScriptName)
180 ) fields { *areatriggerCreateProperties };
184 AreaTriggerId areaTriggerId = { fields.AreaTriggerId().GetUInt32(), fields.IsAreatriggerCustom().GetBool() };
189 if (areaTriggerId.
Id && !areaTriggerTemplate)
191 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties` references invalid AreaTrigger (Id: {}, IsCustom: {}) for AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {})",
198 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with invalid shape {}.",
204 createProperties.
Id = createPropertiesId;
205 createProperties.
Template = areaTriggerTemplate;
208#define VALIDATE_AND_SET_CURVE(Curve, Value) \
209 createProperties.Curve = Value; \
210 if (createProperties.Curve && !sCurveStore.HasRecord(createProperties.Curve)) \
212 TC_LOG_ERROR("sql.sql", "Table `areatrigger_create_properties` has listed AreaTrigger (Id: {}, IsCustom: {}) for AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with invalid " #Curve " ({}), set to 0!", \
213 areaTriggerId.Id, uint32(areaTriggerId.IsCustom), createPropertiesId.Id, uint32(createPropertiesId.IsCustom), createProperties.Curve); \
214 createProperties.Curve = 0; \
222#undef VALIDATE_AND_SET_CURVE
224 createProperties.
AnimId = fields.AnimId().GetInt32();
225 createProperties.
AnimKitId = fields.AnimKitId().GetInt32();
228 createProperties.
SpellForVisuals = fields.SpellForVisuals().GetInt32OrNull();
234 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties` has AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with invalid SpellForVisual {}, set to none.", createPropertiesId.
Id,
uint32(createPropertiesId.
IsCustom), *createProperties.
SpellForVisuals);
240 createProperties.
Speed = fields.Speed().GetFloat();
241 createProperties.
SpeedIsTime = fields.SpeedIsTime().GetBool();
243 std::array<float, MAX_AREATRIGGER_ENTITY_DATA> shapeData =
245 fields.ShapeData0().GetFloat(), fields.ShapeData1().GetFloat(), fields.ShapeData2().GetFloat(), fields.ShapeData3().GetFloat(),
246 fields.ShapeData4().GetFloat(), fields.ShapeData5().GetFloat(), fields.ShapeData6().GetFloat(), fields.ShapeData7().GetFloat()
260 if (polygon.
Height <= 0.0f)
272 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties_polygon_vertex` has invalid target vertices, either all or none vertices must have a corresponding target vertex (AreaTriggerCreatePropertiesId: (Id: {}, IsCustom: {})).",
291 createProperties.
ScriptId =
sObjectMgr->GetScriptId(fields.ScriptName().GetStringView());
294 createProperties.
Movement = std::move(*spline);
296 while (areatriggerCreateProperties->NextRow());
300 TC_LOG_INFO(
"server.loading",
">> Loaded 0 AreaTrigger create properties. DB table `areatrigger_create_properties` is empty.");
304 if (
QueryResult circularMovementInfos =
WorldDatabase.Query(
"SELECT AreaTriggerCreatePropertiesId, IsCustom, ExtraTimeForBlending, CircleRadius, BlendFromRadius, InitialAngle, ZOffset, CounterClockwise, CanLoop FROM `areatrigger_create_properties_orbit`"))
308 Field* circularMovementInfoFields = circularMovementInfos->Fetch();
312 if (!createProperties)
314 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties_orbit` reference invalid AreaTriggerCreatePropertiesId: (Id: {}, IsCustom: {})", createPropertiesId.
Id,
uint32(createPropertiesId.
IsCustom));
322#define VALIDATE_AND_SET_FLOAT(Float, Value) \
323 orbit.Float = Value; \
324 if (!std::isfinite(orbit.Float)) \
326 TC_LOG_ERROR("sql.sql", "Table `areatrigger_create_properties_orbit` has listed areatrigger (AreaTriggerCreatePropertiesId: {}, IsCustom: {}) with invalid " #Float " ({}), set to 0!", \
327 createPropertiesId.Id, uint32(createPropertiesId.IsCustom), orbit.Float); \
328 orbit.Float = 0.0f; \
336#undef VALIDATE_AND_SET_FLOAT
341 while (circularMovementInfos->NextRow());
345 TC_LOG_INFO(
"server.loading",
">> Loaded 0 AreaTrigger templates circular movement infos. DB table `areatrigger_create_properties_orbit` is empty.");
348 TC_LOG_INFO(
"server.loading",
">> Loaded {} spell areatrigger templates in {} ms.", _areaTriggerTemplateStore.size(),
GetMSTimeDiffToNow(oldMSTime));
354 std::unordered_map<uint32, std::set<Difficulty>> spawnMasks;
356 spawnMasks[mapDifficulty->MapID].insert(
Difficulty(mapDifficulty->DifficultyID));
360 if (
QueryResult templates =
WorldDatabase.Query(
"SELECT SpawnId, AreaTriggerCreatePropertiesId, IsCustom, MapId, SpawnDifficulties, PosX, PosY, PosZ, Orientation, PhaseUseFlags, PhaseId, PhaseGroup, ScriptName FROM `areatrigger`"))
364 Field* fields = templates->Fetch();
368 WorldLocation location(fields[3].GetUInt32(), fields[5].GetFloat(), fields[6].GetFloat(), fields[7].GetFloat(), fields[8].GetFloat());
371 if (!createProperties)
373 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) that doesn't exist for SpawnId {}",
380 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with non - zero flags",
387 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with curve values",
394 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with time to target values",
399 if (!std::holds_alternative<std::monostate>(createProperties->
Movement))
401 std::string_view movementType = std::visit([&]<
typename MovementType>(MovementType
const&)
403 if constexpr (std::is_same_v<MovementType, AreaTriggerCreateProperties::SplineInfo>)
405 else if constexpr (std::is_same_v<MovementType, AreaTriggerOrbitInfo>)
407 else if constexpr (std::is_same_v<MovementType, std::monostate>)
410 static_assert(Trinity::dependant_false_v<MovementType>,
"Unsupported movement type");
413 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with {}",
420 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed an invalid position: SpawnId: {}, Location {}",
425 std::vector<Difficulty> difficulties =
sObjectMgr->ParseSpawnDifficulties(fields[4].GetStringView(),
"areatrigger", spawnId, location.
GetMapId(), spawnMasks[location.
GetMapId()]);
426 if (difficulties.empty())
428 TC_LOG_DEBUG(
"sql.sql",
"Table `areatrigger` has areatrigger (GUID: {}) that is not spawned in any difficulty, skipped.", spawnId);
435 spawn.
Id = createPropertiesId;
448 _areaTriggerSpawnsByLocation[{ spawn.
mapId, difficulty }][cellCoord.
GetId()].insert(spawnId);
449 }
while (templates->NextRow());
452 TC_LOG_INFO(
"server.loading",
">> Loaded {} areatrigger spawns in {} ms.", _areaTriggerSpawnsBySpawnId.size(),
GetMSTimeDiffToNow(oldMSTime));