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 Port From (https://github.com/TrinityCore/TrinityCore/commit/c676d1477239aec4d0b235a410e5627a7070a86e)
This commit is contained in:
@@ -19,7 +19,7 @@ namespace Game.Entities
|
||||
{
|
||||
public AreaTrigger() : base(false)
|
||||
{
|
||||
_previousCheckOrientation = float.PositiveInfinity;
|
||||
_verticesUpdatePreviousOrientation = float.PositiveInfinity;
|
||||
_reachedDestination = true;
|
||||
|
||||
ObjectTypeMask |= TypeMask.AreaTrigger;
|
||||
@@ -83,6 +83,7 @@ namespace Game.Entities
|
||||
|
||||
SetMap(caster.GetMap());
|
||||
Relocate(pos);
|
||||
RelocateStationaryPosition(pos);
|
||||
if (!IsPositionValid())
|
||||
{
|
||||
Log.outError(LogFilter.AreaTrigger, $"AreaTrigger (areaTriggerCreatePropertiesId: {areaTriggerCreatePropertiesId}) not created. Invalid coordinates (X: {GetPositionX()} Y: {GetPositionY()})");
|
||||
@@ -110,7 +111,6 @@ namespace Game.Entities
|
||||
SetObjectScale(1.0f);
|
||||
|
||||
_shape = GetCreateProperties().Shape;
|
||||
_maxSearchRadius = GetCreateProperties().GetMaxSearchRadius();
|
||||
|
||||
var areaTriggerData = m_values.ModifyValue(m_areaTriggerData);
|
||||
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.Caster), caster.GetGUID());
|
||||
@@ -125,11 +125,25 @@ namespace Game.Entities
|
||||
SetUpdateFieldValue(ref spellCastVisual.ScriptVisualID, spellVisual.ScriptVisualID);
|
||||
|
||||
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.TimeToTargetScale), GetCreateProperties().TimeToTargetScale != 0 ? GetCreateProperties().TimeToTargetScale : m_areaTriggerData.Duration);
|
||||
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.BoundsRadius2D), GetMaxSearchRadius());
|
||||
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.BoundsRadius2D), GetCreateProperties().GetMaxSearchRadius());
|
||||
SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.DecalPropertiesID), GetCreateProperties().DecalPropertiesId);
|
||||
|
||||
SetScaleCurve(areaTriggerData.ModifyValue(m_areaTriggerData.ExtraScaleCurve), GetCreateProperties().ExtraScale);
|
||||
|
||||
Player modOwner = caster.GetSpellModOwner();
|
||||
if (modOwner != null)
|
||||
{
|
||||
float multiplier = 1.0f;
|
||||
int flat = 0;
|
||||
modOwner.GetSpellModValues(spellInfo, SpellModOp.Radius, spell, (float)m_areaTriggerData.BoundsRadius2D, ref flat, ref multiplier);
|
||||
if (multiplier != 1.0f)
|
||||
{
|
||||
AreaTriggerScaleCurveTemplate overrideScale = new();
|
||||
overrideScale.Curve = multiplier;
|
||||
SetScaleCurve(areaTriggerData.ModifyValue(m_areaTriggerData.OverrideScaleCurve), overrideScale);
|
||||
}
|
||||
}
|
||||
|
||||
VisualAnim visualAnim = areaTriggerData.ModifyValue(m_areaTriggerData.VisualAnim);
|
||||
SetUpdateFieldValue(visualAnim.ModifyValue(visualAnim.AnimationDataID), GetCreateProperties().AnimId);
|
||||
SetUpdateFieldValue(visualAnim.ModifyValue(visualAnim.AnimKitID), GetCreateProperties().AnimKitId);
|
||||
@@ -231,6 +245,7 @@ namespace Game.Entities
|
||||
{
|
||||
SetMap(map);
|
||||
Relocate(position.SpawnPoint);
|
||||
RelocateStationaryPosition(position.SpawnPoint);
|
||||
if (!IsPositionValid())
|
||||
{
|
||||
Log.outError(LogFilter.AreaTrigger, $"AreaTriggerServer (id {areaTriggerTemplate.Id}) not created. Invalid coordinates (X: {GetPositionX()} Y: {GetPositionY()})");
|
||||
@@ -248,7 +263,8 @@ namespace Game.Entities
|
||||
SetObjectScale(1.0f);
|
||||
SetDuration(-1);
|
||||
|
||||
SetUpdateFieldValue(m_areaTriggerData.ModifyValue(m_areaTriggerData.BoundsRadius2D), GetMaxSearchRadius());
|
||||
_shape = position.Shape;
|
||||
|
||||
if (position.SpellForVisuals.HasValue)
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(position.SpellForVisuals.Value, Difficulty.None);
|
||||
@@ -259,6 +275,7 @@ namespace Game.Entities
|
||||
SetUpdateFieldValue(ref spellCastVisual.ScriptVisualID, 0u);
|
||||
}
|
||||
|
||||
SetUpdateFieldValue(m_areaTriggerData.ModifyValue(m_areaTriggerData.BoundsRadius2D), _shape.GetMaxSearchRadius());
|
||||
if (IsServerSide())
|
||||
SetUpdateFieldValue(m_areaTriggerData.ModifyValue(m_areaTriggerData.DecalPropertiesID), 24u); // blue decal, for .debug areatrigger visibility
|
||||
|
||||
@@ -267,11 +284,8 @@ namespace Game.Entities
|
||||
VisualAnim visualAnim = m_areaTriggerData.ModifyValue(m_areaTriggerData.VisualAnim);
|
||||
SetUpdateFieldValue(visualAnim.ModifyValue(visualAnim.AnimationDataID), -1);
|
||||
|
||||
_shape = position.Shape;
|
||||
_maxSearchRadius = _shape.GetMaxSearchRadius();
|
||||
|
||||
if (position.PhaseUseFlags != 0 || position.PhaseId != 0 || position.PhaseGroup != 0)
|
||||
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), (PhaseUseFlagsValues)position.PhaseUseFlags, position.PhaseId, position.PhaseGroup);
|
||||
PhasingHandler.InitDbPhaseShift(GetPhaseShift(), position.PhaseUseFlags, position.PhaseId, position.PhaseGroup);
|
||||
|
||||
UpdateShape();
|
||||
|
||||
@@ -290,7 +304,11 @@ namespace Game.Entities
|
||||
if (!IsServerSide())
|
||||
{
|
||||
// "If" order matter here, Orbit > Attached > Splines
|
||||
if (HasOrbit())
|
||||
if (HasOverridePosition())
|
||||
{
|
||||
UpdateOverridePosition();
|
||||
}
|
||||
else if (HasOrbit())
|
||||
{
|
||||
UpdateOrbitPosition(diff);
|
||||
}
|
||||
@@ -298,10 +316,34 @@ namespace Game.Entities
|
||||
{
|
||||
Unit target = GetTarget();
|
||||
if (target != null)
|
||||
GetMap().AreaTriggerRelocation(this, target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), target.GetOrientation());
|
||||
{
|
||||
float orientation = 0.0f;
|
||||
if (GetCreateProperties().FacingCurveId != 0)
|
||||
orientation = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().FacingCurveId, GetProgress());
|
||||
|
||||
if (GetTemplate() == null || !GetTemplate().HasFlag(AreaTriggerFlags.HasAbsoluteOrientation))
|
||||
orientation += target.GetOrientation();
|
||||
|
||||
GetMap().AreaTriggerRelocation(this, target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), orientation);
|
||||
}
|
||||
}
|
||||
else if (HasSplines())
|
||||
{
|
||||
UpdateSplinePosition(diff);
|
||||
}
|
||||
else
|
||||
UpdateSplinePosition(diff);
|
||||
{
|
||||
if (GetCreateProperties().FacingCurveId != 0)
|
||||
{
|
||||
float orientation = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().FacingCurveId, GetProgress());
|
||||
if (GetTemplate() == null || !GetTemplate().HasFlag(AreaTriggerFlags.HasAbsoluteOrientation))
|
||||
orientation += GetStationaryO();
|
||||
|
||||
SetOrientation(orientation);
|
||||
}
|
||||
|
||||
UpdateShape();
|
||||
}
|
||||
}
|
||||
|
||||
if (GetDuration() != -1)
|
||||
@@ -326,6 +368,57 @@ namespace Game.Entities
|
||||
AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
void SetOverrideScaleCurve(float overrideScale)
|
||||
{
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideScaleCurve), overrideScale);
|
||||
}
|
||||
|
||||
void SetOverrideScaleCurve(Vector2[] points, uint? startTimeOffset, CurveInterpolationMode interpolation)
|
||||
{
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideScaleCurve), points, startTimeOffset, interpolation);
|
||||
}
|
||||
|
||||
void ClearOverrideScaleCurve()
|
||||
{
|
||||
ClearScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideScaleCurve));
|
||||
}
|
||||
|
||||
void SetExtraScaleCurve(float extraScale)
|
||||
{
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.ExtraScaleCurve), extraScale);
|
||||
}
|
||||
|
||||
void SetExtraScaleCurve(Vector2[] points, uint? startTimeOffset, CurveInterpolationMode interpolation)
|
||||
{
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.ExtraScaleCurve), points, startTimeOffset, interpolation);
|
||||
}
|
||||
|
||||
void ClearExtraScaleCurve()
|
||||
{
|
||||
ClearScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.ExtraScaleCurve));
|
||||
}
|
||||
|
||||
void SetOverrideMoveCurve(float x, float y, float z)
|
||||
{
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveX), x);
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveY), y);
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveZ), z);
|
||||
}
|
||||
|
||||
void SetOverrideMoveCurve(Vector2[] xCurvePoints, Vector2[] yCurvePoints, Vector2[] zCurvePoints, uint? startTimeOffset, CurveInterpolationMode interpolation)
|
||||
{
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveX), xCurvePoints, startTimeOffset, interpolation);
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveY), yCurvePoints, startTimeOffset, interpolation);
|
||||
SetScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveZ), zCurvePoints, startTimeOffset, interpolation);
|
||||
}
|
||||
|
||||
void ClearOverrideMoveCurve()
|
||||
{
|
||||
ClearScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveX));
|
||||
ClearScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveY));
|
||||
ClearScaleCurve(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.OverrideMoveCurveZ));
|
||||
}
|
||||
|
||||
public void SetDuration(int newDuration)
|
||||
{
|
||||
_duration = newDuration;
|
||||
@@ -347,18 +440,46 @@ namespace Game.Entities
|
||||
});
|
||||
}
|
||||
|
||||
float GetProgress()
|
||||
float CalcCurrentScale()
|
||||
{
|
||||
return GetTimeSinceCreated() < GetTimeToTargetScale() ? (float)GetTimeSinceCreated() / GetTimeToTargetScale() : 1.0f;
|
||||
float scale = 1.0f;
|
||||
if (m_areaTriggerData.OverrideScaleCurve.GetValue().OverrideActive)
|
||||
scale *= Math.Max(GetScaleCurveValue(m_areaTriggerData.OverrideScaleCurve, m_areaTriggerData.TimeToTargetScale), 0.000001f);
|
||||
else
|
||||
{
|
||||
AreaTriggerCreateProperties createProperties = GetCreateProperties();
|
||||
if (createProperties != null && createProperties.ScaleCurveId != 0)
|
||||
scale *= Math.Max(Global.DB2Mgr.GetCurveValueAt(createProperties.ScaleCurveId, GetScaleCurveProgress(m_areaTriggerData.OverrideScaleCurve, m_areaTriggerData.TimeToTargetScale)), 0.000001f);
|
||||
}
|
||||
|
||||
scale *= Math.Max(GetScaleCurveValue(m_areaTriggerData.ExtraScaleCurve, m_areaTriggerData.TimeToTargetExtraScale), 0.000001f);
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
float GetScaleCurveValue(ScaleCurve scaleCurve, float x)
|
||||
float GetProgress()
|
||||
{
|
||||
if (_totalDuration <= 0)
|
||||
return 1.0f;
|
||||
|
||||
return Math.Clamp((float)GetTimeSinceCreated() / (float)GetTotalDuration(), 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
float GetScaleCurveProgress(ScaleCurve scaleCurve, uint timeTo)
|
||||
{
|
||||
if (timeTo == 0)
|
||||
return 0.0f;
|
||||
|
||||
return Math.Clamp((float)(GetTimeSinceCreated() - scaleCurve.StartTimeOffset) / (float)timeTo, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
float GetScaleCurveValueAtProgress(ScaleCurve scaleCurve, float x)
|
||||
{
|
||||
Cypher.Assert(scaleCurve.OverrideActive, "ScaleCurve must be active to evaluate it");
|
||||
|
||||
// unpack ParameterCurve
|
||||
if ((scaleCurve.ParameterCurve & 1) != 0)
|
||||
return BitConverter.UInt32BitsToSingle((uint)(scaleCurve.ParameterCurve & ~1));
|
||||
if ((scaleCurve.ParameterCurve & 1u) != 0)
|
||||
return BitConverter.UInt32BitsToSingle((uint)(scaleCurve.ParameterCurve & ~1u));
|
||||
|
||||
Vector2[] points = new Vector2[2];
|
||||
for (var i = 0; i < scaleCurve.Points.GetSize(); ++i)
|
||||
@@ -370,6 +491,36 @@ namespace Game.Entities
|
||||
return Global.DB2Mgr.GetCurveValueAt(mode, points.AsSpan(0, pointCount).ToArray(), x);
|
||||
}
|
||||
|
||||
float GetScaleCurveValue(ScaleCurve scaleCurve, uint timeTo)
|
||||
{
|
||||
return GetScaleCurveValueAtProgress(scaleCurve, GetScaleCurveProgress(scaleCurve, timeTo));
|
||||
}
|
||||
|
||||
void SetScaleCurve(ScaleCurve scaleCurve, float constantValue)
|
||||
{
|
||||
AreaTriggerScaleCurveTemplate curveTemplate = new();
|
||||
curveTemplate.Curve = constantValue;
|
||||
SetScaleCurve(scaleCurve, curveTemplate);
|
||||
}
|
||||
|
||||
void SetScaleCurve(ScaleCurve scaleCurve, Vector2[] points, uint? startTimeOffset, CurveInterpolationMode interpolation)
|
||||
{
|
||||
AreaTriggerScaleCurvePointsTemplate curve = new();
|
||||
curve.Mode = interpolation;
|
||||
curve.Points = points;
|
||||
|
||||
AreaTriggerScaleCurveTemplate curveTemplate = new();
|
||||
curveTemplate.StartTimeOffset = startTimeOffset.GetValueOrDefault(GetTimeSinceCreated());
|
||||
curveTemplate.CurveTemplate = curve;
|
||||
|
||||
SetScaleCurve(scaleCurve, curveTemplate);
|
||||
}
|
||||
|
||||
void ClearScaleCurve(ScaleCurve scaleCurve)
|
||||
{
|
||||
SetScaleCurve(scaleCurve, null);
|
||||
}
|
||||
|
||||
void SetScaleCurve(ScaleCurve scaleCurve, AreaTriggerScaleCurveTemplate curve)
|
||||
{
|
||||
if (curve == null)
|
||||
@@ -437,7 +588,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void UpdateTargetList()
|
||||
{
|
||||
List<Unit> targetList = new();
|
||||
@@ -493,99 +644,111 @@ namespace Game.Entities
|
||||
|
||||
void SearchUnitInSphere(List<Unit> targetList)
|
||||
{
|
||||
float radius = _shape.SphereDatas.Radius;
|
||||
if (GetTemplate() != null && GetTemplate().HasFlag(AreaTriggerFlags.HasDynamicShape))
|
||||
{
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
{
|
||||
radius = MathFunctions.Lerp(_shape.SphereDatas.Radius, _shape.SphereDatas.RadiusTarget, Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, GetProgress()));
|
||||
}
|
||||
}
|
||||
float progress = GetProgress();
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
progress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, progress);
|
||||
|
||||
float scale = CalcCurrentScale();
|
||||
float radius = MathFunctions.Lerp(_shape.SphereDatas.Radius, _shape.SphereDatas.RadiusTarget, progress) * scale;
|
||||
|
||||
SearchUnits(targetList, radius, true);
|
||||
}
|
||||
|
||||
void SearchUnitInBox(List<Unit> targetList)
|
||||
{
|
||||
SearchUnits(targetList, GetMaxSearchRadius(), false);
|
||||
|
||||
Position boxCenter = GetPosition();
|
||||
float extentsX, extentsY, extentsZ;
|
||||
float progress = GetProgress();
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
progress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, progress);
|
||||
|
||||
unsafe
|
||||
{
|
||||
extentsX = _shape.BoxDatas.Extents[0];
|
||||
extentsY = _shape.BoxDatas.Extents[1];
|
||||
extentsZ = _shape.BoxDatas.Extents[2];
|
||||
}
|
||||
float scale = CalcCurrentScale();
|
||||
float extentsX = MathFunctions.Lerp(_shape.BoxDatas.Extents[0], _shape.BoxDatas.ExtentsTarget[0], progress) * scale;
|
||||
float extentsY = MathFunctions.Lerp(_shape.BoxDatas.Extents[1], _shape.BoxDatas.ExtentsTarget[1], progress) * scale;
|
||||
float extentsZ = MathFunctions.Lerp(_shape.BoxDatas.Extents[2], _shape.BoxDatas.ExtentsTarget[2], progress) * scale;
|
||||
float radius = MathF.Sqrt(extentsX * extentsX + extentsY * extentsY);
|
||||
|
||||
targetList.RemoveAll(unit => !unit.IsWithinBox(boxCenter, extentsX, extentsY, extentsZ / 2));
|
||||
SearchUnits(targetList, radius, false);
|
||||
|
||||
Position boxCenter = GetPosition();
|
||||
targetList.RemoveAll(unit => !unit.IsWithinBox(boxCenter, extentsX, extentsY, extentsZ / 2));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchUnitInPolygon(List<Unit> targetList)
|
||||
{
|
||||
SearchUnits(targetList, GetMaxSearchRadius(), false);
|
||||
float progress = GetProgress();
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
progress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, progress);
|
||||
|
||||
float height = _shape.PolygonDatas.Height;
|
||||
float height = MathFunctions.Lerp(_shape.PolygonDatas.Height, _shape.PolygonDatas.HeightTarget, progress);
|
||||
float minZ = GetPositionZ() - height;
|
||||
float maxZ = GetPositionZ() + height;
|
||||
|
||||
targetList.RemoveAll(unit => !CheckIsInPolygon2D(unit) || unit.GetPositionZ() < minZ || unit.GetPositionZ() > maxZ);
|
||||
SearchUnits(targetList, GetMaxSearchRadius(), false);
|
||||
|
||||
targetList.RemoveAll(unit => unit.GetPositionZ() < minZ || unit.GetPositionZ() > maxZ || !CheckIsInPolygon2D(unit));
|
||||
}
|
||||
|
||||
void SearchUnitInCylinder(List<Unit> targetList)
|
||||
{
|
||||
SearchUnits(targetList, GetMaxSearchRadius(), false);
|
||||
float progress = GetProgress();
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
progress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, progress);
|
||||
|
||||
float scale = CalcCurrentScale();
|
||||
float radius = MathFunctions.Lerp(_shape.CylinderDatas.Radius, _shape.CylinderDatas.RadiusTarget, progress) * scale;
|
||||
float height = MathFunctions.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;
|
||||
|
||||
SearchUnits(targetList, radius, false);
|
||||
|
||||
targetList.RemoveAll(unit => unit.GetPositionZ() < minZ || unit.GetPositionZ() > maxZ);
|
||||
}
|
||||
|
||||
void SearchUnitInDisk(List<Unit> targetList)
|
||||
{
|
||||
float innerRadius = _shape.DiskDatas.InnerRadius;
|
||||
float outerRadius = _shape.DiskDatas.OuterRadius;
|
||||
float height = _shape.DiskDatas.Height;
|
||||
float progress = GetProgress();
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
progress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, progress);
|
||||
|
||||
if (GetTemplate() != null && GetTemplate().HasFlag(AreaTriggerFlags.HasDynamicShape))
|
||||
{
|
||||
float progress = GetProgress();
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
progress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, progress);
|
||||
|
||||
innerRadius = MathFunctions.Lerp(_shape.DiskDatas.InnerRadius, _shape.DiskDatas.InnerRadiusTarget, progress);
|
||||
outerRadius = MathFunctions.Lerp(_shape.DiskDatas.OuterRadius, _shape.DiskDatas.OuterRadiusTarget, progress);
|
||||
height = MathFunctions.Lerp(_shape.DiskDatas.Height, _shape.DiskDatas.HeightTarget, progress);
|
||||
}
|
||||
|
||||
SearchUnits(targetList, outerRadius, false);
|
||||
float scale = CalcCurrentScale();
|
||||
float innerRadius = MathFunctions.Lerp(_shape.DiskDatas.InnerRadius, _shape.DiskDatas.InnerRadiusTarget, progress) * scale;
|
||||
float outerRadius = MathFunctions.Lerp(_shape.DiskDatas.OuterRadius, _shape.DiskDatas.OuterRadiusTarget, progress) * scale;
|
||||
float height = MathFunctions.Lerp(_shape.DiskDatas.Height, _shape.DiskDatas.HeightTarget, progress);
|
||||
if (!m_areaTriggerData.HeightIgnoresScale)
|
||||
height *= scale;
|
||||
|
||||
float minZ = GetPositionZ() - height;
|
||||
float maxZ = GetPositionZ() + height;
|
||||
|
||||
SearchUnits(targetList, outerRadius, false);
|
||||
|
||||
targetList.RemoveAll(unit => unit.IsInDist2d(this, innerRadius) || unit.GetPositionZ() < minZ || unit.GetPositionZ() > maxZ);
|
||||
}
|
||||
|
||||
void SearchUnitInBoundedPlane(List<Unit> targetList)
|
||||
{
|
||||
SearchUnits(targetList, GetMaxSearchRadius(), false);
|
||||
|
||||
Position boxCenter = GetPosition();
|
||||
float extentsX, extentsY;
|
||||
float progress = GetProgress();
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
progress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, progress);
|
||||
|
||||
unsafe
|
||||
{
|
||||
extentsX = _shape.BoxDatas.Extents[0];
|
||||
extentsY = _shape.BoxDatas.Extents[1];
|
||||
}
|
||||
float scale = CalcCurrentScale();
|
||||
float extentsX = MathFunctions.Lerp(_shape.BoundedPlaneDatas.Extents[0], _shape.BoundedPlaneDatas.ExtentsTarget[0], progress) * scale;
|
||||
float extentsY = MathFunctions.Lerp(_shape.BoundedPlaneDatas.Extents[1], _shape.BoundedPlaneDatas.ExtentsTarget[1], progress) * scale;
|
||||
float radius = MathF.Sqrt(extentsX * extentsX + extentsY * extentsY);
|
||||
|
||||
targetList.RemoveAll(unit =>
|
||||
{
|
||||
return !unit.IsWithinBox(boxCenter, extentsX, extentsY, MapConst.MapSize);
|
||||
});
|
||||
SearchUnits(targetList, radius, false);
|
||||
|
||||
Position boxCenter = GetPosition();
|
||||
targetList.RemoveAll(unit => !unit.IsWithinBox(boxCenter, extentsX, extentsY, MapConst.MapSize));
|
||||
}
|
||||
}
|
||||
|
||||
void HandleUnitEnterExit(List<Unit> newTargetList)
|
||||
@@ -679,16 +842,37 @@ namespace Game.Entities
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdatePolygonOrientation()
|
||||
float GetMaxSearchRadius()
|
||||
{
|
||||
return m_areaTriggerData.BoundsRadius2D * CalcCurrentScale();
|
||||
}
|
||||
|
||||
void UpdatePolygonVertices()
|
||||
{
|
||||
float newOrientation = GetOrientation();
|
||||
|
||||
// No need to recalculate, orientation didn't change
|
||||
if (MathFunctions.fuzzyEq(_previousCheckOrientation, newOrientation))
|
||||
if (MathFunctions.fuzzyEq(_verticesUpdatePreviousOrientation, newOrientation) && GetCreateProperties().PolygonVerticesTarget.Empty())
|
||||
return;
|
||||
|
||||
_polygonVertices = GetCreateProperties().PolygonVertices;
|
||||
|
||||
if (!GetCreateProperties().PolygonVerticesTarget.Empty())
|
||||
{
|
||||
float progress = GetProgress();
|
||||
if (GetCreateProperties().MorphCurveId != 0)
|
||||
progress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MorphCurveId, progress);
|
||||
|
||||
for (var i = 0; i < _polygonVertices.Count; ++i)
|
||||
{
|
||||
Vector2 vertex = _polygonVertices[i];
|
||||
Vector2 vertexTarget = GetCreateProperties().PolygonVerticesTarget[i];
|
||||
|
||||
vertex.X = MathFunctions.Lerp(vertex.X, vertexTarget.X, progress);
|
||||
vertex.Y = MathFunctions.Lerp(vertex.Y, vertexTarget.Y, progress);
|
||||
}
|
||||
}
|
||||
|
||||
float angleSin = (float)Math.Sin(newOrientation);
|
||||
float angleCos = (float)Math.Cos(newOrientation);
|
||||
|
||||
@@ -701,7 +885,7 @@ namespace Game.Entities
|
||||
vertice.Y = vertice.Y * angleCos + vertice.X * angleSin;
|
||||
}
|
||||
|
||||
_previousCheckOrientation = newOrientation;
|
||||
_verticesUpdatePreviousOrientation = newOrientation;
|
||||
}
|
||||
|
||||
bool CheckIsInPolygon2D(Position pos)
|
||||
@@ -773,10 +957,17 @@ namespace Game.Entities
|
||||
return locatedInPolygon;
|
||||
}
|
||||
|
||||
bool HasOverridePosition()
|
||||
{
|
||||
return m_areaTriggerData.OverrideMoveCurveX.GetValue().OverrideActive
|
||||
&& m_areaTriggerData.OverrideMoveCurveY.GetValue().OverrideActive
|
||||
&& m_areaTriggerData.OverrideMoveCurveZ.GetValue().OverrideActive;
|
||||
}
|
||||
|
||||
public void UpdateShape()
|
||||
{
|
||||
if (_shape.IsPolygon())
|
||||
UpdatePolygonOrientation();
|
||||
UpdatePolygonVertices();
|
||||
}
|
||||
|
||||
bool UnitFitToActionRequirement(Unit unit, Unit caster, AreaTriggerAction action)
|
||||
@@ -978,6 +1169,8 @@ namespace Game.Entities
|
||||
|
||||
// AreaTrigger make exactly "Duration / TimeToTarget" loops during his life time
|
||||
float pathProgress = (float)cmi.ElapsedTimeForMovement / cmi.TimeToTarget;
|
||||
if (GetCreateProperties().MoveCurveId != 0)
|
||||
pathProgress = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().MoveCurveId, pathProgress);
|
||||
|
||||
// We already made one circle and can't loop
|
||||
if (!cmi.CanLoop)
|
||||
@@ -1002,7 +1195,17 @@ namespace Game.Entities
|
||||
float y = centerPos.GetPositionY() + (radius * (float)Math.Sin(angle));
|
||||
float z = centerPos.GetPositionZ() + cmi.ZOffset;
|
||||
|
||||
return new Position(x, y, z, angle);
|
||||
float orientation = 0.0f;
|
||||
if (GetCreateProperties().FacingCurveId != 0)
|
||||
orientation = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().FacingCurveId, GetProgress());
|
||||
|
||||
if (GetTemplate() == null || !GetTemplate().HasFlag(AreaTriggerFlags.HasAbsoluteOrientation))
|
||||
{
|
||||
orientation += angle;
|
||||
orientation += cmi.CounterClockwise ? MathFunctions.PiOver4 : -MathFunctions.PiOver4;
|
||||
}
|
||||
|
||||
return new Position(x, y, z, orientation);
|
||||
}
|
||||
|
||||
void UpdateOrbitPosition(uint diff)
|
||||
@@ -1024,9 +1227,6 @@ namespace Game.Entities
|
||||
if (_reachedDestination)
|
||||
return;
|
||||
|
||||
if (!HasSplines())
|
||||
return;
|
||||
|
||||
_movementTime += diff;
|
||||
|
||||
if (_movementTime >= GetTimeToTarget())
|
||||
@@ -1067,11 +1267,15 @@ namespace Game.Entities
|
||||
Vector3 currentPosition;
|
||||
_spline.Evaluate_Percent(lastPositionIndex, percentFromLastPoint, out currentPosition);
|
||||
|
||||
float orientation = GetOrientation();
|
||||
if (GetTemplate() != null && GetTemplate().HasFlag(AreaTriggerFlags.HasFaceMovementDir))
|
||||
float orientation = GetStationaryO();
|
||||
if (GetCreateProperties().FacingCurveId != 0)
|
||||
orientation += Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().FacingCurveId, GetProgress());
|
||||
|
||||
if (GetTemplate() != null && !GetTemplate().HasFlag(AreaTriggerFlags.HasAbsoluteOrientation) && GetTemplate().HasFlag(AreaTriggerFlags.HasFaceMovementDir))
|
||||
{
|
||||
Vector3 nextPoint = _spline.GetPoint(lastPositionIndex + 1);
|
||||
orientation = GetAbsoluteAngle(nextPoint.X, nextPoint.Y);
|
||||
_spline.Evaluate_Derivative(lastPositionIndex, percentFromLastPoint, out Vector3 derivative);
|
||||
if (derivative.X != 0.0f || derivative.Y != 0.0f)
|
||||
orientation += MathF.Atan2(derivative.Y, derivative.X);
|
||||
}
|
||||
|
||||
GetMap().AreaTriggerRelocation(this, currentPosition.X, currentPosition.Y, currentPosition.Z, orientation);
|
||||
@@ -1085,6 +1289,26 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
void 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 != 0)
|
||||
{
|
||||
orientation = Global.DB2Mgr.GetCurveValueAt(GetCreateProperties().FacingCurveId, GetProgress());
|
||||
if (GetTemplate() == null || !GetTemplate().HasFlag(AreaTriggerFlags.HasAbsoluteOrientation))
|
||||
orientation += GetStationaryO();
|
||||
}
|
||||
|
||||
GetMap().AreaTriggerRelocation(this, x, y, z, orientation);
|
||||
}
|
||||
|
||||
|
||||
void AI_Initialize()
|
||||
{
|
||||
AI_Destroy();
|
||||
@@ -1117,7 +1341,7 @@ namespace Game.Entities
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public override void BuildValuesCreate(WorldPacket data, Player target)
|
||||
{
|
||||
UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
|
||||
@@ -1197,12 +1421,31 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public override float GetStationaryX() { return _stationaryPosition.GetPositionX(); }
|
||||
public override float GetStationaryY() { return _stationaryPosition.GetPositionY(); }
|
||||
public override float GetStationaryZ() { return _stationaryPosition.GetPositionZ(); }
|
||||
public override float GetStationaryO() { return _stationaryPosition.GetOrientation(); }
|
||||
void RelocateStationaryPosition(Position pos) { _stationaryPosition.Relocate(pos); }
|
||||
|
||||
public bool IsRemoved() { return _isRemoved; }
|
||||
public uint GetSpellId() { return m_areaTriggerData.SpellID; }
|
||||
public AuraEffect GetAuraEffect() { return _aurEff; }
|
||||
public uint GetTimeSinceCreated() { return _timeSinceCreated; }
|
||||
|
||||
public void SetHeightIgnoresScale(bool heightIgnoresScale) { SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.HeightIgnoresScale), heightIgnoresScale); }
|
||||
|
||||
public uint GetTimeToTarget() { return m_areaTriggerData.TimeToTarget; }
|
||||
public void SetTimeToTarget(uint timeToTarget) { SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTarget), timeToTarget); }
|
||||
|
||||
public uint GetTimeToTargetScale() { return m_areaTriggerData.TimeToTargetScale; }
|
||||
public void SetTimeToTargetScale(uint timeToTargetScale) { SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTargetScale), timeToTargetScale); }
|
||||
|
||||
public uint GetTimeToTargetExtraScale() { return m_areaTriggerData.TimeToTargetExtraScale; }
|
||||
public void SetTimeToTargetExtraScale(uint timeToTargetExtraScale) { SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTargetExtraScale), timeToTargetExtraScale); }
|
||||
|
||||
public uint GetTimeToTargetPos() { return m_areaTriggerData.TimeToTargetPos; }
|
||||
public void SetTimeToTargetPos(uint timeToTargetPos) { SetUpdateFieldValue(m_values.ModifyValue(m_areaTriggerData).ModifyValue(m_areaTriggerData.TimeToTargetPos), timeToTargetPos); }
|
||||
|
||||
public int GetDuration() { return _duration; }
|
||||
public int GetTotalDuration() { return _totalDuration; }
|
||||
|
||||
@@ -1216,7 +1459,6 @@ namespace Game.Entities
|
||||
public ObjectGuid GetCasterGuid() { return m_areaTriggerData.Caster; }
|
||||
|
||||
public AreaTriggerShapeInfo GetShape() { return _shape; }
|
||||
float GetMaxSearchRadius() { return _maxSearchRadius; }
|
||||
public Vector3 GetRollPitchYaw() { return _rollPitchYaw; }
|
||||
public Vector3 GetTargetRollPitchYaw() { return _targetRollPitchYaw; }
|
||||
|
||||
@@ -1224,7 +1466,7 @@ namespace Game.Entities
|
||||
public Spline<int> GetSpline() { return _spline; }
|
||||
public uint GetElapsedTimeForMovement() { return GetTimeSinceCreated(); } // @todo: research the right value, in sniffs both timers are nearly identical
|
||||
|
||||
public AreaTriggerOrbitInfo GetCircularMovementInfo() { return _orbitInfo; }
|
||||
public AreaTriggerOrbitInfo GetOrbit() { return _orbitInfo; }
|
||||
|
||||
AreaTriggerFieldData m_areaTriggerData;
|
||||
|
||||
@@ -1234,12 +1476,12 @@ namespace Game.Entities
|
||||
|
||||
AuraEffect _aurEff;
|
||||
|
||||
Position _stationaryPosition;
|
||||
AreaTriggerShapeInfo _shape;
|
||||
float _maxSearchRadius;
|
||||
int _duration;
|
||||
int _totalDuration;
|
||||
uint _timeSinceCreated;
|
||||
float _previousCheckOrientation;
|
||||
float _verticesUpdatePreviousOrientation;
|
||||
bool _isRemoved;
|
||||
|
||||
Vector3 _rollPitchYaw;
|
||||
|
||||
@@ -163,13 +163,15 @@ namespace Game.Entities
|
||||
case AreaTriggerTypes.Sphere:
|
||||
return Math.Max(SphereDatas.Radius, SphereDatas.RadiusTarget);
|
||||
case AreaTriggerTypes.Box:
|
||||
return MathF.Sqrt(BoxDatas.Extents[0] * BoxDatas.Extents[0] + BoxDatas.Extents[1] * BoxDatas.Extents[1]);
|
||||
return MathF.Sqrt(Math.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 AreaTriggerTypes.Cylinder:
|
||||
return Math.Max(CylinderDatas.Radius, CylinderDatas.RadiusTarget);
|
||||
case AreaTriggerTypes.Disk:
|
||||
return Math.Max(DiskDatas.OuterRadius, DiskDatas.OuterRadiusTarget);
|
||||
case AreaTriggerTypes.BoundedPlane:
|
||||
return MathF.Sqrt(BoundedPlaneDatas.Extents[0] * BoundedPlaneDatas.Extents[0] / 4 + BoundedPlaneDatas.Extents[1] * BoundedPlaneDatas.Extents[1] / 4);
|
||||
return MathF.Sqrt(Math.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));
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
@@ -246,20 +248,18 @@ namespace Game.Entities
|
||||
Position center = new(0.0f, 0.0f);
|
||||
float maxSearchRadius = 0.0f;
|
||||
|
||||
foreach (var vertice in PolygonVertices)
|
||||
{
|
||||
float pointDist = center.GetExactDist2d(vertice.X, vertice.Y);
|
||||
foreach (var vertex in PolygonVertices)
|
||||
maxSearchRadius = Math.Max(maxSearchRadius, center.GetExactDist2d(vertex.X, vertex.Y));
|
||||
|
||||
if (pointDist > maxSearchRadius)
|
||||
maxSearchRadius = pointDist;
|
||||
}
|
||||
foreach (var vertex in PolygonVerticesTarget)
|
||||
maxSearchRadius = Math.Max(maxSearchRadius, center.GetExactDist2d(vertex.X, vertex.Y));
|
||||
|
||||
return maxSearchRadius;
|
||||
}
|
||||
|
||||
return Shape.GetMaxSearchRadius();
|
||||
}
|
||||
|
||||
|
||||
public uint Id;
|
||||
public AreaTriggerTemplate Template;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user