示例#1
0
        /// <summary>
        /// check visibility between two points (in sim units)
        /// </summary>
        /// <returns>a physics body that was between the points (or null)</returns>
        public static Body CheckVisibility(Vector2 rayStart, Vector2 rayEnd, bool ignoreLevel = false, bool ignoreSubs = false, bool ignoreSensors = true)
        {
            Body    closestBody     = null;
            float   closestFraction = 1.0f;
            Vector2 closestNormal   = Vector2.Zero;

            if (Vector2.Distance(rayStart, rayEnd) < 0.01f)
            {
                lastPickedPosition = rayEnd;
                return(null);
            }

            GameMain.World.RayCast((fixture, point, normal, fraction) =>
            {
                if (fixture == null ||
                    (ignoreSensors && fixture.IsSensor) ||
                    (!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) && !fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)))
                {
                    return(-1);
                }

                if (ignoreLevel && fixture.CollisionCategories == Physics.CollisionLevel)
                {
                    return(-1);
                }
                if (ignoreSubs && fixture.Body.UserData is Submarine)
                {
                    return(-1);
                }

                Structure structure = fixture.Body.UserData as Structure;
                if (structure != null)
                {
                    if (structure.IsPlatform || structure.StairDirection != Direction.None)
                    {
                        return(-1);
                    }
                    int sectionIndex = structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(point));
                    if (sectionIndex > -1 && structure.SectionBodyDisabled(sectionIndex))
                    {
                        return(-1);
                    }
                }

                if (fraction < closestFraction)
                {
                    closestBody     = fixture.Body;
                    closestFraction = fraction;
                    closestNormal   = normal;
                }
                return(closestFraction);
            }
                                   , rayStart, rayEnd);


            lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
            lastPickedFraction = closestFraction;
            lastPickedNormal   = closestNormal;
            return(closestBody);
        }
示例#2
0
        private void GetTargetEntity()
        {
            targetEntity = null;

            if (Character.AnimController.CurrentHull != null)
            {
                wallAttackPos = Vector2.Zero;
                return;
            }

            //check if there's a wall between the target and the Character
            Vector2 rayStart = Character.SimPosition;
            Vector2 rayEnd   = selectedAiTarget.SimPosition;

            if (selectedAiTarget.Entity.Submarine != null && Character.Submarine == null)
            {
                rayStart -= ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position);
            }

            Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd);

            if (Submarine.LastPickedFraction == 1.0f || closestBody == null)
            {
                wallAttackPos = Vector2.Zero;
                return;
            }

            Structure wall = closestBody.UserData as Structure;

            if (wall == null)
            {
                wallAttackPos = Submarine.LastPickedPosition;
                if (selectedAiTarget.Entity.Submarine != null && Character.Submarine == null)
                {
                    wallAttackPos -= ConvertUnits.ToSimUnits(selectedAiTarget.Entity.Submarine.Position);
                }
            }
            else
            {
                int sectionIndex = wall.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition));

                float sectionDamage = wall.SectionDamage(sectionIndex);
                for (int i = sectionIndex - 2; i <= sectionIndex + 2; i++)
                {
                    if (wall.SectionBodyDisabled(i))
                    {
                        sectionIndex = i;
                        break;
                    }
                    if (wall.SectionDamage(i) > sectionDamage)
                    {
                        sectionIndex = i;
                    }
                }
                wallAttackPos = wall.SectionPosition(sectionIndex);
                //if (wall.Submarine != null) wallAttackPos += wall.Submarine.Position;
                wallAttackPos = ConvertUnits.ToSimUnits(wallAttackPos);
            }

            targetEntity = closestBody.UserData as IDamageable;
        }