private void UpdateWaypoint()
        {
            int currentTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;

            //find new target player
            if ((m_target == null && currentTime - m_lastTargetUpdate >= 5000) || currentTime - m_lostStartTimeMs >= m_lostTimeMs)
            {
                MyPlayer player = m_remoteControl.GetNearestPlayer();
                m_target           = player != null ? player.Character as MyEntity : null;
                m_lastTargetUpdate = currentTime;
                if (m_target != null)
                {
                    m_lostStartTimeMs   = currentTime;
                    m_farAwayFromTarget = true;
                }
                else
                {
                    m_lostStartTimeMs += 5000;
                }
            }

            if (m_farAwayFromTarget && currentTime - m_lastTargetUpdate >= 5000)
            {
                m_lastTargetUpdate = currentTime;
                NeedUpdate         = true;
            }

            //weapon/suicide update
            float distSq = -1f;

            if (m_operational && currentTime - m_lastWeaponUpdate >= 300)
            {
                m_lastWeaponUpdate = currentTime;
                distSq             = Vector3.DistanceSquared((Vector3)m_target.PositionComp.GetPosition(), (Vector3)m_remoteControl.PositionComp.GetPosition());
                WeaponsUpdate(distSq);
            }

            if (currentTime - m_waypointReachedTimeMs >= m_waypointMaxTime)
            {
                NeedUpdate = true;
            }

            if (!NeedUpdate || m_target == null)
            {
                return;
            }

            //active and prepare waypoints
            IsActive = true;
            if (distSq < 0)
            {
                distSq = Vector3.DistanceSquared((Vector3)m_target.PositionComp.GetPosition(), (Vector3)m_remoteControl.PositionComp.GetPosition());
            }
            m_farAwayFromTarget = distSq > m_maxManeuverDistanceSq;
            bool origUpdate = NeedUpdate;

            if (m_remoteControl.HasWaypoints())
            {
                m_remoteControl.ClearWaypoints();
                //MyGuiAudio.PlaySound(MyGuiSounds.PlayTakeItem); //debug
            }
            m_remoteControl.SetAutoPilotEnabled(true);
            NeedUpdate = origUpdate;

            Vector3D newWaypoint;

            if (m_firstWaypoint != Vector3D.Zero)
            {
                newWaypoint     = m_firstWaypoint;
                m_firstWaypoint = Vector3D.Zero;
            }
            else if (!m_operational && m_kamikazeBehavior)
            {
                //no functional weapons -> ram the player
                if (m_remoteControl.TargettingAimDelta > 0.02f)
                {
                    return;
                }
                newWaypoint = m_target.PositionComp.GetPosition() + m_target.WorldMatrix.Up * PlayerYAxisOffset * 2 - Vector3D.Normalize(m_remoteControl.PositionComp.GetPosition() - m_target.PositionComp.GetPosition()) * m_kamikazeBehaviorDistance;
            }
            else if (!m_operational && !m_kamikazeBehavior)
            {
                //no functional weapons -> try to escape
                newWaypoint = ReturnPosition + Vector3.One * 0.01f;
            }
            else if (m_farAwayFromTarget)
            {
                //too far away from target
                newWaypoint = m_target.PositionComp.GetPosition() + Vector3D.Normalize(m_remoteControl.PositionComp.GetPosition() - m_target.PositionComp.GetPosition()) * m_playerTargetDistance;
            }
            else
            {
                //in proximity to target
                m_lostStartTimeMs = currentTime;
                if (currentTime - m_waypointReachedTimeMs <= m_waypointDelayMs)
                {
                    return;
                }
                newWaypoint = GetRandomPoint();
            }

            //Add new point to waypoints
            Vector3D currentToWaypoint = newWaypoint - m_remoteControl.WorldMatrix.Translation;

            currentToWaypoint.Normalize();
            m_waypointReachedTimeMs = currentTime;
            var strafeLocalDir = Vector3.TransformNormal((Vector3)currentToWaypoint, m_remoteControl.PositionComp.WorldMatrixNormalizedInv);

            Base6Directions.Direction strafeDir = Base6Directions.GetClosestDirection(ref strafeLocalDir);
            bool commitKamikadze = m_kamikazeBehavior && !m_operational;

            m_remoteControl.ChangeFlightMode(MyRemoteControl.FlightMode.OneWay);
            m_remoteControl.SetAutoPilotSpeedLimit(commitKamikadze ? 100f : m_speedLimit);
            m_remoteControl.SetCollisionAvoidance(commitKamikadze ? false : m_avoidCollisions);
            m_remoteControl.ChangeDirection(strafeDir);
            m_remoteControl.AddWaypoint(newWaypoint, m_farAwayFromTarget || commitKamikadze ? "Player Vicinity" : "Strafe");

            NeedUpdate = false;
            IsActive   = true;
        }
        public void InitControl()
        {
            //sets direction of angular force and steering for concrete block based on position in grid
            var     mat = MySession.Static.ControlledEntity.Entity.WorldMatrix * PositionComp.WorldMatrixNormalizedInv;
            Vector3 revolveAxis;

            if (Base6Directions.GetClosestDirection(mat.Forward) == Base6Directions.Direction.Up || Base6Directions.GetClosestDirection(mat.Forward) == Base6Directions.Direction.Down)
            {
                revolveAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Forward;
            }
            else if (Base6Directions.GetClosestDirection(mat.Up) == Base6Directions.Direction.Up || Base6Directions.GetClosestDirection(mat.Up) == Base6Directions.Direction.Down)
            {
                revolveAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Up;
            }
            else
            {
                revolveAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Right;
            }
            // - "epsilon"
            var dotCockpit1 = Vector3.Dot(MySession.Static.ControlledEntity.Entity.WorldMatrix.Up, WorldMatrix.Translation - MySession.Static.ControlledEntity.Entity.WorldMatrix.Translation) - 0.0001 > 0;

            Vector3 steerAxis;

            if (Base6Directions.GetClosestDirection(mat.Forward) == Base6Directions.Direction.Forward || Base6Directions.GetClosestDirection(mat.Forward) == Base6Directions.Direction.Backward)
            {
                steerAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Forward;
            }
            else if (Base6Directions.GetClosestDirection(mat.Up) == Base6Directions.Direction.Forward || Base6Directions.GetClosestDirection(mat.Up) == Base6Directions.Direction.Backward)
            {
                steerAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Up;
            }
            else
            {
                steerAxis = MySession.Static.ControlledEntity.Entity.WorldMatrix.Right;
            }
            // - "epsilon"
            if (CubeGrid.Physics != null)
            {
                var dotMass    = Vector3.Dot(MySession.Static.ControlledEntity.Entity.WorldMatrix.Forward, (WorldMatrix.Translation - CubeGrid.Physics.CenterOfMassWorld)) - 0.0001;
                var dotCockpit = Vector3.Dot(WorldMatrix.Forward, steerAxis);

                m_steerInvert   = ((dotMass * dotCockpit) < 0) ^ dotCockpit1;
                m_revolveInvert = ((WorldMatrix.Up - revolveAxis).Length() > 0.1f) ^ dotCockpit1;
            }
        }
Beispiel #3
0
        /// <summary>
        /// Returns true if the given small block connects to large one.
        /// </summary>
        /// <param name="smallBlock">small block</param>
        /// <param name="smallBlockWorldAabb">small block world AABB</param>
        /// <param name="largeBlock">large block</param>
        /// <param name="largeBlockWorldAabb">large block wotld AABB</param>
        /// <returns>true when connected</returns>
        private bool SmallBlockConnectsToLarge(MySlimBlock smallBlock, ref BoundingBoxD smallBlockWorldAabb, MySlimBlock largeBlock, ref BoundingBoxD largeBlockWorldAabb)
        {
            Debug.Assert(GetCubeSize(smallBlock) == MyCubeSize.Small);
            Debug.Assert(GetCubeSize(largeBlock) == MyCubeSize.Large);
            Debug.Assert(!(smallBlock.FatBlock is MyCompoundCubeBlock));
            Debug.Assert(!(largeBlock.FatBlock is MyCompoundCubeBlock));

            BoundingBoxD smallBlockWorldAabbReduced = smallBlockWorldAabb;

            smallBlockWorldAabbReduced.Inflate(-smallBlock.CubeGrid.GridSize / 4);

            // Small block aabb penetrates large block aabb (large timbers).
            bool penetratesAabbs = largeBlockWorldAabb.Contains(smallBlockWorldAabbReduced) == ContainmentType.Intersects;

            if (!penetratesAabbs)
            {
                Vector3D centerToCenter = smallBlockWorldAabb.Center - largeBlockWorldAabb.Center;
                Vector3I addDir         = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(centerToCenter));
                // Check small grid mount points
                Quaternion smallBlockRotation;
                smallBlock.Orientation.GetQuaternion(out smallBlockRotation);
                smallBlockRotation = Quaternion.CreateFromRotationMatrix(smallBlock.CubeGrid.WorldMatrix) * smallBlockRotation;
                if (!MyCubeGrid.CheckConnectivitySmallBlockToLargeGrid(largeBlock.CubeGrid, smallBlock.BlockDefinition, ref smallBlockRotation, ref addDir))
                {
                    return(false);
                }
            }

            BoundingBoxD smallBlockWorldAabbInflated = smallBlockWorldAabb;

            smallBlockWorldAabbInflated.Inflate(2 * smallBlock.CubeGrid.GridSize / 3);

            // Trim small block aabb with large block aabb.
            BoundingBoxD intersectedBox       = smallBlockWorldAabbInflated.Intersect(largeBlockWorldAabb);
            Vector3D     intersectedBoxCenter = intersectedBox.Center;
            HkShape      shape = new HkBoxShape((Vector3)intersectedBox.HalfExtents);

            Quaternion largeRotation;

            largeBlock.Orientation.GetQuaternion(out largeRotation);
            largeRotation = Quaternion.CreateFromRotationMatrix(largeBlock.CubeGrid.WorldMatrix) * largeRotation;
            Vector3D largeTranslation;

            largeBlock.ComputeWorldCenter(out largeTranslation);

            bool result = false;

            try
            {
                if (largeBlock.FatBlock != null)
                {
                    MyModel model = largeBlock.FatBlock.Model;
                    if (model != null)
                    {
                        HkShape[] shapes = model.HavokCollisionShapes;
                        if (shapes == null || shapes.Length == 0)
                        {
                            return(false);
                        }

                        for (int i = 0; i < shapes.Length; ++i)
                        {
                            result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapes[i], ref largeTranslation, ref largeRotation);
                            if (result)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2);

                        result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation);

                        shapeLarge.RemoveReference();
                    }
                }
                else
                {
                    HkShape shapeLarge = new HkBoxShape(largeBlock.BlockDefinition.Size * largeBlock.CubeGrid.GridSize / 2);

                    result = MyPhysics.IsPenetratingShapeShape(shape, ref intersectedBoxCenter, ref Quaternion.Identity, shapeLarge, ref largeTranslation, ref largeRotation);

                    shapeLarge.RemoveReference();
                }
            }
            finally
            {
                shape.RemoveReference();
            }

            return(result);
        }
        protected bool GetBlockAddPosition(float gridSize, bool placingSmallGridOnLargeStatic, out MySlimBlock intersectedBlock, out Vector3D intersectedBlockPos, out Vector3D intersectExactPos,
                                           out Vector3I addPositionBlock, out Vector3I addDirectionBlock, out ushort?compoundBlockId)
        {
            intersectedBlock    = null;
            intersectedBlockPos = new Vector3D();
            intersectExactPos   = new Vector3();
            addDirectionBlock   = new Vector3I();
            addPositionBlock    = new Vector3I();
            compoundBlockId     = null;

            if (CurrentVoxelMap != null)
            {
                Vector3 hitInfoNormal = m_hitInfo.Value.HkHitInfo.Normal;
                Base6Directions.Direction closestDir = Base6Directions.GetClosestDirection(hitInfoNormal);
                Vector3I hitNormal = Base6Directions.GetIntVector(closestDir);

                double distance = IntersectionDistance * m_hitInfo.Value.HkHitInfo.HitFraction;

                Vector3D rayStart     = IntersectionStart;
                Vector3D rayDir       = Vector3D.Normalize(IntersectionDirection);
                Vector3D intersection = rayStart + distance * rayDir;

                // Get cube block placement position (add little threshold to hit normal direction to avoid wavy surfaces).
                addPositionBlock    = MyCubeGrid.StaticGlobalGrid_WorldToUGInt(intersection + 0.1f * Vector3.Half * hitNormal * gridSize, gridSize, MyPerGameSettings.BuildingSettings.StaticGridAlignToCenter);
                addDirectionBlock   = hitNormal;
                intersectedBlockPos = addPositionBlock - hitNormal;

                // Exact intersection in uniform grid coords.
                intersectExactPos = MyCubeGrid.StaticGlobalGrid_WorldToUG(intersection, gridSize, MyPerGameSettings.BuildingSettings.StaticGridAlignToCenter);
                // Project exact intersection to cube face of intersected block.
                intersectExactPos = ((Vector3.One - Vector3.Abs(hitNormal)) * intersectExactPos) + ((intersectedBlockPos + 0.5f * hitNormal) * Vector3.Abs(hitNormal));

                //Vector3 position = MyCubeGrid.StaticWorldGrid_UGToWorld(addPositionBlock);
                //Vector3 halfExtent = new Vector3(gridSize * 0.5f);
                //BoundingBox cubeBox = new BoundingBox(-halfExtent, halfExtent);

                //Matrix matrix = Matrix.CreateTranslation(position);
                //Vector4 blue = Color.Blue.ToVector4();
                //MySimpleObjectDraw.DrawTransparentBox(ref matrix, ref cubeBox, ref blue, MySimpleObjectRasterizer.Wireframe, 1, 0.04f);

                return(true);
            }

            Vector3D?intersectedObjectPos = GetIntersectedBlockData(ref m_invGridWorldMatrix, out intersectExactPos, out intersectedBlock, out compoundBlockId);

            if (intersectedObjectPos == null)
            {
                return(false);
            }

            intersectedBlockPos = intersectedObjectPos.Value;

            Vector3I removePos;

            if (!GetCubeAddAndRemovePositions(Vector3I.Round(intersectedBlockPos), placingSmallGridOnLargeStatic, out addPositionBlock, out addDirectionBlock, out removePos))
            {
                return(false);
            }

            if (!placingSmallGridOnLargeStatic)
            {
                if (MyFakes.ENABLE_BLOCK_PLACING_ON_INTERSECTED_POSITION)
                {
                    Vector3I newRemovepos = Vector3I.Round(intersectedBlockPos);

                    if (newRemovepos != removePos)
                    {
                        if (m_hitInfo.HasValue)
                        {
                            Vector3 hitInfoNormal = m_hitInfo.Value.HkHitInfo.Normal;
                            Base6Directions.Direction closestDir = Base6Directions.GetClosestDirection(hitInfoNormal);
                            Vector3I hitNormal = Base6Directions.GetIntVector(closestDir);
                            addDirectionBlock = hitNormal;
                        }
                        removePos        = newRemovepos;
                        addPositionBlock = removePos + addDirectionBlock;
                    }
                }
                else
                {
                    if (CurrentGrid.CubeExists(addPositionBlock))
                    {
                        return(false);
                    }
                }
            }

            if (placingSmallGridOnLargeStatic)
            {
                removePos = Vector3I.Round(intersectedBlockPos);
            }

            intersectedBlockPos = removePos;
            intersectedBlock    = CurrentGrid.GetCubeBlock(removePos);
            if (intersectedBlock == null)
            {
                Debug.Assert(false, "No intersected block");
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Returns subblock data from dummy, subblock matrix can be offset (according to useOffset parameter) so the dummy position output is also provided.
        /// </summary>
        /// <returns>true when dummy is subblock otherwise false</returns>
        public static bool GetSubBlockDataFromDummy(MyCubeBlockDefinition ownerBlockDefinition, string dummyName, MyModelDummy dummy, bool useOffset, out MyCubeBlockDefinition subBlockDefinition,
                                                    out MatrixD subBlockMatrix, out Vector3 dummyPosition)
        {
            subBlockDefinition = null;
            subBlockMatrix     = MatrixD.Identity;
            dummyPosition      = Vector3.Zero;

            if (!dummyName.ToLower().StartsWith(MyCubeBlock.DUMMY_SUBBLOCK_ID))
            {
                return(false);
            }

            if (ownerBlockDefinition.SubBlockDefinitions == null)
            {
                return(false);
            }

            string dummyNameShort = dummyName.Substring(MyCubeBlock.DUMMY_SUBBLOCK_ID.Length);

            MyDefinitionId definitiondId;

            if (!ownerBlockDefinition.SubBlockDefinitions.TryGetValue(dummyNameShort, out definitiondId))
            {
                Debug.Assert(false, "SubBlock definition not found!");
                return(false);
            }

            MyDefinitionManager.Static.TryGetCubeBlockDefinition(definitiondId, out subBlockDefinition);
            if (subBlockDefinition == null)
            {
                Debug.Assert(false, "SubBlock definition not found!");
                return(false);
            }

            const double dotEpsilon = 0.00000001;

            subBlockMatrix = MatrixD.Normalize(dummy.Matrix);
            Vector3I forward    = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(subBlockMatrix.Forward));
            double   forwardDot = Vector3D.Dot(subBlockMatrix.Forward, (Vector3D)forward);

            if (Math.Abs(1 - forwardDot) <= dotEpsilon)
            {
                subBlockMatrix.Forward = forward;
            }

            Vector3I right    = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(subBlockMatrix.Right));
            double   rightDot = Vector3D.Dot(subBlockMatrix.Right, (Vector3D)right);

            if (Math.Abs(1 - rightDot) <= dotEpsilon)
            {
                subBlockMatrix.Right = right;
            }

            Vector3I up    = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(subBlockMatrix.Up));
            double   upDot = Vector3D.Dot(subBlockMatrix.Up, (Vector3D)up);

            if (Math.Abs(1 - upDot) <= dotEpsilon)
            {
                subBlockMatrix.Up = up;
            }

            dummyPosition = subBlockMatrix.Translation;
            if (useOffset)
            {
                Vector3 offset = MyCubeBlock.GetBlockGridOffset(subBlockDefinition);
                subBlockMatrix.Translation -= Vector3D.TransformNormal(offset, subBlockMatrix);
            }

            return(true);
        }
Beispiel #6
0
        protected bool GetBlockAddPosition(float gridSize, bool placingSmallGridOnLargeStatic, out MySlimBlock intersectedBlock, out Vector3D intersectedBlockPos, out Vector3D intersectExactPos, out Vector3I addPositionBlock, out Vector3I addDirectionBlock, out ushort?compoundBlockId)
        {
            Vector3I vectori;

            intersectedBlock    = null;
            intersectedBlockPos = new Vector3D();
            Vector3 vector = new Vector3();

            intersectExactPos = vector;
            addDirectionBlock = new Vector3I();
            addPositionBlock  = new Vector3I();
            compoundBlockId   = 0;
            if (this.CurrentVoxelBase != null)
            {
                Vector3I intVector = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(this.m_hitInfo.Value.HkHitInfo.Normal));
                Vector3D worldPos  = IntersectionStart + ((IntersectionDistance * this.m_hitInfo.Value.HkHitInfo.HitFraction) * Vector3D.Normalize(IntersectionDirection));
                addPositionBlock    = MyCubeGrid.StaticGlobalGrid_WorldToUGInt(worldPos + (((0.1f * Vector3.Half) * intVector) * gridSize), gridSize, CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter);
                addDirectionBlock   = intVector;
                intersectedBlockPos = (Vector3D)(addPositionBlock - intVector);
                intersectExactPos   = MyCubeGrid.StaticGlobalGrid_WorldToUG(worldPos, gridSize, CubeBuilderDefinition.BuildingSettings.StaticGridAlignToCenter);
                intersectExactPos   = ((Vector3D.One - Vector3.Abs((Vector3)intVector)) * intersectExactPos) + ((intersectedBlockPos + (0.5f * intVector)) * Vector3.Abs((Vector3)intVector));
                return(true);
            }
            Vector3D?nullable = this.GetIntersectedBlockData(ref this.m_invGridWorldMatrix, out intersectExactPos, out intersectedBlock, out compoundBlockId);

            if (nullable == null)
            {
                return(false);
            }
            intersectedBlockPos = nullable.Value;
            if (!this.GetCubeAddAndRemovePositions(Vector3I.Round(intersectedBlockPos), placingSmallGridOnLargeStatic, out addPositionBlock, out addDirectionBlock, out vectori))
            {
                return(false);
            }
            if (!placingSmallGridOnLargeStatic)
            {
                if (!MyFakes.ENABLE_BLOCK_PLACING_ON_INTERSECTED_POSITION)
                {
                    if (this.CurrentGrid.CubeExists(addPositionBlock))
                    {
                        return(false);
                    }
                }
                else
                {
                    Vector3I vectori3 = Vector3I.Round(intersectedBlockPos);
                    if (vectori3 != vectori)
                    {
                        if (this.m_hitInfo != null)
                        {
                            Vector3I intVector = Base6Directions.GetIntVector(Base6Directions.GetClosestDirection(this.m_hitInfo.Value.HkHitInfo.Normal));
                            addDirectionBlock = intVector;
                        }
                        vectori          = vectori3;
                        addPositionBlock = (Vector3I)(vectori + addDirectionBlock);
                    }
                }
            }
            if (placingSmallGridOnLargeStatic)
            {
                vectori = Vector3I.Round(intersectedBlockPos);
            }
            intersectedBlockPos = (Vector3D)vectori;
            intersectedBlock    = this.CurrentGrid.GetCubeBlock(vectori);
            return(intersectedBlock != null);
        }
Beispiel #7
0
        /// <summary>
        /// Move blocks in m_projectedBlocks to m_damagedBlocks if they are touching any real blocks
        /// </summary>
        private void ProjectedToDamaged()
        {
            foreach (IMySlimBlock block in m_projectedBlocks)
            {
                MyCubeGrid projected     = (MyCubeGrid)block.CubeGrid;
                MyCubeGrid projectorGrid = projected.Projector.CubeGrid;

                if (projected.Closed || projected.Projector.Closed || !projected.Projector.IsWorking || projectorGrid.Closed)
                {
                    Log.DebugLog("projection closed");
                    continue;
                }

                Vector3I min = projectorGrid.WorldToGridInteger(projected.GridIntegerToWorld(block.Min()));

                if (projectorGrid.GetCubeBlock(min) != null)
                {
                    Log.DebugLog("space is occupied: " + min);
                    m_projectedBlocks.Remove(block);
                    continue;
                }

                IMyCubeBlock cubeBlock = block.FatBlock;
                if (cubeBlock != null)
                {
                    Vector3I max = projectorGrid.WorldToGridInteger(projected.GridIntegerToWorld(block.Max()));

                    MatrixD invOrient = projectorGrid.PositionComp.WorldMatrixNormalizedInv.GetOrientation();
                    Vector3 forward   = Vector3D.Transform(cubeBlock.WorldMatrix.Forward, ref invOrient);
                    Vector3 up        = Vector3D.Transform(cubeBlock.WorldMatrix.Up, ref invOrient);

                    MyBlockOrientation orient = new MyBlockOrientation(Base6Directions.GetClosestDirection(ref forward), Base6Directions.GetClosestDirection(ref up));

                    if (projectorGrid.CanPlaceBlock(min, max, orient, ((MyCubeBlock)cubeBlock).BlockDefinition))
                    {
                        Log.DebugLog("can place fatblock: " + cubeBlock.DisplayNameText + ", position: " + min + ", world: " + projectorGrid.GridIntegerToWorld(min));
                        m_damagedBlocks.Add(block);
                        m_projectedBlocks.Remove(block);
                    }

                    continue;
                }

                // no fatblock, cannot get definition
                if (projectorGrid.IsTouchingAnyNeighbor(min, min))
                {
                    Log.DebugLog("can place slimblock: " + block.ToString() + ", position: " + min + ", world: " + projectorGrid.GridIntegerToWorld(min));
                    m_damagedBlocks.Add(block);
                    m_projectedBlocks.Remove(block);
                }
            }

            m_projectedBlocks.ApplyRemovals();
        }