diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index f843856bcc..6e1d39b38c 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -206,9 +206,12 @@ namespace OpenRA.Traits Activity MoveWithinRange(Target target, WRange minRange, WRange maxRange); Activity MoveFollow(Actor self, Target target, WRange minRange, WRange maxRange); Activity MoveIntoWorld(Actor self, CPos cell, SubCell subCell = SubCell.Any); + Activity MoveToTarget(Actor self, Target target); + Activity MoveIntoTarget(Actor self, Target target); Activity VisualMove(Actor self, WPos fromPos, WPos toPos); CPos NearestMoveableCell(CPos target); bool IsMoving { get; set; } + bool CanEnterTargetNow(Actor self, Target target); } public interface INotifyBlockingMove { void OnNotifyBlockingMove(Actor self, Actor blocking); } diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index 7ac89f57d4..11508803b3 100644 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -135,7 +135,7 @@ namespace OpenRA.Mods.RA.Air if (afld == null) return; - var res = afld.Trait(); + var res = afld.TraitOrDefault(); if (res != null) { @@ -204,6 +204,18 @@ namespace OpenRA.Mods.RA.Air public SubCell GetAvailableSubCell(CPos a, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, bool checkTransientActors = true) { return SubCell.Invalid; } // Does not use any subcell public bool CanEnterCell(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true) { return true; } + public bool CanEnterTargetNow(Actor self, Target target) + { + if (target.Positions.Any(p => self.World.ActorMap.GetUnitsAt(self.World.Map.CellContaining(p)).Any(a => a != self && a != target.Actor))) + return false; + var res = target.Actor.TraitOrDefault(); + if (res == null) + return true; + UnReserve(); + Reservation = res.Reserve(target.Actor, self, this); + return true; + } + public int MovementSpeed { get diff --git a/OpenRA.Mods.RA/Air/Helicopter.cs b/OpenRA.Mods.RA/Air/Helicopter.cs index 52cfb744ef..29feee3849 100644 --- a/OpenRA.Mods.RA/Air/Helicopter.cs +++ b/OpenRA.Mods.RA/Air/Helicopter.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -153,6 +154,12 @@ namespace OpenRA.Mods.RA.Air return new HeliFly(self, Target.FromCell(self.World, cell, subCell)); } + public Activity MoveIntoTarget(Actor self, Target target) { return new HeliLand(false); } + public Activity MoveToTarget(Actor self, Target target) + { + return Util.SequenceActivities(new HeliFly(self, target), new Turn(Info.InitialFacing)); + } + public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) { // TODO: Ignore repulsion when moving diff --git a/OpenRA.Mods.RA/Air/Plane.cs b/OpenRA.Mods.RA/Air/Plane.cs index e2292f5e27..ba159fc8c7 100644 --- a/OpenRA.Mods.RA/Air/Plane.cs +++ b/OpenRA.Mods.RA/Air/Plane.cs @@ -8,6 +8,7 @@ */ #endregion +using System; using System.Drawing; using OpenRA.Mods.RA.Activities; using OpenRA.Traits; @@ -129,5 +130,7 @@ namespace OpenRA.Mods.RA.Air public Activity MoveIntoWorld(Actor self, CPos cell, SubCell subCell = SubCell.Any) { return new Fly(self, Target.FromCell(self.World, cell)); } public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) { return Util.SequenceActivities(new CallFunc(() => SetVisualPosition(self, fromPos)), new Fly(self, Target.FromPos(toPos))); } + public Activity MoveToTarget(Actor self, Target target) { return new Fly(self, target, WRange.FromCells(3), WRange.FromCells(5)); } + public Activity MoveIntoTarget(Actor self, Target target) { return new Land(target); } } } diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 149885ce6d..0b8f13f339 100644 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -660,18 +660,38 @@ namespace OpenRA.Mods.RA.Move SetPosition(self, cell, subCell); SetVisualPosition(self, pos); - // Animate transition - var to = self.World.Map.CenterOfSubCell(cell, subCell); - var speed = MovementSpeedForCell(self, cell); - var length = speed > 0 ? (to - pos).Length / speed : 0; + return VisualMove(self, pos, self.World.Map.CenterOfSubCell(cell, subCell), cell); + } - var facing = Util.GetFacing(to - pos, Facing); - return Util.SequenceActivities(new Turn(facing), new Drag(pos, to, length)); + public Activity MoveToTarget(Actor self, Target target) + { + if (target.Type == TargetType.Invalid) + return null; + + return new MoveAdjacentTo(self, target); + } + + public Activity MoveIntoTarget(Actor self, Target target) + { + if (target.Type == TargetType.Invalid) + return null; + + return VisualMove(self, self.CenterPosition, target.CenterPosition); + } + + public bool CanEnterTargetNow(Actor self, Target target) + { + return self.Location == self.World.Map.CellContaining(target.CenterPosition) || Util.AdjacentCells(self.World, target).Any(c => c == self.Location); } public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) { - var speed = MovementSpeedForCell(self, self.Location); + return VisualMove(self, fromPos, toPos, self.Location); + } + + public Activity VisualMove(Actor self, WPos fromPos, WPos toPos, CPos cell) + { + var speed = MovementSpeedForCell(self, cell); var length = speed > 0 ? (toPos - fromPos).Length / speed : 0; var facing = Util.GetFacing(toPos - fromPos, Facing);