From b10a5d27a0c192459a0d642fd7930bb7b1275950 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Wed, 10 Jul 2013 20:34:19 +1200 Subject: [PATCH] Tidy up Move. --- OpenRA.Mods.RA/Move/Move.cs | 180 ++++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 82 deletions(-) diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 24850d36d9..010b18e107 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -21,11 +21,16 @@ namespace OpenRA.Mods.RA.Move class Move : Activity { CPos? destination; - int nearEnough; + WRange nearEnough; public List path; Func> getPath; public Actor ignoreBuilding; + // For dealing with blockers + bool hasWaited; + bool hasNotifiedBlocker; + int waitTicksRemaining; + // Scriptable move order // Ignores lane bias and nearby units public Move(CPos destination) @@ -35,10 +40,14 @@ namespace OpenRA.Mods.RA.Move PathSearch.FromPoint( self.World, mobile.Info, self, mobile.toCell, destination, false ) .WithoutLaneBias()); this.destination = destination; - this.nearEnough = 0; + this.nearEnough = WRange.Zero; } + // Hack for legacy code public Move(CPos destination, int nearEnough) + : this(destination, WRange.FromCells(nearEnough)) {} + + public Move(CPos destination, WRange nearEnough) { this.getPath = (self,mobile) => self.World.WorldActor.Trait().FindUnitPath( mobile.toCell, destination, self ); this.destination = destination; @@ -54,7 +63,7 @@ namespace OpenRA.Mods.RA.Move ); this.destination = destination; - this.nearEnough = 0; + this.nearEnough = WRange.Zero; this.ignoreBuilding = ignoreBuilding; } @@ -72,14 +81,14 @@ namespace OpenRA.Mods.RA.Move }; this.destination = null; - this.nearEnough = range.Range / 1024; + this.nearEnough = range; } public Move(Func> getPath) { this.getPath = (_1,_2) => getPath(); this.destination = null; - this.nearEnough = 0; + this.nearEnough = WRange.Zero; } static int HashList(List xs) @@ -96,12 +105,10 @@ namespace OpenRA.Mods.RA.Move { var path = getPath(self, mobile).TakeWhile(a => a != mobile.toCell).ToList(); mobile.PathHash = HashList(path); - Log.Write("debug", "EvalPathHash #{0} {1}", - self.ActorID, mobile.PathHash); return path; } - public override Activity Tick( Actor self ) + public override Activity Tick(Actor self) { var mobile = self.Trait(); var info = self.Info.Traits.Get(); @@ -110,13 +117,14 @@ namespace OpenRA.Mods.RA.Move { if (mobile.Altitude < info.Altitude) ++mobile.Altitude; + return this; } if (destination == mobile.toCell) return NextActivity; - if( path == null ) + if (path == null) { if (mobile.ticksBeforePathing > 0) { @@ -128,54 +136,51 @@ namespace OpenRA.Mods.RA.Move SanityCheckPath( mobile ); } - if( path.Count == 0 ) + if (path.Count == 0) { destination = mobile.toCell; return this; } - destination = path[ 0 ]; + destination = path[0]; - var nextCell = PopPath( self, mobile ); - if( nextCell == null ) + var nextCell = PopPath(self, mobile); + if (nextCell == null) return this; var dir = nextCell.Value.First - mobile.fromCell; - var firstFacing = Util.GetFacing( dir, mobile.Facing ); - if( firstFacing != mobile.Facing ) + var firstFacing = Util.GetFacing(dir, mobile.Facing); + if (firstFacing != mobile.Facing) { path.Add( nextCell.Value.First ); - return Util.SequenceActivities( new Turn( firstFacing ), this ); + return Util.SequenceActivities(new Turn(firstFacing), this); } else { - mobile.SetLocation( mobile.fromCell, mobile.fromSubCell, nextCell.Value.First, nextCell.Value.Second ); + mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, nextCell.Value.First, nextCell.Value.Second); var move = new MoveFirstHalf( this, - Util.CenterOfCell( mobile.fromCell ) + MobileInfo.SubCellOffsets[mobile.fromSubCell], - Util.BetweenCells( mobile.fromCell, mobile.toCell ) + (MobileInfo.SubCellOffsets[mobile.fromSubCell] + MobileInfo.SubCellOffsets[mobile.toSubCell] ) / 2, + Util.CenterOfCell(mobile.fromCell) + MobileInfo.SubCellOffsets[mobile.fromSubCell], + Util.BetweenCells(mobile.fromCell, mobile.toCell) + (MobileInfo.SubCellOffsets[mobile.fromSubCell] + MobileInfo.SubCellOffsets[mobile.toSubCell]) / 2, mobile.Facing, mobile.Facing, - 0 ); + 0 + ); return move; } } - [Conditional( "SANITY_CHECKS")] - void SanityCheckPath( Mobile mobile ) + [Conditional("SANITY_CHECKS")] + void SanityCheckPath(Mobile mobile) { - if( path.Count == 0 ) + if (path.Count == 0) return; - var d = path[path.Count-1] - mobile.toCell; - if( d.LengthSquared > 2 ) - throw new InvalidOperationException( "(Move) Sanity check failed" ); + var d = path[path.Count - 1] - mobile.toCell; + if (d.LengthSquared > 2) + throw new InvalidOperationException("(Move) Sanity check failed"); } - bool hasWaited; - bool hasNotifiedBlocker; - int waitTicksRemaining; - void NotifyBlocker(Actor self, CPos nextCell) { foreach (var blocker in self.World.ActorMap.GetUnitsAt(nextCell)) @@ -192,22 +197,30 @@ namespace OpenRA.Mods.RA.Move Pair? PopPath(Actor self, Mobile mobile) { - if( path.Count == 0 ) return null; - var nextCell = path[ path.Count - 1 ]; - if( !mobile.CanEnterCell( nextCell, ignoreBuilding, true ) ) + if (path.Count == 0) + return null; + + var nextCell = path[path.Count - 1]; + + // Next cell in the move is blocked by another actor + if (!mobile.CanEnterCell(nextCell, ignoreBuilding, true)) { - if( ( mobile.toCell - destination.Value ).LengthSquared <= nearEnough ) + // Are we close enough? + var cellRange = nearEnough.Range / 1024; + if ((mobile.toCell - destination.Value).LengthSquared <= cellRange*cellRange) { path.Clear(); return null; } + // See if they will move if (!hasNotifiedBlocker) { NotifyBlocker(self, nextCell); hasNotifiedBlocker = true; } + // Wait a bit to see if they leave if (!hasWaited) { var info = self.Info.Traits.Get(); @@ -224,6 +237,7 @@ namespace OpenRA.Mods.RA.Move return null; } + // Calculate a new path mobile.RemoveInfluence(); var newPath = EvalPath(self, mobile); mobile.AddInfluence(); @@ -233,9 +247,10 @@ namespace OpenRA.Mods.RA.Move return null; } + hasNotifiedBlocker = false; hasWaited = false; - path.RemoveAt( path.Count - 1 ); + path.RemoveAt(path.Count - 1); var subCell = mobile.GetDesiredSubcell(nextCell, ignoreBuilding); return Pair.New(nextCell, subCell); @@ -247,11 +262,11 @@ namespace OpenRA.Mods.RA.Move base.Cancel(self); } - public override IEnumerable GetTargets( Actor self ) + public override IEnumerable GetTargets(Actor self) { - if( path != null ) - return Enumerable.Reverse(path).Select( c => Target.FromCell(c) ); - if( destination != null ) + if (path != null) + return Enumerable.Reverse(path).Select(c => Target.FromCell(c)); + if (destination != null) return new Target[] { Target.FromCell(destination.Value) }; return Target.NoTargets; } @@ -272,59 +287,59 @@ namespace OpenRA.Mods.RA.Move this.fromFacing = fromFacing; this.toFacing = toFacing; this.moveFraction = startingFraction; - this.moveFractionTotal = ( ( to - from ) * 3 ).Length; + this.moveFractionTotal = 3*(to - from).Length; } - public override void Cancel( Actor self ) + public override void Cancel(Actor self) { - move.Cancel( self ); - base.Cancel( self ); + move.Cancel(self); + base.Cancel(self); } - public override void Queue( Activity activity ) + public override void Queue(Activity activity) { - move.Queue( activity ); + move.Queue(activity); } - public override Activity Tick( Actor self ) + public override Activity Tick(Actor self) { var mobile = self.Trait(); - var ret = InnerTick( self, mobile ); - mobile.IsMoving = ( ret is MovePart ); + var ret = InnerTick(self, mobile); + mobile.IsMoving = (ret is MovePart); - if( moveFraction > moveFractionTotal ) + if (moveFraction > moveFractionTotal) moveFraction = moveFractionTotal; - UpdateCenterLocation( self, mobile ); + UpdateCenterLocation(self, mobile); return ret; } - Activity InnerTick( Actor self, Mobile mobile ) + Activity InnerTick(Actor self, Mobile mobile) { moveFraction += mobile.MovementSpeedForCell(self, mobile.toCell); - if( moveFraction <= moveFractionTotal ) + if (moveFraction <= moveFractionTotal) return this; - var next = OnComplete( self, mobile, move ); - if( next != null ) + var next = OnComplete(self, mobile, move); + if (next != null) return next; return move; } - void UpdateCenterLocation( Actor self, Mobile mobile ) + void UpdateCenterLocation(Actor self, Mobile mobile) { mobile.PxPosition = PPos.Lerp(from, to, moveFraction, moveFractionTotal); - if( moveFraction >= moveFractionTotal ) + if (moveFraction >= moveFractionTotal) mobile.Facing = toFacing & 0xFF; else - mobile.Facing = int2.Lerp( fromFacing, toFacing, moveFraction, moveFractionTotal ) & 0xFF; + mobile.Facing = int2.Lerp(fromFacing, toFacing, moveFraction, moveFractionTotal) & 0xFF; } - protected abstract MovePart OnComplete( Actor self, Mobile mobile, Move parent ); + protected abstract MovePart OnComplete(Actor self, Mobile mobile, Move parent); - public override IEnumerable GetTargets( Actor self ) + public override IEnumerable GetTargets(Actor self) { return move.GetTargets(self); } @@ -333,50 +348,52 @@ namespace OpenRA.Mods.RA.Move class MoveFirstHalf : MovePart { public MoveFirstHalf(Move move, PPos from, PPos to, int fromFacing, int toFacing, int startingFraction) - : base( move, from, to, fromFacing, toFacing, startingFraction ) { } + : base(move, from, to, fromFacing, toFacing, startingFraction) { } - static bool IsTurn( Mobile mobile, CPos nextCell ) + static bool IsTurn(Mobile mobile, CPos nextCell) { return nextCell - mobile.toCell != mobile.toCell - mobile.fromCell; } - protected override MovePart OnComplete( Actor self, Mobile mobile, Move parent ) + protected override MovePart OnComplete(Actor self, Mobile mobile, Move parent) { var fromSubcellOffset = MobileInfo.SubCellOffsets[mobile.fromSubCell]; var toSubcellOffset = MobileInfo.SubCellOffsets[mobile.toSubCell]; - var nextCell = parent.PopPath( self, mobile ); - if( nextCell != null ) + var nextCell = parent.PopPath(self, mobile); + if (nextCell != null) { - if(IsTurn(mobile, nextCell.Value.First)) + if (IsTurn(mobile, nextCell.Value.First)) { var nextSubcellOffset = MobileInfo.SubCellOffsets[nextCell.Value.Second]; var ret = new MoveFirstHalf( move, - Util.BetweenCells( mobile.fromCell, mobile.toCell ) + (fromSubcellOffset + toSubcellOffset) / 2, - Util.BetweenCells( mobile.toCell, nextCell.Value.First ) + (toSubcellOffset + nextSubcellOffset) / 2, + Util.BetweenCells(mobile.fromCell, mobile.toCell) + (fromSubcellOffset + toSubcellOffset) / 2, + Util.BetweenCells(mobile.toCell, nextCell.Value.First) + (toSubcellOffset + nextSubcellOffset) / 2, mobile.Facing, - Util.GetNearestFacing( mobile.Facing, Util.GetFacing( nextCell.Value.First - mobile.toCell, mobile.Facing ) ), - moveFraction - moveFractionTotal ); + Util.GetNearestFacing(mobile.Facing, Util.GetFacing(nextCell.Value.First - mobile.toCell, mobile.Facing)), + moveFraction - moveFractionTotal + ); - mobile.SetLocation( mobile.toCell, mobile.toSubCell, nextCell.Value.First, nextCell.Value.Second); + mobile.SetLocation(mobile.toCell, mobile.toSubCell, nextCell.Value.First, nextCell.Value.Second); return ret; } - parent.path.Add( nextCell.Value.First ); + parent.path.Add(nextCell.Value.First); } var ret2 = new MoveSecondHalf( move, - Util.BetweenCells( mobile.fromCell, mobile.toCell ) + (fromSubcellOffset + toSubcellOffset) / 2, - Util.CenterOfCell( mobile.toCell ) + toSubcellOffset, + Util.BetweenCells(mobile.fromCell, mobile.toCell) + (fromSubcellOffset + toSubcellOffset) / 2, + Util.CenterOfCell(mobile.toCell) + toSubcellOffset, mobile.Facing, mobile.Facing, - moveFraction - moveFractionTotal ); + moveFraction - moveFractionTotal + ); mobile.EnteringCell(self); - mobile.SetLocation( mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell ); + mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); return ret2; } } @@ -384,14 +401,12 @@ namespace OpenRA.Mods.RA.Move class MoveSecondHalf : MovePart { public MoveSecondHalf(Move move, PPos from, PPos to, int fromFacing, int toFacing, int startingFraction) - : base( move, from, to, fromFacing, toFacing, startingFraction ) - { - } + : base(move, from, to, fromFacing, toFacing, startingFraction) {} - protected override MovePart OnComplete( Actor self, Mobile mobile, Move parent ) + protected override MovePart OnComplete(Actor self, Mobile mobile, Move parent) { - mobile.PxPosition = Util.CenterOfCell( mobile.toCell ); - mobile.SetLocation( mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell ); + mobile.PxPosition = Util.CenterOfCell(mobile.toCell); + mobile.SetLocation(mobile.toCell, mobile.toSubCell, mobile.toCell, mobile.toSubCell); mobile.FinishedMoving(self); return null; } @@ -402,7 +417,8 @@ namespace OpenRA.Mods.RA.Move { public static bool IsMoving(this Actor self) { - if (self.IsIdle) return false; + if (self.IsIdle) + return false; Activity a = self.GetCurrentActivity(); Debug.Assert(a != null);