Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for #7083: Fly stops turning when target is inside the turn radius #16054

Merged
merged 1 commit into from
Feb 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions OpenRA.Mods.Common/Activities/Air/Fly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,26 @@ public override Activity Tick(Actor self)
var targetAltitude = aircraft.CenterPosition.Z + aircraft.Info.CruiseAltitude.Length - self.World.Map.DistanceAboveTerrain(aircraft.CenterPosition).Length;
if (aircraft.CenterPosition.Z < targetAltitude)
desiredFacing = aircraft.Facing;
else
{
// Using the turn rate, compute a hypothetical circle traced by a continuous turn.
// If it contains the destination point, it's unreachable without more complex manuvering.
var turnRadius = CalculateTurnRadius(aircraft.MovementSpeed, aircraft.TurnSpeed);

// The current facing is a tangent of the minimal turn circle.
// Make a perpendicular vector, and use it to locate the turn's center.
var turnCenterFacing = aircraft.Facing;
turnCenterFacing += Util.GetNearestFacing(aircraft.Facing, desiredFacing) > 0 ? 64 : -64;

var turnCenterDir = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(turnCenterFacing));
turnCenterDir *= turnRadius;
turnCenterDir /= 1024;

// Compare with the target point, and keep flying away if it's inside the circle.
var turnCenter = aircraft.CenterPosition + turnCenterDir;
if ((checkTarget.CenterPosition - turnCenter).HorizontalLengthSquared < turnRadius * turnRadius)
desiredFacing = aircraft.Facing;
}

FlyToward(self, aircraft, desiredFacing, aircraft.Info.CruiseAltitude);

Expand All @@ -133,5 +153,13 @@ public override IEnumerable<Target> GetTargets(Actor self)
{
yield return target;
}

public static int CalculateTurnRadius(int speed, int turnSpeed)
{
// turnSpeed -> divide into 256 to get the number of ticks per complete rotation
// speed -> multiply to get distance travelled per rotation (circumference)
// 45 -> divide by 2*pi to get the turn radius: 45==256/(2*pi), with some extra leeway
return 45 * speed / turnSpeed;
}
}
}
9 changes: 2 additions & 7 deletions OpenRA.Mods.Common/Activities/Air/ReturnToBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,6 @@ public static Actor ChooseResupplier(Actor self, bool unreservedOnly)
.ClosestTo(self);
}

int CalculateTurnRadius(int speed)
{
return 45 * speed / aircraft.Info.TurnSpeed;
}

void Calculate(Actor self)
{
if (dest == null || dest.IsDead || Reservable.IsReserved(dest))
Expand All @@ -77,7 +72,7 @@ void Calculate(Actor self)

// Add 10% to the turning radius to ensure we have enough room
var speed = aircraft.MovementSpeed * 32 / 35;
var turnRadius = CalculateTurnRadius(speed);
var turnRadius = Fly.CalculateTurnRadius(speed, aircraft.Info.TurnSpeed);

// Find the center of the turning circles for clockwise and counterclockwise turns
var angle = WAngle.FromFacing(aircraft.Facing);
Expand Down Expand Up @@ -154,7 +149,7 @@ public override Activity Tick(Actor self)

List<Activity> landingProcedures = new List<Activity>();

var turnRadius = CalculateTurnRadius(aircraft.Info.Speed);
var turnRadius = Fly.CalculateTurnRadius(aircraft.Info.Speed, aircraft.Info.TurnSpeed);

landingProcedures.Add(new Fly(self, Target.FromPos(w1), WDist.Zero, new WDist(turnRadius * 3)));
landingProcedures.Add(new Fly(self, Target.FromPos(w2)));
Expand Down