/// <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); }
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; }