aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-10-01 18:56:35 +0200
committerShauren <shauren.trinity@gmail.com>2023-10-01 18:56:35 +0200
commitc676d1477239aec4d0b235a410e5627a7070a86e (patch)
tree2b5b119de0bef124dffb18a61fb4c2b90e53e51d /src
parent2037749ddd1d0dd7a0113d3f86e21a3a1d2425b1 (diff)
Core/AreaTriggers: Implement missing functionality
* Scale curves are now taken into account when searching for units inside * Implemented SpellModOp::Radius for areatrigger radius * Implemented OverrideMoveCurve updatefields - overrides areatrigger position * Implemented FacingCurve and AREATRIGGER_FLAG_HAS_ABSOLUTE_ORIENTATION * Implemented ***Target fields for all shape types * Fixed facing calculation for areatriggers with spline movement
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp396
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.h61
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp18
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h2
-rw-r--r--src/server/game/Entities/Object/Object.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp9
-rw-r--r--src/server/game/Globals/AreaTriggerDataStore.cpp7
7 files changed, 385 insertions, 110 deletions
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
index a17a4f4cc82..8ceeab3b22e 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp
@@ -43,8 +43,8 @@
#include "advstd.h"
#include <bit>
-AreaTrigger::AreaTrigger() : WorldObject(false), MapObject(), _spawnId(0), _aurEff(nullptr), _maxSearchRadius(0.0f),
- _duration(0), _totalDuration(0), _timeSinceCreated(0), _previousCheckOrientation(std::numeric_limits<float>::infinity()),
+AreaTrigger::AreaTrigger() : WorldObject(false), MapObject(), _spawnId(0), _aurEff(nullptr),
+ _duration(0), _totalDuration(0), _timeSinceCreated(0), _verticesUpdatePreviousOrientation(std::numeric_limits<float>::infinity()),
_isRemoved(false), _reachedDestination(true), _lastSplineIndex(0), _movementTime(0),
_areaTriggerCreateProperties(nullptr), _areaTriggerTemplate(nullptr)
{
@@ -101,13 +101,14 @@ void AreaTrigger::RemoveFromWorld()
}
}
-bool AreaTrigger::Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spellInfo, Position const& pos, int32 duration, SpellCastVisual spellVisual, Spell const* spell, AuraEffect const* aurEff)
+bool AreaTrigger::Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spellInfo, Position const& pos, int32 duration, SpellCastVisual spellVisual, Spell* spell, AuraEffect const* aurEff)
{
_targetGuid = target ? target->GetGUID() : ObjectGuid::Empty;
_aurEff = aurEff;
SetMap(caster->GetMap());
Relocate(pos);
+ RelocateStationaryPosition(pos);
if (!IsPositionValid())
{
TC_LOG_ERROR("entities.areatrigger", "AreaTrigger (areaTriggerCreatePropertiesId {}) not created. Invalid coordinates (X: {} Y: {})", areaTriggerCreatePropertiesId, GetPositionX(), GetPositionY());
@@ -135,7 +136,6 @@ bool AreaTrigger::Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Uni
SetObjectScale(1.0f);
_shape = GetCreateProperties()->Shape;
- _maxSearchRadius = GetCreateProperties()->GetMaxSearchRadius();
auto areaTriggerData = m_values.ModifyValue(&AreaTrigger::m_areaTriggerData);
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::Caster), caster->GetGUID());
@@ -147,11 +147,24 @@ bool AreaTrigger::Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Uni
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::SpellVisual).ModifyValue(&UF::SpellCastVisual::SpellXSpellVisualID), spellVisual.SpellXSpellVisualID);
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::SpellVisual).ModifyValue(&UF::SpellCastVisual::ScriptVisualID), spellVisual.ScriptVisualID);
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::TimeToTargetScale), GetCreateProperties()->TimeToTargetScale != 0 ? GetCreateProperties()->TimeToTargetScale : *m_areaTriggerData->Duration);
- SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::BoundsRadius2D), GetMaxSearchRadius());
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::BoundsRadius2D), GetCreateProperties()->GetMaxSearchRadius());
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::DecalPropertiesID), GetCreateProperties()->DecalPropertiesId);
SetScaleCurve(areaTriggerData.ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve), GetCreateProperties()->ExtraScale);
+ if (Player const* modOwner = caster->GetSpellModOwner())
+ {
+ float multiplier = 1.0f;
+ int32 flat = 0;
+ modOwner->GetSpellModValues(spellInfo, SpellModOp::Radius, spell, *m_areaTriggerData->BoundsRadius2D, &flat, &multiplier);
+ if (multiplier != 1.0f)
+ {
+ AreaTriggerScaleCurveTemplate overrideScale;
+ overrideScale.Curve = multiplier;
+ SetScaleCurve(areaTriggerData.ModifyValue(&UF::AreaTriggerData::OverrideScaleCurve), overrideScale);
+ }
+ }
+
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::VisualAnim).ModifyValue(&UF::VisualAnim::AnimationDataID), GetCreateProperties()->AnimId);
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::VisualAnim).ModifyValue(&UF::VisualAnim::AnimKitID), GetCreateProperties()->AnimKitId);
if (GetTemplate() && GetTemplate()->HasFlag(AREATRIGGER_FLAG_UNK3))
@@ -220,7 +233,7 @@ bool AreaTrigger::Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Uni
return true;
}
-AreaTrigger* AreaTrigger::CreateAreaTrigger(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spellInfo, Position const& pos, int32 duration, SpellCastVisual spellVisual, Spell const* spell /*= nullptr*/, AuraEffect const* aurEff /*= nullptr*/)
+AreaTrigger* AreaTrigger::CreateAreaTrigger(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spellInfo, Position const& pos, int32 duration, SpellCastVisual spellVisual, Spell* spell /*= nullptr*/, AuraEffect const* aurEff /*= nullptr*/)
{
AreaTrigger* at = new AreaTrigger();
if (!at->Create(areaTriggerCreatePropertiesId, caster, target, spellInfo, pos, duration, spellVisual, spell, aurEff))
@@ -256,6 +269,7 @@ bool AreaTrigger::CreateServer(Map* map, AreaTriggerTemplate const* areaTriggerT
{
SetMap(map);
Relocate(position.spawnPoint);
+ RelocateStationaryPosition(position.spawnPoint);
if (!IsPositionValid())
{
TC_LOG_ERROR("entities.areatrigger", "AreaTriggerServer (id {}) not created. Invalid coordinates (X: {} Y: {})",
@@ -274,8 +288,9 @@ bool AreaTrigger::CreateServer(Map* map, AreaTriggerTemplate const* areaTriggerT
SetObjectScale(1.0f);
SetDuration(-1);
+ _shape = position.Shape;
+
auto areaTriggerData = m_values.ModifyValue(&AreaTrigger::m_areaTriggerData);
- SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::BoundsRadius2D), GetMaxSearchRadius());
if (position.SpellForVisuals)
{
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(*position.SpellForVisuals, DIFFICULTY_NONE);
@@ -284,6 +299,7 @@ bool AreaTrigger::CreateServer(Map* map, AreaTriggerTemplate const* areaTriggerT
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::SpellVisual).ModifyValue(&UF::SpellCastVisual::ScriptVisualID), 0);
}
+ SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::BoundsRadius2D), _shape.GetMaxSearchRadius());
if (IsServerSide())
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::DecalPropertiesID), 24); // blue decal, for .debug areatrigger visibility
@@ -291,9 +307,6 @@ bool AreaTrigger::CreateServer(Map* map, AreaTriggerTemplate const* areaTriggerT
SetUpdateFieldValue(areaTriggerData.ModifyValue(&UF::AreaTriggerData::VisualAnim).ModifyValue(&UF::VisualAnim::AnimationDataID), -1);
- _shape = position.Shape;
- _maxSearchRadius = _shape.GetMaxSearchRadius();
-
if (position.phaseUseFlags || position.phaseId || position.phaseGroup)
PhasingHandler::InitDbPhaseShift(GetPhaseShift(), position.phaseUseFlags, position.phaseId, position.phaseGroup);
@@ -314,17 +327,45 @@ void AreaTrigger::Update(uint32 diff)
if (!IsServerSide())
{
// "If" order matter here, Orbit > Attached > Splines
- if (HasOrbit())
+ if (HasOverridePosition())
+ {
+ UpdateOverridePosition();
+ }
+ else if (HasOrbit())
{
UpdateOrbitPosition(diff);
}
else if (GetTemplate() && GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_ATTACHED))
{
if (Unit* target = GetTarget())
- GetMap()->AreaTriggerRelocation(this, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation());
+ {
+ float orientation = 0.0f;
+ if (GetCreateProperties()->FacingCurveId)
+ orientation = sDB2Manager.GetCurveValueAt(GetCreateProperties()->FacingCurveId, GetProgress());
+
+ if (!GetTemplate() || !GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_ABSOLUTE_ORIENTATION))
+ orientation += target->GetOrientation();
+
+ GetMap()->AreaTriggerRelocation(this, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), orientation);
+ }
}
- else
+ else if (HasSplines())
+ {
UpdateSplinePosition(diff);
+ }
+ else
+ {
+ if (GetCreateProperties()->FacingCurveId)
+ {
+ float orientation = sDB2Manager.GetCurveValueAt(GetCreateProperties()->FacingCurveId, GetProgress());
+ if (!GetTemplate() || !GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_ABSOLUTE_ORIENTATION))
+ orientation += GetStationaryO();
+
+ SetOrientation(orientation);
+ }
+
+ UpdateShape();
+ }
}
if (GetDuration() != -1)
@@ -351,6 +392,58 @@ void AreaTrigger::Remove()
}
}
+void AreaTrigger::SetOverrideScaleCurve(float overrideScale)
+{
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideScaleCurve), overrideScale);
+}
+
+void AreaTrigger::SetOverrideScaleCurve(std::array<DBCPosition2D, 2> const& points, Optional<uint32> startTimeOffset, CurveInterpolationMode interpolation)
+{
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideScaleCurve), points, startTimeOffset, interpolation);
+}
+
+void AreaTrigger::ClearOverrideScaleCurve()
+{
+ ClearScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideScaleCurve));
+}
+
+void AreaTrigger::SetExtraScaleCurve(float extraScale)
+{
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve), extraScale);
+}
+
+void AreaTrigger::SetExtraScaleCurve(std::array<DBCPosition2D, 2> const& points, Optional<uint32> startTimeOffset, CurveInterpolationMode interpolation)
+{
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve), points, startTimeOffset, interpolation);
+}
+
+void AreaTrigger::ClearExtraScaleCurve()
+{
+ ClearScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::ExtraScaleCurve));
+}
+
+void AreaTrigger::SetOverrideMoveCurve(float x, float y, float z)
+{
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveX), x);
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveY), y);
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveZ), z);
+}
+
+void AreaTrigger::SetOverrideMoveCurve(std::array<DBCPosition2D, 2> const& xCurvePoints, std::array<DBCPosition2D, 2> const& yCurvePoints,
+ std::array<DBCPosition2D, 2> const& zCurvePoints, Optional<uint32> startTimeOffset, CurveInterpolationMode interpolation)
+{
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveX), xCurvePoints, startTimeOffset, interpolation);
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveY), yCurvePoints, startTimeOffset, interpolation);
+ SetScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveZ), zCurvePoints, startTimeOffset, interpolation);
+}
+
+void AreaTrigger::ClearOverrideMoveCurve()
+{
+ ClearScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveX));
+ ClearScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveY));
+ ClearScaleCurve(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::OverrideMoveCurveZ));
+}
+
void AreaTrigger::SetDuration(int32 newDuration)
{
_duration = newDuration;
@@ -372,18 +465,43 @@ void AreaTrigger::_UpdateDuration(int32 newDuration)
});
}
+float AreaTrigger::CalcCurrentScale() const
+{
+ float scale = 1.0f;
+ if (m_areaTriggerData->OverrideScaleCurve->OverrideActive)
+ scale *= std::max(GetScaleCurveValue(*m_areaTriggerData->OverrideScaleCurve, m_areaTriggerData->TimeToTargetScale), 0.000001f);
+ else if (AreaTriggerCreateProperties const* createProperties = GetCreateProperties())
+ if (createProperties->ScaleCurveId)
+ scale *= std::max(sDB2Manager.GetCurveValueAt(createProperties->ScaleCurveId, GetScaleCurveProgress(*m_areaTriggerData->OverrideScaleCurve, m_areaTriggerData->TimeToTargetScale)), 0.000001f);
+
+ scale *= std::max(GetScaleCurveValue(*m_areaTriggerData->ExtraScaleCurve, m_areaTriggerData->TimeToTargetExtraScale), 0.000001f);
+
+ return scale;
+}
+
float AreaTrigger::GetProgress() const
{
- return GetTimeSinceCreated() < GetTimeToTargetScale() ? float(GetTimeSinceCreated()) / float(GetTimeToTargetScale()) : 1.0f;
+ if (_totalDuration <= 0)
+ return 1.0f;
+
+ return std::clamp(float(GetTimeSinceCreated()) / float(GetTotalDuration()), 0.0f, 1.0f);
}
-float AreaTrigger::GetScaleCurveValue(UF::ScaleCurve const& scaleCurve, float x) const
+float AreaTrigger::GetScaleCurveProgress(UF::ScaleCurve const& scaleCurve, uint32 timeTo) const
+{
+ if (!timeTo)
+ return 0.0f;
+
+ return std::clamp(float(GetTimeSinceCreated() - scaleCurve.StartTimeOffset) / float(timeTo), 0.0f, 1.0f);
+}
+
+float AreaTrigger::GetScaleCurveValueAtProgress(UF::ScaleCurve const& scaleCurve, float x) const
{
ASSERT(*scaleCurve.OverrideActive, "ScaleCurve must be active to evaluate it");
// unpack ParameterCurve
- if (*scaleCurve.ParameterCurve & 1)
- return advstd::bit_cast<float>(*scaleCurve.ParameterCurve & ~1);
+ if (*scaleCurve.ParameterCurve & 1u)
+ return advstd::bit_cast<float>(*scaleCurve.ParameterCurve & ~1u);
std::array<DBCPosition2D, 2> points;
for (std::size_t i = 0; i < scaleCurve.Points.size(); ++i)
@@ -395,7 +513,38 @@ float AreaTrigger::GetScaleCurveValue(UF::ScaleCurve const& scaleCurve, float x)
return sDB2Manager.GetCurveValueAt(mode, std::span(points.begin(), pointCount), x);
}
-void AreaTrigger::SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false>&& scaleCurveMutator, Optional<AreaTriggerScaleCurveTemplate> const& curve)
+float AreaTrigger::GetScaleCurveValue(UF::ScaleCurve const& scaleCurve, uint32 timeTo) const
+{
+ return GetScaleCurveValueAtProgress(scaleCurve, GetScaleCurveProgress(scaleCurve, timeTo));
+}
+
+void AreaTrigger::SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false> scaleCurveMutator, float constantValue)
+{
+ AreaTriggerScaleCurveTemplate curveTemplate;
+ curveTemplate.Curve = constantValue;
+ SetScaleCurve(scaleCurveMutator, curveTemplate);
+}
+
+void AreaTrigger::SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false> scaleCurveMutator, std::array<DBCPosition2D, 2> const& points,
+ Optional<uint32> startTimeOffset, CurveInterpolationMode interpolation)
+{
+ AreaTriggerScaleCurvePointsTemplate curve;
+ curve.Mode = interpolation;
+ curve.Points = points;
+
+ AreaTriggerScaleCurveTemplate curveTemplate;
+ curveTemplate.StartTimeOffset = startTimeOffset.value_or(GetTimeSinceCreated());
+ curveTemplate.Curve = curve;
+
+ SetScaleCurve(scaleCurveMutator, curveTemplate);
+}
+
+void AreaTrigger::ClearScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false> scaleCurveMutator)
+{
+ SetScaleCurve(scaleCurveMutator, {});
+}
+
+void AreaTrigger::SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false> scaleCurveMutator, Optional<AreaTriggerScaleCurveTemplate> const& curve)
{
if (!curve)
{
@@ -491,10 +640,10 @@ void AreaTrigger::UpdateTargetList()
{
if (ConditionContainer const* conditions = sConditionMgr->GetConditionsForAreaTrigger(GetTemplate()->Id.Id, GetTemplate()->Id.IsServerSide))
{
- targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [conditions](Unit* target)
+ Trinity::Containers::EraseIf(targetList, [conditions](Unit const* target)
{
return !sConditionMgr->IsObjectMeetToConditions(target, *conditions);
- }), targetList.end());
+ });
}
}
@@ -518,106 +667,123 @@ void AreaTrigger::SearchUnits(std::vector<Unit*>& targetList, float radius, bool
void AreaTrigger::SearchUnitInSphere(std::vector<Unit*>& targetList)
{
- float radius = _shape.SphereDatas.Radius;
- if (GetTemplate() && GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_DYNAMIC_SHAPE))
- {
- if (GetCreateProperties()->MorphCurveId)
- {
- radius = G3D::lerp(_shape.SphereDatas.Radius,
- _shape.SphereDatas.RadiusTarget,
- sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, GetProgress()));
- }
- }
+ float progress = GetProgress();
+ if (GetCreateProperties()->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, progress);
+
+ float scale = CalcCurrentScale();
+ float radius = G3D::lerp(_shape.SphereDatas.Radius, _shape.SphereDatas.RadiusTarget, progress) * scale;
SearchUnits(targetList, radius, true);
}
void AreaTrigger::SearchUnitInBox(std::vector<Unit*>& targetList)
{
- SearchUnits(targetList, GetMaxSearchRadius(), false);
+ float progress = GetProgress();
+ if (GetCreateProperties()->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, progress);
- Position const& boxCenter = GetPosition();
- float extentsX = _shape.BoxDatas.Extents[0];
- float extentsY = _shape.BoxDatas.Extents[1];
- float extentsZ = _shape.BoxDatas.Extents[2];
+ float scale = CalcCurrentScale();
+ float extentsX = G3D::lerp(_shape.BoxDatas.Extents[0], _shape.BoxDatas.ExtentsTarget[0], progress) * scale;
+ float extentsY = G3D::lerp(_shape.BoxDatas.Extents[1], _shape.BoxDatas.ExtentsTarget[1], progress) * scale;
+ float extentsZ = G3D::lerp(_shape.BoxDatas.Extents[2], _shape.BoxDatas.ExtentsTarget[2], progress) * scale;
+ float radius = std::sqrt(extentsX * extentsX + extentsY * extentsY);
+
+ SearchUnits(targetList, radius, false);
- targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [boxCenter, extentsX, extentsY, extentsZ](Unit* unit) -> bool
+ Position const& boxCenter = GetPosition();
+ Trinity::Containers::EraseIf(targetList, [boxCenter, extentsX, extentsY, extentsZ](Unit const* unit) -> bool
{
- return !unit->IsWithinBox(boxCenter, extentsX, extentsY, extentsZ/2);
- }), targetList.end());
+ return !unit->IsWithinBox(boxCenter, extentsX, extentsY, extentsZ / 2);
+ });
}
void AreaTrigger::SearchUnitInPolygon(std::vector<Unit*>& targetList)
{
- SearchUnits(targetList, GetMaxSearchRadius(), false);
+ float progress = GetProgress();
+ if (GetCreateProperties()->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, progress);
- float height = _shape.PolygonDatas.Height;
+ float height = G3D::lerp(_shape.PolygonDatas.Height, _shape.PolygonDatas.HeightTarget, progress);
float minZ = GetPositionZ() - height;
float maxZ = GetPositionZ() + height;
- targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [this, minZ, maxZ](Unit* unit) -> bool
+ SearchUnits(targetList, GetMaxSearchRadius(), false);
+
+ Trinity::Containers::EraseIf(targetList, [this, minZ, maxZ](Unit const* unit) -> bool
{
- return !CheckIsInPolygon2D(unit)
- || unit->GetPositionZ() < minZ
- || unit->GetPositionZ() > maxZ;
- }), targetList.end());
+ return unit->GetPositionZ() < minZ
+ || unit->GetPositionZ() > maxZ
+ || !CheckIsInPolygon2D(unit);
+ });
}
void AreaTrigger::SearchUnitInCylinder(std::vector<Unit*>& targetList)
{
- SearchUnits(targetList, GetMaxSearchRadius(), false);
+ float progress = GetProgress();
+ if (GetCreateProperties()->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, progress);
+
+ float scale = CalcCurrentScale();
+ float radius = G3D::lerp(_shape.CylinderDatas.Radius, _shape.CylinderDatas.RadiusTarget, progress) * scale;
+ float height = G3D::lerp(_shape.CylinderDatas.Height, _shape.CylinderDatas.HeightTarget, progress);
+ if (!m_areaTriggerData->HeightIgnoresScale)
+ height *= scale;
- float height = _shape.CylinderDatas.Height;
float minZ = GetPositionZ() - height;
float maxZ = GetPositionZ() + height;
- targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [minZ, maxZ](Unit* unit) -> bool
+ SearchUnits(targetList, radius, false);
+
+ Trinity::Containers::EraseIf(targetList, [minZ, maxZ](Unit const* unit) -> bool
{
return unit->GetPositionZ() < minZ
|| unit->GetPositionZ() > maxZ;
- }), targetList.end());
+ });
}
void AreaTrigger::SearchUnitInDisk(std::vector<Unit*>& targetList)
{
- float innerRadius = _shape.DiskDatas.InnerRadius;
- float outerRadius = _shape.DiskDatas.OuterRadius;
- float height = _shape.DiskDatas.Height;
-
- if (GetTemplate() && GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_DYNAMIC_SHAPE))
- {
- float progress = GetProgress();
- if (GetCreateProperties()->MorphCurveId)
- progress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, progress);
+ float progress = GetProgress();
+ if (GetCreateProperties()->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, progress);
- innerRadius = G3D::lerp(_shape.DiskDatas.InnerRadius, _shape.DiskDatas.InnerRadiusTarget, progress);
- outerRadius = G3D::lerp(_shape.DiskDatas.OuterRadius, _shape.DiskDatas.OuterRadiusTarget, progress);
- height = G3D::lerp(_shape.DiskDatas.Height, _shape.DiskDatas.HeightTarget, progress);
- }
-
- SearchUnits(targetList, outerRadius, false);
+ float scale = CalcCurrentScale();
+ float innerRadius = G3D::lerp(_shape.DiskDatas.InnerRadius, _shape.DiskDatas.InnerRadiusTarget, progress) * scale;
+ float outerRadius = G3D::lerp(_shape.DiskDatas.OuterRadius, _shape.DiskDatas.OuterRadiusTarget, progress) * scale;
+ float height = G3D::lerp(_shape.DiskDatas.Height, _shape.DiskDatas.HeightTarget, progress);
+ if (!m_areaTriggerData->HeightIgnoresScale)
+ height *= scale;
float minZ = GetPositionZ() - height;
float maxZ = GetPositionZ() + height;
- targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [this, innerRadius, minZ, maxZ](Unit const* unit) -> bool
+ SearchUnits(targetList, outerRadius, false);
+
+ Trinity::Containers::EraseIf(targetList, [this, innerRadius, minZ, maxZ](Unit const* unit) -> bool
{
return unit->IsInDist2d(this, innerRadius) || unit->GetPositionZ() < minZ || unit->GetPositionZ() > maxZ;
- }), targetList.end());
+ });
}
void AreaTrigger::SearchUnitInBoundedPlane(std::vector<Unit*>& targetList)
{
- SearchUnits(targetList, GetMaxSearchRadius(), false);
+ float progress = GetProgress();
+ if (GetCreateProperties()->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, progress);
- Position const& boxCenter = GetPosition();
- float extentsX = _shape.BoxDatas.Extents[0];
- float extentsY = _shape.BoxDatas.Extents[1];
+ float scale = CalcCurrentScale();
+ float extentsX = G3D::lerp(_shape.BoundedPlaneDatas.Extents[0], _shape.BoundedPlaneDatas.ExtentsTarget[0], progress) * scale;
+ float extentsY = G3D::lerp(_shape.BoundedPlaneDatas.Extents[1], _shape.BoundedPlaneDatas.ExtentsTarget[1], progress) * scale;
+ float radius = std::sqrt(extentsX * extentsX + extentsY * extentsY);
- targetList.erase(std::remove_if(targetList.begin(), targetList.end(), [boxCenter, extentsX, extentsY](Unit const* unit) -> bool
+ SearchUnits(targetList, radius, false);
+
+ Position const& boxCenter = GetPosition();
+ Trinity::Containers::EraseIf(targetList, [boxCenter, extentsX, extentsY](Unit const* unit) -> bool
{
return !unit->IsWithinBox(boxCenter, extentsX, extentsY, MAP_SIZE);
- }), targetList.end());
+ });
}
void AreaTrigger::HandleUnitEnterExit(std::vector<Unit*> const& newTargetList)
@@ -707,15 +873,35 @@ uint32 AreaTrigger::GetFaction() const
return 0;
}
-void AreaTrigger::UpdatePolygonOrientation()
+float AreaTrigger::GetMaxSearchRadius() const
+{
+ return *m_areaTriggerData->BoundsRadius2D * CalcCurrentScale();
+}
+
+void AreaTrigger::UpdatePolygonVertices()
{
float newOrientation = GetOrientation();
// No need to recalculate, orientation didn't change
- if (G3D::fuzzyEq(_previousCheckOrientation, newOrientation))
+ if (G3D::fuzzyEq(_verticesUpdatePreviousOrientation, newOrientation) && GetCreateProperties()->PolygonVerticesTarget.empty())
return;
_polygonVertices.assign(GetCreateProperties()->PolygonVertices.begin(), GetCreateProperties()->PolygonVertices.end());
+ if (!GetCreateProperties()->PolygonVerticesTarget.empty())
+ {
+ float progress = GetProgress();
+ if (GetCreateProperties()->MorphCurveId)
+ progress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MorphCurveId, progress);
+
+ for (std::size_t i = 0; i < _polygonVertices.size(); ++i)
+ {
+ Position& vertex = _polygonVertices[i];
+ Position const& vertexTarget = GetCreateProperties()->PolygonVerticesTarget[i].Pos;
+
+ vertex.m_positionX = G3D::lerp(vertex.GetPositionX(), vertexTarget.GetPositionX(), progress);
+ vertex.m_positionY = G3D::lerp(vertex.GetPositionY(), vertexTarget.GetPositionY(), progress);
+ }
+ }
float angleSin = std::sin(newOrientation);
float angleCos = std::cos(newOrientation);
@@ -728,7 +914,7 @@ void AreaTrigger::UpdatePolygonOrientation()
vertice.Relocate(x, y);
}
- _previousCheckOrientation = newOrientation;
+ _verticesUpdatePreviousOrientation = newOrientation;
}
bool AreaTrigger::CheckIsInPolygon2D(Position const* pos) const
@@ -800,10 +986,17 @@ bool AreaTrigger::CheckIsInPolygon2D(Position const* pos) const
return locatedInPolygon;
}
+bool AreaTrigger::HasOverridePosition() const
+{
+ return m_areaTriggerData->OverrideMoveCurveX->OverrideActive
+ && m_areaTriggerData->OverrideMoveCurveY->OverrideActive
+ && m_areaTriggerData->OverrideMoveCurveZ->OverrideActive;
+}
+
void AreaTrigger::UpdateShape()
{
if (_shape.IsPolygon())
- UpdatePolygonOrientation();
+ UpdatePolygonVertices();
}
bool UnitFitToActionRequirement(Unit* unit, Unit* caster, AreaTriggerAction const& action)
@@ -1017,6 +1210,8 @@ Position AreaTrigger::CalculateOrbitPosition() const
// AreaTrigger make exactly "Duration / TimeToTarget" loops during his life time
float pathProgress = float(cmi.ElapsedTimeForMovement) / float(cmi.TimeToTarget);
+ if (GetCreateProperties()->MoveCurveId)
+ pathProgress = sDB2Manager.GetCurveValueAt(GetCreateProperties()->MoveCurveId, pathProgress);
// We already made one circle and can't loop
if (!cmi.CanLoop)
@@ -1041,7 +1236,17 @@ Position AreaTrigger::CalculateOrbitPosition() const
float y = centerPos->GetPositionY() + (radius * std::sin(angle));
float z = centerPos->GetPositionZ() + cmi.ZOffset;
- return { x, y, z, angle };
+ float orientation = 0.0f;
+ if (GetCreateProperties()->FacingCurveId)
+ orientation = sDB2Manager.GetCurveValueAt(GetCreateProperties()->FacingCurveId, GetProgress());
+
+ if (!GetTemplate() || !GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_ABSOLUTE_ORIENTATION))
+ {
+ orientation += angle;
+ orientation += cmi.CounterClockwise ? float(M_PI_4) : -float(M_PI_4);
+ }
+
+ return { x, y, z, orientation };
}
void AreaTrigger::UpdateOrbitPosition(uint32 /*diff*/)
@@ -1064,9 +1269,6 @@ void AreaTrigger::UpdateSplinePosition(uint32 diff)
if (_reachedDestination)
return;
- if (!HasSplines())
- return;
-
_movementTime += diff;
if (_movementTime >= GetTimeToTarget())
@@ -1096,7 +1298,7 @@ void AreaTrigger::UpdateSplinePosition(uint32 diff)
if (progress < 0.f || progress > 1.f)
{
TC_LOG_ERROR("entities.areatrigger", "AreaTrigger (Id: {}, AreaTriggerCreatePropertiesId: {}) has wrong progress ({}) caused by curve calculation (MoveCurveId: {})",
- GetEntry(), GetCreateProperties()->Id, progress, GetCreateProperties()->MorphCurveId);
+ GetEntry(), GetCreateProperties()->Id, progress, GetCreateProperties()->MoveCurveId);
}
else
currentTimePercent = progress;
@@ -1109,11 +1311,16 @@ void AreaTrigger::UpdateSplinePosition(uint32 diff)
G3D::Vector3 currentPosition;
_spline->evaluate_percent(lastPositionIndex, percentFromLastPoint, currentPosition);
- float orientation = GetOrientation();
- if (GetTemplate() && GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_FACE_MOVEMENT_DIR))
+ float orientation = GetStationaryO();
+ if (GetCreateProperties()->FacingCurveId)
+ orientation += sDB2Manager.GetCurveValueAt(GetCreateProperties()->FacingCurveId, GetProgress());
+
+ if (GetTemplate() && !GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_ABSOLUTE_ORIENTATION) && GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_FACE_MOVEMENT_DIR))
{
- G3D::Vector3 const& nextPoint = _spline->getPoint(lastPositionIndex + 1);
- orientation = GetAbsoluteAngle(nextPoint.x, nextPoint.y);
+ G3D::Vector3 derivative;
+ _spline->evaluate_derivative(lastPositionIndex, percentFromLastPoint, derivative);
+ if (derivative.x != 0.0f || derivative.y != 0.0f)
+ orientation += std::atan2(derivative.y, derivative.x);
}
GetMap()->AreaTriggerRelocation(this, currentPosition.x, currentPosition.y, currentPosition.z, orientation);
@@ -1128,6 +1335,25 @@ void AreaTrigger::UpdateSplinePosition(uint32 diff)
}
}
+void AreaTrigger::UpdateOverridePosition()
+{
+ float progress = GetScaleCurveProgress(*m_areaTriggerData->OverrideMoveCurveX, m_areaTriggerData->TimeToTargetPos);
+
+ float x = GetScaleCurveValueAtProgress(*m_areaTriggerData->OverrideMoveCurveX, progress);
+ float y = GetScaleCurveValueAtProgress(*m_areaTriggerData->OverrideMoveCurveY, progress);
+ float z = GetScaleCurveValueAtProgress(*m_areaTriggerData->OverrideMoveCurveZ, progress);
+ float orientation = GetOrientation();
+
+ if (GetCreateProperties()->FacingCurveId)
+ {
+ orientation = sDB2Manager.GetCurveValueAt(GetCreateProperties()->FacingCurveId, GetProgress());
+ if (!GetTemplate() || !GetTemplate()->HasFlag(AREATRIGGER_FLAG_HAS_ABSOLUTE_ORIENTATION))
+ orientation += GetStationaryO();
+ }
+
+ GetMap()->AreaTriggerRelocation(this, x, y, z, orientation);
+}
+
void AreaTrigger::DebugVisualizePosition()
{
if (Unit* caster = GetCaster())
diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.h b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
index ccb83e22c4f..b6bc632c417 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTrigger.h
+++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.h
@@ -77,12 +77,18 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
bool IsNeverVisibleFor(WorldObject const* seer, bool allowServersideObjects = false) const override;
+ float GetStationaryX() const override { return _stationaryPosition.GetPositionX(); }
+ float GetStationaryY() const override { return _stationaryPosition.GetPositionY(); }
+ float GetStationaryZ() const override { return _stationaryPosition.GetPositionZ(); }
+ float GetStationaryO() const override { return _stationaryPosition.GetOrientation(); }
+ void RelocateStationaryPosition(Position const& pos) { _stationaryPosition.Relocate(pos); }
+
private:
- bool Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spellInfo, Position const& pos, int32 duration, SpellCastVisual spellVisual, Spell const* spell, AuraEffect const* aurEff);
+ bool Create(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spellInfo, Position const& pos, int32 duration, SpellCastVisual spellVisual, Spell* spell, AuraEffect const* aurEff);
bool CreateServer(Map* map, AreaTriggerTemplate const* areaTriggerTemplate, AreaTriggerSpawn const& position);
public:
- static AreaTrigger* CreateAreaTrigger(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spellInfo, Position const& pos, int32 duration, SpellCastVisual spellVisual, Spell const* spell = nullptr, AuraEffect const* aurEff = nullptr);
+ static AreaTrigger* CreateAreaTrigger(uint32 areaTriggerCreatePropertiesId, Unit* caster, Unit* target, SpellInfo const* spellInfo, Position const& pos, int32 duration, SpellCastVisual spellVisual, Spell* spell = nullptr, AuraEffect const* aurEff = nullptr);
static ObjectGuid CreateNewMovementForceId(Map* map, uint32 areaTriggerId);
bool LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool allowDuplicate);
@@ -92,8 +98,34 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
uint32 GetSpellId() const { return m_areaTriggerData->SpellID; }
AuraEffect const* GetAuraEffect() const { return _aurEff; }
uint32 GetTimeSinceCreated() const { return _timeSinceCreated; }
+
+ void SetHeightIgnoresScale(bool heightIgnoresScale) { SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::HeightIgnoresScale), heightIgnoresScale); }
+
+ void SetOverrideScaleCurve(float overrideScale);
+ void SetOverrideScaleCurve(std::array<DBCPosition2D, 2> const& points, Optional<uint32> startTimeOffset = {}, CurveInterpolationMode interpolation = CurveInterpolationMode::Linear);
+ void ClearOverrideScaleCurve();
+
+ void SetExtraScaleCurve(float extraScale);
+ void SetExtraScaleCurve(std::array<DBCPosition2D, 2> const& points, Optional<uint32> startTimeOffset = {}, CurveInterpolationMode interpolation = CurveInterpolationMode::Linear);
+ void ClearExtraScaleCurve();
+
+ void SetOverrideMoveCurve(float x, float y, float z);
+ void SetOverrideMoveCurve(std::array<DBCPosition2D, 2> const& xCurvePoints, std::array<DBCPosition2D, 2> const& yCurvePoints, std::array<DBCPosition2D, 2> const& zCurvePoints,
+ Optional<uint32> startTimeOffset = {}, CurveInterpolationMode interpolation = CurveInterpolationMode::Linear);
+ void ClearOverrideMoveCurve();
+
uint32 GetTimeToTarget() const { return m_areaTriggerData->TimeToTarget; }
+ void SetTimeToTarget(uint32 timeToTarget) { SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::TimeToTarget), timeToTarget); }
+
uint32 GetTimeToTargetScale() const { return m_areaTriggerData->TimeToTargetScale; }
+ void SetTimeToTargetScale(uint32 timeToTargetScale) { SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::TimeToTargetScale), timeToTargetScale); }
+
+ uint32 GetTimeToTargetExtraScale() const { return m_areaTriggerData->TimeToTargetExtraScale; }
+ void SetTimeToTargetExtraScale(uint32 timeToTargetExtraScale) { SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::TimeToTargetExtraScale), timeToTargetExtraScale); }
+
+ uint32 GetTimeToTargetPos() const { return m_areaTriggerData->TimeToTargetPos; }
+ void SetTimeToTargetPos(uint32 timeToTargetPos) { SetUpdateFieldValue(m_values.ModifyValue(&AreaTrigger::m_areaTriggerData).ModifyValue(&UF::AreaTriggerData::TimeToTargetPos), timeToTargetPos); }
+
int32 GetDuration() const { return _duration; }
int32 GetTotalDuration() const { return _totalDuration; }
void SetDuration(int32 newDuration);
@@ -113,7 +145,7 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
uint32 GetFaction() const override;
AreaTriggerShapeInfo const& GetShape() const { return _shape; }
- float GetMaxSearchRadius() const { return _maxSearchRadius; }
+ float GetMaxSearchRadius() const;
Position const& GetRollPitchYaw() const { return _rollPitchYaw; }
Position const& GetTargetRollPitchYaw() const { return _targetRollPitchYaw; }
void InitSplineOffsets(std::vector<Position> const& offsets, uint32 timeToTarget);
@@ -124,7 +156,9 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
void InitOrbit(AreaTriggerOrbitInfo const& orbit, uint32 timeToTarget);
bool HasOrbit() const;
- Optional<AreaTriggerOrbitInfo> const& GetCircularMovementInfo() const { return _orbitInfo; }
+ Optional<AreaTriggerOrbitInfo> const& GetOrbit() const { return _orbitInfo; }
+
+ bool HasOverridePosition() const;
void UpdateShape();
@@ -132,10 +166,18 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
protected:
void _UpdateDuration(int32 newDuration);
+
+ float CalcCurrentScale() const;
+
float GetProgress() const;
- float GetScaleCurveValue(UF::ScaleCurve const& scaleCurve, float x) const;
- void SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false>&& scaleCurveMutator, Optional<AreaTriggerScaleCurveTemplate> const& curve);
+ float GetScaleCurveProgress(UF::ScaleCurve const& scaleCurve, uint32 timeTo) const;
+ float GetScaleCurveValueAtProgress(UF::ScaleCurve const& scaleCurve, float x) const;
+ float GetScaleCurveValue(UF::ScaleCurve const& scaleCurve, uint32 timeTo) const;
+ void SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false> scaleCurveMutator, float constantValue);
+ void SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false> scaleCurveMutator, std::array<DBCPosition2D, 2> const& points, Optional<uint32> startTimeOffset, CurveInterpolationMode interpolation);
+ void ClearScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false> scaleCurveMutator);
+ void SetScaleCurve(UF::MutableFieldReference<UF::ScaleCurve, false> scaleCurveMutator, Optional<AreaTriggerScaleCurveTemplate> const& curve);
void UpdateTargetList();
void SearchUnits(std::vector<Unit*>& targetList, float radius, bool check3D);
@@ -151,9 +193,10 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
void DoActions(Unit* unit);
void UndoActions(Unit* unit);
- void UpdatePolygonOrientation();
+ void UpdatePolygonVertices();
void UpdateOrbitPosition(uint32 diff);
void UpdateSplinePosition(uint32 diff);
+ void UpdateOverridePosition();
Position const* GetOrbitCenterPosition() const;
Position CalculateOrbitPosition() const;
@@ -166,12 +209,12 @@ class TC_GAME_API AreaTrigger : public WorldObject, public GridObject<AreaTrigge
AuraEffect const* _aurEff;
+ Position _stationaryPosition;
AreaTriggerShapeInfo _shape;
- float _maxSearchRadius;
int32 _duration;
int32 _totalDuration;
uint32 _timeSinceCreated;
- float _previousCheckOrientation;
+ float _verticesUpdatePreviousOrientation;
bool _isRemoved;
Position _rollPitchYaw;
diff --git a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp
index c1917919be8..906d48437f7 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp
+++ b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.cpp
@@ -42,13 +42,17 @@ float AreaTriggerShapeInfo::GetMaxSearchRadius() const
case AREATRIGGER_TYPE_SPHERE:
return std::max(SphereDatas.Radius, SphereDatas.RadiusTarget);
case AREATRIGGER_TYPE_BOX:
- return std::sqrt(BoxDatas.Extents[0] * BoxDatas.Extents[0] + BoxDatas.Extents[1] * BoxDatas.Extents[1]);
+ return std::sqrt(std::max(
+ BoxDatas.Extents[0] * BoxDatas.Extents[0] + BoxDatas.Extents[1] * BoxDatas.Extents[1],
+ BoxDatas.ExtentsTarget[0] * BoxDatas.ExtentsTarget[0] + BoxDatas.ExtentsTarget[1] * BoxDatas.ExtentsTarget[1]));
case AREATRIGGER_TYPE_CYLINDER:
return std::max(CylinderDatas.Radius, CylinderDatas.RadiusTarget);
case AREATRIGGER_TYPE_DISK:
return std::max(DiskDatas.OuterRadius, DiskDatas.OuterRadiusTarget);
case AREATRIGGER_TYPE_BOUNDED_PLANE:
- return std::sqrt(BoundedPlaneDatas.Extents[0] * BoundedPlaneDatas.Extents[0] / 4 + BoundedPlaneDatas.Extents[1] * BoundedPlaneDatas.Extents[1] / 4);
+ return std::sqrt(std::max(
+ BoundedPlaneDatas.Extents[0] * BoundedPlaneDatas.Extents[0] / 4 + BoundedPlaneDatas.Extents[1] * BoundedPlaneDatas.Extents[1] / 4,
+ BoundedPlaneDatas.ExtentsTarget[0] * BoundedPlaneDatas.ExtentsTarget[0] / 4 + BoundedPlaneDatas.ExtentsTarget[1] * BoundedPlaneDatas.ExtentsTarget[1] / 4));
default:
break;
}
@@ -102,13 +106,11 @@ float AreaTriggerCreateProperties::GetMaxSearchRadius() const
Position center(0.0f, 0.0f);
float maxSearchRadius = 0.0f;
- for (TaggedPosition<Position::XY> const& vertice : PolygonVertices)
- {
- float pointDist = center.GetExactDist2d(vertice);
+ for (TaggedPosition<Position::XY> const& vertex : PolygonVertices)
+ maxSearchRadius = std::max(maxSearchRadius, center.GetExactDist2d(vertex));
- if (pointDist > maxSearchRadius)
- maxSearchRadius = pointDist;
- }
+ for (TaggedPosition<Position::XY> const& vertex : PolygonVerticesTarget)
+ maxSearchRadius = std::max(maxSearchRadius, center.GetExactDist2d(vertex));
return maxSearchRadius;
}
diff --git a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
index ac1a68aa1a6..735a6413e48 100644
--- a/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
+++ b/src/server/game/Entities/AreaTrigger/AreaTriggerTemplate.h
@@ -30,7 +30,7 @@
enum AreaTriggerFlags
{
- AREATRIGGER_FLAG_HAS_ABSOLUTE_ORIENTATION = 0x00001, // NYI
+ AREATRIGGER_FLAG_HAS_ABSOLUTE_ORIENTATION = 0x00001,
AREATRIGGER_FLAG_HAS_DYNAMIC_SHAPE = 0x00002, // Implemented for Spheres & Disks
AREATRIGGER_FLAG_HAS_ATTACHED = 0x00004,
AREATRIGGER_FLAG_HAS_FACE_MOVEMENT_DIR = 0x00008,
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 39b83cf62a1..3678284124f 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -579,7 +579,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags, Playe
// *data << *areaTrigger->GetMovementScript(); // AreaTriggerMovementScriptInfo
if (hasOrbit)
- *data << *areaTrigger->GetCircularMovementInfo();
+ *data << *areaTrigger->GetOrbit();
}
if (flags.GameObject)
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index d68fc26cf3a..90e3e7816c4 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -409,6 +409,7 @@ Unit::~Unit()
ASSERT(m_removedAuras.empty());
ASSERT(m_gameObj.empty());
ASSERT(m_dynObj.empty());
+ ASSERT(m_areaTrigger.empty());
ASSERT(!m_unitMovedByMe || (m_unitMovedByMe == this));
ASSERT(!m_playerMovingMe || (m_playerMovingMe == this));
}
@@ -5244,7 +5245,7 @@ void Unit::_RegisterAreaTrigger(AreaTrigger* areaTrigger)
void Unit::_UnregisterAreaTrigger(AreaTrigger* areaTrigger)
{
- m_areaTrigger.erase(std::remove(m_areaTrigger.begin(), m_areaTrigger.end(), areaTrigger));
+ std::erase(m_areaTrigger, areaTrigger);
if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
ToCreature()->AI()->JustUnregisteredAreaTrigger(areaTrigger);
}
@@ -5267,8 +5268,6 @@ std::vector<AreaTrigger*> Unit::GetAreaTriggers(uint32 spellId) const
void Unit::RemoveAreaTrigger(uint32 spellId)
{
- if (m_areaTrigger.empty())
- return;
for (AreaTriggerList::iterator i = m_areaTrigger.begin(); i != m_areaTrigger.end();)
{
AreaTrigger* areaTrigger = *i;
@@ -5284,8 +5283,6 @@ void Unit::RemoveAreaTrigger(uint32 spellId)
void Unit::RemoveAreaTrigger(AuraEffect const* aurEff)
{
- if (m_areaTrigger.empty())
- return;
for (AreaTrigger* areaTrigger : m_areaTrigger)
{
if (areaTrigger->GetAuraEffect() == aurEff)
@@ -5299,7 +5296,7 @@ void Unit::RemoveAreaTrigger(AuraEffect const* aurEff)
void Unit::RemoveAllAreaTriggers()
{
while (!m_areaTrigger.empty())
- m_areaTrigger.front()->Remove();
+ m_areaTrigger.back()->Remove();
}
void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage const* log)
diff --git a/src/server/game/Globals/AreaTriggerDataStore.cpp b/src/server/game/Globals/AreaTriggerDataStore.cpp
index b1cf3db98cd..3cb2943229a 100644
--- a/src/server/game/Globals/AreaTriggerDataStore.cpp
+++ b/src/server/game/Globals/AreaTriggerDataStore.cpp
@@ -238,6 +238,13 @@ void AreaTriggerDataStore::LoadAreaTriggerTemplates()
createProperties.PolygonVertices = std::move(verticesByCreateProperties[createProperties.Id]);
createProperties.PolygonVerticesTarget = std::move(verticesTargetByCreateProperties[createProperties.Id]);
+ if (!createProperties.PolygonVerticesTarget.empty() && createProperties.PolygonVertices.size() != createProperties.PolygonVerticesTarget.size())
+ {
+ 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: {}).",
+ createProperties.Id);
+ createProperties.PolygonVerticesTarget.clear();
+ }
+
createProperties.SplinePoints = std::move(splinesByCreateProperties[createProperties.Id]);
_areaTriggerCreateProperties[createProperties.Id] = createProperties;