diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 6e1d39b38c..a9d628a3bb 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -101,6 +101,7 @@ namespace OpenRA.Traits public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); } public interface INotifyHarvest { void Harvested(Actor self, ResourceType resource); } public interface INotifyInfiltrated { void Infiltrated(Actor self, Actor infiltrator); } + public interface IDisableMove { bool MoveDisabled(Actor self); } public interface IUpgradable { diff --git a/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs b/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs index f509ae8ed8..c6c491e430 100644 --- a/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs +++ b/OpenRA.Mods.Cnc/Activities/HarvesterDockSequence.cs @@ -47,10 +47,10 @@ namespace OpenRA.Mods.Cnc return this; case State.Turn: state = State.DragIn; - return Util.SequenceActivities(new Turn(112), this); + return Util.SequenceActivities(new Turn(self, 112), this); case State.DragIn: state = State.Dock; - return Util.SequenceActivities(new Drag(startDock, endDock, 12), this); + return Util.SequenceActivities(new Drag(self, startDock, endDock, 12), this); case State.Dock: ru.PlayCustomAnimation(self, "dock", () => { ru.PlayCustomAnimRepeating(self, "dock-loop"); @@ -73,7 +73,7 @@ namespace OpenRA.Mods.Cnc state = State.Wait; return this; case State.DragOut: - return Util.SequenceActivities(new Drag(endDock, startDock, 12), NextActivity); + return Util.SequenceActivities(new Drag(self, endDock, startDock, 12), NextActivity); } throw new InvalidOperationException("Invalid harvester dock state"); diff --git a/OpenRA.Mods.RA/Activities/Attack.cs b/OpenRA.Mods.RA/Activities/Attack.cs index ef7bfb7e84..1034122638 100755 --- a/OpenRA.Mods.RA/Activities/Attack.cs +++ b/OpenRA.Mods.RA/Activities/Attack.cs @@ -64,7 +64,7 @@ namespace OpenRA.Mods.RA.Activities var desiredFacing = Util.GetFacing(Target.CenterPosition - self.CenterPosition, 0); if (facing.Facing != desiredFacing) - return Util.SequenceActivities(new Turn(desiredFacing), this); + return Util.SequenceActivities(new Turn(self, desiredFacing), this); attack.DoAttack(self, Target); diff --git a/OpenRA.Mods.RA/Activities/FindResources.cs b/OpenRA.Mods.RA/Activities/FindResources.cs index 41be46c913..1b119efb52 100755 --- a/OpenRA.Mods.RA/Activities/FindResources.cs +++ b/OpenRA.Mods.RA/Activities/FindResources.cs @@ -153,7 +153,7 @@ namespace OpenRA.Mods.RA.Activities var facing = self.Trait().Facing; var desired = Util.QuantizeFacing(facing, harvInfo.HarvestFacings) * (256 / harvInfo.HarvestFacings); if (desired != facing) - return Util.SequenceActivities(new Turn(desired), this); + return Util.SequenceActivities(new Turn(self, desired), this); } var resLayer = self.World.WorldActor.Trait(); diff --git a/OpenRA.Mods.RA/Activities/RAHarvesterDockSequence.cs b/OpenRA.Mods.RA/Activities/RAHarvesterDockSequence.cs index bad965a5e8..9655735332 100644 --- a/OpenRA.Mods.RA/Activities/RAHarvesterDockSequence.cs +++ b/OpenRA.Mods.RA/Activities/RAHarvesterDockSequence.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA return this; case State.Turn: state = State.Dock; - return Util.SequenceActivities(new Turn(angle), this); + return Util.SequenceActivities(new Turn(self, angle), this); case State.Dock: ru.PlayCustomAnimation(self, "dock", () => { ru.PlayCustomAnimRepeating(self, "dock-loop"); diff --git a/OpenRA.Mods.RA/Activities/Turn.cs b/OpenRA.Mods.RA/Activities/Turn.cs index e48d687f76..ea428fc1f8 100755 --- a/OpenRA.Mods.RA/Activities/Turn.cs +++ b/OpenRA.Mods.RA/Activities/Turn.cs @@ -8,22 +8,30 @@ */ #endregion +using System.Collections.Generic; +using System.Linq; using OpenRA.Traits; namespace OpenRA.Mods.RA.Activities { public class Turn : Activity { - int desiredFacing; + readonly IEnumerable moveDisablers; + readonly int desiredFacing; - public Turn( int desiredFacing ) + public Turn(Actor self, int desiredFacing) { + moveDisablers = self.TraitsImplementing(); this.desiredFacing = desiredFacing; } public override Activity Tick( Actor self ) { - if (IsCanceled) return NextActivity; + if (IsCanceled) + return NextActivity; + if (moveDisablers.Any(d => d.MoveDisabled(self))) + return this; + var facing = self.Trait(); if( desiredFacing == facing.Facing ) diff --git a/OpenRA.Mods.RA/Air/HeliReturn.cs b/OpenRA.Mods.RA/Air/HeliReturn.cs index 8a066c463b..5fa2924f02 100755 --- a/OpenRA.Mods.RA/Air/HeliReturn.cs +++ b/OpenRA.Mods.RA/Air/HeliReturn.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA.Air .ClosestTo(self); if (nearestHpad == null) - return Util.SequenceActivities(new Turn(initialFacing), new HeliLand(true), NextActivity); + return Util.SequenceActivities(new Turn(self, initialFacing), new HeliLand(true), NextActivity); else return Util.SequenceActivities(new HeliFly(self, Target.FromActor(nearestHpad))); } @@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA.Air return Util.SequenceActivities( new HeliFly(self, Target.FromPos(dest.CenterPosition + offset)), - new Turn(initialFacing), + new Turn(self, initialFacing), new HeliLand(false), new ResupplyAircraft()); } diff --git a/OpenRA.Mods.RA/Air/Helicopter.cs b/OpenRA.Mods.RA/Air/Helicopter.cs index 29feee3849..bc2dc46471 100644 --- a/OpenRA.Mods.RA/Air/Helicopter.cs +++ b/OpenRA.Mods.RA/Air/Helicopter.cs @@ -71,7 +71,7 @@ namespace OpenRA.Mods.RA.Air if (Info.LandWhenIdle) { if (Info.TurnToLand) - self.QueueActivity(new Turn(Info.InitialFacing)); + self.QueueActivity(new Turn(self, Info.InitialFacing)); self.QueueActivity(new HeliLand(true)); } @@ -97,7 +97,7 @@ namespace OpenRA.Mods.RA.Air self.CancelActivity(); self.QueueActivity(new HeliFly(self, Target.FromPos(order.TargetActor.CenterPosition + offset))); - self.QueueActivity(new Turn(Info.InitialFacing)); + self.QueueActivity(new Turn(self, Info.InitialFacing)); self.QueueActivity(new HeliLand(false)); self.QueueActivity(new ResupplyAircraft()); self.QueueActivity(new TakeOff()); @@ -117,7 +117,7 @@ namespace OpenRA.Mods.RA.Air if (Info.LandWhenIdle) { if (Info.TurnToLand) - self.QueueActivity(new Turn(Info.InitialFacing)); + self.QueueActivity(new Turn(self, Info.InitialFacing)); self.QueueActivity(new HeliLand(true)); } @@ -157,7 +157,7 @@ namespace OpenRA.Mods.RA.Air 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)); + return Util.SequenceActivities(new HeliFly(self, target), new Turn(self, Info.InitialFacing)); } public Activity VisualMove(Actor self, WPos fromPos, WPos toPos) diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index 4e43874f7e..aa57435a4d 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA var finalPos = init.world.Map.CenterOfCell(TopLeft); var distance = (finalPos - CenterPosition).Length; if (speed > 0 && distance > 0) - self.QueueActivity(new Drag(CenterPosition, finalPos, distance / speed)); + self.QueueActivity(new Drag(init.self, CenterPosition, finalPos, distance / speed)); } public IEnumerable> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); } diff --git a/OpenRA.Mods.RA/Move/Drag.cs b/OpenRA.Mods.RA/Move/Drag.cs index d3c6d50d2d..8d1bab4472 100755 --- a/OpenRA.Mods.RA/Move/Drag.cs +++ b/OpenRA.Mods.RA/Move/Drag.cs @@ -9,18 +9,25 @@ #endregion using System.Collections.Generic; +using System.Linq; using OpenRA.Traits; namespace OpenRA.Mods.RA.Move { public class Drag : Activity { + readonly IPositionable positionable; + readonly IMove movement; + readonly IEnumerable moveDisablers; WPos start, end; int length; int ticks = 0; - public Drag(WPos start, WPos end, int length) + public Drag(Actor self, WPos start, WPos end, int length) { + positionable = self.Trait(); + movement = self.TraitOrDefault(); + moveDisablers = self.TraitsImplementing(); this.start = start; this.end = end; this.length = length; @@ -28,8 +35,8 @@ namespace OpenRA.Mods.RA.Move public override Activity Tick(Actor self) { - var positionable = self.Trait(); - var movement = self.TraitOrDefault(); + if (moveDisablers.Any(d => d.MoveDisabled(self))) + return this; var pos = length > 1 ? WPos.Lerp(start, end, ticks, length - 1) diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 0b8f13f339..f4ae825988 100644 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -695,7 +695,7 @@ namespace OpenRA.Mods.RA.Move var length = speed > 0 ? (toPos - fromPos).Length / speed : 0; var facing = Util.GetFacing(toPos - fromPos, Facing); - return Util.SequenceActivities(new Turn(facing), new Drag(fromPos, toPos, length)); + return Util.SequenceActivities(new Turn(self, facing), new Drag(self, fromPos, toPos, length)); } } } diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 6df61ce348..1d792d800a 100644 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -151,7 +151,7 @@ namespace OpenRA.Mods.RA.Move if (firstFacing != mobile.Facing) { path.Add(nextCell.Value.First); - return Util.SequenceActivities(new Turn(firstFacing), this); + return Util.SequenceActivities(new Turn(self, firstFacing), this); } else { diff --git a/OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs index 6dc646a029..1f2994118e 100644 --- a/OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/ReinforcementsGlobal.cs @@ -177,7 +177,7 @@ namespace OpenRA.Mods.RA.Scripting var heli = transport.TraitOrDefault(); if (heli != null) { - transport.QueueActivity(new Turn(heli.Info.InitialFacing)); + transport.QueueActivity(new Turn(transport, heli.Info.InitialFacing)); transport.QueueActivity(new HeliLand(true)); transport.QueueActivity(new Wait(15)); } diff --git a/OpenRA.Mods.RA/Transforms.cs b/OpenRA.Mods.RA/Transforms.cs index aca9bd65f7..f28ddbd023 100644 --- a/OpenRA.Mods.RA/Transforms.cs +++ b/OpenRA.Mods.RA/Transforms.cs @@ -87,7 +87,7 @@ namespace OpenRA.Mods.RA self.CancelActivity(); if (self.HasTrait()) - self.QueueActivity(new Turn(info.Facing)); + self.QueueActivity(new Turn(self, info.Facing)); foreach (var nt in self.TraitsImplementing()) nt.BeforeTransform(self); diff --git a/OpenRA.Mods.TS/Activities/VoxelHarvesterDockSequence.cs b/OpenRA.Mods.TS/Activities/VoxelHarvesterDockSequence.cs index 142756c4d5..4c3a6a24d6 100644 --- a/OpenRA.Mods.TS/Activities/VoxelHarvesterDockSequence.cs +++ b/OpenRA.Mods.TS/Activities/VoxelHarvesterDockSequence.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.TS { case State.Turn: state = State.Dock; - return Util.SequenceActivities(new Turn(160), this); + return Util.SequenceActivities(new Turn(self, 160), this); case State.Dock: if (proc.IsInWorld && !proc.IsDead()) foreach (var nd in proc.TraitsImplementing())