private void BlockIntersect(MyCubeGrid breaching, MyOrientedBoundingBoxD bOriBBoxD, EntIntersectInfo entInfo)
        {
            var collisionAvg = Vector3D.Zero;
            var transformInv = DetectMatrixOutsideInv;
            var normalMat    = MatrixD.Transpose(transformInv);
            var damageBlocks = Session.Enforced.DisableBlockDamage == 0;

            var blockDmgNum = 5;

            if (ShieldMode == ShieldType.Station && DsState.State.Enhancer)
            {
                blockDmgNum = 50;
            }
            var intersection = bOriBBoxD.Intersects(ref SOriBBoxD);

            try
            {
                if (intersection)
                {
                    var      cacheBlockList = entInfo.CacheBlockList;
                    var      bPhysics       = ((IMyCubeGrid)breaching).Physics;
                    var      sPhysics       = Shield.CubeGrid.Physics;
                    var      sGrid          = (MyCubeGrid)Shield.CubeGrid;
                    var      bMass          = breaching.GetCurrentMass();
                    var      sMass          = sGrid.GetCurrentMass();
                    var      momentum       = (bMass * bPhysics.LinearVelocity) + (sMass * sPhysics.LinearVelocity);
                    var      resultVelocity = momentum / (bMass + sMass);
                    Vector3D bBlockCenter;
                    var      stale     = false;
                    var      rawDamage = 0f;
                    var      blockSize = breaching.GridSize;
                    var      gc        = breaching.WorldToGridInteger(DetectionCenter);
                    var      rc        = ShieldSize.AbsMax() / blockSize;
                    rc *= rc;
                    rc  = rc + 1;
                    rc  = Math.Ceiling(rc);
                    var hits        = 0;
                    var blockPoints = new Vector3D[9];
                    for (int i = 0; i < cacheBlockList.Count; i++)
                    {
                        var block    = cacheBlockList[i];
                        var blockPos = block.Position;
                        var num1     = gc.X - blockPos.X;
                        var num2     = gc.Y - blockPos.Y;
                        var num3     = gc.Z - blockPos.Z;
                        var result   = (num1 * num1) + (num2 * num2) + (num3 * num3);

                        if (_isServer)
                        {
                            if (result > rc)
                            {
                                continue;
                            }
                            if (damageBlocks && block.IsDestroyed)
                            {
                                DestroyedBlocks.Enqueue(block);
                                continue;
                            }
                            if (block.CubeGrid != breaching)
                            {
                                stale = true;
                                continue;
                            }
                        }
                        else
                        {
                            if (hits > blockDmgNum)
                            {
                                break;
                            }
                            if (result > rc || block.IsDestroyed || block.CubeGrid != breaching)
                            {
                                continue;
                            }
                        }
                        BoundingBoxD blockBox;
                        block.GetWorldBoundingBox(out blockBox);

                        blockBox.GetCorners(blockPoints);
                        blockPoints[8] = blockBox.Center;
                        for (int j = 8; j > -1; j--)
                        {
                            var point = blockPoints[j];
                            if (Vector3.Transform(point, DetectMatrixOutsideInv).LengthSquared() > 1)
                            {
                                continue;
                            }
                            collisionAvg += point;
                            hits++;
                            if (!_isServer)
                            {
                                break;
                            }

                            if (!damageBlocks)
                            {
                                if (hits > blockDmgNum)
                                {
                                    break;
                                }
                            }
                            else if (CollidingBlocks.Count > blockDmgNum)
                            {
                                break;
                            }

                            rawDamage += MathHelper.Clamp(block.Integrity, 0, 350);
                            if (damageBlocks)
                            {
                                CollidingBlocks.Enqueue(block);
                            }
                            break;
                        }
                    }

                    entInfo.MarkForClose = stale;

                    if (collisionAvg != Vector3D.Zero)
                    {
                        collisionAvg /= hits;

                        if (sPhysics.IsStatic && !bPhysics.IsStatic)
                        {
                            var bLSpeed    = bPhysics.LinearVelocity;
                            var bASpeed    = bPhysics.AngularVelocity * 100;
                            var bLSpeedLen = bLSpeed.Length();
                            var bASpeedLen = bASpeed.Length();
                            bASpeedLen = MathHelper.Clamp(bASpeedLen, 0, 50);
                            var bSpeedLen   = bLSpeedLen > bASpeedLen ? bLSpeedLen : bASpeedLen;
                            var surfaceMass = (bMass > sMass) ? sMass : bMass;

                            var surfaceMulti  = (hits > 5) ? 5 : hits;
                            var localNormal   = Vector3D.Transform(collisionAvg, transformInv);
                            var surfaceNormal = Vector3D.Normalize(Vector3D.TransformNormal(localNormal, normalMat));

                            var impulseData1 = new MyImpulseData {
                                MyGrid = breaching, Direction = (resultVelocity - bLSpeed) * bMass, Position = bPhysics.CenterOfMassWorld
                            };
                            var impulseData2 = new MyImpulseData {
                                MyGrid = breaching, Direction = surfaceMulti * (surfaceMass * 0.025) * -Vector3D.Dot(bLSpeed, surfaceNormal) * surfaceNormal, Position = collisionAvg
                            };
                            var forceData = new MyAddForceData {
                                MyGrid = breaching, Force = (bPhysics.CenterOfMassWorld - collisionAvg) * (bMass * bSpeedLen), MaxSpeed = MathHelper.Clamp(bSpeedLen, 1f, bSpeedLen * 0.5f)
                            };
                            ImpulseData.Enqueue(impulseData1);
                            ImpulseData.Enqueue(impulseData2);
                            ForceData.Enqueue(forceData);
                        }
                        else
                        {
                            var bLSpeed    = bPhysics.LinearVelocity;
                            var bASpeed    = bPhysics.AngularVelocity * 100;
                            var bLSpeedLen = bLSpeed.Length();
                            var bASpeedLen = bASpeed.Length();
                            bASpeedLen = MathHelper.Clamp(bASpeedLen, 0, 50);
                            var   bSpeedLen = bLSpeedLen > bASpeedLen ? bLSpeedLen : bASpeedLen;
                            float?speed;


                            if (!bPhysics.IsStatic)
                            {
                                var bImpulseData = new MyImpulseData {
                                    MyGrid = breaching, Direction = (resultVelocity - bLSpeed) * bMass, Position = bPhysics.CenterOfMassWorld
                                };
                                ImpulseData.Enqueue(bImpulseData);
                            }

                            if (!sPhysics.IsStatic)
                            {
                                var sImpulseData = new MyImpulseData {
                                    MyGrid = sGrid, Direction = (resultVelocity - sPhysics.LinearVelocity) * sMass, Position = sPhysics.CenterOfMassWorld
                                };
                                ImpulseData.Enqueue(sImpulseData);
                            }

                            if (!sPhysics.IsStatic)
                            {
                                if (bMass / sMass > 20)
                                {
                                    speed = MathHelper.Clamp(bSpeedLen, 1f, bSpeedLen * 0.5f);
                                }
                                else
                                {
                                    speed = null;
                                }

                                var sForceData = new MyAddForceData {
                                    MyGrid = sGrid, Force = (sPhysics.CenterOfMassWorld - collisionAvg) * bMass, MaxSpeed = speed
                                };
                                ForceData.Enqueue(sForceData);
                            }

                            if (!bPhysics.IsStatic)
                            {
                                if (sMass / bMass > 20)
                                {
                                    speed = MathHelper.Clamp(bSpeedLen, 1f, bSpeedLen * 0.5f);
                                }
                                else
                                {
                                    speed = null;
                                }

                                var bForceData = new MyAddForceData {
                                    MyGrid = breaching, Force = (bPhysics.CenterOfMassWorld - collisionAvg) * sMass, MaxSpeed = speed
                                };
                                ForceData.Enqueue(bForceData);
                            }
                        }
                        WebDamage    = true;
                        bBlockCenter = collisionAvg;
                    }
                    else
                    {
                        return;
                    }
                    if (!_isServer)
                    {
                        return;
                    }

                    var damage = rawDamage * DsState.State.ModulateEnergy;

                    entInfo.Damage = damage;
                    if (_mpActive)
                    {
                        if (_isServer && bBlockCenter != Vector3D.NegativeInfinity)
                        {
                            AddShieldHit(breaching.EntityId, damage, Session.Instance.MPKinetic, null, false, collisionAvg);
                        }
                    }
                    else
                    {
                        if (bBlockCenter != Vector3D.NegativeInfinity)
                        {
                            entInfo.ContactPoint = bBlockCenter;
                            ImpactSize           = entInfo.Damage;

                            entInfo.Damage      = 0;
                            entInfo.EmpSize     = 0;
                            WorldImpactPosition = bBlockCenter;
                        }
                    }
                    Absorb += damage;
                }
            }
            catch (Exception ex) { Log.Line($"Exception in BlockIntersect: {ex}"); }
        }
Example #2
0
        internal void CreateShieldShape()
        {
            if (GridIsMobile)
            {
                _updateMobileShape = false;
                if (_shapeChanged)
                {
                    CreateMobileShape();
                }
                DetectionMatrix     = ShieldShapeMatrix * MyGrid.WorldMatrix;
                DetectionCenter     = MyGridCenter;
                _sQuaternion        = Quaternion.CreateFromRotationMatrix(MyGrid.WorldMatrix);
                ShieldSphere.Center = DetectionCenter;
                ShieldSphere.Radius = ShieldSize.AbsMax();
            }
            else
            {
                IMyUpgradeModule emitter;
                if (_isServer)
                {
                    emitter = ShieldComp.StationEmitter.Emitter;
                }
                else
                {
                    emitter = (IMyUpgradeModule)MyEntities.GetEntityById(DsState.State.ActiveEmitterId, true);
                }

                if (emitter == null)
                {
                    UpdateDimensions = true;
                    return;
                }

                var width  = DsSet.Settings.Width;
                var height = DsSet.Settings.Height;
                var depth  = DsSet.Settings.Depth;

                var wOffset = DsSet.Settings.ShieldOffset.X;
                var hOffset = DsSet.Settings.ShieldOffset.Y;
                var dOffset = DsSet.Settings.ShieldOffset.Z;

                var blockGridPosMeters   = new Vector3D(emitter.Position) * MyGrid.GridSize;
                var localOffsetMeters    = new Vector3D(wOffset, hOffset, dOffset) * MyGrid.GridSize;
                var localOffsetPosMeters = localOffsetMeters + blockGridPosMeters;
                var emitterCenter        = emitter.PositionComp.GetPosition();
                var offsetLMatrix        = Matrix.CreateWorld(localOffsetPosMeters, Vector3D.Forward, Vector3D.Up);

                var worldOffset             = Vector3D.TransformNormal(localOffsetMeters, MyGrid.WorldMatrix);
                var translationInWorldSpace = emitterCenter + worldOffset;

                OffsetEmitterWMatrix = MatrixD.CreateWorld(translationInWorldSpace, MyGrid.WorldMatrix.Forward, MyGrid.WorldMatrix.Up);

                DetectionCenter = OffsetEmitterWMatrix.Translation;

                var halfDistToCenter = 600 - Vector3D.Distance(DetectionCenter, emitterCenter);
                var vectorScale      = new Vector3D(MathHelper.Clamp(width, 30, halfDistToCenter), MathHelper.Clamp(height, 30, halfDistToCenter), MathHelper.Clamp(depth, 30, halfDistToCenter));

                DetectionMatrix   = MatrixD.Rescale(OffsetEmitterWMatrix, vectorScale);
                ShieldShapeMatrix = MatrixD.Rescale(offsetLMatrix, vectorScale);

                ShieldSize = DetectionMatrix.Scale;

                _sQuaternion        = Quaternion.CreateFromRotationMatrix(OffsetEmitterWMatrix);
                ShieldSphere.Center = DetectionCenter;
                ShieldSphere.Radius = ShieldSize.AbsMax();
            }

            ShieldSphere3K.Center = DetectionCenter;
            WebSphere.Center      = DetectionCenter;

            SOriBBoxD.Center      = DetectionCenter;
            SOriBBoxD.Orientation = _sQuaternion;
            if (_shapeChanged)
            {
                SOriBBoxD.HalfExtent = ShieldSize;
                ShieldAabbScaled.Min = ShieldSize;
                ShieldAabbScaled.Max = -ShieldSize;
                _ellipsoidSa.Update(DetectMatrixOutside.Scale.X, DetectMatrixOutside.Scale.Y, DetectMatrixOutside.Scale.Z);
                BoundingRange = ShieldSize.AbsMax();

                ShieldSphere3K.Radius = BoundingRange + 3000;
                WebSphere.Radius      = BoundingRange + 7;

                _ellipsoidSurfaceArea = _ellipsoidSa.Surface;
                EllipsoidVolume       = 1.333333 * Math.PI * DetectMatrixOutside.Scale.X * DetectMatrixOutside.Scale.Y * DetectMatrixOutside.Scale.Z;
                _shieldVol            = DetectMatrixOutside.Scale.Volume;
                if (_isServer)
                {
                    ShieldChangeState();
                    ShieldComp.ShieldVolume = DetectMatrixOutside.Scale.Volume;
                }
            }

            if (_shapeChanged)
            {
                var zeroMatrix   = Matrix.Zero;
                var shieldMatrix = (Matrix)ShieldShapeMatrix;
                if (!_isDedicated)
                {
                    _shellPassive.PositionComp.SetLocalMatrix(ref zeroMatrix, null, true);  // Bug - Cannot just change X coord, so I reset first.
                    _shellActive.PositionComp.SetLocalMatrix(ref zeroMatrix, null, true);
                    _shellPassive.PositionComp.SetLocalMatrix(ref shieldMatrix, null, true);
                    _shellActive.PositionComp.SetLocalMatrix(ref shieldMatrix, null, true);
                }
                ShieldEnt.PositionComp.SetLocalMatrix(ref zeroMatrix, null, true);
                ShieldEnt.PositionComp.SetLocalMatrix(ref shieldMatrix, null, true);
                ShieldEnt.PositionComp.LocalAABB    = BoundingBox.CreateFromHalfExtent(Vector3.Zero, (float)ShieldSize.AbsMax());
                ShieldEnt.PositionComp.WorldMatrix *= MyGrid.PositionComp.WorldMatrix.GetOrientation();
            }
            ShieldEnt.PositionComp.SetPosition(DetectionCenter);
            BoundingBoxD.CreateFromSphere(ref WebSphere, out WebBox);
            BoundingBoxD.CreateFromSphere(ref ShieldSphere3K, out ShieldBox3K);
        }
        private void BlockIntersect(MyCubeGrid breaching, MyOrientedBoundingBoxD bOriBBoxD, ref EntIntersectInfo entInfo)
        {
            try
            {
                if (entInfo == null || breaching == null || breaching.MarkedForClose)
                {
                    return;
                }

                if (bOriBBoxD.Intersects(ref SOriBBoxD))
                {
                    var collisionAvg = Vector3D.Zero;
                    var damageBlocks = Session.Enforced.DisableBlockDamage == 0;
                    var bQuaternion  = Quaternion.CreateFromRotationMatrix(breaching.WorldMatrix);

                    const int blockDmgNum = 250;

                    var rawDamage       = 0f;
                    var blockSize       = breaching.GridSize;
                    var scaledBlockSize = blockSize * 3;
                    var gc = breaching.WorldToGridInteger(DetectionCenter);
                    var rc = ShieldSize.AbsMax() / blockSize;
                    rc *= rc;
                    rc  = rc + 1;
                    rc  = Math.Ceiling(rc);
                    var hits        = 0;
                    var blockPoints = new Vector3D[9];

                    var cloneCacheList = Session.Instance.ListCubeAccelPool.Get();
                    cloneCacheList.AddRange(entInfo.CacheBlockList);
                    var cubeHitSet = Session.Instance.SetCubeAccelPool.Get();

                    for (int i = 0; i < cloneCacheList.Count; i++)
                    {
                        var accel    = cloneCacheList[i];
                        var blockPos = accel.BlockPos;
                        var num1     = gc.X - blockPos.X;
                        var num2     = gc.Y - blockPos.Y;
                        var num3     = gc.Z - blockPos.Z;
                        var result   = (num1 * num1) + (num2 * num2) + (num3 * num3);

                        if (_isServer)
                        {
                            if (result > rc || accel.CubeExists && result > rc + scaledBlockSize)
                            {
                                continue;
                            }
                            if (accel.Block == null || accel.Block.CubeGrid != breaching)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (hits > blockDmgNum)
                            {
                                break;
                            }
                            if (result > rc || accel.CubeExists && result > rc + scaledBlockSize || accel.Block == null || accel.Block.CubeGrid != breaching || accel.Block.IsDestroyed)
                            {
                                continue;
                            }
                        }

                        var block = accel.Block;
                        var point = CustomCollision.BlockIntersect(block, accel.CubeExists, bQuaternion, DetectMatrixOutside, DetectMatrixOutsideInv, ref blockPoints);
                        if (point == null)
                        {
                            continue;
                        }
                        collisionAvg += (Vector3D)point;
                        hits++;
                        if (!_isServer)
                        {
                            continue;
                        }

                        if (hits > blockDmgNum)
                        {
                            break;
                        }

                        rawDamage += block.Integrity;
                        if (damageBlocks)
                        {
                            cubeHitSet.Add(accel);
                        }
                    }
                    cloneCacheList.Clear();
                    Session.Instance.ListCubeAccelPool.Return(cloneCacheList);

                    if (collisionAvg != Vector3D.Zero)
                    {
                        collisionAvg /= hits;
                        ComputeCollisionPhysics(breaching, MyGrid, collisionAvg);
                        entInfo.Touched = true;
                    }
                    else
                    {
                        return;
                    }
                    if (!_isServer)
                    {
                        return;
                    }

                    var damage = rawDamage * DsState.State.ModulateEnergy;

                    var blockEvent = Session.Instance.ManyBlocksPool.Get();
                    blockEvent.Init(cubeHitSet, this, damage, collisionAvg, breaching.EntityId);

                    Session.Instance.ThreadEvents.Enqueue(blockEvent);
                }
            }
            catch (Exception ex) { Log.Line($"Exception in BlockIntersect: {ex}"); }
        }
Example #4
0
        private void CreateShieldShape()
        {
            /*
             * Basically find the point on the surface of the ellipsoid given a normal vector.
             * Equation for ellipsoid is x^2/a^2 + y^2/b^2 ... = 1
             * So given a normal vector x hat, y hat, z hat find the values for x y z that are parallel and satisfy that equation.
             * So x = dist*x normVec, y = dist * y normVec
             * a,b,c are the radii if the ellipsoid in X Y Z
             * So signed distance from surface is distance(point, origin) - distance(support(norm(point-origin)), origin)
             * support gives you the point on the surface in the given direction.
             */
            Asleep = false;

            if (GridIsMobile)
            {
                _updateMobileShape = false;
                if (_shapeChanged)
                {
                    CreateMobileShape();
                }
                DetectionMatrix     = ShieldShapeMatrix * MyGrid.WorldMatrix;
                DetectionCenter     = MyGridCenter;
                _sQuaternion        = Quaternion.CreateFromRotationMatrix(MyGrid.WorldMatrix);
                ShieldSphere.Center = DetectionCenter;
                ShieldSphere.Radius = ShieldSize.AbsMax();
            }
            else
            {
                var emitter = ShieldComp.StationEmitter.Emitter;
                var width   = DsSet.Settings.Width;
                var height  = DsSet.Settings.Height;
                var depth   = DsSet.Settings.Depth;

                var wOffset = DsSet.Settings.ShieldOffset.X;
                var hOffset = DsSet.Settings.ShieldOffset.Y;
                var dOffset = DsSet.Settings.ShieldOffset.Z;

                var blockGridPosMeters   = new Vector3D(emitter.Position) * MyGrid.GridSize;
                var localOffsetMeters    = new Vector3D(wOffset, hOffset, dOffset) * MyGrid.GridSize;
                var localOffsetPosMeters = localOffsetMeters + blockGridPosMeters;
                var emitterCenter        = emitter.PositionComp.GetPosition();
                var offsetLMatrix        = Matrix.CreateWorld(localOffsetPosMeters, Vector3D.Forward, Vector3D.Up);

                var worldOffset             = Vector3D.TransformNormal(localOffsetMeters, MyGrid.WorldMatrix);
                var translationInWorldSpace = emitterCenter + worldOffset;

                OffsetEmitterWMatrix = MatrixD.CreateWorld(translationInWorldSpace, MyGrid.WorldMatrix.Forward, MyGrid.WorldMatrix.Up);

                DetectionCenter = OffsetEmitterWMatrix.Translation;

                var halfDistToCenter = 600 - Vector3D.Distance(DetectionCenter, emitterCenter);
                var vectorScale      = new Vector3D(MathHelper.Clamp(width, 30, halfDistToCenter), MathHelper.Clamp(height, 30, halfDistToCenter), MathHelper.Clamp(depth, 30, halfDistToCenter));

                DetectionMatrix   = MatrixD.Rescale(OffsetEmitterWMatrix, vectorScale);
                ShieldShapeMatrix = MatrixD.Rescale(offsetLMatrix, vectorScale);

                ShieldSize = DetectionMatrix.Scale;

                _sQuaternion        = Quaternion.CreateFromRotationMatrix(OffsetEmitterWMatrix);
                ShieldSphere.Center = DetectionCenter;
                ShieldSphere.Radius = ShieldSize.AbsMax();
            }

            ShieldSphere3K.Center = DetectionCenter;
            WebSphere.Center      = DetectionCenter;

            SOriBBoxD.Center      = DetectionCenter;
            SOriBBoxD.Orientation = _sQuaternion;
            if (_shapeChanged)
            {
                SOriBBoxD.HalfExtent = ShieldSize;
                ShieldAabbScaled.Min = ShieldSize;
                ShieldAabbScaled.Max = -ShieldSize;
                _ellipsoidSa.Update(DetectMatrixOutside.Scale.X, DetectMatrixOutside.Scale.Y, DetectMatrixOutside.Scale.Z);
                BoundingRange = ShieldSize.AbsMax();

                ShieldSphere3K.Radius = BoundingRange + 3000;
                WebSphere.Radius      = BoundingRange + 7;

                _ellipsoidSurfaceArea = _ellipsoidSa.Surface;
                EllipsoidVolume       = 1.333333 * Math.PI * DetectMatrixOutside.Scale.X * DetectMatrixOutside.Scale.Y * DetectMatrixOutside.Scale.Z;
                _shieldVol            = DetectMatrixOutside.Scale.Volume;
                if (_isServer)
                {
                    if (Session.Enforced.Debug == 3)
                    {
                        Log.Line($"StateUpdate: CreateShieldShape - Broadcast:{DsState.State.Message} - ShieldId [{Shield.EntityId}]");
                    }
                    ShieldChangeState();
                    ShieldComp.ShieldVolume = DetectMatrixOutside.Scale.Volume;
                }
                if (Session.Enforced.Debug == 3)
                {
                    Log.Line($"CreateShape: shapeChanged - GridMobile:{GridIsMobile} - ShieldId [{Shield.EntityId}]");
                }
            }
            if (!DsState.State.Lowered)
            {
                SetShieldShape();
            }

            BoundingBoxD.CreateFromSphere(ref WebSphere, out WebBox);
            BoundingBoxD.CreateFromSphere(ref ShieldSphere3K, out ShieldBox3K);
        }
        internal void CreateShieldShape()
        {
            var width  = DsSet.Settings.Width;
            var height = DsSet.Settings.Height;
            var depth  = DsSet.Settings.Depth;

            var maxMulti = ShieldMode != ShieldType.SmallGrid ? 0.33333f : 1f;

            var xMax = GridIsMobile ? DsState.State.GridHalfExtents.X * maxMulti : float.MaxValue;
            var yMax = GridIsMobile ? DsState.State.GridHalfExtents.Y * maxMulti : float.MaxValue;
            var zMax = GridIsMobile ? DsState.State.GridHalfExtents.Z * maxMulti : float.MaxValue;

            var offsetMulti = ShieldMode != ShieldType.SmallGrid ? 1 : 0.2f;

            var wOffset           = MathHelper.Clamp(DsSet.Settings.ShieldOffset.X * offsetMulti, -xMax, xMax);
            var hOffset           = MathHelper.Clamp(DsSet.Settings.ShieldOffset.Y * offsetMulti, -yMax, yMax);
            var dOffset           = MathHelper.Clamp(DsSet.Settings.ShieldOffset.Z * offsetMulti, -zMax, zMax);
            var localOffsetMeters = new Vector3D(wOffset, hOffset, dOffset) * MyGrid.GridSize;

            var gridMatrix  = MyGrid.PositionComp.WorldMatrixRef;
            var worldOffset = Vector3D.TransformNormal(localOffsetMeters, gridMatrix);

            if (GridIsMobile)
            {
                DetectionCenter = MyGridCenter + worldOffset;

                _updateMobileShape = false;
                if (_shapeChanged)
                {
                    CreateMobileShape(localOffsetMeters);
                }
                DetectionMatrix     = ShieldShapeMatrix * gridMatrix;
                SQuaternion         = Quaternion.CreateFromRotationMatrix(gridMatrix);
                ShieldSphere.Center = DetectionCenter;
                ShieldSphere.Radius = ShieldSize.AbsMax();
            }
            else
            {
                IMyUpgradeModule emitter;
                if (_isServer)
                {
                    emitter = ShieldComp.StationEmitter.Emitter;
                }
                else
                {
                    emitter = (IMyUpgradeModule)MyEntities.GetEntityById(DsState.State.ActiveEmitterId, true);
                }

                if (emitter == null)
                {
                    UpdateDimensions = true;
                    return;
                }


                var blockGridPosMeters   = new Vector3D(emitter.Position) * MyGrid.GridSize;
                var localOffsetPosMeters = localOffsetMeters + blockGridPosMeters;
                var emitterCenter        = emitter.PositionComp.GetPosition();
                var offsetLMatrix        = Matrix.CreateWorld(localOffsetPosMeters, Vector3D.Forward, Vector3D.Up);

                var translationInWorldSpace = emitterCenter + worldOffset;

                OffsetEmitterWMatrix = MatrixD.CreateWorld(translationInWorldSpace, gridMatrix.Forward, gridMatrix.Up);

                DetectionCenter = OffsetEmitterWMatrix.Translation;

                var halfDistToCenter = 1000 - Vector3D.Distance(DetectionCenter, emitterCenter);
                var vectorScale      = new Vector3D(MathHelper.Clamp(width, 30, halfDistToCenter), MathHelper.Clamp(height, 30, halfDistToCenter), MathHelper.Clamp(depth, 30, halfDistToCenter));

                DetectionMatrix   = MatrixD.Rescale(OffsetEmitterWMatrix, vectorScale);
                ShieldShapeMatrix = MatrixD.Rescale(offsetLMatrix, vectorScale);

                ShieldSize          = DetectionMatrix.Scale;
                SQuaternion         = Quaternion.CreateFromRotationMatrix(OffsetEmitterWMatrix);
                ShieldSphere.Center = DetectionCenter;
                ShieldSphere.Radius = ShieldSize.AbsMax();
            }

            ShieldSphere3K.Center = DetectionCenter;
            WebSphere.Center      = DetectionCenter;

            SOriBBoxD.Center      = DetectionCenter;
            SOriBBoxD.Orientation = SQuaternion;

            if (_shapeChanged)
            {
                SOriBBoxD.HalfExtent = ShieldSize;
                ShieldAabbScaled.Min = -ShieldSize;
                ShieldAabbScaled.Max = ShieldSize;
                _ellipsoidSa.Update(DetectMatrixOutside.Scale.X, DetectMatrixOutside.Scale.Y, DetectMatrixOutside.Scale.Z);
                BoundingRange         = ShieldSize.AbsMax();
                ShieldSphere3K.Radius = BoundingRange + 3000;
                WebSphere.Radius      = BoundingRange + (IsStatic ? 20 : 10);

                _ellipsoidSurfaceArea = _ellipsoidSa.Surface;
                var magicMod       = DsState.State.Enhancer && ShieldMode == ShieldType.Station ? 100f : DsState.State.Enhancer && DsSet.Settings.FortifyShield ? 12f + Math.Sqrt(DsSet.Settings.Fit) : 1f;
                var ellipsoidMagic = _ellipsoidSurfaceArea / (MagicEllipsoidRatio * magicMod);
                var rawScaler      = Math.Sqrt(ellipsoidMagic);
                _sizeScaler = (float)rawScaler;

                /// Large ship bonus
                var size           = DsState.State.RealGridHalfExtents.Volume * 2;
                var scaleMod       = size * (size * 0.00000012d);
                var scaleSqrt      = Math.Sqrt(scaleMod) - 1d;
                var safeSqrt       = scaleSqrt <= 0 ? 0.1d : scaleSqrt;
                var volumeModifier = Math.Log10(safeSqrt);

                if (ShieldMode != ShieldType.Station && DsState.State.BlockDensity >= 1 && volumeModifier >= 1)
                {
                    _sizeScaler /= (float)volumeModifier;
                }
                ///

                if (_isServer)
                {
                    ShieldChangeState();
                    ShieldComp.ShieldVolume = DetectMatrixOutside.Scale.Volume;
                }
            }

            if (_shapeChanged)
            {
                var zeroMatrix   = Matrix.Zero;
                var shieldMatrix = (Matrix)ShieldShapeMatrix;
                if (!_isDedicated)
                {
                    _shellPassive.PositionComp.SetLocalMatrix(ref zeroMatrix, null, true);  // Bug - Cannot just change X coord, so I reset first.
                    ShellActive.PositionComp.SetLocalMatrix(ref zeroMatrix, null, true);
                    _shellPassive.PositionComp.SetLocalMatrix(ref shieldMatrix, null, true);
                    ShellActive.PositionComp.SetLocalMatrix(ref shieldMatrix, null, true);
                }
                ShieldEnt.PositionComp.SetLocalMatrix(ref zeroMatrix, null, true);
                ShieldEnt.PositionComp.SetLocalMatrix(ref shieldMatrix, null, true);
                ShieldEnt.PositionComp.LocalAABB    = BoundingBox.CreateFromHalfExtent(Vector3.Zero, (float)ShieldSize.AbsMax());
                ShieldEnt.PositionComp.WorldMatrix *= MyGrid.PositionComp.WorldMatrix.GetOrientation();

                ShapeChangeTick = _tick;
            }
            ShieldEnt.PositionComp.SetPosition(DetectionCenter);
            BoundingBoxD.CreateFromSphere(ref WebSphere, out WebBox);
            BoundingBoxD.CreateFromSphere(ref ShieldSphere3K, out ShieldBox3K);
        }