TrinityCore
Loading...
Searching...
No Matches
AreaTriggerDataStore.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
19#include "AreaTriggerTemplate.h"
20#include "DB2Stores.h"
21#include "DatabaseEnv.h"
22#include "Log.h"
23#include "MapManager.h"
24#include "MapUtils.h"
25#include "ObjectMgr.h"
27#include "SpellMgr.h"
28#include "Timer.h"
29#include "Types.h"
30#include <cmath>
31
32template <>
33struct std::hash<AreaTriggerId>
34{
35 std::size_t operator()(AreaTriggerId const& value) const noexcept
36 {
38 hash.UpdateData(value.Id);
39 hash.UpdateData(value.IsCustom);
40 return hash.Value;
41 }
42};
43
44namespace
45{
46 typedef std::unordered_map<uint32/*cell_id*/, std::set<ObjectGuid::LowType>> AtCellObjectGuidsMap;
47 typedef std::unordered_map<std::pair<uint32 /*mapId*/, Difficulty>, AtCellObjectGuidsMap> AtMapObjectGuids;
48
49 AtMapObjectGuids _areaTriggerSpawnsByLocation;
50 std::unordered_map<ObjectGuid::LowType, AreaTriggerSpawn> _areaTriggerSpawnsBySpawnId;
51 std::unordered_map<AreaTriggerId, AreaTriggerTemplate> _areaTriggerTemplateStore;
52 std::unordered_map<AreaTriggerCreatePropertiesId, AreaTriggerCreateProperties> _areaTriggerCreateProperties;
53}
54
56{
57 uint32 oldMSTime = getMSTime();
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;
62
63 // 0 1 2 3 4
64 if (QueryResult templateActions = WorldDatabase.Query("SELECT AreaTriggerId, IsCustom, ActionType, ActionParam, TargetType FROM `areatrigger_template_actions`"))
65 {
66 do
67 {
68 Field* templateActionFields = templateActions->Fetch();
69 AreaTriggerId areaTriggerId = { templateActionFields[0].GetUInt32(), templateActionFields[1].GetBool()};
70
71 AreaTriggerAction action;
72 action.Param = templateActionFields[3].GetUInt32();
73 uint32 actionType = templateActionFields[2].GetUInt32();
74 uint32 targetType = templateActionFields[4].GetUInt32();
75
76 if (actionType >= AREATRIGGER_ACTION_MAX)
77 {
78 TC_LOG_ERROR("sql.sql", "Table `areatrigger_template_actions` has invalid ActionType {} for AreaTriggerId ({},{}) and Param {}",
79 actionType, areaTriggerId.Id, uint32(areaTriggerId.IsCustom), action.Param);
80 continue;
81 }
82
83 if (targetType >= AREATRIGGER_ACTION_USER_MAX)
84 {
85 TC_LOG_ERROR("sql.sql", "Table `areatrigger_template_actions` has invalid TargetType {} for AreaTriggerId ({},{}) and Param {}",
86 targetType, areaTriggerId.Id, uint32(areaTriggerId.IsCustom), action.Param);
87 continue;
88 }
89
90 if (actionType == AREATRIGGER_ACTION_TELEPORT)
91 {
92 if (!sObjectMgr->GetWorldSafeLoc(action.Param))
93 {
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",
95 areaTriggerId.Id, uint32(areaTriggerId.IsCustom), action.Param);
96 continue;
97 }
98 }
99
100 action.TargetType = AreaTriggerActionUserTypes(targetType);
101 action.ActionType = AreaTriggerActionTypes(actionType);
102
103 actionsByAreaTrigger[areaTriggerId].push_back(action);
104 }
105 while (templateActions->NextRow());
106 }
107 else
108 {
109 TC_LOG_INFO("server.loading", ">> Loaded 0 AreaTrigger templates actions. DB table `areatrigger_template_actions` is empty.");
110 }
111
112 // 0 1 2 3 4 5 6
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`"))
114 {
115 do
116 {
117 Field* verticeFields = vertices->Fetch();
118 AreaTriggerCreatePropertiesId createPropertiesId = { verticeFields[0].GetUInt32(), verticeFields[1].GetBool() };
119
120 verticesByCreateProperties[createPropertiesId].emplace_back(verticeFields[3].GetFloat(), verticeFields[4].GetFloat());
121
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: {}).",
126 createPropertiesId.Id, uint32(createPropertiesId.IsCustom), verticeFields[1].GetUInt32());
127 }
128 while (vertices->NextRow());
129 }
130 else
131 {
132 TC_LOG_INFO("server.loading", ">> Loaded 0 AreaTrigger polygon vertices. DB table `areatrigger_create_properties_polygon_vertex` is empty.");
133 }
134
135 // 0 1 2 3, 4
136 if (QueryResult splines = WorldDatabase.Query("SELECT AreaTriggerCreatePropertiesId, IsCustom, X, Y, Z FROM `areatrigger_create_properties_spline_point` ORDER BY `AreaTriggerCreatePropertiesId`, `IsCustom`, `Idx`"))
137 {
138 do
139 {
140 Field* splineFields = splines->Fetch();
141 AreaTriggerCreatePropertiesId createPropertiesId = { splineFields[0].GetUInt32(), splineFields[1].GetBool() };
142 splinesByCreateProperties[createPropertiesId].emplace_back(splineFields[2].GetFloat(), splineFields[3].GetFloat(), splineFields[4].GetFloat());
143 }
144 while (splines->NextRow());
145 }
146 else
147 {
148 TC_LOG_INFO("server.loading", ">> Loaded 0 AreaTrigger splines. DB table `areatrigger_create_properties_spline_point` is empty.");
149 }
150
151 // 0 1 2 3 4
152 if (QueryResult templates = WorldDatabase.Query("SELECT Id, IsCustom, Flags, ActionSetId, ActionSetFlags FROM `areatrigger_template`"))
153 {
154 do
155 {
156 Field* fields = templates->Fetch();
157
158 AreaTriggerTemplate areaTriggerTemplate;
159 areaTriggerTemplate.Id.Id = fields[0].GetUInt32();
160 areaTriggerTemplate.Id.IsCustom = fields[1].GetBool();
161 areaTriggerTemplate.Flags = AreaTriggerFlag(fields[2].GetUInt32());
162 areaTriggerTemplate.ActionSetId = fields[3].GetUInt32();
163 areaTriggerTemplate.ActionSetFlags = AreaTriggerActionSetFlag(fields[4].GetUInt32());
164 areaTriggerTemplate.Actions = std::move(actionsByAreaTrigger[areaTriggerTemplate.Id]);
165
166 _areaTriggerTemplateStore[areaTriggerTemplate.Id] = areaTriggerTemplate;
167 }
168 while (templates->NextRow());
169 }
170
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`"))
174 {
175 do
176 {
177 DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(ResultSet, (Id)(IsCustom)(AreaTriggerId)(IsAreatriggerCustom)(Flags)
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 };
181
182 AreaTriggerCreatePropertiesId createPropertiesId = { fields.Id().GetUInt32(), fields.IsCustom().GetBool() };
183
184 AreaTriggerId areaTriggerId = { fields.AreaTriggerId().GetUInt32(), fields.IsAreatriggerCustom().GetBool() };
185 AreaTriggerTemplate const* areaTriggerTemplate = GetAreaTriggerTemplate(areaTriggerId);
186
187 AreaTriggerShapeType shape = AreaTriggerShapeType(fields.Shape().GetUInt8());
188
189 if (areaTriggerId.Id && !areaTriggerTemplate)
190 {
191 TC_LOG_ERROR("sql.sql", "Table `areatrigger_create_properties` references invalid AreaTrigger (Id: {}, IsCustom: {}) for AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {})",
192 areaTriggerId.Id, uint32(areaTriggerId.IsCustom), createPropertiesId.Id, uint32(createPropertiesId.IsCustom));
193 continue;
194 }
195
197 {
198 TC_LOG_ERROR("sql.sql", "Table `areatrigger_create_properties` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with invalid shape {}.",
199 createPropertiesId.Id, uint32(createPropertiesId.IsCustom), uint32(shape));
200 continue;
201 }
202
203 AreaTriggerCreateProperties& createProperties = _areaTriggerCreateProperties[createPropertiesId];
204 createProperties.Id = createPropertiesId;
205 createProperties.Template = areaTriggerTemplate;
206 createProperties.Flags = AreaTriggerCreatePropertiesFlag(fields.Flags().GetUInt32());
207
208#define VALIDATE_AND_SET_CURVE(Curve, Value) \
209 createProperties.Curve = Value; \
210 if (createProperties.Curve && !sCurveStore.HasRecord(createProperties.Curve)) \
211 { \
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; \
215 }
216
217 VALIDATE_AND_SET_CURVE(MoveCurveId, fields.MoveCurveId().GetUInt32());
218 VALIDATE_AND_SET_CURVE(ScaleCurveId, fields.ScaleCurveId().GetUInt32());
219 VALIDATE_AND_SET_CURVE(MorphCurveId, fields.MorphCurveId().GetUInt32());
220 VALIDATE_AND_SET_CURVE(FacingCurveId, fields.FacingCurveId().GetUInt32());
221
222#undef VALIDATE_AND_SET_CURVE
223
224 createProperties.AnimId = fields.AnimId().GetInt32();
225 createProperties.AnimKitId = fields.AnimKitId().GetInt32();
226
227 createProperties.DecalPropertiesId = fields.DecalPropertiesId().GetUInt32();
228 createProperties.SpellForVisuals = fields.SpellForVisuals().GetInt32OrNull();
229
230 if (createProperties.SpellForVisuals)
231 {
232 if (!sSpellMgr->GetSpellInfo(*createProperties.SpellForVisuals, DIFFICULTY_NONE))
233 {
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);
235 createProperties.SpellForVisuals.reset();
236 }
237 }
238
239 createProperties.TimeToTargetScale = fields.TimeToTargetScale().GetUInt32();
240 createProperties.Speed = fields.Speed().GetFloat();
241 createProperties.SpeedIsTime = fields.SpeedIsTime().GetBool();
242
243 std::array<float, MAX_AREATRIGGER_ENTITY_DATA> shapeData =
244 {
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()
247 };
248
249 switch (shape)
250 {
252 createProperties.Shape.Data.emplace<AreaTriggerShapeInfo::Sphere>(shapeData);
253 break;
255 createProperties.Shape.Data.emplace<AreaTriggerShapeInfo::Box>(shapeData);
256 break;
258 {
259 AreaTriggerShapeInfo::Polygon& polygon = createProperties.Shape.Data.emplace<AreaTriggerShapeInfo::Polygon>(shapeData);
260 if (polygon.Height <= 0.0f)
261 {
262 polygon.Height = 1.0f;
263 if (polygon.HeightTarget <= 0.0f)
264 polygon.HeightTarget = 1.0f;
265 }
266 if (std::vector<TaggedPosition<Position::XY>>* vertices = Trinity::Containers::MapGetValuePtr(verticesByCreateProperties, createProperties.Id))
267 polygon.PolygonVertices = std::move(*vertices);
268 if (std::vector<TaggedPosition<Position::XY>>* vertices = Trinity::Containers::MapGetValuePtr(verticesTargetByCreateProperties, createProperties.Id))
269 polygon.PolygonVerticesTarget = std::move(*vertices);
270 if (!polygon.PolygonVerticesTarget.empty() && polygon.PolygonVertices.size() != polygon.PolygonVerticesTarget.size())
271 {
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: {})).",
273 createPropertiesId.Id, uint32(createPropertiesId.IsCustom));
274 polygon.PolygonVerticesTarget.clear();
275 }
276 break;
277 }
279 createProperties.Shape.Data.emplace<AreaTriggerShapeInfo::Cylinder>(shapeData);
280 break;
282 createProperties.Shape.Data.emplace<AreaTriggerShapeInfo::Disk>(shapeData);
283 break;
285 createProperties.Shape.Data.emplace<AreaTriggerShapeInfo::BoundedPlane>(shapeData);
286 break;
287 default:
288 break;
289 }
290
291 createProperties.ScriptId = sObjectMgr->GetScriptId(fields.ScriptName().GetStringView());
292
293 if (std::vector<Position>* spline = Trinity::Containers::MapGetValuePtr(splinesByCreateProperties, createProperties.Id))
294 createProperties.Movement = std::move(*spline);
295 }
296 while (areatriggerCreateProperties->NextRow());
297 }
298 else
299 {
300 TC_LOG_INFO("server.loading", ">> Loaded 0 AreaTrigger create properties. DB table `areatrigger_create_properties` is empty.");
301 }
302
303 // 0 1 2 3 4 5 6 7 8
304 if (QueryResult circularMovementInfos = WorldDatabase.Query("SELECT AreaTriggerCreatePropertiesId, IsCustom, ExtraTimeForBlending, CircleRadius, BlendFromRadius, InitialAngle, ZOffset, CounterClockwise, CanLoop FROM `areatrigger_create_properties_orbit`"))
305 {
306 do
307 {
308 Field* circularMovementInfoFields = circularMovementInfos->Fetch();
309 AreaTriggerCreatePropertiesId createPropertiesId = { circularMovementInfoFields[0].GetUInt32(), circularMovementInfoFields[1].GetBool() };
310
311 AreaTriggerCreateProperties* createProperties = Trinity::Containers::MapGetValuePtr(_areaTriggerCreateProperties, createPropertiesId);
312 if (!createProperties)
313 {
314 TC_LOG_ERROR("sql.sql", "Table `areatrigger_create_properties_orbit` reference invalid AreaTriggerCreatePropertiesId: (Id: {}, IsCustom: {})", createPropertiesId.Id, uint32(createPropertiesId.IsCustom));
315 continue;
316 }
317
318 AreaTriggerOrbitInfo& orbit = createProperties->Movement.emplace<AreaTriggerOrbitInfo>();
319
320 orbit.ExtraTimeForBlending = circularMovementInfoFields[2].GetInt32();
321
322#define VALIDATE_AND_SET_FLOAT(Float, Value) \
323 orbit.Float = Value; \
324 if (!std::isfinite(orbit.Float)) \
325 { \
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; \
329 }
330
331 VALIDATE_AND_SET_FLOAT(Radius, circularMovementInfoFields[3].GetFloat());
332 VALIDATE_AND_SET_FLOAT(BlendFromRadius, circularMovementInfoFields[4].GetFloat());
333 VALIDATE_AND_SET_FLOAT(InitialAngle, circularMovementInfoFields[5].GetFloat());
334 VALIDATE_AND_SET_FLOAT(ZOffset, circularMovementInfoFields[6].GetFloat());
335
336#undef VALIDATE_AND_SET_FLOAT
337
338 orbit.CounterClockwise = circularMovementInfoFields[7].GetBool();
339 orbit.CanLoop = circularMovementInfoFields[8].GetBool();
340 }
341 while (circularMovementInfos->NextRow());
342 }
343 else
344 {
345 TC_LOG_INFO("server.loading", ">> Loaded 0 AreaTrigger templates circular movement infos. DB table `areatrigger_create_properties_orbit` is empty.");
346 }
347
348 TC_LOG_INFO("server.loading", ">> Loaded {} spell areatrigger templates in {} ms.", _areaTriggerTemplateStore.size(), GetMSTimeDiffToNow(oldMSTime));
349}
350
352{
353 // build single time for check spawnmask
354 std::unordered_map<uint32, std::set<Difficulty>> spawnMasks;
355 for (MapDifficultyEntry const* mapDifficulty : sMapDifficultyStore)
356 spawnMasks[mapDifficulty->MapID].insert(Difficulty(mapDifficulty->DifficultyID));
357
358 uint32 oldMSTime = getMSTime();
359 // 0 1 2 3 4 5 6 7 8 9 10 11 12
360 if (QueryResult templates = WorldDatabase.Query("SELECT SpawnId, AreaTriggerCreatePropertiesId, IsCustom, MapId, SpawnDifficulties, PosX, PosY, PosZ, Orientation, PhaseUseFlags, PhaseId, PhaseGroup, ScriptName FROM `areatrigger`"))
361 {
362 do
363 {
364 Field* fields = templates->Fetch();
365
366 ObjectGuid::LowType spawnId = fields[0].GetUInt64();
367 AreaTriggerCreatePropertiesId createPropertiesId = { fields[1].GetUInt32(), fields[2].GetBool() };
368 WorldLocation location(fields[3].GetUInt32(), fields[5].GetFloat(), fields[6].GetFloat(), fields[7].GetFloat(), fields[8].GetFloat());
369
370 AreaTriggerCreateProperties const* createProperties = GetAreaTriggerCreateProperties(createPropertiesId);
371 if (!createProperties)
372 {
373 TC_LOG_ERROR("sql.sql", "Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) that doesn't exist for SpawnId {}",
374 createPropertiesId.Id, uint32(createPropertiesId.IsCustom), spawnId);
375 continue;
376 }
377
378 if (createProperties->Flags != AreaTriggerCreatePropertiesFlag::None)
379 {
380 TC_LOG_ERROR("sql.sql", "Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with non - zero flags",
381 createPropertiesId.Id, uint32(createPropertiesId.IsCustom));
382 continue;
383 }
384
385 if (createProperties->ScaleCurveId || createProperties->MorphCurveId || createProperties->FacingCurveId || createProperties->MoveCurveId)
386 {
387 TC_LOG_ERROR("sql.sql", "Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with curve values",
388 createPropertiesId.Id, uint32(createPropertiesId.IsCustom));
389 continue;
390 }
391
392 if (createProperties->TimeToTargetScale)
393 {
394 TC_LOG_ERROR("sql.sql", "Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with time to target values",
395 createPropertiesId.Id, uint32(createPropertiesId.IsCustom));
396 continue;
397 }
398
399 if (!std::holds_alternative<std::monostate>(createProperties->Movement))
400 {
401 std::string_view movementType = std::visit([&]<typename MovementType>(MovementType const&)
402 {
403 if constexpr (std::is_same_v<MovementType, AreaTriggerCreateProperties::SplineInfo>)
404 return "spline"sv;
405 else if constexpr (std::is_same_v<MovementType, AreaTriggerOrbitInfo>)
406 return "orbit"sv;
407 else if constexpr (std::is_same_v<MovementType, std::monostate>)
408 return ""sv;
409 else
410 static_assert(Trinity::dependant_false_v<MovementType>, "Unsupported movement type");
411 }, createProperties->Movement);
412
413 TC_LOG_ERROR("sql.sql", "Table `areatrigger` has listed AreaTriggerCreatePropertiesId (Id: {}, IsCustom: {}) with {}",
414 createPropertiesId.Id, uint32(createPropertiesId.IsCustom), movementType);
415 continue;
416 }
417
418 if (!MapManager::IsValidMapCoord(location))
419 {
420 TC_LOG_ERROR("sql.sql", "Table `areatrigger` has listed an invalid position: SpawnId: {}, Location {}",
421 spawnId, location);
422 continue;
423 }
424
425 std::vector<Difficulty> difficulties = sObjectMgr->ParseSpawnDifficulties(fields[4].GetStringView(), "areatrigger", spawnId, location.GetMapId(), spawnMasks[location.GetMapId()]);
426 if (difficulties.empty())
427 {
428 TC_LOG_DEBUG("sql.sql", "Table `areatrigger` has areatrigger (GUID: {}) that is not spawned in any difficulty, skipped.", spawnId);
429 continue;
430 }
431
432 AreaTriggerSpawn& spawn = _areaTriggerSpawnsBySpawnId[spawnId];
433 spawn.spawnId = spawnId;
434 spawn.mapId = location.GetMapId();
435 spawn.Id = createPropertiesId;
436 spawn.spawnPoint.Relocate(location);
437
438 spawn.phaseUseFlags = fields[9].GetUInt8();
439 spawn.phaseId = fields[10].GetUInt32();
440 spawn.phaseGroup = fields[11].GetUInt32();
441
442 spawn.scriptId = sObjectMgr->GetScriptId(fields[12].GetStringView());
443 spawn.spawnGroupData = sObjectMgr->GetLegacySpawnGroup();
444
445 // Add the trigger to a map::cell map, which is later used by GridLoader to query
447 for (Difficulty difficulty : difficulties)
448 _areaTriggerSpawnsByLocation[{ spawn.mapId, difficulty }][cellCoord.GetId()].insert(spawnId);
449 } while (templates->NextRow());
450 }
451
452 TC_LOG_INFO("server.loading", ">> Loaded {} areatrigger spawns in {} ms.", _areaTriggerSpawnsBySpawnId.size(), GetMSTimeDiffToNow(oldMSTime));
453}
454
456{
457 return Trinity::Containers::MapGetValuePtr(_areaTriggerTemplateStore, areaTriggerId);
458}
459
461{
462 return Trinity::Containers::MapGetValuePtr(_areaTriggerCreateProperties, areaTriggerCreatePropertiesId);
463}
464
465std::set<ObjectGuid::LowType> const* AreaTriggerDataStore::GetAreaTriggersForMapAndCell(uint32 mapId, Difficulty difficulty, uint32 cellId) const
466{
467 if (auto* atForMapAndDifficulty = Trinity::Containers::MapGetValuePtr(_areaTriggerSpawnsByLocation, { mapId, difficulty }))
468 return Trinity::Containers::MapGetValuePtr(*atForMapAndDifficulty, cellId);
469
470 return nullptr;
471}
472
474{
475 return Trinity::Containers::MapGetValuePtr(_areaTriggerSpawnsBySpawnId, spawnId);
476}
477
479{
480 static AreaTriggerDataStore instance;
481 return &instance;
482}
#define VALIDATE_AND_SET_CURVE(Curve, Value)
#define VALIDATE_AND_SET_FLOAT(Float, Value)
AreaTriggerCreatePropertiesFlag
AreaTriggerActionTypes
@ AREATRIGGER_ACTION_TELEPORT
@ AREATRIGGER_ACTION_MAX
AreaTriggerFlag
AreaTriggerActionUserTypes
@ AREATRIGGER_ACTION_USER_MAX
DB2Storage< MapDifficultyEntry > sMapDifficultyStore("MapDifficulty.db2", &MapDifficultyLoadInfo::Instance)
AreaTriggerShapeType
Definition DBCEnums.h:196
AreaTriggerActionSetFlag
Definition DBCEnums.h:175
Difficulty
Definition DBCEnums.h:932
@ DIFFICULTY_NONE
Definition DBCEnums.h:933
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint32_t uint32
Definition Define.h:154
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_INFO(filterType__, message__,...)
Definition Log.h:184
#define sObjectMgr
Definition ObjectMgr.h:1885
#define DEFINE_FIELD_ACCESSOR_CACHE_ANONYMOUS(result_type, fields_list)
#define sSpellMgr
Definition SpellMgr.h:812
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
EnumFlag< AreaTriggerCreatePropertiesFlag > Flags
AreaTriggerCreatePropertiesId Id
std::variant< std::monostate, SplineInfo, AreaTriggerOrbitInfo > Movement
AreaTriggerTemplate const * Template
AreaTriggerTemplate const * GetAreaTriggerTemplate(AreaTriggerId const &areaTriggerId) const
AreaTriggerCreateProperties const * GetAreaTriggerCreateProperties(AreaTriggerCreatePropertiesId const &areaTriggerCreatePropertiesId) const
std::set< ObjectGuid::LowType > const * GetAreaTriggersForMapAndCell(uint32 mapId, Difficulty difficulty, uint32 cellId) const
AreaTriggerSpawn const * GetAreaTriggerSpawn(ObjectGuid::LowType spawnId) const
static AreaTriggerDataStore * Instance()
EnumFlag< AreaTriggerActionSetFlag > ActionSetFlags
std::vector< AreaTriggerAction > Actions
EnumFlag< AreaTriggerFlag > Flags
Class used to access individual fields of database query result.
Definition Field.h:94
uint64 GetUInt64() const noexcept
Definition Field.cpp:71
bool GetBool() const noexcept
Definition Field.h:102
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
uint8 GetUInt8() const noexcept
Definition Field.cpp:29
int32 GetInt32() const noexcept
Definition Field.cpp:64
static bool IsValidMapCoord(uint32 mapid, float x, float y)
Definition MapManager.h:83
uint64 LowType
Definition ObjectGuid.h:321
constexpr uint32 GetMapId() const
Definition Position.h:216
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
CellCoord ComputeCellCoord(float x, float y)
AreaTriggerActionTypes ActionType
AreaTriggerActionUserTypes TargetType
std::vector< TaggedPosition< Position::XY > > PolygonVerticesTarget
std::vector< TaggedPosition< Position::XY > > PolygonVertices
std::variant< Sphere, Box, Polygon, Cylinder, Disk, BoundedPlane > Data
AreaTriggerCreatePropertiesId Id
uint32 GetId() const
constexpr float GetPositionX() const
Definition Position.h:87
constexpr float GetPositionY() const
Definition Position.h:88
constexpr void Relocate(float x, float y)
Definition Position.h:74
uint32 scriptId
Definition SpawnData.h:144
uint8 phaseUseFlags
Definition SpawnData.h:137
uint32 phaseId
Definition SpawnData.h:138
Position spawnPoint
Definition SpawnData.h:136
uint32 phaseGroup
Definition SpawnData.h:139
SpawnGroupTemplateData const * spawnGroupData
Definition SpawnData.h:124
uint64 spawnId
Definition SpawnData.h:121
constexpr void UpdateData(std::span< V, Extent > data) noexcept
Definition Hash.h:85
std::size_t operator()(AreaTriggerId const &value) const noexcept