diff --git a/OpenRa.Game/Game.cs b/OpenRa.Game/Game.cs index dbede28207..ff6d9244fb 100644 --- a/OpenRa.Game/Game.cs +++ b/OpenRa.Game/Game.cs @@ -160,10 +160,14 @@ namespace OpenRa.Game .Where(x => (x.CenterLocation - a).LengthSquared < r * r); } - public static IEnumerable FindTilesInCircle(int2 a, int r) + public static IEnumerable FindTilesInCircle( int2 a, int r ) { var min = a - new int2(r, r); var max = a + new int2(r, r); + if( min.X < 0 ) min.X = 0; + if( min.Y < 0 ) min.Y = 0; + if( max.X > 127 ) max.X = 127; + if( max.Y > 127 ) max.Y = 127; for (var j = min.Y; j <= max.Y; j++) for (var i = min.X; i <= max.X; i++) diff --git a/OpenRa.Game/Traits/Mobile.cs b/OpenRa.Game/Traits/Mobile.cs index 280b53717b..2746fb115f 100644 --- a/OpenRa.Game/Traits/Mobile.cs +++ b/OpenRa.Game/Traits/Mobile.cs @@ -144,7 +144,7 @@ namespace OpenRa.Game.Traits static bool CanEnterCell(int2 c, Actor self) { - var u = Game.UnitInfluence.GetUnitAt(c); + var u = Game.UnitInfluence.GetUnitAt(c); var b = Game.BuildingInfluence.GetBuildingAt(c); return (u == null || u == self) && b == null; } @@ -171,51 +171,65 @@ namespace OpenRa.Game.Traits return; } - destination = path[0]; - - var nextCell = PopPath( self, mobile ); - if( nextCell == null ) + destination = path[0]; + + var nextCell = PopPath( self, mobile ); + if( nextCell == null ) return; int2 dir = nextCell.Value - mobile.fromCell; - var firstFacing = Util.GetFacing( dir, mobile.facing ); - if( firstFacing != mobile.facing ) - { - mobile.currentActivity = new Turn( firstFacing ) { NextActivity = this }; - path.Add( nextCell.Value ); - } - else - { - mobile.toCell = nextCell.Value; - move = new MoveFirstHalf( - CenterOfCell( mobile.fromCell ), - BetweenCells( mobile.fromCell, mobile.toCell ), - mobile.facing, - mobile.facing, - 0 ); - - Game.UnitInfluence.Update( mobile ); + var firstFacing = Util.GetFacing( dir, mobile.facing ); + if( firstFacing != mobile.facing ) + { + mobile.currentActivity = new Turn( firstFacing ) { NextActivity = this }; + path.Add( nextCell.Value ); + } + else + { + mobile.toCell = nextCell.Value; + move = new MoveFirstHalf( + CenterOfCell( mobile.fromCell ), + BetweenCells( mobile.fromCell, mobile.toCell ), + mobile.facing, + mobile.facing, + 0 ); + + Game.UnitInfluence.Update( mobile ); } mobile.currentActivity.Tick( self, mobile ); - } - - int2? PopPath( Actor self, Mobile mobile ) - { - if( path.Count == 0 ) return null; - var nextCell = path[ path.Count - 1 ]; - if( !CanEnterCell( nextCell, self ) ) - { - Game.UnitInfluence.Remove( mobile ); - path = Game.PathFinder.FindPathToPath( self.Location, path, mobile.GetMovementType() ) - .TakeWhile( a => a != self.Location ) - .ToList(); - Game.UnitInfluence.Add( mobile ); - if( path.Count == 0 ) - return null; - nextCell = path[ path.Count - 1 ]; - } - path.RemoveAt( path.Count - 1 ); - return nextCell; + } + + int2? PopPath( Actor self, Mobile mobile ) + { + if( path.Count == 0 ) return null; + var nextCell = path[ path.Count - 1 ]; + if( !CanEnterCell( nextCell, self ) ) + { + if( ( mobile.toCell - destination.Value ).LengthSquared < 4 ) + { + path.Clear(); + return null; + } + + Game.UnitInfluence.Remove( mobile ); + var newPath = Game.PathFinder.FindPathToPath( self.Location, path, mobile.GetMovementType() ) + .TakeWhile( a => a != self.Location ) + .ToList(); + Game.UnitInfluence.Add( mobile ); + if( newPath.Count == 0 ) + return null; + + while( path[ path.Count - 1 ] != newPath[ 0 ] ) + path.RemoveAt( path.Count - 1 ); + for( int i = 1 ; i < newPath.Count ; i++ ) + path.Add( newPath[ i ] ); + + if( path.Count == 0 ) + return null; + nextCell = path[ path.Count - 1 ]; + } + path.RemoveAt( path.Count - 1 ); + return nextCell; } static float2 CenterOfCell( int2 loc ) @@ -282,24 +296,24 @@ namespace OpenRa.Game.Traits } protected override MovePart OnComplete( Actor self, Mobile mobile, MoveTo parent ) - { + { var nextCell = parent.PopPath( self, mobile ); if( nextCell != null ) - { - if( ( nextCell - mobile.toCell ) != ( mobile.toCell - mobile.fromCell ) ) - { - var ret = new MoveFirstHalf( - BetweenCells( mobile.fromCell, mobile.toCell ), - BetweenCells( mobile.toCell, nextCell.Value ), - mobile.facing, - Util.GetNearestFacing( mobile.facing, Util.GetFacing( nextCell.Value - mobile.toCell, mobile.facing ) ), - moveFraction - moveFractionTotal ); - mobile.fromCell = mobile.toCell; - mobile.toCell = nextCell.Value; - Game.UnitInfluence.Update( mobile ); - return ret; - } - else + { + if( ( nextCell - mobile.toCell ) != ( mobile.toCell - mobile.fromCell ) ) + { + var ret = new MoveFirstHalf( + BetweenCells( mobile.fromCell, mobile.toCell ), + BetweenCells( mobile.toCell, nextCell.Value ), + mobile.facing, + Util.GetNearestFacing( mobile.facing, Util.GetFacing( nextCell.Value - mobile.toCell, mobile.facing ) ), + moveFraction - moveFractionTotal ); + mobile.fromCell = mobile.toCell; + mobile.toCell = nextCell.Value; + Game.UnitInfluence.Update( mobile ); + return ret; + } + else parent.path.Add( nextCell.Value ); } var ret2 = new MoveSecondHalf( @@ -309,6 +323,7 @@ namespace OpenRa.Game.Traits mobile.facing, moveFraction - moveFractionTotal ); mobile.fromCell = mobile.toCell; + Game.UnitInfluence.Update( mobile ); return ret2; } } @@ -330,7 +345,7 @@ namespace OpenRa.Game.Traits public void Cancel( Actor self, Mobile mobile ) { - path.Clear(); + path = new List(); NextActivity = null; } }