internal bool IsInsideHelper(Vector3D pt, List <int> selector)
        {
            // ReSharper disable once ImpureMethodCallOnReadonlyValueField
            if (Box.Contains(pt) == ContainmentType.Disjoint)
            {
                return(false);
            }
            var    ray = new RayD(pt, QueryDir);
            double dist;
            var    i = 0;

            if (selector != null)
            {
                foreach (var id in selector)
                {
                    var k = _tris[id];
                    if (k.Intersects(ref ray, out dist))
                    {
                        i++;
                    }
                }
            }
            else
            {
                foreach (var k in _tris)
                {
                    if (k.Intersects(ref ray, out dist))
                    {
                        i++;
                    }
                }
            }

            return((i & 1) == 1);
        }
            private bool CheckIfEntityRelevant(HaE_Entity entity, Vector3D currentHeading)
            {
                if (entity.entityInfo.EntityId == rc.CubeGrid.EntityId)
                {
                    return(false);
                }

                if (entity.BoundingSphere.Radius <= 0)
                {
                    return(false);
                }

                Vector3D movementDir = rc.GetShipVelocities().LinearVelocity;

                movementDir.Normalize();

                RayD movementRay = new RayD(rc.CubeGrid.WorldVolume.Center, movementDir);
                RayD headingRay  = new RayD(rc.CubeGrid.WorldVolume.Center, currentHeading);

                BoundingSphereD sphere = entity.BoundingSphere;

                sphere.Radius += rc.CubeGrid.WorldVolume.Radius;

                double?intersectVel     = sphere.Intersects(movementRay);
                double?intersectHeading = sphere.Intersects(headingRay);

                return(intersectVel.HasValue || intersectHeading.HasValue);
            }
Пример #3
0
            /// <summary>
            /// Moller-Trumbore Intersection
            /// </summary>
            /// <param name="ray"></param>
            /// <param name="t"></param>
            /// <returns></returns>
            public bool Intersects(ref RayD ray, out double t)
            {
                t = double.NaN;
                const float epsilon = 0.0000001f;
                Vector3     h       = ((Vector3)ray.Direction).Cross(Edge2);
                float       a       = h.Dot(Edge1);

                if (a > -epsilon && a < epsilon)
                {
                    return(false);
                }
                var      f = 1 / a;
                Vector3D s = ray.Position - Origin;
                var      u = f * (s.Dot(h));

                if (u < 0.0 || u > 1.0)
                {
                    return(false);
                }
                Vector3D q = s.Cross(Edge1);
                var      v = f * ray.Direction.Dot(q);

                if (v < 0.0 || u + v > 1.0)
                {
                    return(false);
                }
                t = f * q.Dot(Edge2);
                return(t > epsilon);
            }
Пример #4
0
        private Vector3D ComputeHandlerImpact()
        {
            WebDamage            = false;
            HandlerImpact.Active = false;
            if (HandlerImpact.HitBlock == null)
            {
                return(DetectionCenter);
            }

            Vector3D originHit;

            HandlerImpact.HitBlock.ComputeWorldCenter(out originHit);

            var line = new LineD(HandlerImpact.Attacker.PositionComp.WorldAABB.Center, originHit);

            var testDir       = Vector3D.Normalize(line.From - line.To);
            var ray           = new RayD(line.From, -testDir);
            var matrix        = DetectionMatrix;
            var invMatrix     = MatrixD.Invert(matrix);
            var intersectDist = CustomCollision.IntersectEllipsoid(ref invMatrix, matrix, ref ray);
            var ellipsoid     = intersectDist ?? line.Length;
            var shieldHitPos  = line.From + (testDir * -ellipsoid);

            return(shieldHitPos);
        }
Пример #5
0
        public bool HitFriendlyShield(Vector3D weaponPos, Vector3D targetPos, Vector3D dir)
        {
            var testRay = new RayD(weaponPos, dir);

            Comp.Ai.TestShields.Clear();
            var checkDistanceSqr = Vector3.DistanceSquared(targetPos, weaponPos);

            for (int i = 0; i < Comp.Ai.NearByFriendlyShields.Count; i++)
            {
                var shield = Comp.Ai.NearByFriendlyShields[i];
                var dist   = testRay.Intersects(shield.PositionComp.WorldVolume);
                if (dist != null && dist.Value * dist.Value <= checkDistanceSqr)
                {
                    Comp.Ai.TestShields.Add(shield);
                }
            }

            if (Comp.Ai.TestShields.Count == 0)
            {
                return(false);
            }

            var result = Comp.Ai.Session.SApi.IntersectEntToShieldFast(Comp.Ai.TestShields, testRay, true, false, Comp.Ai.AiOwner, checkDistanceSqr);

            return(result.Item1 && result.Item2 > 0);
        }
Пример #6
0
        public void Execute()
        {
            if (Entity == null || Entity.MarkedForClose)
            {
                return;
            }
            var floater   = (IMyFloatingObject)Entity;
            var entVel    = Entity.Physics.LinearVelocity;
            var movingVel = entVel != Vector3.Zero ? entVel : -Shield.MyGrid.Physics.LinearVelocity;

            var rayDir    = Vector3D.Normalize(movingVel);
            var ray       = new RayD(Entity.PositionComp.WorldVolume.Center, rayDir);
            var intersect = CustomCollision.IntersectEllipsoid(Shield.DetectMatrixOutsideInv, Shield.DetectionMatrix, ray);
            var hitDist   = intersect ?? 0;
            var hitPos    = ray.Position + (ray.Direction * -hitDist);

            if (Session.Instance.MpActive)
            {
                Shield.AddShieldHit(Entity.EntityId, 1, Session.Instance.MPKinetic, null, false, hitPos);
                floater.DoDamage(9999999, Session.Instance.MpIgnoreDamage, true, null, Shield.MyCube.EntityId);
            }
            else
            {
                Shield.WorldImpactPosition = hitPos;
                Shield.ImpactSize          = 10;
                floater.DoDamage(9999999, Session.Instance.MpIgnoreDamage, false, null, Shield.MyCube.EntityId);
            }
            Shield.WebDamage = true;
            Shield.Absorb   += 1;
        }
Пример #7
0
    public void TestPlaneRayCast()
    {
        Random.InitState(123);
        for (int i = 0; i < 1000; i++)
        {
            Vector3  direction  = Random.onUnitSphere;
            float    dist       = Random.Range(-999, 999);
            Vector3D directionD = new Vector3D(direction);
            Plane3D  planeD     = new Plane3D(directionD, dist);
            Plane    plane      = new Plane(direction, dist);
            for (int j = 0; j < 10; j++)
            {
                Vector3  pos     = Random.insideUnitSphere * 999;
                Vector3  rayDir  = Random.onUnitSphere;
                Vector3D posD    = new Vector3D(pos);
                Vector3D rayDirD = new Vector3D(rayDir);
                Ray      r       = new Ray(pos, rayDir);
                RayD     rd      = new RayD(posD, rayDirD);

                float  enter;
                double enterD;
                bool   res  = plane.Raycast(r, out enter);
                bool   resD = planeD.Raycast(rd, out enterD);
                Assert.AreEqual(res, resD, "Raycast Res " + plane + " ray " + r);
                if (enterD < 1e7)
                {
                    Assert.AreEqual((double)enter, enterD, Mathf.Abs(enter) / 1000,
                                    "GetDistanceToPoint " + plane + " ray " + r);
                }
            }
        }
    }
        private Vector3 GetBoneOnSphere(Vector3I center, Vector3I bonePos, MyCubeGrid grid)
        {
            Vector3D worldCenter = BoneToWorld(center, Vector3.Zero, grid);
            Vector3D worldBone   = BoneToWorld(bonePos, Vector3.Zero, grid);

            BoundingSphereD sphere    = new BoundingSphereD(worldCenter, grid.GridSize);
            Vector3D        direction = worldCenter - worldBone;

            direction.Normalize();
            RayD ray = new RayD(worldBone, direction);

            double tmin, tmax;

            if (sphere.IntersectRaySphere(ray, out tmin, out tmax))
            {
                Vector3D onSphere = worldBone + direction * tmin;

                var worldOnSphere = Vector3D.Transform(onSphere, grid.PositionComp.WorldMatrixInvScaled);
                worldOnSphere += new Vector3D(grid.GridSize / grid.Skeleton.BoneDensity);
                return(worldOnSphere - (Vector3D)(bonePos / (float)grid.Skeleton.BoneDensity) * grid.GridSize);
            }
            else
            {
                return(Vector3.Zero);
            }
        }
Пример #9
0
        private static Vector3D?TAPI_LineIntersectShield(IMyTerminalBlock block, LineD line)
        {
            var logic = block?.GameLogic?.GetAs <DefenseShields>()?.ShieldComp?.DefenseShields;

            if (logic == null)
            {
                return(null);
            }
            var ray = new RayD(line.From, line.Direction);

            float?intersectDist;

            lock (logic.MatrixLock)
                intersectDist = CustomCollision.IntersectEllipsoid(logic.DetectMatrixOutsideInv, logic.DetectMatrixOutside, ray);

            if (!intersectDist.HasValue)
            {
                return(null);
            }
            var ellipsoid = intersectDist ?? 0;

            if (ellipsoid > line.Length)
            {
                return(null);
            }
            return(ray.Position + (ray.Direction * ellipsoid));
        }
Пример #10
0
        private bool RayCheckTargets(Vector3D origin, Vector3D dir, out MyEntity closestEnt, out Vector3D hitPos, out bool foundOther, bool checkOthers = false)
        {
            var ai          = _session.TrackingAi;
            var closestDist = double.MaxValue;

            closestEnt = null;
            foreach (var info in ai.Targets.Keys)
            {
                var hit = info as MyCubeGrid;
                if (hit == null)
                {
                    continue;
                }
                var ray  = new RayD(origin, dir);
                var dist = ray.Intersects(info.PositionComp.WorldVolume);
                if (dist.HasValue)
                {
                    if (dist.Value < closestDist)
                    {
                        closestDist = dist.Value;
                        closestEnt  = hit;
                    }
                }
            }

            foundOther = false;
            if (checkOthers)
            {
                for (int i = 0; i < ai.Obstructions.Count; i++)
                {
                    var otherEnt = ai.Obstructions[i];
                    if (otherEnt is MyCubeGrid)
                    {
                        var ray  = new RayD(origin, dir);
                        var dist = ray.Intersects(otherEnt.PositionComp.WorldVolume);
                        if (dist.HasValue)
                        {
                            if (dist.Value < closestDist)
                            {
                                closestDist = dist.Value;
                                closestEnt  = otherEnt;
                                foundOther  = true;
                            }
                        }
                    }
                }
            }

            if (closestDist < double.MaxValue)
            {
                hitPos = origin + (dir * closestDist);
            }
            else
            {
                hitPos = Vector3D.Zero;
            }

            return(closestEnt != null);
        }
Пример #11
0
        // ModApi only methods below
        private static Vector3D?TAPI_RayAttackShield(IMyTerminalBlock block, RayD ray, long attackerId, float damage, bool energy, bool drawParticle)
        {
            var logic = block?.GameLogic?.GetAs <DefenseShields>()?.ShieldComp?.DefenseShields;

            if (logic == null)
            {
                return(null);
            }

            float?intersectDist;

            lock (logic.MatrixLock)
                intersectDist = CustomCollision.IntersectEllipsoid(logic.DetectMatrixOutsideInv, logic.DetectMatrixOutside, ray);

            if (!intersectDist.HasValue)
            {
                return(null);
            }
            var ellipsoid = intersectDist ?? 0;
            var hitPos    = ray.Position + (ray.Direction * ellipsoid);

            if (energy)
            {
                damage *= logic.DsState.State.ModulateKinetic;
            }
            else
            {
                damage *= logic.DsState.State.ModulateEnergy;
            }

            if (Session.Instance.MpActive)
            {
                var damageType = energy ? Session.Instance.MPEnergy : Session.Instance.MPKinetic;
                logic.AddShieldHit(attackerId, damage, damageType, null, true, hitPos);
            }
            else
            {
                if (!drawParticle)
                {
                    logic.EnergyHit = DefenseShields.HitType.Other;
                }
                else if (energy)
                {
                    logic.EnergyHit = DefenseShields.HitType.Energy;
                }
                else
                {
                    logic.EnergyHit = DefenseShields.HitType.Kinetic;
                }

                logic.ImpactSize          = damage;
                logic.WorldImpactPosition = hitPos;
            }
            logic.WebDamage = true;
            logic.Absorb   += damage;

            return(hitPos);
        }
Пример #12
0
        private void CheckInput()
        {
            MatrixD headMatrix = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(true);
            RayD    ray        = new RayD(headMatrix.Translation, headMatrix.Forward);

            BoundingSphereD holoSphere = new BoundingSphereD(m_offset.ToWorld(m_block), m_radiusHolo);
            double          tmin, tmax;

            if (!holoSphere.IntersectRaySphere(ray, out tmin, out tmax) || tmin > CrosshairRange)
            {
                return;
            }

            int scroll = MyAPIGateway.Input.DeltaMouseScrollWheelValue();

            if (scroll != 0)
            {
                int   scrollSteps = (int)Math.Round(scroll * InputScrollMulti);
                float rangeMulti  = 1f;
                while (scrollSteps > 0)
                {
                    rangeMulti *= ScrollRangeMulti;
                    scrollSteps--;
                }
                while (scrollSteps < 0)
                {
                    rangeMulti /= ScrollRangeMulti;
                    scrollSteps++;
                }
                m_rangeDetection *= rangeMulti;
            }

            if (MyAPIGateway.Input.IsNewRightMousePressed())
            {
                m_centreEntityId = 0L;
            }
            else if (MyAPIGateway.Input.IsNewLeftMousePressed())
            {
                IMyEntity firstHit         = null;
                double    firstHitDistance = CrosshairRange;

                foreach (SeenHolo sh in m_holoEntities.Values)
                {
                    if (sh.Holo.Render.Visible && sh.Holo.PositionComp.WorldAABB.Intersect(ref ray, out tmin, out tmax) && tmin < firstHitDistance)
                    {
                        firstHit         = sh.Seen.Entity;
                        firstHitDistance = tmin;
                    }
                }

                if (firstHit != null)
                {
                    m_centreEntityId = firstHit.EntityId;
                }
            }
        }
Пример #13
0
            private double?CollisionDistance(ref MyDetectedEntityInfo e, ref BoundingSphereD volume, ref Vector3D myVel)
            {
                BoundingSphereD sphere = new BoundingSphereD(e.Position, e.BoundingBox.Size.Length() / 2 + volume.Radius + Clearance);
                Vector3D        vel    = myVel + e.Velocity;

                vel.Normalize();
                RayD ray = new RayD(ref volume.Center, ref vel);

                return(sphere.Intersects(ray));
            }
Пример #14
0
        public double GetSurfaceHeight(Vector3d planetLocalPosition, int detailDensity = 1)
        {
            double height = -1;

            //planetLocalPosition.Normalize();

            var rayFromPlanet = new RayD(Vector3d.Zero, planetLocalPosition);

            var chunk = rootSegments.FirstOrDefault(c => rayFromPlanet.CastRay(c.NoElevationRange).DidHit);

            if (chunk != null)
            {
                //lock (chunk)
                {
                    int safe = 100;
                    while (chunk.Children.Count > 0 && chunk.Children.Any(c => c.IsGenerationDone) && safe-- > 0)
                    {
                        foreach (var child in chunk.Children)
                        {
                            if (child.IsGenerationDone && rayFromPlanet.CastRay(child.NoElevationRange).DidHit)
                            {
                                chunk = child;
                            }
                        }
                    }
                }

                var chunkLocalPosition = (planetLocalPosition - chunk.NoElevationRange.CenterPos);

                height = chunk.GetHeight(chunkLocalPosition);
            }

            if (GetSurfaceHeightDebug)
            {
                if (height == -1)
                {
                    height = RadiusMin;
                    if (chunk == null)
                    {
                        Scene.DebugShere(GetPosition(planetLocalPosition, height), 1000, new Vector4(1, 0, 0, 1));
                    }
                    else
                    {
                        Scene.DebugShere(GetPosition(planetLocalPosition, height), 1000, new Vector4(1, 1, 0, 1));
                    }
                }
                else
                {
                    Scene.DebugShere(GetPosition(planetLocalPosition, height), 1000, new Vector4(0, 1, 0, 1));
                }
            }


            return(height);
        }
Пример #15
0
        //Method From DarkStar for Detecting Sphere Intersections in Defense Shield
        public static Vector3D?DsRayCast(IMyEntity shield, LineD line, long attackerId, float damage, MyStringId effect)
        {
            var worldSphere = new BoundingSphereD(shield.PositionComp.WorldVolume.Center, shield.PositionComp.LocalAABB.HalfExtents.AbsMax());
            var myObb       = MyOrientedBoundingBoxD.Create(shield.PositionComp.LocalAABB, shield.PositionComp.WorldMatrix.GetOrientation());

            myObb.Center = shield.PositionComp.WorldVolume.Center;
            var obbCheck = myObb.Intersects(ref line);

            var testDir = line.From - line.To;

            testDir.Normalize();
            var ray         = new RayD(line.From, -testDir);
            var sphereCheck = worldSphere.Intersects(ray);

            var    obb    = obbCheck ?? 0;
            var    sphere = sphereCheck ?? 0;
            double furthestHit;

            if (obb <= 0 && sphere <= 0)
            {
                furthestHit = 0;
            }
            else if (obb > sphere)
            {
                furthestHit = obb;
            }
            else
            {
                furthestHit = sphere;
            }
            var hitPos = line.From + testDir * -furthestHit;

            /*
             * var parent = MyAPIGateway.Entities.GetEntityById(long.Parse(shield.Name));
             * var cubeBlock = (MyCubeBlock)parent;
             * var block = (IMySlimBlock)cubeBlock.SlimBlock;
             *
             * if(block == null){
             *
             *      return null;
             *
             * }
             *
             * block.DoDamage(damage, MyStringHash.GetOrCompute(effect.ToString()), true, null, attackerId);
             * shield.Render.ColorMaskHsv = hitPos;
             *
             * if(effect.ToString() == "bypass"){
             *
             *      return null;
             *
             * }
             */
            return(hitPos);
        }
Пример #16
0
        protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos)
        {
            bool result = false;

            addPos    = new Vector3I();
            addDir    = new Vector3I();
            removePos = new Vector3I();

            MatrixD worldInv = MatrixD.Invert(CurrentGrid.WorldMatrix);

            Vector3D intersectionPos;

            addPos = intersectedCube;
            addDir = Vector3I.Forward;

            Vector3D rayStart = Vector3D.Transform(IntersectionStart, worldInv);
            Vector3D rayDir   = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldInv));

            RayD r = new RayD(rayStart, rayDir);

            for (int i = 0; i < 100; ++i) // Limit iterations to 100
            {
                var cubeBb = GetCubeBoundingBox(addPos);
                if (!placingSmallGridOnLargeStatic && cubeBb.Contains(rayStart) == ContainmentType.Contains)
                {
                    break;
                }

                double?dist = cubeBb.Intersects(r);
                if (!dist.HasValue)
                {
                    break;
                }

                removePos = addPos;

                intersectionPos = rayStart + rayDir * dist.Value;
                Vector3  center = removePos * CurrentGrid.GridSize;
                Vector3I dirInt = Vector3I.Sign(Vector3.DominantAxisProjection(intersectionPos - center));

                addPos = removePos + dirInt;
                addDir = dirInt;
                result = true;

                if (!CurrentGrid.CubeExists(addPos))
                {
                    break;
                }
            }

            Debug.Assert(!result || addDir != Vector3I.Zero, "Direction vector cannot be zero");
            return(result);
        }
Пример #17
0
 public bool Raycast(RayD ray, out double enter)
 {
     double num = Vector3D.Dot (ray.direction, this.normal);
     double num2 = -Vector3D.Dot (ray.origin, this.normal) - this.distance;
     if (Mathf.Approximately ((float)num, 0f))
     {
         enter = 0f;
         return false;
     }
     enter = num2 / num;
     return enter > 0f;
 }
Пример #18
0
        private static MyTuple <float?, IMyTerminalBlock> TAPI_ClosestShieldInLine(LineD line, bool onlyIfOnline)
        {
            var segment = SegmentPool.Get();

            MyGamePruningStructure.GetTopmostEntitiesOverlappingRay(ref line, segment, MyEntityQueryType.Dynamic);
            var ray = new RayD(line.From, line.Direction);

            var closest = float.MaxValue;
            IMyTerminalBlock closestShield = null;

            for (int i = 0; i < segment.Count; i++)
            {
                var ent = segment[i].Element;
                if (ent == null || ent.Physics != null && !ent.Physics.IsPhantom)
                {
                    continue;
                }
                ShieldGridComponent c;
                if (Session.Instance.IdToBus.TryGetValue(ent.EntityId, out c) && c.DefenseShields != null)
                {
                    if (onlyIfOnline && (!c.DefenseShields.DsState.State.Online || c.DefenseShields.DsState.State.Lowered))
                    {
                        continue;
                    }
                    var s             = c.DefenseShields;
                    var intersectDist = CustomCollision.IntersectEllipsoid(s.DetectMatrixOutsideInv, s.DetectMatrixOutside, ray);
                    if (!intersectDist.HasValue)
                    {
                        continue;
                    }
                    var ellipsoid = intersectDist ?? 0;
                    if (ellipsoid > line.Length || ellipsoid > closest || CustomCollision.PointInShield(ray.Position, s.DetectMatrixOutsideInv))
                    {
                        continue;
                    }
                    closest       = ellipsoid;
                    closestShield = s.Shield;
                }
            }
            segment.Clear();
            SegmentPool.Return(segment);
            var response = new MyTuple <float?, IMyTerminalBlock>();

            if (closestShield == null)
            {
                response.Item1 = null;
                response.Item2 = null;
                return(response);
            }
            response.Item1 = closest;
            response.Item2 = closestShield;
            return(response);
        }
Пример #19
0
    public bool Raycast(RayD ray, out double enter)
    {
        double num  = Vector3D.Dot(ray.direction, normal);
        double num2 = -Vector3D.Dot(ray.origin, normal) - distance;

        if (Mathf.Approximately((float)num, 0f))
        {
            enter = 0f;
            return(false);
        }
        enter = num2 / num;
        return(enter > 0f);
    }
Пример #20
0
    // return NaN if line is parallel with plane
    public Vector3D LineIntersection(Vector3D lineFrom, Vector3D lineTo)
    {
        var    ray = new RayD(lineFrom, (lineTo - lineFrom).normalized);
        double enter;
        double num  = Vector3D.Dot(ray.direction, normal);
        double num2 = -Vector3D.Dot(ray.origin, normal) - distance;

        if (num == 0)
        {
            return(Vector3D.one * double.NaN);
        }
        enter = num2 / num;
        return(ray.GetPointAt(enter));
    }
Пример #21
0
    Vector3D ProjectToTriangle(Vector3D point)
    {
        Plane3D plane          = new Plane3D(Normal, points[0]);
        bool    isPointInPlane = System.Math.Abs(plane.GetDistanceToPoint(point)) < 0.0001;

        if (!isPointInPlane)
        {
            double dist;
            point.y = 0;
            var ray = new RayD(point, Vector3D.up);
            plane.Raycast(ray, out dist);
            point.y = dist;
        }
        return(point);
    }
Пример #22
0
        /**
         * Project a position to a face of the (-1, -1, -1)(1, 1, 1) cube.
         */
        public static void ProjectToNearestFace(ref Vector3D localPos, out Vector3 faceCoords)
        {
            Vector3D gravity;

            Vector3D.Normalize(ref localPos, out gravity);
            gravity = -gravity;

            RayD r = new RayD(localPos, gravity);

            double?travel = s_unitsBox.Intersects(r);

            Debug.Assert(travel.HasValue, "Ray does not intersect with planet!");

            faceCoords = localPos + (Vector3D)(gravity * travel);
        }
Пример #23
0
            public bool IsBlockInTheWay(Vector3D origin, Vector3D targetPos, IMyCubeBlock constructBlock = null)
            {
                if (!Enabled)
                {
                    return(false);
                }



                Vector3D targetDir = targetPos - origin;
                RayD     line      = new RayD(origin, targetDir);

                foreach (var grid in grids.Values)
                {
                    if (constructBlock != null)
                    {
                        if (!constructBlock.CubeGrid.IsSameConstructAs(grid.grid))
                        {
                            continue;
                        }
                    }

                    double?result;
                    if (grid.grid.WorldVolume.Contains(origin) != ContainmentType.Contains)
                    {
                        result = grid.grid.WorldVolume.Intersects(line);
                        if (!result.HasValue)
                        {
                            continue;
                        }

                        targetDir.Normalize();

                        if (grid.IsBlockInTheWay(origin + targetDir * result.Value, targetPos))
                        {
                            return(true);
                        }
                    }

                    if (grid.IsBlockInTheWay(origin, targetPos))
                    {
                        return(true);
                    }
                }

                return(false);
            }
            public void NextPosition(ref Vector3D nextDirection, Vector3D headingDir, double safetyMargin = 1.25)
            {
                CreateSphereFromEntities(headingDir);

                Vector3D position    = rc.CubeGrid.WorldVolume.Center;
                Vector3D movementDir = rc.GetShipVelocities().LinearVelocity;

                movementDir.Normalize();

                RayD movementRay = new RayD(position, movementDir);
                RayD headingRay  = new RayD(rc.CubeGrid.WorldVolume.Center, headingDir);

                BoundingSphereD sphere = boundingSphere;

                sphere.Radius += rc.CubeGrid.WorldVolume.Radius;

                if (sphere.Contains(position) != ContainmentType.Disjoint)
                {
                    Vector3D dodgeDirection = Vector3D.Normalize(position - sphere.Center);

                    nextDirection = sphere.Center + dodgeDirection * sphere.Radius * safetyMargin;
                    return;
                }

                double?movementDist = sphere.Intersects(movementRay);
                double?headingDist  = sphere.Intersects(headingRay);

                if (movementDist.HasValue || headingDist.HasValue)
                {
                    Vector3D pointOnSphere;
                    Vector3D dodgeDirection;
                    if (movementDist.HasValue)
                    {
                        pointOnSphere  = position + movementDir * movementDist.Value;
                        dodgeDirection = GetAvoidanceVector(pointOnSphere, sphere, movementDir);
                    }
                    else
                    {
                        pointOnSphere  = position + headingDir * headingDist.Value;
                        dodgeDirection = GetAvoidanceVector(pointOnSphere, sphere, headingDir);
                    }

                    nextDirection = dodgeDirection;
                }
            }
Пример #25
0
    private bool IsVerticesLinear()
    {
        List <Vector3D> list         = new List <Vector3D>();
        double          maxDist      = 0;
        int             maxIndexFrom = -1;
        int             maxIndexTo   = -1;
        var             hes          = Circulate();

        for (int i = 0; i < hes.Count; i++)
        {
            var pos = hes[i].vert.positionD;
            if (list.Count > 2)
            {
                for (int j = 0; j < list.Count; j++)
                {
                    double dist = Vector3D.Distance(pos, list[j]);
                    if (dist > maxDist)
                    {
                        maxDist      = dist;
                        maxIndexFrom = i;
                        maxIndexTo   = j;
                    }
                }
            }

            list.Add(pos);
        }
        if (maxIndexFrom == maxIndexTo)
        {
            // all same position
            return(true);
        }

        RayD r = new RayD(list[maxIndexFrom], list[maxIndexFrom] - list[maxIndexTo]);

        foreach (var p in list)
        {
            if (r.LinePointDistance(p) > hmesh.zeroMagnitudeTreshold)
            {
                // not linear
                return(false);
            }
        }
        return(true);
    }
Пример #26
0
        internal void AddProjectileTargets() // This calls AI late for fragments need to fix
        {
            for (int i = 0; i < AddTargets.Count; i++)
            {
                var p = AddTargets[i];
                for (int t = 0; t < p.Info.Ai.TargetAis.Count; t++)
                {
                    var targetAi      = p.Info.Ai.TargetAis[t];
                    var addProjectile = p.Info.AmmoDef.Trajectory.Guidance != GuidanceType.None && targetAi.PointDefense;
                    if (!addProjectile && targetAi.PointDefense)
                    {
                        if (Vector3.Dot(p.Info.Direction, p.Info.Origin - targetAi.MyGrid.PositionComp.WorldMatrixRef.Translation) < 0)
                        {
                            var targetSphere = targetAi.MyGrid.PositionComp.WorldVolume;
                            targetSphere.Radius *= 3;
                            var testRay    = new RayD(p.Info.Origin, p.Info.Direction);
                            var quickCheck = Vector3D.IsZero(targetAi.GridVel, 0.025) && targetSphere.Intersects(testRay) != null;

                            if (!quickCheck)
                            {
                                var deltaPos        = targetSphere.Center - p.Info.Origin;
                                var deltaVel        = targetAi.GridVel - p.Info.Ai.GridVel;
                                var timeToIntercept = MathFuncs.Intercept(deltaPos, deltaVel, p.Info.AmmoDef.Const.DesiredProjectileSpeed);
                                var predictedPos    = targetSphere.Center + (float)timeToIntercept * deltaVel;
                                targetSphere.Center = predictedPos;
                            }

                            if (quickCheck || targetSphere.Intersects(testRay) != null)
                            {
                                addProjectile = true;
                            }
                        }
                    }
                    if (addProjectile)
                    {
                        targetAi.DeadProjectiles.Remove(p);
                        targetAi.LiveProjectile.Add(p);
                        targetAi.LiveProjectileTick = Session.Tick;
                        targetAi.NewProjectileTick  = Session.Tick;
                        p.Watchers.Add(targetAi);
                    }
                }
            }
            AddTargets.Clear();
        }
Пример #27
0
    void ReprojectY(List <Triangle> res, Plane3D plane)
    {
        double pos = 0;

        foreach (var t in res)
        {
            for (int i = 0; i < 3; i++)
            {
                var p = t.points[i];
                p.y = 0;
                RayD r = new RayD(p, Vector3D.up);
                if (plane.Raycast(r, out pos))
                {
                    p.y         = (float)pos;
                    t.points[i] = p;
                }
            }
        }
    }
Пример #28
0
        protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos)
        {
            bool flag = false;

            addPos    = new Vector3I();
            addDir    = new Vector3I();
            removePos = new Vector3I();
            MatrixD worldMatrixInvScaled = this.CurrentGrid.PositionComp.WorldMatrixInvScaled;

            addPos = intersectedCube;
            addDir = Vector3I.Forward;
            Vector3D position  = Vector3D.Transform(IntersectionStart, worldMatrixInvScaled);
            Vector3D direction = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldMatrixInvScaled));
            RayD     ray       = new RayD(position, direction);
            int      num       = 0;

            while (true)
            {
                if (num < 100)
                {
                    BoundingBoxD cubeBoundingBox = this.GetCubeBoundingBox(addPos);
                    if (placingSmallGridOnLargeStatic || (cubeBoundingBox.Contains(position) != ContainmentType.Contains))
                    {
                        double?nullable = cubeBoundingBox.Intersects(ray);
                        if (nullable != null)
                        {
                            removePos = addPos;
                            Vector3I vectori = Vector3I.Sign(Vector3.DominantAxisProjection((Vector3)((position + (direction * nullable.Value)) - (removePos * this.CurrentGrid.GridSize))));
                            addPos = (Vector3I)(removePos + vectori);
                            addDir = vectori;
                            if (this.CurrentGrid.CubeExists(addPos))
                            {
                                num++;
                                continue;
                            }
                            flag = true;
                        }
                    }
                }
                return(flag);
            }
        }
Пример #29
0
        public void Execute()
        {
            if (Entity == null || !Entity.InScene || Entity.MarkedForClose)
            {
                return;
            }
            var computedDamage = UtilsStatic.ComputeAmmoDamage(Entity);

            var damage = computedDamage * Shield.DsState.State.ModulateKinetic;

            if (computedDamage < 0)
            {
                damage = computedDamage;
            }

            var rayDir    = Vector3D.Normalize(Entity.Physics.LinearVelocity);
            var ray       = new RayD(Entity.PositionComp.WorldVolume.Center, rayDir);
            var intersect = CustomCollision.IntersectEllipsoid(ref Shield.DetectMatrixOutsideInv, Shield.DetectionMatrix, ref ray);
            var hitDist   = intersect ?? 0;
            var hitPos    = ray.Position + (ray.Direction * -hitDist);

            if (Session.Instance.MpActive)
            {
                Shield.AddShieldHit(Entity.EntityId, damage, Session.Instance.MPExplosion, null, true, hitPos);
                Entity.Close();
                Entity.InScene = false;
            }
            else
            {
                Shield.EnergyHit           = DefenseShields.HitType.Energy;
                Shield.WorldImpactPosition = hitPos;
                Shield.ImpactSize          = damage;
                UtilsStatic.CreateFakeSmallExplosion(hitPos);
                Entity.Close();
                Entity.InScene = false;
            }
            Shield.WebDamage     = true;
            Shield.Absorb       += damage;
            Shield.EnergyDamage += damage;

            Session.Instance.MissilePool.Return(this);
        }
Пример #30
0
        public override IMyUseObject RaycastDetectors(Vector3D worldFrom, Vector3D worldTo, out float parameter)
        {
            MyPositionComponentBase base2         = base.Container.Get <MyPositionComponentBase>();
            MatrixD      worldMatrixNormalizedInv = base2.WorldMatrixNormalizedInv;
            RayD         ray       = new RayD(worldFrom, worldTo - worldFrom);
            IMyUseObject useObject = null;

            parameter = float.MaxValue;
            foreach (KeyValuePair <uint, DetectorData> pair in this.m_detectorInteractiveObjects)
            {
                MatrixD matrix   = pair.Value.Matrix * base2.WorldMatrix;
                double? nullable = new MyOrientedBoundingBoxD(matrix).Intersects(ref ray);
                if ((nullable != null) && (nullable.Value < ((double)parameter)))
                {
                    parameter = (float)nullable.Value;
                    useObject = pair.Value.UseObject;
                }
            }
            return(useObject);
        }
        public static bool IntersectPoints(this BoundingBoxD boundingBox, Vector3D position, Vector3D target, out Vector3D?hitIngoing, out Vector3D?hitOutgoing)
        {
            //if (!Sandbox.Game.Entities.MyEntities.IsRaycastBlocked(position, target))
            //{
            //    hitIngoing = null;
            //    hitOutgoing = null;
            //    return false;
            //}

            // big enough for planets
            double outbound = 200000;

            var direction = Vector3D.Normalize(target - position);
            var ray       = new RayD(position + direction * -outbound, Vector3D.Normalize(direction * outbound));
            var interset  = boundingBox.Intersects(ray);

            if (interset.HasValue)
            {
                hitIngoing = position + direction * -outbound + (direction * interset.Value);
            }
            else
            {
                hitIngoing = null;
            }

            direction = Vector3D.Normalize(position - target);
            ray       = new RayD(target + direction * -outbound, Vector3D.Normalize(direction * outbound));
            interset  = boundingBox.Intersects(ray);
            if (interset.HasValue)
            {
                hitOutgoing = target + direction * -outbound + (direction * interset.Value);
            }
            else
            {
                hitOutgoing = null;
            }


            return(hitIngoing.HasValue && hitOutgoing.HasValue);
        }
        public override bool Invoke(string messageText)
        {
            #region test

            if (messageText.Equals("/test", StringComparison.InvariantCultureIgnoreCase))
            {
                // for testing things.
                //MyAPIGateway.Utilities.ShowMessage("path", MyAPIGateway.Session.CurrentPath);

                //MyAPIGateway.Utilities.ShowMessage("size1", MyAPIGateway.Utilities.ConfigDedicated.SessionSettings.WorldSizeKm.ToString());
                //MyAPIGateway.Utilities.ShowMessage("size2", MyAPIGateway.Session.GetWorld().Checkpoint.Settings.WorldSizeKm.ToString());

                IMyConfigDedicated config = null;
                //List<string> admins = null;
                try
                {
                    config = MyAPIGateway.Utilities.ConfigDedicated;
                    config.Load();
                    //config.
                }
                catch (Exception)
                {
                    MyAPIGateway.Utilities.ShowMessage("Exception", "ConfigDedicated"); //ex.Message);
                }
                if (config != null)
                {
                    try
                    {
                        var players = new List<IMyPlayer>();
                        MyAPIGateway.Players.GetPlayers(players, p => p != null);
                        MyAPIGateway.Utilities.ShowMessage("Player Count", string.Format("{0}", players.Count));

                        var identities = new List<IMyIdentity>();
                        MyAPIGateway.Players.GetAllIdentites(identities);
                        MyAPIGateway.Utilities.ShowMessage("Identities Count", string.Format("{0}", identities.Count));

                        MyAPIGateway.Utilities.ShowMessage("Admin Count", string.Format("{0}", config.Administrators.Count));
                        //MyAPIGateway.Utilities.ShowMessage("WorldName", string.Format("{0}", config.WorldName));
                        //MyAPIGateway.Utilities.ShowMessage("WorldSize", string.Format("{0}", config.SessionSettings.WorldSizeKm));
                        MyAPIGateway.Utilities.ShowMessage("Mods Count", string.Format("{0}", config.Mods.Count));
                        //MyAPIGateway.Utilities.ShowMessage("IP", string.Format("{0}", config.IP));

                        var clients = MyAPIGateway.Session.GetWorld().Checkpoint.Clients;
                        MyAPIGateway.Utilities.ShowMessage("Client Count", clients == null ? "null" : string.Format("{0}", clients.Count));

                        if (clients != null)
                        {
                            var client = clients.FirstOrDefault(c => c.SteamId == MyAPIGateway.Multiplayer.MyId);
                            if (client != null)
                            {
                                MyAPIGateway.Utilities.ShowMessage("IsAdmin", string.Format("{0}", client.IsAdmin));
                            }
                        }
                    }
                    catch (Exception)
                    {
                        MyAPIGateway.Utilities.ShowMessage("Exception", "reading config"); //ex.Message);
                    }
                }
                return true;
            }

            #endregion

            #region test2

            if (messageText.Equals("/test2", StringComparison.InvariantCultureIgnoreCase))
            {
                // for testing things.
                var count = MyAPIGateway.Utilities.ConfigDedicated.Administrators.Count.ToString(CultureInfo.InvariantCulture);
                MyAPIGateway.Utilities.ShowMessage("Admins", string.Format("Count {0}", count));
                MyAPIGateway.Utilities.ShowMessage("Players", string.Format("Count {0}", MyAPIGateway.Players.Count));
                MyAPIGateway.Utilities.ShowMessage("MultiPlayers", string.Format("Count {0}", MyAPIGateway.Multiplayer.Players.Count));
                return true;
            }

            #endregion

            #region test3

            if (messageText.Equals("/test3", StringComparison.InvariantCultureIgnoreCase))
            {
                // for testing things.
                MyAPIGateway.Utilities.ShowMessage("MyId", "{0}", MyAPIGateway.Multiplayer.MyId);
                MyAPIGateway.Utilities.ShowMessage("SteamId", "{0}", MyAPIGateway.Session.Player.SteamUserId);
                MyAPIGateway.Utilities.ShowMessage("MyName", "{0}", MyAPIGateway.Multiplayer.MyName);
                MyAPIGateway.Utilities.ShowMessage("IsServer", "{0}", MyAPIGateway.Multiplayer.IsServer);
                MyAPIGateway.Utilities.ShowMessage("IsServerPlayer", "{0}", MyAPIGateway.Multiplayer.IsServerPlayer(MyAPIGateway.Session.Player.Client));
                MyAPIGateway.Utilities.ShowMessage("MultiplayerActive", "{0}", MyAPIGateway.Multiplayer.MultiplayerActive);
                MyAPIGateway.Utilities.ShowMessage("OnlineMode", "{0}", MyAPIGateway.Session.OnlineMode);
                MyAPIGateway.Utilities.ShowMessage("IsDedicated", "{0}", MyAPIGateway.Utilities.IsDedicated);
                //MyAPIGateway.Utilities.ShowMessage("Culture", "{0}", MyTexts.Culture.IetfLanguageTag);
                MyAPIGateway.Utilities.ShowMessage("Culture", "{0} {1}", CultureInfo.CurrentUICulture, CultureInfo.CurrentUICulture.IetfLanguageTag);

                var ed = ((MyObjectBuilder_EnvironmentDefinition)MyDefinitionManager.Static.EnvironmentDefinition.GetObjectBuilder());
                MyAPIGateway.Utilities.ShowMessage("LargeShipMaxSpeed", "{0}", ed.LargeShipMaxSpeed);
                MyAPIGateway.Utilities.ShowMessage("SunDirection", "{0} {1} {2}", ed.SunDirection.X, ed.SunDirection.Y, ed.SunDirection.Z);
                return true;
            }

            #endregion

            #region test4

            if (messageText.Equals("/test4", StringComparison.InvariantCultureIgnoreCase))
            {
                var player = MyAPIGateway.Session.Player;
                if (player != null)
                {
                    var pos = player.GetPosition();
                    MyAPIGateway.Utilities.ShowMessage("Player", "pos={0:N},{1:N},{2:N}", pos.X, pos.Y, pos.Z);
                }

                var cockpit = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.Ingame.IMyCockpit;
                var remoteControl = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.Ingame.IMyRemoteControl;
                var character = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.IMyCharacter;
                var character2 = MyAPIGateway.Session.ControlledObject as Sandbox.Game.Entities.Character.MyCharacter;
                var camera = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.IMyCamera;
                var cameraBlock = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.Ingame.IMyCameraBlock;
                var cameraController = MyAPIGateway.Session.ControlledObject as Sandbox.ModAPI.Interfaces.IMyCameraController;
                var spectator = MyAPIGateway.Session.ControlledObject as VRage.MySpectator;

                if (cockpit != null)
                {
                    MyAPIGateway.Utilities.ShowMessage("Control", "in cockpit.");
                }
                if (remoteControl != null)
                {
                    MyAPIGateway.Utilities.ShowMessage("Control", "remoting.");
                }
                if (character != null)
                {
                    MyAPIGateway.Utilities.ShowMessage("Control", "character.");
                }
                if (character2 != null)
                {
                    //var pos = character2.PositionComp.GetPosition(); // Uses MyEntity which is not whitelisted.
                    MyAPIGateway.Utilities.ShowMessage("Control", "character2.");
                }
                if (camera != null)
                {
                    MyAPIGateway.Utilities.ShowMessage("Control", "camera.");
                }
                if (cameraBlock != null)
                {
                    MyAPIGateway.Utilities.ShowMessage("Control", "camera block.");
                }
                if (cameraController != null)
                {
                    var pos = cameraController.GetViewMatrix().Translation;
                    MyAPIGateway.Utilities.ShowMessage("Control", "camera controller 1. FPV={0} POS={1:N},{2:N},{3:N}", cameraController.IsInFirstPersonView, pos.X, pos.Y, pos.Z);
                }
                if (MyAPIGateway.Session.ControlledObject.Entity is Sandbox.ModAPI.Interfaces.IMyCameraController)
                {
                    MyAPIGateway.Utilities.ShowMessage("Control", "camera controller 2.");
                }

                //MyAPIGateway.Utilities.ShowMessage("Player", "Spectator1. {0}", VRage.Common.MySpectator.Static.IsInFirstPersonView);

                //System.Windows.Forms.Clipboard.SetText("hello");

                if (spectator != null)
                {
                    MyAPIGateway.Utilities.ShowMessage("Player", "Spectator1.");
                }
                if (MyAPIGateway.Session.ControlledObject.Entity is MySpectator)
                {
                    MyAPIGateway.Utilities.ShowMessage("Player", "Spectator2.");
                }
                //else
                //{
                //    MyAPIGateway.Utilities.ShowMessage("Player", "other.");
                //}

                return true;

                var playerMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix;
                var playerPosition = playerMatrix.Translation + playerMatrix.Forward * 0.5f + playerMatrix.Up * 1.0f;
                MyAPIGateway.Utilities.ShowMessage("Pos", string.Format("x={0:N},y={1:N},z={2:N}  x={3:N},y={4:N},z={5:N}", playerPosition.X, playerPosition.Y, playerPosition.Z, playerMatrix.Forward.X, playerMatrix.Forward.Y, playerMatrix.Forward.Z));
                //MyAPIGateway.Utilities.ShowMessage("Up", string.Format("x={0:N},y={1:N},z={2:N}", playerMatrix.Up.X, playerMatrix.Up.Y, playerMatrix.Up.Z));

                // TODO: need to properly establish control state and how to tell which state we are in.
                // Player - First person.
                // Player - thrid person.
                // Cockpit - First person.  ControlledObject.GetHeadMatrix(true, true, true);
                // Cockpit - thrid person.  ControlledObject.GetHeadMatrix(true, true, true);
                // Spectator freeview.      CameraController.GetViewMatrix()  but corrupted pos and vector.
                // Camera.                  CameraController.GetViewMatrix()

                //MyAPIGateway.Session.Player.PlayerCharacter.GetHeadMatrix(true, true, true);
                //MyAPIGateway.Session.CameraController.GetViewMatrix();
                //MyAPIGateway.Session.ControlledObject.GetHeadMatrix(true, true, true);
                //Sandbox.ModAPI.IMyControllerInfo //?
                //Sandbox.ModAPI.IMyEntityController
                //Sandbox.ModAPI.Interfaces.IMyCameraController
                //Sandbox.ModAPI.Interfaces.IMyControllableEntity

                // The CameraController.GetViewMatrix appears warped at the moment.
                //var position = ((IMyEntity)MyAPIGateway.Session.CameraController).GetPosition();
                var camMatrix = MyAPIGateway.Session.CameraController.GetViewMatrix();
                var camPosition = camMatrix.Translation;
                MyAPIGateway.Utilities.ShowMessage("Cam", string.Format("x={0:N},y={1:N},z={2:N}  x={3:N},y={4:N},z={5:N}", camPosition.X, camPosition.Y, camPosition.Z, camMatrix.Forward.X, camMatrix.Forward.Y, camMatrix.Forward.Z));

                //var worldMatrix = MyAPIGateway.Session.ControlledObject.Entity.WorldMatrix;
                var worldMatrix = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(true, true, true);
                var position = worldMatrix.Translation;
                MyAPIGateway.Utilities.ShowMessage("Con", string.Format("x={0:N},y={1:N},z={2:N}  x={3:N},y={4:N},z={5:N}", position.X, position.Y, position.Z, worldMatrix.Forward.X, worldMatrix.Forward.Y, worldMatrix.Forward.Z));

                //MyAPIGateway.Session.Player.PlayerCharacter.MoveAndRotate(new Vector3(), new Vector2(0, 0), 90f);
                //MyAPIGateway.Session.Player.PlayerCharacter.MoveAndRotate(new Vector3(), new Vector2(3.14f, 0), 0f);
                //MyAPIGateway.Session.Player.PlayerCharacter.Up();
                // thrust, walk player forward?

                //MyAPIGateway.Session.Player.PlayerCharacter.Entity.worldmatrix

                //var character = (MyObjectBuilder_Character)obj;

                return true;
            }

            #endregion

            #region test5

            if (messageText.Equals("/test5", StringComparison.InvariantCultureIgnoreCase))
            {
                var worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, true); // most accurate for player view.
                var position = worldMatrix.Translation + worldMatrix.Forward * 0.5f;

                var entites = new HashSet<IMyEntity>();
                MyAPIGateway.Entities.GetEntities(entites, e => e != null);

                var list = new Dictionary<IMyEntity, double>();

                foreach (var entity in entites)
                {
                    var cubeGrid = entity as Sandbox.ModAPI.IMyCubeGrid;

                    // check if the ray comes anywhere near the Grid before continuing.
                    var ray = new RayD(position, worldMatrix.Forward);
                    if (cubeGrid != null && ray.Intersects(entity.WorldAABB).HasValue)
                    {
                        var hit = cubeGrid.RayCastBlocks(position, worldMatrix.Forward * 1000);
                        if (hit.HasValue)
                        {
                            var blocks = new List<Sandbox.ModAPI.IMySlimBlock>();
                            cubeGrid.GetBlocks(blocks, f => f.FatBlock != null);
                            MyAPIGateway.Utilities.ShowMessage("AABB", string.Format("{0}", entity.WorldAABB));

                            //    var block = blocks[0];
                            //    //block.wo
                            //    var hsv = block.FatBlock.GetDiffuseColor();
                            //    MyAPIGateway.Utilities.ShowMessage("Hsv", string.Format("{0},{1},{2}  {3}", hsv.X, hsv.Y, hsv.Z, 1.45f));
                            //    var c = VRageMath.ColorExtensions.HSVtoColor(hsv);
                            //    MyAPIGateway.Utilities.ShowMessage("Rgb", string.Format("{0},{1},{2}", c.R, c.G, c.B));
                        }
                    }
                }
                return true;
            }

            #endregion

            #region test6

            if (messageText.Equals("/test6", StringComparison.InvariantCultureIgnoreCase))
            {
                var entity = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity;
                //MyAPIGateway.Utilities.ShowMessage("AABB", string.Format("{0}", entity.WorldAABB));
                //MyAPIGateway.Utilities.ShowMessage("Size", string.Format("{0}", entity.WorldAABB.Size()));

                //if (entity is IMyPlayer)
                //    MyAPIGateway.Utilities.ShowMessage("IMyPlayer", "true");
                //if (entity is IMyCubeBlock)
                //    MyAPIGateway.Utilities.ShowMessage("IMyCubeBlock", "true");  // Ship
                //if (entity is IMyCubeGrid)
                //    MyAPIGateway.Utilities.ShowMessage("IMyCubeGrid", "true");
                //if (entity is IMyIdentity)
                //    MyAPIGateway.Utilities.ShowMessage("IMyIdentity", "true");
                //if (entity is IMyNetworkClient)
                //    MyAPIGateway.Utilities.ShowMessage("IMyNetworkClient", "true");
                //if (entity is IMyEntityController)
                //    MyAPIGateway.Utilities.ShowMessage("IMyEntityController", "true");
                //if (entity is IMyControllableEntity)
                //    MyAPIGateway.Utilities.ShowMessage("IMyControllableEntity", "true");   // Ship and player
                //if (entity is IMyCameraController)
                //    MyAPIGateway.Utilities.ShowMessage("IMyCameraController", "true");  // Everything
                //if (entity is IMyMultiplayer)
                //    MyAPIGateway.Utilities.ShowMessage("IMyMultiplayer", "true");

                if (entity is Sandbox.ModAPI.IMyCubeGrid) entity = entity.Parent;

                if (entity.Physics != null)
                {
                    var pos = entity.GetPosition();
                    //var pos = Vector3.Zero;
                    var m = Matrix.CreateWorld(pos, Vector3.Forward, Vector3.Up);
                    entity.SetWorldMatrix(m);

                    //MyAPIGateway.Multiplayer.SendEntitiesCreated();
                    //entity.LocalMatrix

                    //entity.SetPosition(pos);
                    //if (entity.SyncObject.UpdatesOnlyOnServer)
                    //    entity.SyncObject.UpdatePosition();

                    //MyAPIGateway.Utilities.ShowMessage("Physics=null", string.Format("{0}", phys == null));
                    MyAPIGateway.Utilities.ShowMessage("LinearVelocity", string.Format("{0}", entity.Physics.LinearVelocity));
                    //MyAPIGateway.Utilities.ShowMessage("Speed", string.Format("{0}", phys.Speed));
                    //MyAPIGateway.Utilities.ShowMessage("Mass", string.Format("{0}", phys.Mass));

                    //phys.AddForce(Sandbox.Engine.Physics.MyPhysicsForceType.ADD_BODY_FORCE_AND_BODY_TORQUE, Vector3.Forward, Vector3.Zero, Vector3.Zero);
                    //phys.LinearVelocity = Vector3.Forward;
                    //phys
                }

                //var vm = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, true); // most accurate for player view.
                return true;
            }

            #endregion

            #region test7

            if (messageText.Equals("/test7", StringComparison.InvariantCultureIgnoreCase))
            {
                var character = (MyObjectBuilder_Character)MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.GetObjectBuilder();

                //var obj = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.GetObjectBuilder();
                var obj = MyAPIGateway.Session.Player.Client as IMyEntity;

                MyAPIGateway.Utilities.ShowMessage("isNull", string.Format("{0}", obj == null));
                //MyAPIGateway.Utilities.ShowMessage("Name", string.Format("{0}", obj.GetType().Name));

                return true;
            }

            #endregion

            #region test8

            if (messageText.Equals("/test8A", StringComparison.InvariantCultureIgnoreCase))
            {
                var gridBuilder = new MyObjectBuilder_CubeGrid()
                {
                    PersistentFlags = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene,
                    GridSizeEnum = MyCubeSize.Large,
                    IsStatic = true,
                    LinearVelocity = new SerializableVector3(0, 0, 0),
                    AngularVelocity = new SerializableVector3(0, 0, 0),
                    PositionAndOrientation = new MyPositionAndOrientation(Vector3.Zero, Vector3.Forward, Vector3.Up),
                    DisplayName = "test grid"
                };

                Sandbox.Common.ObjectBuilders.MyObjectBuilder_CubeBlock cube = new Sandbox.Common.ObjectBuilders.MyObjectBuilder_CubeBlock();
                cube.Min = new SerializableVector3I(0, 0, 0);
                cube.SubtypeName = "LargeBlockArmorBlock";
                cube.ColorMaskHSV = new SerializableVector3(0, -1, 0);
                cube.ShareMode = MyOwnershipShareModeEnum.None;
                cube.EntityId = 0;
                cube.Owner = 0;
                cube.BlockOrientation = new SerializableBlockOrientation(Base6Directions.Direction.Forward, Base6Directions.Direction.Up);
                cube.ShareMode = Sandbox.Common.ObjectBuilders.MyOwnershipShareModeEnum.All;
                gridBuilder.CubeBlocks.Add(cube);

                // multiple grids...
                //var tempList = new List<MyObjectBuilder_EntityBase>();
                //tempList.Add(gridBuilder);
                //MyAPIGateway.Entities.RemapObjectBuilderCollection(tempList);
                //tempList.ForEach(grid => MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(grid));
                //MyAPIGateway.Multiplayer.SendEntitiesCreated(tempList);

                // Single grid.
                MyAPIGateway.Entities.RemapObjectBuilder(gridBuilder);
                MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(gridBuilder);
                MyAPIGateway.Multiplayer.SendEntitiesCreated(new List<MyObjectBuilder_EntityBase> { gridBuilder });

                MyAPIGateway.Utilities.ShowMessage("OK", "fine");

                return true;
            }

            if (messageText.Equals("/test8B", StringComparison.InvariantCultureIgnoreCase))
            {
                var entity = Support.FindLookAtEntity(MyAPIGateway.Session.ControlledObject, true, false, false) as Sandbox.ModAPI.IMyCubeGrid;

                if (entity == null)
                    return false;

                var gridBuilder = new MyObjectBuilder_CubeGrid()
                {
                    PersistentFlags = MyPersistentEntityFlags2.CastShadows | MyPersistentEntityFlags2.InScene,
                    GridSizeEnum = MyCubeSize.Large,
                    IsStatic = true,
                    LinearVelocity = new SerializableVector3(0, 0, 0),
                    AngularVelocity = new SerializableVector3(0, 0, 0),
                    PositionAndOrientation = new MyPositionAndOrientation(Vector3.Zero, Vector3.Forward, Vector3.Up),
                    DisplayName = "test grid"
                };

                Sandbox.Common.ObjectBuilders.MyObjectBuilder_CubeBlock cube = new Sandbox.Common.ObjectBuilders.MyObjectBuilder_CubeBlock();
                cube.Min = new SerializableVector3I(0, 0, 0);
                cube.SubtypeName = "LargeBlockArmorBlock";
                cube.ColorMaskHSV = new SerializableVector3(0, -1, 0);
                cube.ShareMode = MyOwnershipShareModeEnum.None;
                cube.Owner = 0;
                cube.BlockOrientation = new SerializableBlockOrientation(Base6Directions.Direction.Forward, Base6Directions.Direction.Up);
                cube.ShareMode = Sandbox.Common.ObjectBuilders.MyOwnershipShareModeEnum.All;
                gridBuilder.CubeBlocks.Add(cube);

                //var tempList = new List<MyObjectBuilder_EntityBase>();
                //tempList.Add(gridBuilder);
                //MyAPIGateway.Entities.RemapObjectBuilderCollection(tempList); //no need for this on new object
                //var newEntity = (IMyCubeGrid)MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(tempList[0]);
                //MyAPIGateway.Multiplayer.SendEntitiesCreated(tempList);

                MyAPIGateway.Entities.RemapObjectBuilder(gridBuilder);
                var newEntity = (Sandbox.ModAPI.IMyCubeGrid)MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(gridBuilder);
                MyAPIGateway.Multiplayer.SendEntitiesCreated(new List<MyObjectBuilder_EntityBase> { gridBuilder });
                entity.MergeGrid_MergeBlock(newEntity, new Vector3I(0, 1, 0));

                MyAPIGateway.Utilities.ShowMessage("OK", "fine");

                return true;
            }

            #endregion

            #region test9

            if (messageText.Equals("/test9", StringComparison.InvariantCultureIgnoreCase))
            {
                var allEntites = new HashSet<IMyEntity>();
                MyAPIGateway.Entities.GetEntities(allEntites, e => e != null);

                var sphere = new BoundingSphereD(Vector3D.Zero, 1000000f);
                var allSphereEntities = MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere);

                MyAPIGateway.Utilities.ShowMessage("All Entities", String.Format("{0} == {1} ??", allEntites.Count, allSphereEntities.Count));

                return true;
            }

            #endregion

            #region test10

            if (messageText.StartsWith("/test10 ", StringComparison.InvariantCultureIgnoreCase))
            {
                var match = Regex.Match(messageText, @"/test10\s{1,}(?<Key>.+)", RegexOptions.IgnoreCase);
                if (match.Success)
                {
                    var prefabName = match.Groups["Key"].Value;

                    var entities = new HashSet<IMyEntity>();
                    MyAPIGateway.Entities.GetEntities(entities, e => e is Sandbox.ModAPI.IMyCubeGrid);

                    var idx = Int32.Parse(prefabName);
                    var cubeGrid = (Sandbox.ModAPI.IMyCubeGrid)entities.ToArray()[idx];

                    var grids = cubeGrid.GetAttachedGrids();

                    MyAPIGateway.Utilities.ShowMessage("Attached Count", string.Format("{0}", grids.Count));

                    //foreach (var grid in grids)
                    //    MyAPIGateway.Utilities.ShowMessage("Attached", string.Format("{0}", grid.EntityId));

                    return true;
                }
                //var vm = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, true); // most accurate for player view.
            }

            #endregion

            #region test11

            if (messageText.Equals("/test11", StringComparison.InvariantCultureIgnoreCase))
            {

                //var identities = new List<IMyIdentity>();
                //MyAPIGateway.Players.GetAllIdentites(identities);
                //var ident = identities.FirstOrDefault();
                //var bIdent = ((IMyEntity)ident).GetObjectBuilder();
                //MyAPIGateway.Utilities.ShowMessage("IMyIdentity", string.Format("{0}", bIdent.GetType()));

                var players = new List<IMyPlayer>();
                MyAPIGateway.Players.GetPlayers(players, p => p != null);
                var player = players.FirstOrDefault();

                var cpnt = MyAPIGateway.Session.GetCheckpoint("null");
                MyAPIGateway.Utilities.ShowMessage("cpnt", cpnt.Clients == null ? "null" : string.Format("{0}", cpnt.Clients.Count));

                var c = MyAPIGateway.Session.GetWorld().Checkpoint.Clients;
                MyAPIGateway.Utilities.ShowMessage("Count", c == null ? "null" : string.Format("{0}", c.Count));

                var nc = player.Client;
                MyAPIGateway.Utilities.ShowMessage("IMyNetworkClient", string.Format("{0}", nc.GetType()));
                //MyAPIGateway.Utilities.ShowMessage("IMyNetworkClient", string.Format("{0}", nc.GetType().BaseType));

                //var bPlayer = ((IMyEntity)nc).GetObjectBuilder();
                //MyAPIGateway.Utilities.ShowMessage("IMyPlayer", string.Format("{0}", bPlayer.GetType()));

                //var vm = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, true); // most accurate for player view.
                return true;
            }

            #endregion

            #region test12

            if (messageText.Equals("/test12", StringComparison.InvariantCultureIgnoreCase))
            {
                var entity = Support.FindLookAtEntity(MyAPIGateway.Session.ControlledObject);
                var resultList = new List<ITerminalAction>();
                if (entity != null)
                {
                    var displayName = entity.DisplayName;
                    MyAPIGateway.Utilities.ShowMessage("ID", displayName);

                    MyAPIGateway.Utilities.ShowMessage("Components", string.Format("{0}", entity.Components == null));
                    MyAPIGateway.Utilities.ShowMessage("Hierarchy", string.Format("{0}", entity.Hierarchy == null));

                    var cockpits = entity.FindWorkingCockpits();
                    var terminal = (IMyTerminalBlock)cockpits[0];
                    //cockpits[0]
                    terminal.GetActions(resultList);
                    MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count));
                }

                //Vector3D? FindFreePlace(Vector3D basePos, float radius, int maxTestCount = 20, int testsPerDistance = 5, float stepSize = 1f);
                //MyAPIGateway.Entities.FindFreePlace(

                //resultList.Clear();
                //var myObject = Sandbox.Common.ObjectBuilders.Serializer.MyObjectBuilderSerializer.CreateNewObject(typeof(MyObjectBuilder_Reactor), "SmallBlockLargeGenerator");
                //MyAPIGateway.TerminalActionsHelper.GetActions(typeof(MyObjectBuilder_Reactor), resultList);
                //MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count));

                //MyAPIGateway.TerminalActionsHelper.GetActions(typeof(IMyMotorStator), resultList);
                //MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count));

                //MyAPIGateway.TerminalActionsHelper.GetActions(typeof(IMyFunctionalBlock), resultList);
                //MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count));

                //MyAPIGateway.TerminalActionsHelper.GetActions(typeof(IMyTerminalBlock), resultList);
                //MyAPIGateway.Utilities.ShowMessage("count", string.Format("{0}", resultList.Count));

                foreach (var a in resultList)
                {
                    MyAPIGateway.Utilities.ShowMessage("item", string.Format("{0}={1}", a.Name, a.Id));
                }

                return true;
            }

            #endregion

            #region test13

            if (messageText.Equals("/test13", StringComparison.InvariantCultureIgnoreCase))
            {
                var entites = new HashSet<IMyEntity>();
                MyAPIGateway.Entities.GetEntities(entites, e => e != null);

                //var physicalItem = MyDefinitionManager.Static.GetCubeBlockDefinition(new MyDefinitionId(typeof(MyObjectBuilder_SpaceBall), "SpaceBallLarge"));
                //physicalItem.Public = true;

                //MyDefinitionManager.Static.EnvironmentDefinition.SmallShipMaxSpeed = 2000;
                //MyDefinitionManager.Static.EnvironmentDefinition.LargeShipMaxSpeed = 2000;
                MyAPIGateway.Session.GetCheckpoint("null").GameMode = MyGameModeEnum.Creative;
                //MyAPIGateway.Session.GetCheckpoint("null").CargoShipsEnabled
                //MyAPIGateway.Session.GetCheckpoint("null").EnableCopyPaste = true;

                //MyAPIGateway.Utilities.ShowMessage("Sun Distance", string.Format("{0}", MyDefinitionManager.Static.EnvironmentDefinition.DistanceToSun));
                //MyDefinitionManager.Static.EnvironmentDefinition.DirectionToSun = new Vector3(0, 1, 0);

                foreach (var entity in entites)
                {
                    var cubeGrid = entity as Sandbox.ModAPI.IMyCubeGrid;
                    if (cubeGrid != null)
                    {
                        var terminalsys = MyAPIGateway.TerminalActionsHelper.GetTerminalSystemForGrid(cubeGrid);
                        //MyAPIGateway.Utilities.ShowMessage("Grid count", string.Format("{0} {1} {2}", cubeGrid.DisplayName, terminalsys.Blocks.Count, terminalsys.BlockGroups.Count));

                        //var blocks = new List<Sandbox.ModAPI.IMySlimBlock>();
                        //cubeGrid.GetBlocks(blocks, f => f.FatBlock != null && f.FatBlock == MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity);
                        //MyAPIGateway.Utilities.ShowMessage("Pilot count", string.Format("{0}", blocks.Count));

                        //cubeGrid.GetBlocks(blocks);
                        //foreach (var block in blocks)
                        //{
                        //    cubeGrid.ColorBlocks(block.Position, block.Position, VRageMath.Color.Gold.ToHsvColor());
                        //}

                    }
                }

                return true;
            }

            #endregion

            #region test14

            // Tag every floating object in player GPS.
            if (messageText.Equals("/test14", StringComparison.InvariantCultureIgnoreCase))
            {
                var entites = new HashSet<IMyEntity>();
                MyAPIGateway.Entities.GetEntities(entites, e => (e is Sandbox.ModAPI.IMyFloatingObject));

                foreach (var entity in entites)
                {
                    var pos = entity.GetPosition();
                    var gps = MyAPIGateway.Session.GPS.Create("Floating " + entity.DisplayName, "Some drifting junk", pos, true, false);
                    MyAPIGateway.Session.GPS.AddLocalGps(gps);
                }

                return true;
            }

            #endregion

            return false;
        }
Пример #33
0
        /// <summary>
        /// Gets a destination and tries to fix it so that it does not collide with anything
        /// </summary>
        /// <param name="originalDestination">The final destination that the remote wants to get to.</param>
        /// <param name="checkRadius">The maximum radius until which this method should search.</param>
        /// <param name="shipRadius">The radius of our ship. Make sure that this is large enough to avoid collision.</param>
        Vector3D ModAPI.Ingame.IMyRemoteControl.GetFreeDestination(Vector3D originalDestination, float checkRadius, float shipRadius)
        {
            MyCestmirDebugInputComponent.ClearDebugSpheres();
            MyCestmirDebugInputComponent.ClearDebugPoints();

            MyCestmirDebugInputComponent.AddDebugPoint(this.WorldMatrix.Translation, Color.Green);

            Vector3D retval = originalDestination;
            BoundingSphereD sphere = new BoundingSphereD(this.WorldMatrix.Translation, shipRadius + checkRadius);

            Vector3D rayDirection = originalDestination - this.WorldMatrix.Translation;
            double originalDistance = rayDirection.Length();
            rayDirection = rayDirection / originalDistance;
            RayD ray = new RayD(this.WorldMatrix.Translation, rayDirection);

            double closestIntersection = double.MaxValue;
            BoundingSphereD closestSphere = default(BoundingSphereD);

            var entities = MyEntities.GetEntitiesInSphere(ref sphere);
            for (int i = 0; i < entities.Count; ++i)
            {
                var entity = entities[i];

                if (!(entity is MyCubeGrid) && !(entity is MyVoxelMap)) continue;
                if (entity.Parent != null) continue;
                if (entity == this.Parent) continue;

                BoundingSphereD entitySphere = entity.PositionComp.WorldVolume;
                entitySphere.Radius += shipRadius;

                MyCestmirDebugInputComponent.AddDebugSphere(entitySphere.Center, (float)entity.PositionComp.WorldVolume.Radius, Color.Plum);
                MyCestmirDebugInputComponent.AddDebugSphere(entitySphere.Center, (float)entity.PositionComp.WorldVolume.Radius + shipRadius, Color.Purple);

                double? intersection = ray.Intersects(entitySphere);
                if (intersection.HasValue && intersection.Value < closestIntersection)
                {
                    closestIntersection = intersection.Value;
                    closestSphere = entitySphere;
                }
            }

            if (closestIntersection != double.MaxValue)
            {
                Vector3D correctedDestination = ray.Position + closestIntersection * ray.Direction;
                MyCestmirDebugInputComponent.AddDebugSphere(correctedDestination, 1.0f, Color.Blue);
                Vector3D normal = correctedDestination - closestSphere.Center;
                if (Vector3D.IsZero(normal))
                {
                    normal = Vector3D.Up;
                }
                normal.Normalize();
                MyCestmirDebugInputComponent.AddDebugSphere(correctedDestination + normal, 1.0f, Color.Red);
                Vector3D newDirection = Vector3D.Reject(ray.Direction, normal);
                newDirection.Normalize();
                newDirection *= Math.Max(20.0, closestSphere.Radius * 0.5);
                MyCestmirDebugInputComponent.AddDebugSphere(correctedDestination + newDirection, 1.0f, Color.LightBlue);
                retval = correctedDestination + newDirection;
            }
            else
            {
                retval = ray.Position + ray.Direction * Math.Min(checkRadius, originalDistance);
            }

            entities.Clear();

            return retval;
        }
Пример #34
0
        private bool IsInStoppingDistance()
        {
            int currentIndex = m_waypoints.IndexOf(CurrentWaypoint);
            double currentDstSqr = (WorldMatrix.Translation - CurrentWaypoint.Coords).LengthSquared();
            double dstError = CubeGrid.GridSize * 3;

            if (m_automaticBehaviour != null && m_automaticBehaviour.IsActive)
            {
                dstError = m_automaticBehaviour.WaypointThresholdDistance;
            }
            else if (m_waypointThresholdDistance > 0)
            {
                dstError = m_waypointThresholdDistance;
            }
            else if (m_dockingModeEnabled || (m_currentFlightMode == FlightMode.OneWay && currentIndex == m_waypoints.Count - 1))
            {
                if (CubeGrid.GridSize >= 0.5f)
                    dstError = CubeGrid.GridSize * 0.25;
                else
                    dstError = CubeGrid.GridSize;
            }

            if (MyFakes.ENABLE_VR_REMOTE_CONTROL_WAYPOINTS_FAST_MOVEMENT)
            {
                // Check if movement from previous position to current position intersects waypoint sphere.
                if (currentDstSqr < dstError * dstError)
                    return true;

                double prevDstSqr = (m_previousWorldPosition - CurrentWaypoint.Coords).LengthSquared();
                if (prevDstSqr < dstError * dstError)
                    return true;

                var dir = WorldMatrix.Translation - m_previousWorldPosition;
                double rayLength = dir.Normalize();
                if (rayLength > 0.01)
                {
                    RayD ray = new RayD(m_previousWorldPosition, dir);
                    BoundingSphereD sphere = new BoundingSphereD(CurrentWaypoint.Coords, dstError);
                    double? intersection = sphere.Intersects(ray);
                    return (intersection != null) ? intersection.Value <= rayLength : false;
                }
            }

            return currentDstSqr < dstError * dstError;
        }
Пример #35
0
 void ReprojectY(List<Triangle> res, Plane3D plane)
 {
     double pos = 0;
     foreach (var t in res){
         for (int i=0;i<3;i++){
             var p = t.points[i];
             p.y = 0;
             RayD r = new RayD(p, Vector3D.up);
             if (plane.Raycast(r,out pos)){
                 p.y = (float)pos;
                 t.points[i] = p;
             }
         }
     }
 }
Пример #36
0
 Vector3D ProjectToTriangle(Vector3D point)
 {
     Plane3D plane = new Plane3D(Normal, points[0]);
     bool isPointInPlane = System.Math.Abs(plane.GetDistanceToPoint(point))<0.0001;
     if (!isPointInPlane) {
         double dist;
         point.y = 0;
         var ray = new RayD(point, Vector3D.up);
         plane.Raycast(ray, out dist);
         point.y = dist;
     }
     return point;
 }
        protected override void DoDetection(bool useHead)
        {
            ProfilerShort.Begin("DoDetection");
            if (Character == MySession.Static.ControlledEntity)
                MyHud.SelectedObjectHighlight.RemoveHighlight();

            var head = Character.GetHeadMatrix(false);
            var headPos = head.Translation - (Vector3D)head.Forward * 0.3; // Move to center of head, we don't want eyes (in front of head)

            Vector3D from;
            Vector3D dir;

            if (!useHead)
            {
                //Ondrej version
                var cameraMatrix = MySector.MainCamera.WorldMatrix;
                dir = cameraMatrix.Forward;
                from = MyUtils.LinePlaneIntersection(headPos, (Vector3)dir, cameraMatrix.Translation, (Vector3)dir);
            }
            else
            {
                //Petr version
                dir = head.Forward;
                from = headPos;
            }

            Vector3D to = from + dir * MyConstants.DEFAULT_INTERACTIVE_DISTANCE;

            //EnableDetectorsInArea(from);
            GatherDetectorsInArea(from);
            float closestDetector = float.MaxValue;
            IMyEntity closestEntity = null;
            IMyUseObject closestInteractive = null;
            foreach(var entity in m_detectableEntities)
            {
                if (entity == Character)
                    continue;
                var use = entity.Components.Get<MyUseObjectsComponentBase>() as MyUseObjectsComponent;
                if(use != null)
                {
                    float detectorDistance;
                    var interactive = use.RaycastDetectors(from, to, out detectorDistance);
                    if(Math.Abs(detectorDistance) < Math.Abs(closestDetector))
                    {
                        closestDetector = detectorDistance;
                        closestEntity = entity;
                        closestInteractive = interactive;
                    }
                }

                //Floating object handling - give FO useobject component!
                var use2 = entity as IMyUseObject;
                if (use2 != null)
                {
                    var m = use2.ActivationMatrix;
                    var ray = new RayD(from, to - from);
                    var obb = new MyOrientedBoundingBoxD(m);
                    var dist = obb.Intersects(ref ray);
                    if(dist.HasValue && Math.Abs(dist.Value) < Math.Abs(closestDetector))
                    {
                        closestDetector = (float)dist.Value;
                        closestEntity = entity;
                        closestInteractive = use2;
                    }
                }
            }
            m_detectableEntities.Clear();
            //VRageRender.MyRenderProxy.DebugDrawLine3D(from, to, Color.Red, Color.Green, true);
            //VRageRender.MyRenderProxy.DebugDrawSphere(headPos, 0.05f, Color.Red.ToVector3(), 1.0f, false);

            StartPosition = from;

            MyPhysics.CastRay(from, to, m_hits, MyPhysics.CollisionLayers.FloatingObjectCollisionLayer);

            bool hasInteractive = false;

            int index = 0;
            while (index < m_hits.Count && (m_hits[index].HkHitInfo.Body == null || m_hits[index].HkHitInfo.GetHitEntity() == Character
                || m_hits[index].HkHitInfo.GetHitEntity() == null
                || m_hits[index].HkHitInfo.Body.HasProperty(HkCharacterRigidBody.MANIPULATED_OBJECT)
                || m_hits[index].HkHitInfo.Body.Layer == MyPhysics.CollisionLayers.VoxelLod1CollisionLayer)) // Skip invalid hits and self character
            {
                index++;
            }

            if (index < m_hits.Count && m_hits[index].HkHitInfo.HitFraction > closestDetector - 0.05f)//compensation
            {
                // TODO: Uncomment to enforce that character must face object by front to activate it
                //if (TestInteractionDirection(head.Forward, h.Position - GetPosition()))
                //return;
                HitPosition = from + dir * closestDetector;
                MyUseObjectsComponentBase useObject;
                if(closestEntity.Components.TryGet<MyUseObjectsComponentBase>(out useObject))
                {
                    var detectorPhysics = useObject.DetectorPhysics;
                    HitMaterial = detectorPhysics.GetMaterialAt(HitPosition);
                    HitBody = ((MyPhysicsBody)detectorPhysics).RigidBody;
                }
                else
                {
                    HitMaterial = closestEntity.Physics.GetMaterialAt(HitPosition);
                    HitBody = ((MyPhysicsBody)closestEntity.Physics).RigidBody;
                }

                DetectedEntity = closestEntity;
                var interactive = closestInteractive;

                if (UseObject != null && interactive != null && UseObject != interactive)
                {
                    UseObject.OnSelectionLost();
                }

                //if (interactive != null && interactive.SupportedActions != UseActionEnum.None && (Vector3D.Distance(from, (Vector3D)h.Position)) < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity)
                if (interactive != null && interactive.SupportedActions != UseActionEnum.None && closestDetector * MyConstants.DEFAULT_INTERACTIVE_DISTANCE < interactive.InteractiveDistance && Character == MySession.Static.ControlledEntity)
                {
                    HandleInteractiveObject(interactive);

                    UseObject = interactive;
                    hasInteractive = true;
                }
            }

            if (!hasInteractive)
            {
                if (UseObject != null)
                {
                    UseObject.OnSelectionLost();
                }

                UseObject = null;         
            }

            ProfilerShort.End();
        }
Пример #38
0
        public bool Intersect(LineD line, ref Vector3D p1, ref Vector3D p2, ref Vector3 n1, ref Vector3 n2)
        {
            RayD ray = new RayD(line.From, line.Direction);
            if (Intersect(ray, ref p1, ref p2, ref n1, ref n2))
            {
                Vector3D p1Dir = p1 - line.From;
                Vector3D p2Dir = p2 - line.From;
                double p1Len = p1Dir.Normalize();
                double p2Len = p2Dir.Normalize();

                if (Vector3D.Dot(line.Direction, p1Dir) < 0.9)
                    return false;

                if (Vector3D.Dot(line.Direction, p2Dir) < 0.9)
                    return false;

                if (line.Length < p1Len)
                    return false;

                return true;
            }

            return false;
        }
Пример #39
0
		private void GetDeposit()
		{
			Vector3D pos = m_navDrill.WorldPosition;
			IMyVoxelBase foundMap;
			if (m_oreDetector.FindClosestOre(pos, OreTargets, out m_depositPos, out foundMap, out m_depostitOre))
			{
				// from the centre of the voxel, passing through the deposit, find the edge of the AABB
				m_voxelCentre = foundMap.GetCentre();
				Vector3D centreOut = m_depositPos - m_voxelCentre;
				centreOut.Normalize();
				Vector3D bodEdgeFinderStart = m_voxelCentre + centreOut * foundMap.WorldAABB.GetLongestDim();
				RayD boxEdgeFinder = new RayD(bodEdgeFinderStart, -centreOut);
				double? boxEdgeDist = foundMap.WorldAABB.Intersects(boxEdgeFinder);
				if (boxEdgeDist == null)
					throw new Exception("Math fail");
				Vector3D boxEdge = bodEdgeFinderStart - centreOut * boxEdgeDist.Value;

				// was getting memory access violation, so not using MainLock.RayCastVoxel_Safe()
				MyAPIGateway.Utilities.TryInvokeOnGameThread(() => {
					Vector3 surfacePoint;
					if (foundMap is IMyVoxelMap)
					{
						MyAPIGateway.Entities.IsInsideVoxel(boxEdge, m_voxelCentre, out surfacePoint);
						m_miningPlanet = false;
					}
					else
					{
						MyPlanet planet = foundMap as MyPlanet;
						surfacePoint = planet.GetClosestSurfacePointGlobal(ref m_depositPos);
						m_logger.debugLog("Mining target is a planet, from nav drill position: " + m_navDrill.WorldPosition + ", surface is " + surfacePoint, "GetDeposit()");
						m_miningPlanet = true;
					}
					m_approach = new Line(surfacePoint + centreOut * m_controlBlock.CubeGrid.GetLongestDim() * 2, surfacePoint);

					m_logger.debugLog("centre: " + m_voxelCentre.ToGpsTag("centre")
						+ ", deposit: " + m_depositPos.ToGpsTag("deposit")
						+ ", boxEdge: " + boxEdge.ToGpsTag("boxEdge")
						+ ", m_approach: " + m_approach.From.ToGpsTag("m_approach From")
						+ ", " + m_approach.To.ToGpsTag("m_approach To")
						+ ", surfacePoint: " + surfacePoint
						, "GetDeposit()");

					m_state = State.Approaching;
				}, m_logger);

				return;
			}

			m_logger.debugLog("No ore target found", "GetDeposit()", Logger.severity.INFO);
			m_navSet.OnTaskComplete_NavRot();
		}
Пример #40
0
        protected bool GetCubeAddAndRemovePositions(Vector3I intersectedCube, bool placingSmallGridOnLargeStatic, out Vector3I addPos, out Vector3I addDir, out Vector3I removePos)
        {
            bool result = false;

            addPos = new Vector3I();
            addDir = new Vector3I();
            removePos = new Vector3I();

            MatrixD worldInv = MatrixD.Invert(CurrentGrid.WorldMatrix);

            Vector3D intersectionPos;
            addPos = intersectedCube;
            addDir = Vector3I.Forward;

            Vector3D rayStart = Vector3D.Transform(IntersectionStart, worldInv);
            Vector3D rayDir = Vector3D.Normalize(Vector3D.TransformNormal(IntersectionDirection, worldInv));

            RayD r = new RayD(rayStart, rayDir);

            for (int i = 0; i < 100; ++i) // Limit iterations to 100
            {
                var cubeBb = GetCubeBoundingBox(addPos);
                if (!placingSmallGridOnLargeStatic && cubeBb.Contains(rayStart) == ContainmentType.Contains)
                    break;

                double? dist = cubeBb.Intersects(r);
                if (!dist.HasValue) 
                    break;

                removePos = addPos;

                intersectionPos = rayStart + rayDir * dist.Value;
                Vector3 center = removePos * CurrentGrid.GridSize;
                Vector3I dirInt = Vector3I.Sign(Vector3.DominantAxisProjection(intersectionPos - center));

                addPos = removePos + dirInt;
                addDir = dirInt;
                result = true;

                if (!CurrentGrid.CubeExists(addPos)) 
                    break;
            }

            Debug.Assert(!result || addDir != Vector3I.Zero, "Direction vector cannot be zero");
            return result;
        }
        public static void FindLookAtEntity(IMyControllableEntity controlledEntity, out IMyEntity lookEntity, out double lookDistance, bool findShips = true, bool findPlayers = true, bool findAsteroids = true, bool findPlanets = true)
        {
            const float range = 5000000;
            Matrix worldMatrix;
            Vector3D startPosition;
            Vector3D endPosition;
            if (MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.Parent == null)
            {
                worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.GetHeadMatrix(true, true, false); // dead center of player cross hairs.
                startPosition = worldMatrix.Translation + worldMatrix.Forward * 0.5f;
                endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 0.5f);
            }
            else
            {
                worldMatrix = MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.WorldMatrix;
                // TODO: need to adjust for position of cockpit within ship.
                startPosition = worldMatrix.Translation + worldMatrix.Forward * 1.5f;
                endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 1.5f);
            }

            //var worldMatrix = MyAPIGateway.Session.Player.PlayerCharacter.Entity.WorldMatrix;
            //var position = MyAPIGateway.Session.Player.PlayerCharacter.Entity.GetPosition();
            //var position = worldMatrix.Translation + worldMatrix.Forward * 0.5f + worldMatrix.Up * 1.0f;
            //MyAPIGateway.Utilities.ShowMessage("Pos", string.Format("x={0:N},y={1:N},z={2:N}  x={3:N},y={4:N},z={5:N}", playerPos.X, playerPos.Y, playerPos.Z, playerMatrix.Forward.X, playerMatrix.Forward.Y, playerMatrix.Forward.Z));

            // The CameraController.GetViewMatrix appears warped at the moment.
            //var position = ((IMyEntity)MyAPIGateway.Session.CameraController).GetPosition();
            //var worldMatrix = MyAPIGateway.Session.CameraController.GetViewMatrix();
            //var position = worldMatrix.Translation;
            //MyAPIGateway.Utilities.ShowMessage("Cam", string.Format("x={0:N},y={1:N},z={2:N}  x={3:N},y={4:N},z={5:N}", position.X, position.Y, position.Z, worldMatrix.Forward.X, worldMatrix.Forward.Y, worldMatrix.Forward.Z));

            var entites = new HashSet<IMyEntity>();
            MyAPIGateway.Entities.GetEntities(entites, e => e != null);

            var list = new Dictionary<IMyEntity, double>();
            var ray = new RayD(startPosition, worldMatrix.Forward);

            foreach (var entity in entites)
            {
                if (findShips)
                {
                    var cubeGrid = entity as Sandbox.ModAPI.IMyCubeGrid;

                    // check if the ray comes anywhere near the Grid before continuing.
                    if (cubeGrid != null && ray.Intersects(entity.WorldAABB).HasValue)
                    {
                        var hit = cubeGrid.RayCastBlocks(startPosition, endPosition);
                        if (hit.HasValue)
                        {
                            var distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length();
                            list.Add(entity, distance);
                        }
                    }
                }

                if (findPlayers)
                {
                    var controller = entity as IMyControllableEntity;
                    if (MyAPIGateway.Session.Player.Controller.ControlledEntity.Entity.EntityId != entity.EntityId && controller != null && ray.Intersects(entity.WorldAABB).HasValue)
                    {
                        var distance = (startPosition - entity.GetPosition()).Length();
                        list.Add(entity, distance);
                    }
                }

                if (findAsteroids)
                {
                    var voxelMap = entity as IMyVoxelMap;
                    if (voxelMap != null)
                    {
                        var aabb = new BoundingBoxD(voxelMap.PositionLeftBottomCorner, voxelMap.PositionLeftBottomCorner + voxelMap.Storage.Size);
                        var hit = ray.Intersects(aabb);
                        if (hit.HasValue)
                        {
                            var center = voxelMap.PositionLeftBottomCorner + (voxelMap.Storage.Size / 2);
                            var distance = (startPosition - center).Length();  // use distance to center of asteroid.
                            list.Add(entity, distance);
                        }
                    }
                }

                if (findPlanets)
                {
                    // Looks to be working against Git and public release.
                    var planet = entity as Sandbox.Game.Entities.MyPlanet;
                    if (planet != null)
                    {
                        var aabb = new BoundingBoxD(planet.PositionLeftBottomCorner, planet.PositionLeftBottomCorner + planet.Size);
                        var hit = ray.Intersects(aabb);
                        if (hit.HasValue)
                        {
                            var center = planet.PositionLeftBottomCorner + (planet.Size / 2);
                            var distance = (startPosition - center).Length(); // use distance to center of planet.
                            list.Add(entity, distance);
                        }
                    }
                }
            }

            if (list.Count == 0)
            {
                lookEntity = null;
                lookDistance = 0;
                return;
            }

            // find the closest Entity.
            var item = list.OrderBy(f => f.Value).First();
            lookEntity = item.Key;
            lookDistance = item.Value;
        }
        public bool TryNamingAnBlockOrFloatingObject()
        {
            var worldMatrix = MyAPIGateway.Session.Camera.WorldMatrix; // most accurate for player view.
            var position = worldMatrix.Translation + worldMatrix.Forward * 0.5f;
            var ray = new RayD(position, worldMatrix.Forward * 1000);

            var boundingSphere = new BoundingSphereD(worldMatrix.Translation, 30);
            var entites = MyEntities.GetEntitiesInSphere(ref boundingSphere);

            List<MyPhysics.HitInfo> hits = new List<MyPhysics.HitInfo>();
            MyPhysics.CastRay(worldMatrix.Translation, worldMatrix.Translation + worldMatrix.Forward * 5, hits, 15);

            foreach (var hitInfo in hits)
            {
                var body = (MyPhysicsBody)hitInfo.HkHitInfo.Body.UserObject;
                if (body.Entity is MyFloatingObject)
                {
                    var rayEntity = (MyEntity) body.Entity;
                    NameDialog(rayEntity);
                    return true;
                }
            }

            foreach (var entity in entites)
            {
                var cubeGrid = entity as MyCubeGrid;

                if (cubeGrid != null && ray.Intersects(entity.PositionComp.WorldAABB).HasValue)
                {
                    var hit = cubeGrid.RayCastBlocks(worldMatrix.Translation, worldMatrix.Translation + worldMatrix.Forward * 100);
                    if (hit.HasValue)
                    {
                        var block = cubeGrid.GetCubeBlock(hit.Value);
                        
                        if(block.FatBlock != null)
                        {
                            var dialog = new ValueGetScreenWithCaption("Name block dialog: " + block.FatBlock.DefinitionDisplayNameText, block.FatBlock.Name ?? block.FatBlock.DefinitionDisplayNameText + " has no name.", delegate(string text)
                            {
                                MyEntity foundEntity;
                                if (MyEntities.TryGetEntityByName(text, out foundEntity))
                                {
                                    MyGuiSandbox.AddScreen(MyGuiSandbox.CreateMessageBox(
                                        buttonType: MyMessageBoxButtonsType.OK,
                                        messageText: new StringBuilder("Entity with same name already exits, please enter different name."),
                                        messageCaption: new StringBuilder("Naming error")));
                                }
                                else
                                {
                                    block.FatBlock.Name = text;
                                    MyEntities.SetEntityName(block.FatBlock, true);

                                    return true;
                                }

                                return false;
                            }); 
                            MyGuiSandbox.AddScreen(dialog);
                            entites.Clear();
                            return true;
                        }
                    }
                }
            }

            entites.Clear();
            return false;
        }
        public static void OnGlobalSpawnEvent(object senderEvent)
        {
            // Select a spawn group to spawn
            MySpawnGroupDefinition spawnGroup = PickRandomSpawnGroup();
            if (spawnGroup == null)
            {
                return;
            }

            spawnGroup.ReloadPrefabs();

            ProfilerShort.Begin("Generate position and direction");
            
            double spawnDistance = NEUTRAL_SHIP_SPAWN_DISTANCE;
            Vector3D playerPosition = Vector3D.Zero;
            bool isWorldLimited = MyEntities.IsWorldLimited();
            int numPlayers = 0;
            if (isWorldLimited)
            {
                spawnDistance = Math.Min(spawnDistance, MyEntities.WorldSafeHalfExtent() - spawnGroup.SpawnRadius);
            }
            else
            {
                // In infinite worlds players can be thousands of kilometers away, so spawn ship around random player
                // so cargo ships will be spawned around every player at some time
                var players = MySession.Static.Players.GetOnlinePlayers();
                // In DS there can be no players connected
                numPlayers = Math.Max(0, players.Count - 1);
                int randomPlayerPosition = MyUtils.GetRandomInt(0, numPlayers);
                int i = 0;
                foreach (var player in players)
                {
                    if (i == randomPlayerPosition)
                    {
                        if (player.Character != null)
                        {
                            playerPosition = player.GetPosition();
                        }
                        break;
                    }
                    i++;
                }

            }
            if (spawnDistance < 0.0f)
            {
                MySandboxGame.Log.WriteLine("Not enough space in the world to spawn such a huge spawn group!");
                return;
            }

            double forbiddenRadius = NEUTRAL_SHIP_FORBIDDEN_RADIUS;
            BoundingBoxD spawnBox;
            if (isWorldLimited)
            {
                spawnBox = new BoundingBoxD(new Vector3D(playerPosition - spawnDistance), new Vector3D(playerPosition + spawnDistance));
            }
            else
            {
                // We need to extend bouding box so cargo ships aren't spawned near other players
                GetSafeBoundingBoxForPlayers(playerPosition, spawnDistance, out spawnBox);
                // Forbidden radius is sphere around all players in box.
                // Bounding box is generated from players positions so their distance to center shall be same for all players
                forbiddenRadius += spawnBox.HalfExtents.Max() - NEUTRAL_SHIP_FORBIDDEN_RADIUS;
            }

            // Get the direction to the center and deviate it randomly
            Vector3D? origin = MyUtils.GetRandomBorderPosition(ref spawnBox);
            origin = MyEntities.FindFreePlace(origin.Value, spawnGroup.SpawnRadius);
            if (!origin.HasValue)
            {
            
                MySandboxGame.Log.WriteLine("Could not spawn neutral ships - no free place found");
                MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                ProfilerShort.End();
                return;
            }

            // Radius in arc units of the forbidden sphere in the center, when viewed from origin
            float centerArcRadius = (float)Math.Atan(forbiddenRadius / (origin.Value - spawnBox.Center).Length());

            // Generate direction with elevation from centerArcRadius radians to (cAR + N_S_D_S) radians
            Vector3D direction = -Vector3D.Normalize(origin.Value);
            float theta = MyUtils.GetRandomFloat(centerArcRadius, centerArcRadius + NEUTRAL_SHIP_DIRECTION_SPREAD);
            float phi = MyUtils.GetRandomRadian();
            Vector3D cosVec = Vector3D.CalculatePerpendicularVector(direction);
            Vector3D sinVec = Vector3D.Cross(direction, cosVec);
            cosVec *= (Math.Sin(theta) * Math.Cos(phi));
            sinVec *= (Math.Sin(theta) * Math.Sin(phi));
            direction = direction * Math.Cos(theta) + cosVec + sinVec;

            Vector3D destination = Vector3D.Zero;
            RayD ray = new RayD(origin.Value, direction);
            double? intersection = ray.Intersects(spawnBox);
            Vector3D directionMult;
            if (!intersection.HasValue || intersection.Value < NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH)
            {
                directionMult = direction * NEUTRAL_SHIP_MINIMAL_ROUTE_LENGTH;
            }
            else
            {
                directionMult = direction * intersection.Value;
            }
            destination = origin.Value + directionMult;

            Vector3D upVector = Vector3D.CalculatePerpendicularVector(direction);
            Vector3D rightVector = Vector3D.Cross(direction, upVector);
            MatrixD originMatrix = MatrixD.CreateWorld(origin.Value, direction, upVector);

            ProfilerShort.End();

            ProfilerShort.Begin("Check free space");

            // CH:TODO: Convex cast to detect collision
            // Check ships' path to avoid possible collisions. (TODO: But only if it is said in the definitions)
            m_raycastHits.Clear();
            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                var prefabDef = MyDefinitionManager.Static.GetPrefabDefinition(shipPrefab.SubtypeId);
                Debug.Assert(prefabDef != null);

                Vector3D shipPosition = Vector3.Transform(shipPrefab.Position, originMatrix);
                Vector3D shipDestination = shipPosition + directionMult;
                float radius = prefabDef == null ? 10.0f : prefabDef.BoundingSphere.Radius;

                MyPhysics.CastRay(shipPosition, shipDestination, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer);
                if (m_raycastHits.Count > 0)
                {
                    MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision");
                    MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                    ProfilerShort.End();
                    return;
                }

                for (int i = 0; i < 4; ++i)
                {
                    Vector3D shiftVector = upVector * m_upVecMultipliers[i] * radius + rightVector * m_rightVecMultipliers[i] * radius;
                    MyPhysics.CastRay(shipPosition + shiftVector, shipDestination + shiftVector, m_raycastHits, MyPhysics.CollisionLayers.ObjectDetectionCollisionLayer);

                    if (m_raycastHits.Count > 0)
                    {
                        MySandboxGame.Log.WriteLine("Could not spawn neutral ships due to collision");
                        MyGlobalEvents.RescheduleEvent(senderEvent as MyGlobalEventBase, NEUTRAL_SHIP_RESCHEDULE_TIME);
                        ProfilerShort.End();
                        return;
                    }
                }
            }

            ProfilerShort.End();

            ProfilerShort.Begin("Spawn ships");

            long spawnGroupId = MyPirateAntennas.GetPiratesId();

            // The ships were collision-free. Now spawn them
            foreach (var shipPrefab in spawnGroup.Prefabs)
            {
                ProfilerShort.Begin(shipPrefab.BeaconText);

                // Yes, this could have been saved in the previous loop, but compared to (e.g.) raycasts, this does not take too much time to recalculate
                Vector3D shipPosition = Vector3D.Transform((Vector3D)shipPrefab.Position, originMatrix);
                Vector3D shipDestination = shipPosition + directionMult;
                Vector3D up = Vector3D.CalculatePerpendicularVector(-direction);

                m_tmpGridList.Clear();

                // CH: We don't want a new identity for each ship anymore. We should handle that in a better way...
                /*if (shipPrefab.ResetOwnership)
                {
                    if (spawnGroupId == 0)
                    {
                        //This is not an NPC so that it doesn't show up in assign ownership drop down menu
                        MyIdentity spawnGroupIdentity = Sync.Players.CreateNewIdentity("Neutral NPC");
                        spawnGroupId = spawnGroupIdentity.IdentityId;
                    }
                }*/

                // Deploy ship
                ProfilerShort.Begin("Spawn cargo ship");
                MyPrefabManager.Static.SpawnPrefab(
                    resultList: m_tmpGridList,
                    prefabName: shipPrefab.SubtypeId,
                    position: shipPosition,
                    forward: direction,
                    up: up,
                    initialLinearVelocity: shipPrefab.Speed * direction,
                    beaconName: shipPrefab.BeaconText,
                    spawningOptions: Sandbox.ModAPI.SpawningOptions.RotateFirstCockpitTowardsDirection |
                                     Sandbox.ModAPI.SpawningOptions.SpawnRandomCargo |
                                     Sandbox.ModAPI.SpawningOptions.DisableDampeners,
                                     ownerId: shipPrefab.ResetOwnership ? spawnGroupId : 0,
                    updateSync: true);
                ProfilerShort.End();

                foreach (var grid in m_tmpGridList)
                {
                    var cockpit = grid.GetFirstBlockOfType<MyCockpit>();
                    if (cockpit != null)
                    {
                        MySimpleAutopilot ai = new MySimpleAutopilot(shipDestination, (Vector3)direction);
                        cockpit.AttachAutopilot(ai);
                        break;
                    }
                }

                m_tmpGridList.Clear();

                ProfilerShort.End();
            }

            ProfilerShort.End();
        }
Пример #44
0
        private void CheckInput()
        {
            MatrixD headMatrix = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(true);
            RayD ray = new RayD(headMatrix.Translation, headMatrix.Forward);

            BoundingSphereD holoSphere = new BoundingSphereD(m_offset.ToWorld(m_block), m_radiusHolo.Value);
            double tmin, tmax;

            if (!holoSphere.IntersectRaySphere(ray, out tmin, out tmax) || tmin > CrosshairRange)
                return;

            int scroll = MyAPIGateway.Input.DeltaMouseScrollWheelValue();
            if (scroll != 0)
            {
                int scrollSteps = (int)Math.Round(scroll * InputScrollMulti);
                float rangeMulti = 1f;
                while (scrollSteps > 0)
                {
                    rangeMulti *= ScrollRangeMulti;
                    scrollSteps--;
                }
                while (scrollSteps < 0)
                {
                    rangeMulti /= ScrollRangeMulti;
                    scrollSteps++;
                }
                m_rangeDetection.Value *= rangeMulti;
            }

            if (MyAPIGateway.Input.IsNewRightMousePressed())
            {
                m_centreEntityId.Value = 0L;
            }
            else if (MyAPIGateway.Input.IsNewLeftMousePressed())
            {
                IMyEntity firstHit = null;
                double firstHitDistance = CrosshairRange;

                foreach (SeenHolo sh in m_holoEntities.Values)
                    if (sh.Holo.Render.Visible && sh.Holo.PositionComp.WorldAABB.Intersect(ref ray, out tmin, out tmax) && tmin < firstHitDistance)
                    {
                        firstHit = sh.Seen.Entity;
                        firstHitDistance = tmin;
                    }

                if (firstHit != null)
                    m_centreEntityId.Value = firstHit.EntityId;
            }
        }
Пример #45
0
        public static void FindLookAtEntity(IMyControllableEntity controlledEntity, bool ignoreOccupiedGrid, bool ignoreProjection, out IMyEntity lookEntity, out double lookDistance, out Vector3D hitPoint, bool findShips, bool findCubes, bool findPlayers, bool findAsteroids, bool findPlanets, bool findReplicable)
        {
            const float range = 5000000;
            Matrix worldMatrix;
            Vector3D startPosition;
            Vector3D endPosition;
            IMyCubeGrid occupiedGrid = null;

            if (controlledEntity.Entity.Parent == null)
            {
                worldMatrix = controlledEntity.GetHeadMatrix(true, true, false); // dead center of player cross hairs, or the direction the player is looking with ALT.
                startPosition = worldMatrix.Translation + worldMatrix.Forward * 0.5f;
                endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 0.5f);
            }
            else
            {
                occupiedGrid = controlledEntity.Entity.GetTopMostParent() as IMyCubeGrid;
                worldMatrix = controlledEntity.Entity.WorldMatrix;
                // TODO: need to adjust for position of cockpit within ship.
                startPosition = worldMatrix.Translation + worldMatrix.Forward * 1.5f;
                endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 1.5f);
            }

            var entites = new HashSet<IMyEntity>();
            MyAPIGateway.Entities.GetEntities(entites, e => e != null);

            var list = new Dictionary<IMyEntity, double>();
            var ray = new RayD(startPosition, worldMatrix.Forward);

            foreach (var entity in entites)
            {
                if (findShips || findCubes)
                {
                    var cubeGrid = entity as IMyCubeGrid;

                    if (cubeGrid != null)
                    {
                        if (ignoreOccupiedGrid && occupiedGrid != null && occupiedGrid.EntityId == cubeGrid.EntityId)
                            continue;

                        // Will ignore Projected grids, new grid/cube placement, and grids in middle of copy/paste.
                        if (ignoreProjection && cubeGrid.Physics == null)
                            continue;

                        // check if the ray comes anywhere near the Grid before continuing.
                        if (ray.Intersects(entity.WorldAABB).HasValue)
                        {
                            var hit = cubeGrid.RayCastBlocks(startPosition, endPosition);
                            if (hit.HasValue)
                            {
                                var distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length();
                                var block = cubeGrid.GetCubeBlock(hit.Value);

                                if (block.FatBlock != null && findCubes)
                                    list.Add(block.FatBlock, distance);
                                else if (findShips)
                                    list.Add(entity, distance);
                            }
                        }
                    }
                }

                if (findPlayers)
                {
                    var controller = entity as IMyControllableEntity;
                    if (controlledEntity.Entity.EntityId != entity.EntityId && controller != null && ray.Intersects(entity.WorldAABB).HasValue)
                    {
                        var distance = (startPosition - entity.GetPosition()).Length();
                        list.Add(entity, distance);
                    }
                }

                if (findReplicable)
                {
                    var replicable = entity as Sandbox.Game.Entities.MyInventoryBagEntity;
                    if (replicable != null && ray.Intersects(entity.WorldAABB).HasValue)
                    {
                        var distance = (startPosition - entity.GetPosition()).Length();
                        list.Add(entity, distance);
                    }
                }

                if (findAsteroids)
                {
                    var voxelMap = entity as IMyVoxelMap;
                    if (voxelMap != null)
                    {
                        var aabb = new BoundingBoxD(voxelMap.PositionLeftBottomCorner, voxelMap.PositionLeftBottomCorner + voxelMap.Storage.Size);
                        var hit = ray.Intersects(aabb);
                        if (hit.HasValue)
                        {
                            var center = voxelMap.PositionLeftBottomCorner + (voxelMap.Storage.Size / 2);
                            var distance = (startPosition - center).Length();  // use distance to center of asteroid.
                            list.Add(entity, distance);
                        }
                    }
                }

                if (findPlanets)
                {
                    // Looks to be working against Git and public release.
                    var planet = entity as Sandbox.Game.Entities.MyPlanet;
                    if (planet != null)
                    {
                        var aabb = new BoundingBoxD(planet.PositionLeftBottomCorner, planet.PositionLeftBottomCorner + planet.Size);
                        var hit = ray.Intersects(aabb);
                        if (hit.HasValue)
                        {
                            var center = planet.WorldMatrix.Translation;
                            var distance = (startPosition - center).Length(); // use distance to center of planet.
                            list.Add(entity, distance);
                        }
                    }
                }
            }

            if (list.Count == 0)
            {
                lookEntity = null;
                lookDistance = 0;
                hitPoint = Vector3D.Zero;
                return;
            }

            // find the closest Entity.
            var item = list.OrderBy(f => f.Value).First();
            lookEntity = item.Key;
            lookDistance = item.Value;
            hitPoint = startPosition + (Vector3D.Normalize(ray.Direction) * lookDistance);
        }
        public static void FindLookAtEntity(IMyControllableEntity controlledEntity, bool ignoreOccupiedGrid, bool ignoreProjection, out IMyEntity lookEntity, out double lookDistance, out Vector3D hitPoint, bool findShips, bool findCubes, bool findPlayers, bool findAsteroids, bool findPlanets, bool findReplicable)
        {
            const float range = 5000000;
            Matrix worldMatrix;
            Vector3D startPosition;
            Vector3D endPosition;
            IMyCubeGrid occupiedGrid = null;

            if (controlledEntity.Entity.Parent == null)
            {
                worldMatrix = controlledEntity.GetHeadMatrix(true, true, false); // dead center of player cross hairs, or the direction the player is looking with ALT.
                startPosition = worldMatrix.Translation + worldMatrix.Forward * 0.5f;
                endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 0.5f);
            }
            else
            {
                occupiedGrid = controlledEntity.Entity.GetTopMostParent() as IMyCubeGrid;
                worldMatrix = controlledEntity.Entity.WorldMatrix;
                // TODO: need to adjust for position of cockpit within ship.
                startPosition = worldMatrix.Translation + worldMatrix.Forward * 1.5f;
                endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 1.5f);
            }

            //var worldMatrix = MyAPIGateway.Session.Player.PlayerCharacter.Entity.WorldMatrix;
            //var position = MyAPIGateway.Session.Player.PlayerCharacter.Entity.GetPosition();
            //var position = worldMatrix.Translation + worldMatrix.Forward * 0.5f + worldMatrix.Up * 1.0f;
            //MyAPIGateway.Utilities.ShowMessage("Pos", string.Format("x={0:N},y={1:N},z={2:N}  x={3:N},y={4:N},z={5:N}", playerPos.X, playerPos.Y, playerPos.Z, playerMatrix.Forward.X, playerMatrix.Forward.Y, playerMatrix.Forward.Z));

            // The CameraController.GetViewMatrix appears warped at the moment.
            //var position = ((IMyEntity)MyAPIGateway.Session.CameraController).GetPosition();
            //var worldMatrix = MyAPIGateway.Session.CameraController.GetViewMatrix();
            //var position = worldMatrix.Translation;
            //MyAPIGateway.Utilities.ShowMessage("Cam", string.Format("x={0:N},y={1:N},z={2:N}  x={3:N},y={4:N},z={5:N}", position.X, position.Y, position.Z, worldMatrix.Forward.X, worldMatrix.Forward.Y, worldMatrix.Forward.Z));

            var entites = new HashSet<IMyEntity>();
            MyAPIGateway.Entities.GetEntities(entites, e => e != null);

            var list = new Dictionary<IMyEntity, double>();
            var ray = new RayD(startPosition, worldMatrix.Forward);

            foreach (var entity in entites)
            {
                if (findShips || findCubes)
                {
                    var cubeGrid = entity as Sandbox.ModAPI.IMyCubeGrid;

                    if (cubeGrid != null)
                    {
                        if (ignoreOccupiedGrid && occupiedGrid != null && occupiedGrid.EntityId == cubeGrid.EntityId)
                            continue;

                        // TODO: ignore construction. New cube, new ship, new station, new paste.
                        //if (ignoreConstruction && (MyAPIGateway.CubeBuilder.BlockCreationIsActivated || MyAPIGateway.CubeBuilder.ShipCreationIsActivated || MyAPIGateway.CubeBuilder.CopyPasteIsActivated))
                        //    continue;

                        // Will ignore Projected grids, new grid/cube placement, and grids in middle of copy/paste.
                        // TODO: need a better way of determining projection other than Physics, as constructions have no physics either..
                        if (ignoreProjection && cubeGrid.Physics == null)
                            continue;

                        // check if the ray comes anywhere near the Grid before continuing.    
                        if (ray.Intersects(entity.WorldAABB).HasValue)
                        {
                            var hit = cubeGrid.RayCastBlocks(startPosition, endPosition);
                            if (hit.HasValue)
                            {
                                var distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length();
                                var block = cubeGrid.GetCubeBlock(hit.Value);

                                if (block.FatBlock != null && findCubes)
                                    list.Add(block.FatBlock, distance);
                                else if (findShips)
                                    list.Add(entity, distance);
                            }
                        }
                    }
                }

                if (findPlayers)
                {
                    var controller = entity as IMyControllableEntity;
                    if (controlledEntity.Entity.EntityId != entity.EntityId && controller != null && ray.Intersects(entity.WorldAABB).HasValue)
                    {
                        var distance = (startPosition - entity.GetPosition()).Length();
                        list.Add(entity, distance);
                    }
                }

                if (findReplicable)
                {
                    var replicable = entity as Sandbox.Game.Entities.MyInventoryBagEntity;
                    if (replicable != null && ray.Intersects(entity.WorldAABB).HasValue)
                    {
                        var distance = (startPosition - entity.GetPosition()).Length();
                        list.Add(entity, distance);
                    }
                }

                if (findAsteroids)
                {
                    var voxelMap = entity as IMyVoxelMap;
                    if (voxelMap != null)
                    {
                        var aabb = new BoundingBoxD(voxelMap.PositionLeftBottomCorner, voxelMap.PositionLeftBottomCorner + voxelMap.Storage.Size);
                        var hit = ray.Intersects(aabb);
                        if (hit.HasValue)
                        {
                            Vector3D? hitIngoing;
                            Vector3D? hitOutgoing;

                            // May not be asteroid that is blocking ray, so am doing additional checks. It's still not reliable.
                            if (voxelMap.WorldAABB.IntersectPoints(startPosition, endPosition, out hitIngoing, out hitOutgoing)
                                && Sandbox.Game.Entities.MyEntities.IsRaycastBlocked(hitIngoing.Value, hitOutgoing.Value))
                            {
                                Vector3 lastOutsidePos;
                                // TODO: IsInsideVoxel doesn't appear to be reliable. Need to find an improved method.

                                //List<Sandbox.Engine.Physics.MyPhysics.HitInfo> m_hits = new List<Sandbox.Engine.Physics.MyPhysics.HitInfo>();
                                //Sandbox.Engine.Physics.MyPhysics.CastRay(startPosition, endPosition, m_hits, 0);   // MyPhysics is not whitelisted.

                                if (Sandbox.Game.Entities.MyEntities.IsInsideVoxel(startPosition, endPosition, out lastOutsidePos))
                                {
                                    list.Add(entity, Vector3D.Distance(startPosition, lastOutsidePos));
                                    //MyAPIGateway.Utilities.ShowMessage("Range", "CheckA");
                                }
                                else
                                {
                                    var center = voxelMap.PositionLeftBottomCorner + (voxelMap.Storage.Size / 2);
                                    // use distance to center of asteroid as an approximation.
                                    //MyAPIGateway.Utilities.ShowMessage("Range", "CheckB");
                                    list.Add(entity, Vector3D.Distance(startPosition, center));
                                }
                            }
                        }
                    }
                }

                if (findPlanets)
                {
                    // Looks to be working against Git and public release.
                    var planet = entity as Sandbox.Game.Entities.MyPlanet;
                    if (planet != null)
                    {
                        var aabb = new BoundingBoxD(planet.PositionLeftBottomCorner, planet.PositionLeftBottomCorner + planet.Size);
                        var hit = ray.Intersects(aabb);
                        if (hit.HasValue)
                        {
                            var center = planet.WorldMatrix.Translation;
                            var distance = (startPosition - center).Length(); // use distance to center of planet.
                            list.Add(entity, distance);
                        }
                    }
                }
            }

            if (list.Count == 0)
            {
                lookEntity = null;
                lookDistance = 0;
                hitPoint = Vector3D.Zero;
                return;
            }

            // find the closest Entity.
            var item = list.OrderBy(f => f.Value).First();
            lookEntity = item.Key;
            lookDistance = item.Value;
            hitPoint = startPosition + (Vector3D.Normalize(ray.Direction) * lookDistance);
        }
Пример #47
0
        private void PlayerUpdate()
        {
            var playerControlled = MyAPIGateway.Session.ControlledObject;

            if(playerControlled != null)
            {
                if(playerControlled.Entity is IMyCharacter)
                {
                    SetCharacterReference(playerControlled.Entity);
                }
                else if(playerControlled.Entity is IMyCockpit) // in a seat, certainly not gonna climb ladders
                {
                    SetCharacterReference(null);
                }
                // other cases depend on having the character controlled for a bit to get the reference
                else if(character != null && character.Closed)
                {
                    SetCharacterReference(null);
                }
            }
            else
            {
                character = null;
            }

            if(character != null)
            {
                var cb = MyCubeBuilder.Static;

                // Dynamically enable/disable UseModelIntersection on ladder blocks that you hold to have the useful effect
                // of being able the block when another entity is blocking the grid space but not the blocks's physical shape.
                // This will still have the side effect issue if you aim at a ladder block with the same ladder block.
                if(cb.IsActivated && cb.CubeBuilderState != null && cb.CubeBuilderState.CurrentBlockDefinition != null && LadderLogic.ladderIds.Contains(cb.CubeBuilderState.CurrentBlockDefinition.Id.SubtypeName))
                {
                    if(prevCubeBuilderDefinition == null || prevCubeBuilderDefinition.Id != cb.CubeBuilderState.CurrentBlockDefinition.Id)
                    {
                        if(prevCubeBuilderDefinition != null)
                            prevCubeBuilderDefinition.UseModelIntersection = false;

                        prevCubeBuilderDefinition = cb.CubeBuilderState.CurrentBlockDefinition;
                        cb.CubeBuilderState.CurrentBlockDefinition.UseModelIntersection = true;
                    }
                }
                else if(prevCubeBuilderDefinition != null)
                {
                    prevCubeBuilderDefinition.UseModelIntersection = false;
                    prevCubeBuilderDefinition = null;
                }

                var charCtrl = character as IMyControllableEntity;
                bool controllingCharacter = (playerControlled != null && playerControlled.Entity is IMyCharacter);
                IMyTerminalBlock ladder = null;
                MyCubeBlock ladderInternal = null;

                MatrixD ladderMatrix = character.WorldMatrix; // temporarily using it for character matrix, then used for ladder matrix
                var charPos = ladderMatrix.Translation + ladderMatrix.Up * 0.05;
                var charPos2 = ladderMatrix.Translation + ladderMatrix.Up * RAY_HEIGHT;
                var charRay = new RayD(charPos, ladderMatrix.Up);

                if(dismounting <= 1) // relative top dismount sequence
                {
                    if(usingLadder == null)
                    {
                        dismounting = 2;
                        return;
                    }

                    ladder = usingLadder;
                    ladderInternal = ladder as MyCubeBlock;
                    dismounting *= ALIGN_MUL;

                    if(settings.clientPrediction)
                    {
                        ladderMatrix = ladder.WorldMatrix;
                        var charOnLadder = ladderMatrix.Translation + ladderMatrix.Forward * (ladderInternal.BlockDefinition.ModelOffset.Z + EXTRA_OFFSET_Z);

                        if(ladder.CubeGrid.GridSizeEnum == MyCubeSize.Large)
                            charOnLadder += ladderMatrix.Backward;

                        var topDir = Vector3D.Dot(character.WorldMatrix.Up, ladderMatrix.Up);
                        var matrix = character.WorldMatrix;
                        var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2);
                        matrix.Translation = charOnLadder + (topDir > 0 ? ladderMatrix.Up : ladderMatrix.Down) * (halfY + 0.1f) + ladderMatrix.Backward * 0.75;

                        character.SetWorldMatrix(MatrixD.SlerpScale(character.WorldMatrix, matrix, MathHelper.Clamp(dismounting, 0.0f, 1.0f)));

                        character.Physics.LinearVelocity = ladder.CubeGrid.Physics.GetVelocityAtPoint(character.WorldMatrix.Translation); // sync velocity with the ladder
                    }

                    SetLadderStatus("Dismounting ladder...", MyFontEnum.White);

                    if(dismounting > 1f)
                        ExitLadder(false);

                    return;
                }

                // UNDONE DEBUG
                //{
                //    var c = Color.Blue.ToVector4();
                //    MySimpleObjectDraw.DrawLine(charPos, charPos2, "WeaponLaserIgnoreDepth", ref c, 0.5f);
                //}

                // find a ladder
                foreach(var l in ladders.Values)
                {
                    if(l.Closed || l.MarkedForClose || !l.IsFunctional)
                        continue;

                    if(Vector3D.DistanceSquared(l.WorldMatrix.Translation, charPos) <= UPDATE_RADIUS)
                    {
                        ladderInternal = l as MyCubeBlock;
                        ladderMatrix = l.WorldMatrix;

                        // update ladder oriented box to find character in it accurately
                        Quaternion.CreateFromRotationMatrix(ref ladderMatrix, out ladderBox.Orientation);

                        if(l is MyAdvancedDoor && !(l as MyAdvancedDoor).FullyOpen)
                        {
                            ladderBox.HalfExtent = (ladderInternal.BlockDefinition.Size * l.CubeGrid.GridSize) / 2;

                            var offset = ladderInternal.BlockDefinition.ModelOffset;
                            ladderBox.Center = ladderMatrix.Translation + ladderMatrix.Up * 1.125f + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z);

                            ladderBox.HalfExtent.Y = 0.25 + 0.06; // 6mm offset to avoid some inaccuracies
                            ladderBox.HalfExtent.Z = 0.5;

                            if(l.CubeGrid.GridSizeEnum == MyCubeSize.Large)
                                ladderBox.Center += ladderMatrix.Backward;
                        }
                        else
                        {
                            ladderBox.HalfExtent = (ladderInternal.BlockDefinition.Size * l.CubeGrid.GridSize) / 2;
                            ladderBox.HalfExtent.Y += 0.06; // 6mm offset to avoid some inaccuracies
                            ladderBox.HalfExtent.Z = 0.5;

                            var offset = ladderInternal.BlockDefinition.ModelOffset;
                            ladderBox.Center = ladderMatrix.Translation + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z);

                            if(l.CubeGrid.GridSizeEnum == MyCubeSize.Large)
                                ladderBox.Center += ladderMatrix.Backward;
                        }

                        if(!ladderBox.Contains(ref charPos) && !ladderBox.Contains(ref charPos2))
                        {
                            var intersect = ladderBox.Intersects(ref charRay);

                            if(!intersect.HasValue || intersect.Value < 0 || intersect.Value > RAY_HEIGHT)
                                continue;
                        }

                        // UNDONE DEBUG
                        //{
                        //    {
                        //        var c = Color.Red.ToVector4();
                        //        MySimpleObjectDraw.DrawLine(ladderBox.Center + ladderMatrix.Down * ladderBox.HalfExtent.Y, ladderBox.Center + ladderMatrix.Up * ladderBox.HalfExtent.Y, "WeaponLaserIgnoreDepth", ref c, 0.01f);
                        //    }
                        //
                        //    if(debugBox == null)
                        //    {
                        //        debugBox = new MyEntity();
                        //        debugBox.Init(null, @"Models\Debug\Error.mwm", null, null, null);
                        //        debugBox.PositionComp.LocalMatrix = Matrix.Identity;
                        //        debugBox.Flags = EntityFlags.Visible | EntityFlags.NeedsDraw | EntityFlags.NeedsDrawFromParent | EntityFlags.InvalidateOnMove;
                        //        debugBox.OnAddedToScene(null);
                        //        debugBox.Render.Transparency = 0.5f;
                        //        debugBox.Render.RemoveRenderObjects();
                        //        debugBox.Render.AddRenderObjects();
                        //    }
                        //    var matrix = MatrixD.CreateWorld(ladderBox.Center, ladderMatrix.Forward, ladderMatrix.Up);
                        //    var scale = ladderBox.HalfExtent * 2;
                        //    MatrixD.Rescale(ref matrix, ref scale);
                        //    debugBox.PositionComp.SetWorldMatrix(matrix);
                        //}

                        ladder = l;
                        ladderInternal = l as MyCubeBlock;
                        break;
                    }
                }

                if(ladder != null)
                {
                    var offset = ladderInternal.BlockDefinition.ModelOffset;
                    var charOnLadder = ladderMatrix.Translation + ladderMatrix.Forward * (offset.Z + EXTRA_OFFSET_Z);

                    if(ladder.CubeGrid.GridSizeEnum == MyCubeSize.Large)
                        charOnLadder += ladderMatrix.Backward;

                    if(++skipRetryGravity >= GRAVITY_UPDATERATE)
                    {
                        skipRetryGravity = 0;
                        alignedToGravity = true;
                        var gravity = MyParticlesManager.CalculateGravityInPoint(character.WorldMatrix.Translation);
                        var gravityLength = gravity.Normalize();

                        if(gravityLength > 0)
                        {
                            float gravDot = Vector3.Dot(gravity, ladderMatrix.Down);

                            if(!(gravDot >= 0.9f || gravDot <= -0.9f))
                            {
                                alignedToGravity = false;
                            }
                        }
                    }

                    //bool readInput = InputHandler.IsInputReadable(); // HACK use before GetPressedOr() once ActiveGameplayScreen's NRE is resolved

                    if(!alignedToGravity)
                    {
                        bool pressed = InputHandler.GetPressedOr(settings.useLadder1, settings.useLadder2, false, false) && InputHandler.IsInputReadable(); // needs to support hold-press, so don't set JustPressed to true!

                        if(pressed)
                            SetLadderStatus("Gravity not parallel to ladder!", MyFontEnum.Red, 1000);

                        if(usingLadder != null)
                            ExitLadder(false);

                        return;
                    }

                    if(usingLadder == null) // first ladder interaction
                    {
                        //var controlUse = MyAPIGateway.Input.GetGameControl(MyControlsSpace.USE);
                        //
                        //if(!controlUse.IsPressed())
                        //{
                        //    string assigned = (controlUse.GetKeyboardControl() != MyKeys.None ? MyAPIGateway.Input.GetKeyName(controlUse.GetKeyboardControl()) : (controlUse.GetMouseControl() != MyMouseButtonsEnum.None ? MyAPIGateway.Input.GetName(controlUse.GetMouseControl()) : "(NONE)")) + (controlUse.GetSecondKeyboardControl() != MyKeys.None ? " or " + MyAPIGateway.Input.GetKeyName(controlUse.GetSecondKeyboardControl()) : null);
                        //    SetLadderStatus("Press "+assigned+" to use the ladder.", MyFontEnum.White);
                        //    return;
                        //}

                        if(grabOnLoad)
                        {
                            grabOnLoad = false;
                        }
                        else
                        {
                            aimingAtLadder = true;

                            if(settings.useLadder1 == null && settings.useLadder2 == null)
                            {
                                SetLadderStatus("Ladder interaction is unassigned, edit the settings.cfg file!\nFor now you can use the USE key.", MyFontEnum.Red);

                                if(!MyAPIGateway.Input.IsGameControlPressed(MyControlsSpace.USE))
                                    return;
                            }
                            else
                            {
                                bool pressed = InputHandler.GetPressedOr(settings.useLadder1, settings.useLadder2, false, false) && InputHandler.IsInputReadable(); // needs to support hold-press, so don't set JustPressed to true!

                                if(!pressed)
                                {
#if !STABLE // STABLE CONDITION
                                    if(!highlightedLadders.Contains(ladder.EntityId))
                                    {
                                        if(highlightedLadders.Count > 0)
                                        {
                                            foreach(var id in highlightedLadders)
                                            {
                                                MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, false);
                                            }

                                            highlightedLadders.Clear();
                                        }

                                        var envDef = MyDefinitionManager.Static.EnvironmentDefinition;
                                        var color = envDef.ContourHighlightColor;
                                        var thick = (int)envDef.ContourHighlightThickness;

                                        highlightedLadders.Add(ladder.EntityId);
                                        MyVisualScriptLogicProvider.SetHighlight(ladder.Name, true, thick, LADDER_HIGHLIGHT_PULSE, color);

                                        var ladderGrid = ladder.CubeGrid;

                                        for(int i = 1; i <= 10; i++)
                                        {
                                            var slim = ladderGrid.GetCubeBlock(ladderGrid.WorldToGridInteger(ladderMatrix.Translation + ladderMatrix.Up * i * ladderGrid.GridSize));

                                            if(slim?.FatBlock?.GameLogic?.GetAs<LadderLogic>() == null)
                                                break;

                                            var id = slim.FatBlock.EntityId;
                                            highlightedLadders.Add(id);
                                            MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, true, thick, LADDER_HIGHLIGHT_PULSE, color);
                                        }

                                        for(int i = 1; i <= 10; i++)
                                        {
                                            var slim = ladderGrid.GetCubeBlock(ladderGrid.WorldToGridInteger(ladderMatrix.Translation + ladderMatrix.Down * i * ladderGrid.GridSize));

                                            if(slim?.FatBlock?.GameLogic?.GetAs<LadderLogic>() == null)
                                                break;

                                            var id = slim.FatBlock.EntityId;
                                            highlightedLadders.Add(id);
                                            MyVisualScriptLogicProvider.SetHighlight(LADDER_NAME_PREFIX + id, true, thick, LADDER_HIGHLIGHT_PULSE, color);
                                        }
                                    }
#endif

                                    SetLadderStatus("Press " + InputHandler.GetFriendlyStringOr(settings.useLadder1, settings.useLadder2) + " to use the ladder.", MyFontEnum.White);
                                    return;
                                }
                            }
                        }

                        skipRefreshAnim = 60;
                        mounting = (controllingCharacter ? ALIGN_STEP : 2);
                        usingLadder = ladder;
                        SendLadderData(LadderAction.MOUNT, entId: ladder.EntityId);
                        LadderAnim(character, LadderAnimation.MOUNTING);
                    }

                    if(usingLadder != ladder)
                    {
                        usingLadder = ladder;
                        SendLadderData(LadderAction.CHANGE_LADDER, entId: ladder.EntityId);
                    }

                    if(charCtrl.Entity.Physics == null)
                    {
                        ExitLadder(false);
                        return;
                    }

                    if(settings.clientPrediction)
                        character.Physics.LinearVelocity = ladder.CubeGrid.Physics.GetVelocityAtPoint(character.WorldMatrix.Translation); // sync velocity with the ladder

                    if(skipRefreshAnim > 0 && --skipRefreshAnim == 0) // force refresh animation after mounting due to an issue
                    {
                        var anim = lastLadderAnim;
                        lastLadderAnim = LadderAnimation.NONE;
                        LadderAnim(character, anim);
                    }

                    if(mounting <= 1) // mounting on ladder sequence
                    {
                        mounting *= ALIGN_MUL;

                        if(settings.clientPrediction)
                        {
                            float align = Vector3.Dot(ladderMatrix.Up, character.WorldMatrix.Up);

                            var matrix = MatrixD.CreateFromDir(ladderMatrix.Backward, (align > 0 ? ladderMatrix.Up : ladderMatrix.Down));
                            var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2);
                            var diff = Vector3D.Dot(character.WorldMatrix.Translation, ladderMatrix.Up) - Vector3D.Dot(charOnLadder, ladderMatrix.Up);
                            matrix.Translation = charOnLadder + ladderMatrix.Up * MathHelper.Clamp(diff, -halfY, halfY);

                            character.SetWorldMatrix(MatrixD.SlerpScale(character.WorldMatrix, matrix, MathHelper.Clamp(mounting, 0.0f, 1.0f)));
                        }

                        if(mounting >= 0.75f && charCtrl.EnabledThrusts) // delayed turning off thrusts because gravity aligns you faster and can make you fail to attach to the ladder
                            charCtrl.SwitchThrusts();

                        SetLadderStatus("Mounting ladder...", MyFontEnum.White);
                        return;
                    }

                    // TODO jetpack assited climb/descend ? / gravity assisted descend ?

                    if(charCtrl.EnabledThrusts)
                    {
                        if(!learned[4])
                            learned[4] = true;

                        ExitLadder(false); // leave ladder if jetpack is turned on
                        return;
                    }

                    // HACK use once input reading NRE is fixed
                    //if(!controllingCharacter) // disable ladder control if not controlling character
                    //    readInput = false;

                    bool movingSideways = false;
                    var analogInput = MyAPIGateway.Input.GetPositionDelta();

                    // HACK use in-line once NRE is fixed
                    if(!controllingCharacter)
                        analogInput = Vector3.Zero;
                    else if(analogInput.LengthSquared() > 0 && !InputHandler.IsInputReadable())
                        analogInput = Vector3.Zero;

                    if(analogInput.Y < 0) // crouch
                    {
                        if(!learned[4])
                            learned[4] = true;

                        ExitLadder(false);
                        return;
                    }

                    float move = MathHelper.Clamp((float)Math.Round(-analogInput.Z, 1), -1, 1); // forward/backward
                    float side = MathHelper.Clamp((float)Math.Round(analogInput.X, 1), -1, 1); // left/right

                    //float move = readInput ? MathHelper.Clamp(MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.FORWARD) - MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.BACKWARD), -1, 1) : 0;
                    //float side = readInput ? MathHelper.Clamp(MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.STRAFE_RIGHT) - MyAPIGateway.Input.GetGameControlAnalogState(MyControlsSpace.STRAFE_LEFT), -1, 1) : 0;
                    var alignVertical = ladderMatrix.Up.Dot(character.WorldMatrix.Up);

                    if(!loadedAllLearned)
                    {
                        bool allLearned = (learned[0] && learned[1] && learned[2] && learned[3] && learned[4]);

                        for(int i = 0; i < learned.Length; i++)
                        {
                            if(learnNotify[i] == null)
                                learnNotify[i] = MyAPIGateway.Utilities.CreateNotification("");

                            learnNotify[i].Text = (learned[i] ? LEARN_CHECK : LEARN_UNCHECK) + learnText[i];
                            learnNotify[i].Font = (learned[i] ? MyFontEnum.White : MyFontEnum.DarkBlue);
                            learnNotify[i].AliveTime = (allLearned ? 1000 : 100);
                            learnNotify[i].Show();
                        }

                        if(allLearned)
                        {
                            SaveLearn();
                            loadedAllLearned = true;
                        }
                    }

                    var view = MyAPIGateway.Session.ControlledObject.GetHeadMatrix(false, true);
                    float lookVertical = Vector3.Dot(character.WorldMatrix.Up, view.Forward);

                    if(settings.relativeControls) // climbing relative to camera
                    {
                        float verticalModifier = MathHelper.Clamp((lookVertical + 0.65f) / 0.5f, -0.5f, 1.0f);

                        if(verticalModifier < 0)
                            verticalModifier *= 2;

                        move = (float)Math.Round(move * verticalModifier, 1);
                    }

                    if(analogInput.Y > 0) // jump
                    {
                        if(characterMovementState == MyCharacterMovementEnum.Jump) // this is still fine for avoiding jump as the character still is able to jump without needing feet on the ground
                        {
                            ExitLadder(false); // only release if on the floor as the character will jump regardless
                            return;
                        }

                        if(settings.clientPrediction)
                            character.Physics.LinearVelocity += view.Forward * (characterDefinition == null ? VEL_JUMP : 200 * characterDefinition.JumpForce) * TICKRATE;

                        SendLadderData(LadderAction.JUMP_OFF, vec: view.Forward);
                        LadderAnim(character, LadderAnimation.JUMP_OFF);

                        if(!learned[3])
                            learned[3] = true;

                        ExitLadder(false);
                        return;
                    }

                    bool sprint = (characterDefinition != null && characterDefinition.Jetpack != null && MyAPIGateway.Input.IsGameControlPressed(MyControlsSpace.SPRINT));

                    if(Math.Abs(side) > 0.0001f)
                    {
                        if(settings.relativeControls) // side dismounting relative to camera
                        {
                            var alignForward = ladderMatrix.Backward.Dot(character.WorldMatrix.Forward);

                            if(alignForward < 0)
                                side = -side;
                        }

                        float speed = (characterDefinition == null ? (sprint ? VEL_SIDE : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxSprintSpeed : characterDefinition.MaxRunStrafingSpeed));

                        if(settings.clientPrediction)
                            character.Physics.LinearVelocity += side * (alignVertical > 0 ? ladderMatrix.Left : ladderMatrix.Right) * speed * TICKRATE;

                        LadderAnim(character, (side > 0 ? LadderAnimation.DISMOUNT_LEFT : LadderAnimation.DISMOUNT_RIGHT));
                        movingSideways = true;

                        if(!learned[2])
                            learned[2] = true;
                    }
                    else
                    {
                        // aligning player to ladder

                        if(settings.clientPrediction)
                        {
                            Vector3 dir = charOnLadder - charPos;
                            Vector3 vel = dir - (ladderMatrix.Up * Vector3D.Dot(dir, ladderMatrix.Up)); // projecting up/down direction to ignore it
                            float len = vel.Normalize();

                            if(len >= ALIGN_ACCURACY)
                            {
                                float speed = (characterDefinition == null ? (sprint ? VEL_SIDE : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxRunStrafingSpeed : characterDefinition.MaxWalkStrafingSpeed));
                                len = MathHelper.Clamp(len, 0.1f, 1);
                                character.Physics.LinearVelocity += vel * len * speed * TICKRATE;
                            }
                        }
                    }

                    // TODO find a way to control view
                    {
                        //var ctrl2 = (Sandbox.Game.Entities.IMyControllableEntity)character;
                        //
                        //ctrl2.HeadLocalYAngle = 0;
                        //ctrl2.HeadLocalXAngle = 0;
                        //
                        // or MoveAndRotate() ?
                        // or... angularvelocity ?
                        // or I dunno!
                    }

                    if(Math.Abs(move) > 0.0001f)
                    {
                        if(!learned[0])
                            learned[0] = true;

                        var halfY = ((ladderInternal.BlockDefinition.Size.Y * ladder.CubeGrid.GridSize) / 2);
                        var edge = charOnLadder + ((alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * halfY);

                        // climb over at the end when climbing up
                        if(move > 0 && Vector3D.DistanceSquared(charPos, edge) <= 0.0625) // 0.25 squared
                        {
                            var nextBlockWorldPos = ladderMatrix.Translation + ladderMatrix.Forward * offset.Z + ((alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * (halfY + 0.1f));
                            var nextBlockPos = ladder.CubeGrid.WorldToGridInteger(nextBlockWorldPos);
                            var slim = ladder.CubeGrid.GetCubeBlock(nextBlockPos);

                            // if the next block is not a ladder, dismount
                            if(slim == null || !(slim.FatBlock is IMyTerminalBlock) || !LadderLogic.ladderIds.Contains(slim.FatBlock.BlockDefinition.SubtypeId))
                            {
                                dismounting = ALIGN_STEP;
                                SendLadderData(LadderAction.DISMOUNT);
                                return;
                            }
                        }

                        // on the floor and moving backwards makes you dismount
                        if(move < 0)
                        {
                            var feetStart = character.WorldMatrix.Translation + character.WorldMatrix.Up * 0.2; // a bit higher because the floor might clip through the character
                            var feetTarget = feetStart + character.WorldMatrix.Down * 0.3;
                            IHitInfo hit;

                            if(MyAPIGateway.Physics.CastRay(feetStart, feetTarget, out hit, COLLISSIONLAYER_NOCHARACTER))
                            {
                                // need to check the block under the ladder if it's anything but a ladder because "standing" stance occurs when character rests on its chest-sphere collision mesh too
                                var prevBlockWorldPos = ladderMatrix.Translation + ladderMatrix.Forward * offset.Z + (alignVertical > 0 ? ladderMatrix.Down : ladderMatrix.Up) * (halfY + 0.1f);
                                var prevBlockPos = ladder.CubeGrid.WorldToGridInteger(prevBlockWorldPos);
                                var slim = ladder.CubeGrid.GetCubeBlock(prevBlockPos);

                                // if it's not a ladder, check the distance and confirm your feet are close to its edge
                                if(slim == null || !(slim.FatBlock is IMyTerminalBlock) || !LadderLogic.ladderIds.Contains(slim.FatBlock.BlockDefinition.SubtypeId))
                                {
                                    // get the block's edge and the character feet position only along the ladder's up/down axis
                                    var blockPosProjectedUp = ladderMatrix.Up * Vector3D.Dot(prevBlockWorldPos, ladderMatrix.Up);
                                    var charPosProjectedUp = ladderMatrix.Up * Vector3D.Dot(character.WorldMatrix.Translation, ladderMatrix.Up);

                                    if(Vector3D.DistanceSquared(blockPosProjectedUp, charPosProjectedUp) <= 0.04) // 0.2 squared
                                    {
                                        ExitLadder(false); // to recap: if you're moving char-relative down and in "standing" stance and the block below is not a ladder and you're closer than 0.1m to its edge, then let go of the ladder.
                                        return;
                                    }
                                }
                            }
                        }

                        // climbing on the ladder

                        if(!learned[1] && sprint)
                            learned[1] = true;

                        float speed = (characterDefinition == null ? (sprint ? VEL_SPRINT : VEL_CLIMB) : CHAR_SPEED_MUL * (sprint ? characterDefinition.MaxSprintSpeed : characterDefinition.MaxRunSpeed));

                        if(settings.clientPrediction)
                            character.Physics.LinearVelocity += (alignVertical > 0 ? ladderMatrix.Up : ladderMatrix.Down) * move * speed * TICKRATE;

                        if(!movingSideways)
                            LadderAnim(character, (move > 0 ? LadderAnimation.UP : LadderAnimation.DOWN));
                    }
                    else if(!movingSideways)
                    {
                        LadderAnim(character, LadderAnimation.IDLE);
                    }

                    SendLadderData(LadderAction.CLIMB,
                                   climb: (alignVertical > 0 ? move : -move),
                                   side: (alignVertical > 0 ? side : -side),
                                   sprint: sprint);

                    return;
                }
            }

            ExitLadder();
        }
Пример #48
0
        public bool Intersect(RayD ray, ref Vector3D p1, ref Vector3D p2, ref Vector3 n1, ref Vector3 n2)
        {
            // Substituting equ. (1) - (6) to equ. (I) and solving for t' gives:
            //
            // t' = (t * dot(AB, d) + dot(AB, AO)) / dot(AB, AB); (7) or
            // t' = t * m + n where 
            // m = dot(AB, d) / dot(AB, AB) and 
            // n = dot(AB, AO) / dot(AB, AB)
            //
            Vector3D AB = P1 - P0;
            Vector3D AO = ray.Position - P0;

            double AB_dot_d = AB.Dot(ray.Direction);
            double AB_dot_AO = AB.Dot(AO);
            double AB_dot_AB = AB.Dot(AB);

            double m = AB_dot_AB > 0 ? AB_dot_d / AB_dot_AB : 0;
            double n = AB_dot_AB > 0 ? AB_dot_AO / AB_dot_AB : 0;

            // Substituting (7) into (II) and solving for t gives:
            //
            // dot(Q, Q)*t^2 + 2*dot(Q, R)*t + (dot(R, R) - r^2) = 0
            // where
            // Q = d - AB * m
            // R = AO - AB * n
            Vector3D Q = ray.Direction - (AB * m);
            Vector3D R = AO - (AB * n);

            double a = Q.Dot(Q);
            double b = 2.0f * Q.Dot(R);
            double c = R.Dot(R) - (Radius * Radius);

            if (a == 0.0)
            {
                // Special case: AB and ray direction are parallel. If there is an intersection it will be on the end spheres...
                // NOTE: Why is that?
                // Q = d - AB * m =>
                // Q = d - AB * (|AB|*|d|*cos(AB,d) / |AB|^2) => |d| == 1.0
                // Q = d - AB * (|AB|*cos(AB,d)/|AB|^2) =>
                // Q = d - AB * cos(AB, d) / |AB| =>
                // Q = d - unit(AB) * cos(AB, d)
                //
                // |Q| == 0 means Q = (0, 0, 0) or d = unit(AB) * cos(AB,d)
                // both d and unit(AB) are unit vectors, so cos(AB, d) = 1 => AB and d are parallel.
                // 
                BoundingSphereD sphereA, sphereB;
                sphereA.Center = P0;
                sphereA.Radius = Radius;
                sphereB.Center = P1;
                sphereB.Radius = Radius;

                double atmin, atmax, btmin, btmax;
                if (!sphereA.IntersectRaySphere(ray, out atmin, out atmax) ||
                    !sphereB.IntersectRaySphere(ray, out btmin, out btmax))
                {
                    // No intersection with one of the spheres means no intersection at all...
                    return false;
                }

                if (atmin < btmin)
                {
                    p1 = ray.Position + (ray.Direction * atmin);
                    n1 = p1 - P0;
                    n1.Normalize();
                }
                else
                {
                    p1 = ray.Position + (ray.Direction * btmin);
                    n1 = p1 - P1;
                    n1.Normalize();
                }

                if (atmax > btmax)
                {
                    p2 = ray.Position + (ray.Direction * atmax);
                    n2 = p2 - P0;
                    n2.Normalize();
                }
                else
                {
                    p2 = ray.Position + (ray.Direction * btmax);
                    n2 = p2 - P1;
                    n2.Normalize();
                }

                return true;
            }

            double discriminant = b * b - 4.0 * a * c;
            if (discriminant < 0.0f)
            {
                // The ray doesn't hit the infinite cylinder defined by (A, B).
                // No intersection.
                return false;
            }

            double tmin = (-b - Math.Sqrt(discriminant)) / (2.0 * a);
            double tmax = (-b + Math.Sqrt(discriminant)) / (2.0 * a);
            if (tmin > tmax)
            {
                double temp = tmin;
                tmin = tmax;
                tmax = temp;
            }

            // Now check to see if K1 and K2 are inside the line segment defined by A,B
            double t_k1 = tmin * m + n;
            if (t_k1 < 0.0f)
            {
                // On sphere (A, r)...
                BoundingSphereD s;
                s.Center = P0;
                s.Radius = Radius;

                double stmin, stmax;
                if (s.IntersectRaySphere(ray, out stmin, out stmax))
                {
                    p1 = ray.Position + (ray.Direction * stmin);
                    n1 = p1 - P0;
                    n1.Normalize();
                }
                else
                    return false;
            }
            else if (t_k1 > 1.0f)
            {
                // On sphere (B, r)...
                BoundingSphereD s;
                s.Center = P1;
                s.Radius = Radius;

                double stmin, stmax;
                if (s.IntersectRaySphere(ray, out stmin, out stmax))
                {
                    p1 = ray.Position + (ray.Direction * stmin);
                    n1 = p1 - P1;
                    n1.Normalize();
                }
                else
                    return false;
            }
            else
            {
                // On the cylinder...
                p1 = ray.Position + (ray.Direction * tmin);

                Vector3 k1 = P0 + AB * t_k1;
                n1 = p1 - k1;
                n1.Normalize();
            }

            double t_k2 = tmax * m + n;
            if (t_k2 < 0.0f)
            {
                // On sphere (A, r)...
                BoundingSphereD s;
                s.Center = P0;
                s.Radius = Radius;

                double stmin, stmax;
                if (s.IntersectRaySphere(ray, out stmin, out stmax))
                {
                    p2 = ray.Position + (ray.Direction * stmax);
                    n2 = p2 - P0;
                    n2.Normalize();
                }
                else
                    return false;
            }
            else if (t_k2 > 1.0f)
            {
                // On sphere (B, r)...
                BoundingSphereD s;
                s.Center = P1;
                s.Radius = Radius;

                double stmin, stmax;
                if (s.IntersectRaySphere(ray, out stmin, out stmax))
                {
                    p2 = ray.Position + (ray.Direction * stmax);
                    n2 = p2 - P1;
                    n2.Normalize();
                }
                else
                    return false;
            }
            else
            {
                p2 = ray.Position + (ray.Direction * tmax);

                Vector3D k2 = P0 + AB * t_k2;
                n2 = p2 - k2;
                n2.Normalize();
            }

            return true;
        }
        private Vector3 GetBoneOnSphere(Vector3I center, Vector3I bonePos, MyCubeGrid grid)
        {
            Vector3D worldCenter = BoneToWorld(center, Vector3.Zero, grid);
            Vector3D worldBone = BoneToWorld(bonePos, Vector3.Zero, grid);

            BoundingSphereD sphere = new BoundingSphereD(worldCenter, grid.GridSize);
            Vector3D direction = worldCenter - worldBone;
            direction.Normalize();
            RayD ray = new RayD(worldBone, direction);

            double tmin, tmax;
            if (sphere.IntersectRaySphere(ray, out tmin, out tmax))
            {
                Vector3D onSphere = worldBone + direction * tmin;

                var worldOnSphere = Vector3D.Transform(onSphere, grid.PositionComp.WorldMatrixInvScaled);
                worldOnSphere += new Vector3D(grid.GridSize / MyGridSkeleton.BoneDensity);
                return (worldOnSphere - (Vector3D)(bonePos / (float)MyGridSkeleton.BoneDensity) * grid.GridSize);
            }
            else
            {
                return Vector3.Zero;
            }
        }
        /**
         * Project a position to a face of the (-1, -1, -1)(1, 1, 1) cube.
         */
        public static void ProjectToNearestFace(ref Vector3D localPos, out Vector3 faceCoords)
        {
            Vector3D gravity;
            Vector3D.Normalize(ref localPos, out gravity);
            gravity = -gravity;

            RayD r = new RayD(localPos, gravity);

            double? travel = s_unitsBox.Intersects(r);

            Debug.Assert(travel.HasValue, "Ray does not intersect with planet!");

            faceCoords = localPos + (Vector3D)(gravity * travel);
        }