diff --git a/Source/Framework/Framework.csproj b/Source/Framework/Framework.csproj index 17460f660..7eefe5cfb 100644 --- a/Source/Framework/Framework.csproj +++ b/Source/Framework/Framework.csproj @@ -8,6 +8,7 @@ + diff --git a/Source/Game/DataStorage/AreaTriggerDataStorage.cs b/Source/Game/DataStorage/AreaTriggerDataStorage.cs index 2958abedb..4898d15ba 100644 --- a/Source/Game/DataStorage/AreaTriggerDataStorage.cs +++ b/Source/Game/DataStorage/AreaTriggerDataStorage.cs @@ -72,7 +72,7 @@ namespace Game.DataStorage { do { - AreaTriggerId createPropertiesId = new (vertices.Read(0), vertices.Read(1)); + AreaTriggerId createPropertiesId = new(vertices.Read(0), vertices.Read(1)); verticesByCreateProperties.Add(createPropertiesId, new Vector2(vertices.Read(3), vertices.Read(4))); @@ -149,7 +149,7 @@ namespace Game.DataStorage continue; } - if (shape >= AreaTriggerShapeType.Max) + if (shape == AreaTriggerShapeType.Unk || shape >= AreaTriggerShapeType.Max) { Log.outError(LogFilter.Sql, $"Table `areatrigger_create_properties` has listed AreaTriggerCreatePropertiesId (Id: {createPropertiesId.Id}, IsCustom: {createPropertiesId.IsCustom}) with invalid shape {shape}."); continue; @@ -188,33 +188,55 @@ namespace Game.DataStorage createProperties.TimeToTargetScale = areatriggerCreateProperties.Read(13); createProperties.Speed = areatriggerCreateProperties.Read(14); - createProperties.Shape.TriggerType = shape; - unsafe + float[] shapeData = new float[SharedConst.MaxAreatriggerEntityData]; + for (byte i = 0; i < SharedConst.MaxAreatriggerEntityData; ++i) + shapeData[i] = areatriggerCreateProperties.Read(16 + i); + + switch (shape) { - for (byte i = 0; i < SharedConst.MaxAreatriggerEntityData; ++i) - createProperties.Shape.DefaultDatas.Data[i] = areatriggerCreateProperties.Read(16 + i); + case AreaTriggerShapeType.Sphere: + createProperties.Shape.Data = new AreaTriggerShapeInfo.Sphere(shapeData); + break; + case AreaTriggerShapeType.Box: + createProperties.Shape.Data = new AreaTriggerShapeInfo.Box(shapeData); + break; + case AreaTriggerShapeType.Polygon: + AreaTriggerShapeInfo.Polygon polygon = new AreaTriggerShapeInfo.Polygon(shapeData); + if (polygon.Height <= 0.0f) + { + polygon.Height = 1.0f; + if (polygon.HeightTarget <= 0.0f) + polygon.HeightTarget = 1.0f; + } + var vertices1 = verticesByCreateProperties.LookupByKey(createProperties.Id); + if (vertices1 != null) + polygon.PolygonVertices = vertices1; + vertices1 = verticesTargetByCreateProperties.LookupByKey(createProperties.Id); + if (vertices != null) + polygon.PolygonVerticesTarget = vertices1; + if (!polygon.PolygonVerticesTarget.Empty() && polygon.PolygonVertices.Count != polygon.PolygonVerticesTarget.Count) + { + Log.outError(LogFilter.Sql, $"Table `areatrigger_create_properties_polygon_vertex` has invalid target vertices, either all or none vertices must have a corresponding target vertex (AreaTriggerCreatePropertiesId: (Id: {createPropertiesId.Id}, IsCustom: {createPropertiesId.IsCustom}))."); + polygon.PolygonVerticesTarget.Clear(); + } + + createProperties.Shape.Data = polygon; + break; + case AreaTriggerShapeType.Cylinder: + createProperties.Shape.Data = new AreaTriggerShapeInfo.Cylinder(shapeData); + break; + case AreaTriggerShapeType.Disk: + createProperties.Shape.Data = new AreaTriggerShapeInfo.Disk(shapeData); + break; + case AreaTriggerShapeType.BoundedPlane: + createProperties.Shape.Data = new AreaTriggerShapeInfo.BoundedPlane(shapeData); + break; + default: + break; } createProperties.ScriptId = Global.ObjectMgr.GetScriptId(areatriggerCreateProperties.Read(24)); - if (shape == AreaTriggerShapeType.Polygon) - { - if (createProperties.Shape.PolygonDatas.Height <= 0.0f) - { - createProperties.Shape.PolygonDatas.Height = 1.0f; - if (createProperties.Shape.PolygonDatas.HeightTarget <= 0.0f) - createProperties.Shape.PolygonDatas.HeightTarget = 1.0f; - } - } - - createProperties.Shape.PolygonVertices = verticesByCreateProperties[createProperties.Id]; - createProperties.Shape.PolygonVerticesTarget = verticesTargetByCreateProperties[createProperties.Id]; - if (!createProperties.Shape.PolygonVerticesTarget.Empty() && createProperties.Shape.PolygonVertices.Count != createProperties.Shape.PolygonVerticesTarget.Count) - { - Log.outError(LogFilter.Sql, $"Table `areatrigger_create_properties_polygon_vertex` has invalid target vertices, either all or none vertices must have a corresponding target vertex (AreaTriggerCreatePropertiesId: (Id: {createPropertiesId.Id}, IsCustom: {createPropertiesId.IsCustom}))."); - createProperties.Shape.PolygonVerticesTarget.Clear(); - } - var spline = splinesByCreateProperties.LookupByKey(createProperties.Id); if (spline != null) createProperties.SplinePoints = spline; @@ -384,7 +406,7 @@ namespace Game.DataStorage public AreaTriggerTemplate GetAreaTriggerTemplate(AreaTriggerId areaTriggerId) { - return _areaTriggerTemplateStore.LookupByKey(areaTriggerId); + return _areaTriggerTemplateStore.LookupByKey(areaTriggerId); } public AreaTriggerCreateProperties GetAreaTriggerCreateProperties(AreaTriggerId areaTriggerCreatePropertiesId) diff --git a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs index 1a68b73e3..9127ea0c7 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTrigger.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTrigger.cs @@ -229,7 +229,7 @@ namespace Game.Entities InitOrbit(orbit, GetCreateProperties().Speed); } - else if (GetCreateProperties().HasSplines()) + else if (GetCreateProperties().SplinePoints != null) { InitSplineOffsets(GetCreateProperties().SplinePoints); } @@ -933,81 +933,73 @@ namespace Game.Entities return 0; } - unsafe void SetShape(AreaTriggerShapeInfo shape) + void SetShape(AreaTriggerShapeInfo shape) { var areaTriggerData = m_values.ModifyValue(m_areaTriggerData); - switch (shape.TriggerType) - { - case AreaTriggerShapeType.Sphere: + shape.Data.Switch + ( + sphereInfo => { SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)0); var sphere = areaTriggerData.ModifyValue(m_areaTriggerData.ShapeData); - SetUpdateFieldValue(sphere.ModifyValue(sphere.Radius), shape.SphereDatas.Radius); - SetUpdateFieldValue(sphere.ModifyValue(sphere.RadiusTarget), shape.SphereDatas.RadiusTarget); - break; - } - case AreaTriggerShapeType.Box: + SetUpdateFieldValue(sphere.ModifyValue(sphere.Radius), sphereInfo.Radius); + SetUpdateFieldValue(sphere.ModifyValue(sphere.RadiusTarget), sphereInfo.RadiusTarget); + }, + boxInfo => { SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)1); var box = areaTriggerData.ModifyValue(m_areaTriggerData.ShapeData); - SetUpdateFieldValue(box.ModifyValue(box.Extents), new Vector3(shape.BoxDatas.Extents[0], shape.BoxDatas.Extents[1], shape.BoxDatas.Extents[2])); - SetUpdateFieldValue(box.ModifyValue(box.ExtentsTarget), new Vector3(shape.BoxDatas.ExtentsTarget[0], shape.BoxDatas.ExtentsTarget[1], shape.BoxDatas.ExtentsTarget[2])); - break; - } - case AreaTriggerShapeType.Polygon: + SetUpdateFieldValue(box.ModifyValue(box.Extents), boxInfo.Extents); + SetUpdateFieldValue(box.ModifyValue(box.ExtentsTarget), boxInfo.ExtentsTarget); + }, + polygonInfo => { SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)3); var polygon = areaTriggerData.ModifyValue(m_areaTriggerData.ShapeData); var vertices = polygon.ModifyValue(polygon.Vertices); ClearDynamicUpdateFieldValues(vertices); - foreach (Vector2 vertex in shape.PolygonVertices) + foreach (Vector2 vertex in polygonInfo.PolygonVertices) AddDynamicUpdateFieldValue(vertices, vertex); var verticesTarget = polygon.ModifyValue(polygon.VerticesTarget); ClearDynamicUpdateFieldValues(verticesTarget); - foreach (Vector2 vertex in shape.PolygonVerticesTarget) + foreach (Vector2 vertex in polygonInfo.PolygonVerticesTarget) AddDynamicUpdateFieldValue(verticesTarget, vertex); - SetUpdateFieldValue(polygon.ModifyValue(polygon.Height), shape.PolygonDatas.Height); - SetUpdateFieldValue(polygon.ModifyValue(polygon.HeightTarget), shape.PolygonDatas.HeightTarget); - break; - } - case AreaTriggerShapeType.Cylinder: + SetUpdateFieldValue(polygon.ModifyValue(polygon.Height), polygonInfo.Height); + SetUpdateFieldValue(polygon.ModifyValue(polygon.HeightTarget), polygonInfo.HeightTarget); + }, + cylinderInfo => { SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)4); var cylinder = areaTriggerData.ModifyValue(m_areaTriggerData.ShapeData); - SetUpdateFieldValue(cylinder.ModifyValue(cylinder.Radius), shape.CylinderDatas.Radius); - SetUpdateFieldValue(cylinder.ModifyValue(cylinder.RadiusTarget), shape.CylinderDatas.RadiusTarget); - SetUpdateFieldValue(cylinder.ModifyValue(cylinder.Height), shape.CylinderDatas.Height); - SetUpdateFieldValue(cylinder.ModifyValue(cylinder.HeightTarget), shape.CylinderDatas.HeightTarget); - SetUpdateFieldValue(cylinder.ModifyValue(cylinder.LocationZOffset), shape.CylinderDatas.LocationZOffset); - SetUpdateFieldValue(cylinder.ModifyValue(cylinder.LocationZOffsetTarget), shape.CylinderDatas.LocationZOffsetTarget); - break; - } - case AreaTriggerShapeType.Disk: + SetUpdateFieldValue(cylinder.ModifyValue(cylinder.Radius), cylinderInfo.Radius); + SetUpdateFieldValue(cylinder.ModifyValue(cylinder.RadiusTarget), cylinderInfo.RadiusTarget); + SetUpdateFieldValue(cylinder.ModifyValue(cylinder.Height), cylinderInfo.Height); + SetUpdateFieldValue(cylinder.ModifyValue(cylinder.HeightTarget), cylinderInfo.HeightTarget); + SetUpdateFieldValue(cylinder.ModifyValue(cylinder.LocationZOffset), cylinderInfo.LocationZOffset); + SetUpdateFieldValue(cylinder.ModifyValue(cylinder.LocationZOffsetTarget), cylinderInfo.LocationZOffsetTarget); + }, + diskInfo => { SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)7); var disk = areaTriggerData.ModifyValue(m_areaTriggerData.ShapeData); - SetUpdateFieldValue(disk.ModifyValue(disk.InnerRadius), shape.DiskDatas.InnerRadius); - SetUpdateFieldValue(disk.ModifyValue(disk.InnerRadiusTarget), shape.DiskDatas.InnerRadiusTarget); - SetUpdateFieldValue(disk.ModifyValue(disk.OuterRadius), shape.DiskDatas.OuterRadius); - SetUpdateFieldValue(disk.ModifyValue(disk.OuterRadiusTarget), shape.DiskDatas.OuterRadiusTarget); - SetUpdateFieldValue(disk.ModifyValue(disk.Height), shape.DiskDatas.Height); - SetUpdateFieldValue(disk.ModifyValue(disk.HeightTarget), shape.DiskDatas.HeightTarget); - SetUpdateFieldValue(disk.ModifyValue(disk.LocationZOffset), shape.DiskDatas.LocationZOffset); - SetUpdateFieldValue(disk.ModifyValue(disk.LocationZOffsetTarget), shape.DiskDatas.LocationZOffsetTarget); - break; - } - case AreaTriggerShapeType.BoundedPlane: + SetUpdateFieldValue(disk.ModifyValue(disk.InnerRadius), diskInfo.InnerRadius); + SetUpdateFieldValue(disk.ModifyValue(disk.InnerRadiusTarget), diskInfo.InnerRadiusTarget); + SetUpdateFieldValue(disk.ModifyValue(disk.OuterRadius), diskInfo.OuterRadius); + SetUpdateFieldValue(disk.ModifyValue(disk.OuterRadiusTarget), diskInfo.OuterRadiusTarget); + SetUpdateFieldValue(disk.ModifyValue(disk.Height), diskInfo.Height); + SetUpdateFieldValue(disk.ModifyValue(disk.HeightTarget), diskInfo.HeightTarget); + SetUpdateFieldValue(disk.ModifyValue(disk.LocationZOffset), diskInfo.LocationZOffset); + SetUpdateFieldValue(disk.ModifyValue(disk.LocationZOffsetTarget), diskInfo.LocationZOffsetTarget); + }, + boundedPlaneInfo => { SetUpdateFieldValue(areaTriggerData.ModifyValue(m_areaTriggerData.ShapeType), (byte)8); var boundedPlane = areaTriggerData.ModifyValue(m_areaTriggerData.ShapeData); - SetUpdateFieldValue(boundedPlane.ModifyValue(boundedPlane.Extents), new Vector2(shape.BoundedPlaneDatas.Extents[0], shape.BoundedPlaneDatas.Extents[1])); - SetUpdateFieldValue(boundedPlane.ModifyValue(boundedPlane.ExtentsTarget), new Vector2(shape.BoundedPlaneDatas.ExtentsTarget[0], shape.BoundedPlaneDatas.ExtentsTarget[1])); - break; + SetUpdateFieldValue(boundedPlane.ModifyValue(boundedPlane.Extents), boundedPlaneInfo.Extents); + SetUpdateFieldValue(boundedPlane.ModifyValue(boundedPlane.ExtentsTarget), boundedPlaneInfo.ExtentsTarget); } - default: - break; - } + ); } public float GetMaxSearchRadius() diff --git a/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs b/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs index 139afaad1..9dc607263 100644 --- a/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs +++ b/Source/Game/Entities/AreaTrigger/AreaTriggerTemplate.cs @@ -3,94 +3,13 @@ using Framework.Constants; using Game.Maps; -using Game.Networking; +using OneOf; using System; using System.Collections.Generic; using System.Numerics; -using System.Runtime.InteropServices; namespace Game.Entities { - [StructLayout(LayoutKind.Explicit)] - public unsafe class AreaTriggerData - { - [FieldOffset(0)] - public defaultdatas DefaultDatas; - - [FieldOffset(0)] - public spheredatas SphereDatas; - - [FieldOffset(0)] - public boxdatas BoxDatas; - - [FieldOffset(0)] - public polygondatas PolygonDatas; - - [FieldOffset(0)] - public cylinderdatas CylinderDatas; - - [FieldOffset(0)] - public diskDatas DiskDatas; - - [FieldOffset(0)] - public boundedPlaneDatas BoundedPlaneDatas; - - public struct defaultdatas - { - public fixed float Data[SharedConst.MaxAreatriggerEntityData]; - } - - // AREATRIGGER_TYPE_SPHERE - public struct spheredatas - { - public float Radius; - public float RadiusTarget; - } - - // AREATRIGGER_TYPE_BOX - public struct boxdatas - { - public fixed float Extents[3]; - public fixed float ExtentsTarget[3]; - } - - // AREATRIGGER_TYPE_POLYGON - public struct polygondatas - { - public float Height; - public float HeightTarget; - } - - // AREATRIGGER_TYPE_CYLINDER - public struct cylinderdatas - { - public float Radius; - public float RadiusTarget; - public float Height; - public float HeightTarget; - public float LocationZOffset; - public float LocationZOffsetTarget; - } - // AREATRIGGER_TYPE_DISK - public struct diskDatas - { - public float InnerRadius; - public float InnerRadiusTarget; - public float OuterRadius; - public float OuterRadiusTarget; - public float Height; - public float HeightTarget; - public float LocationZOffset; - public float LocationZOffsetTarget; - } - // AREATRIGGER_TYPE_BOUNDED_PLANE - public struct boundedPlaneDatas - { - public fixed float Extents[2]; - public fixed float ExtentsTarget[2]; - } - } - public struct AreaTriggerId { public uint Id; @@ -122,59 +41,166 @@ namespace Game.Entities } } - public class AreaTriggerShapeInfo : AreaTriggerData + interface IShapeInfo { - public AreaTriggerShapeType TriggerType; - public List PolygonVertices; - public List PolygonVerticesTarget; + float GetMaxSearchRadius(); + } - public AreaTriggerShapeInfo() - { - TriggerType = AreaTriggerShapeType.Max; - PolygonVertices = new(); - PolygonVerticesTarget = new(); - } + public class AreaTriggerShapeInfo + { + public OneOf Data; - public unsafe float GetMaxSearchRadius() + public bool IsSphere() { return Data.IsT0; } + public bool IsBox() { return Data.IsT1; } + public bool IsPolygon() { return Data.IsT2; } + public bool IsCylinder() { return Data.IsT3; } + public bool IsDisk() { return Data.IsT4; } + public bool IsBoundedPlane() { return Data.IsT5; } + + public float GetMaxSearchRadius() { return ((IShapeInfo)Data.Value).GetMaxSearchRadius(); } + + public struct Sphere : IShapeInfo { - switch (TriggerType) + public float Radius; + public float RadiusTarget; + + public Sphere() { } + public Sphere(float[] raw) { - case AreaTriggerShapeType.Sphere: - return Math.Max(SphereDatas.Radius, SphereDatas.RadiusTarget); - case AreaTriggerShapeType.Box: - 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 AreaTriggerShapeType.Polygon: - { - Position center = new(0.0f, 0.0f); - float maxSearchRadius = 0.0f; - - foreach (var vertex in PolygonVertices) - maxSearchRadius = Math.Max(maxSearchRadius, center.GetExactDist2d(vertex.X, vertex.Y)); - - foreach (var vertex in PolygonVerticesTarget) - maxSearchRadius = Math.Max(maxSearchRadius, center.GetExactDist2d(vertex.X, vertex.Y)); - - return maxSearchRadius; - } - case AreaTriggerShapeType.Cylinder: - return Math.Max(CylinderDatas.Radius, CylinderDatas.RadiusTarget); - case AreaTriggerShapeType.Disk: - return Math.Max(DiskDatas.OuterRadius, DiskDatas.OuterRadiusTarget); - case AreaTriggerShapeType.BoundedPlane: - 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)); + Radius = raw[0]; + RadiusTarget = raw[1]; } - return 0.0f; + public float GetMaxSearchRadius() + { + return Math.Max(Radius, RadiusTarget); + } } - public bool IsSphere() { return TriggerType == AreaTriggerShapeType.Sphere; } - public bool IsBox() { return TriggerType == AreaTriggerShapeType.Box; } - public bool IsPolygon() { return TriggerType == AreaTriggerShapeType.Polygon; } - public bool IsCylinder() { return TriggerType == AreaTriggerShapeType.Cylinder; } - public bool IsDisk() { return TriggerType == AreaTriggerShapeType.Disk; } - public bool IsBoundedPlane() { return TriggerType == AreaTriggerShapeType.BoundedPlane; } + public struct Box : IShapeInfo + { + public Vector3 Extents; + public Vector3 ExtentsTarget; + + public Box() { } + public Box(float[] raw) + { + Extents = new(raw[0], raw[1], raw[2]); + ExtentsTarget = new(raw[3], raw[4], raw[5]); + } + + public float GetMaxSearchRadius() + { + return MathF.Sqrt(MathF.Max( + Extents.X * Extents.X + Extents.Y * Extents.Y, + ExtentsTarget.X * ExtentsTarget.X + ExtentsTarget.Y * ExtentsTarget.Y)); + } + } + + public struct Polygon : IShapeInfo + { + public List PolygonVertices = new(); + public List PolygonVerticesTarget = new(); + public float Height; + public float HeightTarget; + + public Polygon() { } + public Polygon(float[] raw) + { + Height = raw[0]; + HeightTarget = raw[1]; + } + + public float GetMaxSearchRadius() + { + Position center = new(0.0f, 0.0f); + float maxSearchRadius = 0.0f; + + foreach (var vertex in PolygonVertices) + maxSearchRadius = Math.Max(maxSearchRadius, center.GetExactDist2d(vertex.X, vertex.Y)); + + foreach (var vertex in PolygonVerticesTarget) + maxSearchRadius = Math.Max(maxSearchRadius, center.GetExactDist2d(vertex.X, vertex.Y)); + + return maxSearchRadius; + } + } + + public struct Cylinder : IShapeInfo + { + public float Radius; + public float RadiusTarget; + public float Height; + public float HeightTarget; + public float LocationZOffset; + public float LocationZOffsetTarget; + + public Cylinder() { } + public Cylinder(float[] raw) + { + Radius = raw[0]; + RadiusTarget = raw[1]; + Height = raw[2]; + HeightTarget = raw[3]; + LocationZOffset = raw[4]; + LocationZOffsetTarget = raw[5]; + } + + public float GetMaxSearchRadius() + { + return Math.Max(Radius, RadiusTarget); + } + } + + public struct Disk : IShapeInfo + { + public float InnerRadius; + public float InnerRadiusTarget; + public float OuterRadius; + public float OuterRadiusTarget; + public float Height; + public float HeightTarget; + public float LocationZOffset; + public float LocationZOffsetTarget; + + public Disk() { } + public Disk(float[] raw) + { + InnerRadius = raw[0]; + InnerRadiusTarget = raw[1]; + OuterRadius = raw[2]; + OuterRadiusTarget = raw[3]; + Height = raw[4]; + HeightTarget = raw[5]; + LocationZOffset = raw[6]; + LocationZOffsetTarget = raw[7]; + } + + public float GetMaxSearchRadius() + { + return Math.Max(OuterRadius, OuterRadiusTarget); + } + } + + public struct BoundedPlane : IShapeInfo + { + public Vector2 Extents; + public Vector2 ExtentsTarget; + + public BoundedPlane() { } + public BoundedPlane(float[] raw) + { + Extents = new(raw[0], raw[1]); + ExtentsTarget = new(raw[2], raw[3]); + } + + public float GetMaxSearchRadius() + { + return MathF.Sqrt(Math.Max( + Extents.X * Extents.X / 4 + Extents.Y * Extents.Y / 4, + ExtentsTarget.X * ExtentsTarget.X / 4 + ExtentsTarget.Y * ExtentsTarget.Y / 4)); + } + } } public class AreaTriggerOrbitInfo