diff --git a/OpenRA.Mods.Common/Activities/LegacyEnter.cs b/OpenRA.Mods.Common/Activities/LegacyEnter.cs index 9b5837496d..0e5befd085 100644 --- a/OpenRA.Mods.Common/Activities/LegacyEnter.cs +++ b/OpenRA.Mods.Common/Activities/LegacyEnter.cs @@ -205,7 +205,7 @@ namespace OpenRA.Mods.Common.Activities isEnteringOrInside = true; savedPos = self.CenterPosition; // Save position of self, before entering, for returning on exit - inner = move.MoveIntoTarget(self, target); // Enter + inner = move.VisualMove(self, self.CenterPosition, target.Positions.PositionClosestTo(self.CenterPosition)); if (inner != null) { @@ -228,7 +228,7 @@ namespace OpenRA.Mods.Common.Activities Unreserve(self, false); if (Reserve(self) == ReserveStatus.Ready) { - inner = move.MoveIntoTarget(self, target); // Enter + inner = move.VisualMove(self, self.CenterPosition, target.Positions.PositionClosestTo(self.CenterPosition)); if (inner != null) return EnterState.ApproachingOrEntering; diff --git a/OpenRA.Mods.Common/Activities/Move/VisualMoveIntoTarget.cs b/OpenRA.Mods.Common/Activities/Move/VisualMoveIntoTarget.cs new file mode 100644 index 0000000000..48b93d7259 --- /dev/null +++ b/OpenRA.Mods.Common/Activities/Move/VisualMoveIntoTarget.cs @@ -0,0 +1,97 @@ +#region Copyright & License Information +/* + * Copyright 2007-2019 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using OpenRA.Activities; +using OpenRA.Mods.Common.Traits; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Activities +{ + public class VisualMoveIntoTarget : Activity + { + readonly Mobile mobile; + readonly Target target; + readonly WDist targetMovementThreshold; + WPos targetStartPos; + + public VisualMoveIntoTarget(Actor self, Target target, WDist targetMovementThreshold) + { + mobile = self.Trait(); + this.target = target; + this.targetMovementThreshold = targetMovementThreshold; + } + + protected override void OnFirstRun(Actor self) + { + targetStartPos = target.Positions.PositionClosestTo(self.CenterPosition); + mobile.IsMoving = true; + } + + public override Activity Tick(Actor self) + { + if (ChildActivity != null) + { + ChildActivity = ActivityUtils.RunActivity(self, ChildActivity); + if (ChildActivity != null) + return this; + } + + if (IsCanceled || target.Type == TargetType.Invalid) + return NextActivity; + + if (mobile.IsTraitDisabled) + return this; + + var currentPos = self.CenterPosition; + var targetPos = target.Positions.PositionClosestTo(currentPos); + + // Give up if the target has moved too far + if (targetMovementThreshold > WDist.Zero && (targetPos - targetStartPos).LengthSquared > targetMovementThreshold.LengthSquared) + return NextActivity; + + // Turn if required + var delta = targetPos - currentPos; + var facing = delta.HorizontalLengthSquared != 0 ? delta.Yaw.Facing : mobile.Facing; + if (facing != mobile.Facing) + { + var turn = ActivityUtils.RunActivity(self, new Turn(self, facing)); + if (turn != null) + QueueChild(turn); + + return this; + } + + // Can complete the move in this step + var speed = mobile.MovementSpeedForCell(self, self.Location); + if (delta.LengthSquared <= speed * speed) + { + mobile.SetVisualPosition(self, targetPos); + return NextActivity; + } + + // Move towards the target + mobile.SetVisualPosition(self, currentPos + delta * speed / delta.Length); + + return this; + } + + protected override void OnLastRun(Actor self) + { + mobile.IsMoving = false; + } + + public override IEnumerable GetTargets(Actor self) + { + yield return target; + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 8c3df4e4cd..d50c0b5587 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -103,6 +103,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/Mobile.cs b/OpenRA.Mods.Common/Traits/Mobile.cs index 68ec3b8f28..a94afc7f5f 100644 --- a/OpenRA.Mods.Common/Traits/Mobile.cs +++ b/OpenRA.Mods.Common/Traits/Mobile.cs @@ -517,7 +517,9 @@ namespace OpenRA.Mods.Common.Traits if (target.Type == TargetType.Invalid) return null; - return VisualMove(self, self.CenterPosition, target.Positions.PositionClosestTo(self.CenterPosition)); + // Activity cancels if the target moves by more than half a cell + // to avoid problems with the cell grid + return new VisualMoveIntoTarget(self, target, new WDist(512)); } public Activity VisualMove(Actor self, WPos fromPos, WPos toPos)