diff --git a/OpenRA.Mods.RA/Activities/FindResources.cs b/OpenRA.Mods.RA/Activities/FindResources.cs index 74aa6b34b047..f48226ba57c5 100755 --- a/OpenRA.Mods.RA/Activities/FindResources.cs +++ b/OpenRA.Mods.RA/Activities/FindResources.cs @@ -53,7 +53,7 @@ public override Activity Tick(Actor self) // Find harvestable resources nearby: var path = self.World.WorldActor.Trait().FindPath( - PathSearch.Search(self.World, mobileInfo, self.Owner, true) + PathSearch.Search(self.World, mobileInfo, self, true) .WithCustomCost(loc => { // Avoid enemy territory: diff --git a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs index 5b2ce313a9f4..1c07b6d2ded2 100755 --- a/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs +++ b/OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs @@ -25,7 +25,7 @@ public override Activity Tick( Actor self ) var mobile = self.Trait(); - var ps1 = new PathSearch( self.World, mobile.Info, self.Owner ) + var ps1 = new PathSearch( self.World, mobile.Info, self ) { checkForBlocked = true, heuristic = location => 0, @@ -40,7 +40,7 @@ public override Activity Tick( Actor self ) ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell ); - var ps2 = PathSearch.FromPoint( self.World, mobile.Info, self.Owner, mobile.toCell, target.CenterLocation.ToCPos(), true ); + var ps2 = PathSearch.FromPoint( self.World, mobile.Info, self, mobile.toCell, target.CenterLocation.ToCPos(), true ); var ret = self.World.WorldActor.Trait().FindBidiPath( ps1, ps2 ); return Util.SequenceActivities( mobile.MoveTo( () => ret ), this ); diff --git a/OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs b/OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs index 614b518a9f1b..e9d04e8afeb4 100644 --- a/OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs +++ b/OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs @@ -66,7 +66,7 @@ IEnumerable GetSuitableCells(CPos near) for (var i = -1; i < 2; i++) for (var j = -1; j < 2; j++) - if (mi.CanEnterCell(self.World, self.Owner, near + new CVec(i, j), null, true, true)) + if (mi.CanEnterCell(self.World, self, near + new CVec(i, j), null, true, true)) yield return near + new CVec(i, j); } diff --git a/OpenRA.Mods.RA/Harvester.cs b/OpenRA.Mods.RA/Harvester.cs index 4199aa7a6624..06ee171ba263 100644 --- a/OpenRA.Mods.RA/Harvester.cs +++ b/OpenRA.Mods.RA/Harvester.cs @@ -112,7 +112,7 @@ Actor ClosestProc(Actor self, Actor ignore) // Start a search from each refinery's delivery location: var mi = self.Info.Traits.Get(); var path = self.World.WorldActor.Trait().FindPath( - PathSearch.FromPoints(self.World, mi, self.Owner, refs.Values.Select(r => r.Location), self.Location, false) + PathSearch.FromPoints(self.World, mi, self, refs.Values.Select(r => r.Location), self.Location, false) .WithCustomCost((loc) => { if (!refs.ContainsKey(loc)) return 0; @@ -349,7 +349,7 @@ public void ResolveOrder(Actor self, Order order) // Find any harvestable resources: var path = self.World.WorldActor.Trait().FindPath( - PathSearch.Search(self.World, mobileInfo, self.Owner, true) + PathSearch.Search(self.World, mobileInfo, self, true) .WithHeuristic(loc => { // Get the resource at this location: diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 797f359597d9..da7f4e0b5e31 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -77,7 +77,25 @@ public int MovementCostForCell(World world, CPos cell) {SubCell.FullCell, new PVecInt(0,0)}, }; - public bool CanEnterCell(World world, Player owner, CPos cell, Actor ignoreActor, bool checkTransientActors, bool blockedByMovers) + static bool IsMovingInMyDirection(Actor self, Actor other) + { + if (!other.IsMoving()) return false; + if (self == null) return true; + + var selfMobile = self.TraitOrDefault(); + if (selfMobile == null) return false; + + var otherMobile = other.TraitOrDefault(); + if (otherMobile == null) return false; + + // Sign of dot-product indicates (roughly) if vectors are facing in same or opposite directions: + var dp = CVec.Dot((selfMobile.toCell - self.Location), (otherMobile.toCell - other.Location)); + if (dp <= 0) return false; + + return true; + } + + public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor, bool checkTransientActors, bool blockedByMovers) { if (MovementCostForCell(world, cell) == int.MaxValue) return false; @@ -88,7 +106,7 @@ public bool CanEnterCell(World world, Player owner, CPos cell, Actor ignoreActor var blockingActors = world.ActorMap.GetUnitsAt(cell) .Where(x => x != ignoreActor) // Neutral/enemy units are blockers. Allied units that are moving are not blockers. - .Where(x => blockedByMovers || ((owner.Stances[x.Owner] != Stance.Ally) || !x.IsMoving())) + .Where(x => blockedByMovers || ((self.Owner.Stances[x.Owner] != Stance.Ally) || !IsMovingInMyDirection(self, x))) .ToList(); if (checkTransientActors && blockingActors.Count > 0) @@ -98,7 +116,7 @@ public bool CanEnterCell(World world, Player owner, CPos cell, Actor ignoreActor return false; if (blockingActors.Any(a => !(a.HasTrait() && - a.TraitsImplementing().Any(b => b.CrushableBy(Crushes, owner))))) + a.TraitsImplementing().Any(b => b.CrushableBy(Crushes, self.Owner))))) return false; } @@ -347,7 +365,7 @@ public bool CanEnterCell(CPos p) public bool CanEnterCell(CPos cell, Actor ignoreActor, bool checkTransientActors) { - return Info.CanEnterCell(self.World, self.Owner, cell, ignoreActor, checkTransientActors, true); + return Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors, true); } public void EnteringCell(Actor self) diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index fe9f8bb261cd..480659302059 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -32,7 +32,7 @@ public Move(CPos destination) { this.getPath = (self,mobile) => self.World.WorldActor.Trait().FindPath( - PathSearch.FromPoint( self.World, mobile.Info, self.Owner, mobile.toCell, destination, false ) + PathSearch.FromPoint( self.World, mobile.Info, self, mobile.toCell, destination, false ) .WithoutLaneBias()); this.destination = destination; this.nearEnough = 0; @@ -49,7 +49,7 @@ public Move(CPos destination, Actor ignoreBuilding) { this.getPath = (self,mobile) => self.World.WorldActor.Trait().FindPath( - PathSearch.FromPoint( self.World, mobile.Info, self.Owner, mobile.toCell, destination, false ) + PathSearch.FromPoint( self.World, mobile.Info, self, mobile.toCell, destination, false ) .WithIgnoredBuilding( ignoreBuilding )); this.destination = destination; diff --git a/OpenRA.Mods.RA/Move/PathFinder.cs b/OpenRA.Mods.RA/Move/PathFinder.cs index 0a3e465656ac..870546328304 100755 --- a/OpenRA.Mods.RA/Move/PathFinder.cs +++ b/OpenRA.Mods.RA/Move/PathFinder.cs @@ -55,8 +55,8 @@ public List FindUnitPath(CPos from, CPos target, Actor self) var mi = self.Info.Traits.Get(); var pb = FindBidiPath( - PathSearch.FromPoint(world, mi, self.Owner, target, from, true), - PathSearch.FromPoint(world, mi, self.Owner, from, target, true).InReverse() + PathSearch.FromPoint(world, mi, self, target, from, true), + PathSearch.FromPoint(world, mi, self, from, target, true).InReverse() ); CheckSanePath2(pb, from, target); @@ -73,11 +73,11 @@ public List FindUnitPathToRange(CPos src, CPos target, int range, Actor se { var mi = self.Info.Traits.Get(); var tilesInRange = world.FindTilesInCircle(target, range) - .Where(t => mi.CanEnterCell(self.World, self.Owner, t, null, true, true)); + .Where(t => mi.CanEnterCell(self.World, self, t, null, true, true)); var path = FindBidiPath( - PathSearch.FromPoints(world, mi, self.Owner, tilesInRange, src, true), - PathSearch.FromPoint(world, mi, self.Owner, src, target, true).InReverse() + PathSearch.FromPoints(world, mi, self, tilesInRange, src, true), + PathSearch.FromPoint(world, mi, self, src, target, true).InReverse() ); return path; diff --git a/OpenRA.Mods.RA/Move/PathSearch.cs b/OpenRA.Mods.RA/Move/PathSearch.cs index cc1226c69eb9..8261f807b788 100755 --- a/OpenRA.Mods.RA/Move/PathSearch.cs +++ b/OpenRA.Mods.RA/Move/PathSearch.cs @@ -28,14 +28,15 @@ public class PathSearch : IDisposable public bool inReverse; MobileInfo mobileInfo; - Player owner; + Actor self; + public Player owner { get { return self.Owner; } } - public PathSearch(World world, MobileInfo mobileInfo, Player owner) + public PathSearch(World world, MobileInfo mobileInfo, Actor self) { this.world = world; cellInfo = InitCellInfo(); this.mobileInfo = mobileInfo; - this.owner = owner; + this.self = self; customCost = null; queue = new PriorityQueue(); } @@ -120,7 +121,7 @@ public CPos Expand(World world) if (costHere == int.MaxValue) continue; - if (!mobileInfo.CanEnterCell(world, owner, newHere, ignoreBuilding, checkForBlocked, false)) + if (!mobileInfo.CanEnterCell(world, self, newHere, ignoreBuilding, checkForBlocked, false)) continue; if (customBlock != null && customBlock(newHere)) @@ -182,18 +183,18 @@ public void AddInitialCell(CPos location) queue.Add(new PathDistance(heuristic(location), location)); } - public static PathSearch Search(World world, MobileInfo mi, Player owner, bool checkForBlocked) + public static PathSearch Search(World world, MobileInfo mi, Actor self, bool checkForBlocked) { - var search = new PathSearch(world, mi, owner) + var search = new PathSearch(world, mi, self) { checkForBlocked = checkForBlocked }; return search; } - public static PathSearch FromPoint(World world, MobileInfo mi, Player owner, CPos from, CPos target, bool checkForBlocked) + public static PathSearch FromPoint(World world, MobileInfo mi, Actor self, CPos from, CPos target, bool checkForBlocked) { - var search = new PathSearch(world, mi, owner) + var search = new PathSearch(world, mi, self) { heuristic = DefaultEstimator(target), checkForBlocked = checkForBlocked @@ -203,9 +204,9 @@ public static PathSearch FromPoint(World world, MobileInfo mi, Player owner, CPo return search; } - public static PathSearch FromPoints(World world, MobileInfo mi, Player owner, IEnumerable froms, CPos target, bool checkForBlocked) + public static PathSearch FromPoints(World world, MobileInfo mi, Actor self, IEnumerable froms, CPos target, bool checkForBlocked) { - var search = new PathSearch(world, mi, owner) + var search = new PathSearch(world, mi, self) { heuristic = DefaultEstimator(target), checkForBlocked = checkForBlocked diff --git a/OpenRA.Mods.RA/Production.cs b/OpenRA.Mods.RA/Production.cs index 06a5a8ad914f..07ba7015a96b 100755 --- a/OpenRA.Mods.RA/Production.cs +++ b/OpenRA.Mods.RA/Production.cs @@ -129,7 +129,7 @@ static bool CanUseExit(Actor self, ActorInfo producee, ExitInfo s) var mobileInfo = producee.Traits.GetOrDefault(); return mobileInfo == null || - mobileInfo.CanEnterCell(self.World, self.Owner, self.Location + s.ExitCellVector, self, true, true); + mobileInfo.CanEnterCell(self.World, self, self.Location + s.ExitCellVector, self, true, true); } } }