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, "
173 "PositionalSoundKitId, TimeToTargetScale, Speed, SpeedIsTime, "
174 "Shape, ShapeData0, ShapeData1, ShapeData2, ShapeData3, ShapeData4, ShapeData5, ShapeData6, ShapeData7, "
175 "Roll, Pitch, Yaw, TargetRoll, TargetPitch, TargetYaw, ScriptName FROM `areatrigger_create_properties`"))
180 (MoveCurveId)(ScaleCurveId)(MorphCurveId)(FacingCurveId)(AnimId)(AnimKitId)(DecalPropertiesId)(SpellForVisuals)
181 (PositionalSoundKitId)(TimeToTargetScale)(Speed)(SpeedIsTime)
182 (Shape)(ShapeData0)(ShapeData1)(ShapeData2)(ShapeData3)(ShapeData4)(ShapeData5)(ShapeData6)(ShapeData7)
183 (Roll)(Pitch)(Yaw)(TargetRoll)(TargetPitch)(TargetYaw)(ScriptName)
184 ) fields { *areatriggerCreateProperties };
188 AreaTriggerId areaTriggerId = { fields.AreaTriggerId().GetUInt32(), fields.IsAreatriggerCustom().GetBool() };
193 if (areaTriggerId.
Id && !areaTriggerTemplate)
195 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties` references invalid AreaTrigger (Id: {}, IsCustom: {}) for AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {})",
202 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with invalid shape {}.",
208 createProperties.
Id = createPropertiesId;
209 createProperties.
Template = areaTriggerTemplate;
212#define VALIDATE_AND_SET_CURVE(Curve, Value) \
213 createProperties.Curve = Value; \
214 if (createProperties.Curve && !sCurveStore.HasRecord(createProperties.Curve)) \
216 TC_LOG_ERROR("sql.sql", "Table `areatrigger_create_properties` has listed AreaTrigger (Id: {}, IsCustom: {}) for AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with invalid " #Curve " ({}), set to 0!", \
217 areaTriggerId.Id, uint32(areaTriggerId.IsCustom), createPropertiesId.Id, uint32(createPropertiesId.IsCustom), createProperties.Curve); \
218 createProperties.Curve = 0; \
226#undef VALIDATE_AND_SET_CURVE
228 createProperties.
AnimId = fields.AnimId().GetInt32();
229 createProperties.
AnimKitId = fields.AnimKitId().GetInt32();
232 createProperties.
SpellForVisuals = fields.SpellForVisuals().GetInt32OrNull();
238 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);
248 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties` has AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with invalid PositionalSoundKitId {}, set to 0.",
254 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties` has AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with PositionalSoundKitId {} on unsupported shape {}, set to 0.",
261 createProperties.
Speed = fields.Speed().GetFloat();
262 createProperties.
SpeedIsTime = fields.SpeedIsTime().GetBool();
264 std::array<float, MAX_AREATRIGGER_ENTITY_DATA> shapeData =
266 fields.ShapeData0().GetFloat(), fields.ShapeData1().GetFloat(), fields.ShapeData2().GetFloat(), fields.ShapeData3().GetFloat(),
267 fields.ShapeData4().GetFloat(), fields.ShapeData5().GetFloat(), fields.ShapeData6().GetFloat(), fields.ShapeData7().GetFloat()
282 if (polygon.
Height <= 0.0f)
294 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: {})).",
314 fields.Roll().GetFloat(),
315 fields.Pitch().GetFloat(),
316 fields.Yaw().GetFloat());
318 std::array<Optional<float>, 3> targetRollPitchYaw =
320 fields.TargetRoll().GetFloatOrNull(),
321 fields.TargetPitch().GetFloatOrNull(),
322 fields.TargetYaw().GetFloatOrNull()
325 if (std::ptrdiff_t trpyFields = std::ranges::count_if(targetRollPitchYaw, [](
Optional<float> const& angle) {
return angle.has_value(); }); trpyFields == 3)
328 *targetRollPitchYaw[0],
329 *targetRollPitchYaw[1],
330 *targetRollPitchYaw[2]);
334 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties` has AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with invalid TargetRoll {}, TargetPitch {}, TargetYaw {} combination, they must either all be NULL or all have value, ignored.",
335 createPropertiesId.
Id,
uint32(createPropertiesId.
IsCustom), targetRollPitchYaw[0], targetRollPitchYaw[1], targetRollPitchYaw[2]);
338 createProperties.
ScriptId =
sObjectMgr->GetScriptId(fields.ScriptName().GetStringView());
341 createProperties.
Movement = std::move(*spline);
343 while (areatriggerCreateProperties->NextRow());
347 TC_LOG_INFO(
"server.loading",
">> Loaded 0 AreaTrigger create properties. DB table `areatrigger_create_properties` is empty.");
351 if (
QueryResult circularMovementInfos =
WorldDatabase.Query(
"SELECT AreaTriggerCreatePropertiesId, IsCustom, ExtraTimeForBlending, CircleRadius, BlendFromRadius, InitialAngle, ZOffset, CounterClockwise, CanLoop FROM `areatrigger_create_properties_orbit`"))
355 Field* circularMovementInfoFields = circularMovementInfos->Fetch();
359 if (!createProperties)
361 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger_create_properties_orbit` reference invalid AreaTriggerCreatePropertiesId: (Id: {}, IsCustom: {})", createPropertiesId.
Id,
uint32(createPropertiesId.
IsCustom));
369#define VALIDATE_AND_SET_FLOAT(Float, Value) \
370 orbit.Float = Value; \
371 if (!std::isfinite(orbit.Float)) \
373 TC_LOG_ERROR("sql.sql", "Table `areatrigger_create_properties_orbit` has listed areatrigger (AreaTriggerCreatePropertiesId: {}, IsCustom: {}) with invalid " #Float " ({}), set to 0!", \
374 createPropertiesId.Id, uint32(createPropertiesId.IsCustom), orbit.Float); \
375 orbit.Float = 0.0f; \
383#undef VALIDATE_AND_SET_FLOAT
388 while (circularMovementInfos->NextRow());
392 TC_LOG_INFO(
"server.loading",
">> Loaded 0 AreaTrigger templates circular movement infos. DB table `areatrigger_create_properties_orbit` is empty.");
395 TC_LOG_INFO(
"server.loading",
">> Loaded {} spell areatrigger templates in {} ms.", _areaTriggerTemplateStore.size(),
GetMSTimeDiffToNow(oldMSTime));
401 std::unordered_map<uint32, std::set<Difficulty>> spawnMasks;
403 spawnMasks[mapDifficulty->MapID].insert(
Difficulty(mapDifficulty->DifficultyID));
407 if (
QueryResult templates =
WorldDatabase.Query(
"SELECT SpawnId, AreaTriggerCreatePropertiesId, IsCustom, MapId, SpawnDifficulties, PosX, PosY, PosZ, Orientation, PhaseUseFlags, PhaseId, PhaseGroup, ScriptName FROM `areatrigger`"))
411 Field* fields = templates->Fetch();
415 WorldLocation location(fields[3].GetUInt32(), fields[5].GetFloat(), fields[6].GetFloat(), fields[7].GetFloat(), fields[8].GetFloat());
418 if (!createProperties)
420 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) that doesn't exist for SpawnId {}",
427 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with non - zero flags",
434 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with curve values",
441 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with time to target values",
446 if (!std::holds_alternative<std::monostate>(createProperties->
Movement))
448 std::string_view movementType = std::visit([&]<
typename MovementType>(MovementType
const&)
450 if constexpr (std::is_same_v<MovementType, AreaTriggerCreateProperties::SplineInfo>)
452 else if constexpr (std::is_same_v<MovementType, AreaTriggerOrbitInfo>)
454 else if constexpr (std::is_same_v<MovementType, std::monostate>)
457 static_assert(Trinity::dependant_false_v<MovementType>,
"Unsupported movement type");
460 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with {}",
467 TC_LOG_ERROR(
"sql.sql",
"Table `areatrigger` has listed an invalid position: SpawnId: {}, Location {}",
472 std::vector<Difficulty> difficulties =
sObjectMgr->ParseSpawnDifficulties(fields[4].GetStringView(),
"areatrigger", spawnId, location.
GetMapId(), spawnMasks[location.
GetMapId()]);
473 if (difficulties.empty())
475 TC_LOG_DEBUG(
"sql.sql",
"Table `areatrigger` has areatrigger (GUID: {}) that is not spawned in any difficulty, skipped.", spawnId);
482 spawn.
Id = createPropertiesId;
495 _areaTriggerSpawnsByLocation[{ spawn.
mapId, difficulty }][gridCoord.
GetId()].insert(spawnId);
496 }
while (templates->NextRow());
499 TC_LOG_INFO(
"server.loading",
">> Loaded {} areatrigger spawns in {} ms.", _areaTriggerSpawnsBySpawnId.size(),
GetMSTimeDiffToNow(oldMSTime));