diff --git a/OpenRA.Game/Traits/Mobile.cs b/OpenRA.Game/Traits/Mobile.cs index 9a38d4121b..40076f2a3b 100644 --- a/OpenRA.Game/Traits/Mobile.cs +++ b/OpenRA.Game/Traits/Mobile.cs @@ -88,7 +88,6 @@ namespace OpenRA.Traits Shroud shroud; UnitInfluence uim; - BuildingInfluence bim; bool canShareCell; public Mobile(ActorInitializer init, MobileInfo info) @@ -98,7 +97,6 @@ namespace OpenRA.Traits shroud = self.World.WorldActor.Trait(); uim = self.World.WorldActor.Trait(); - bim = self.World.WorldActor.Trait(); canShareCell = self.HasTrait(); if (init.Contains()) @@ -208,50 +206,47 @@ namespace OpenRA.Traits public bool CanEnterCell(int2 p) { - return CanEnterCell(p, null, true); + return CanEnterCell( p, null, true); } - public virtual bool CanEnterCell(int2 cell, Actor ignoreActor, bool checkTransientActors) + public virtual bool CanEnterCell( int2 cell, Actor ignoreActor, bool checkTransientActors ) { - if (MovementCostForCell(self, cell) == float.PositiveInfinity) + return CanEnterCell( Info, self.World, cell, ignoreActor, checkTransientActors ); + } + + public static bool CanEnterCell( MobileInfo mobileInfo, World world, int2 cell, Actor ignoreActor, bool checkTransientActors ) + { + if (MovementCostForCell(mobileInfo, world, cell) == float.PositiveInfinity) return false; + var bim = world.WorldActor.Trait(); + var uim = world.WorldActor.Trait(); + // Check for buildings var building = bim.GetBuildingBlocking(cell); if (building != null && building != ignoreActor) { - if (Info.Crushes == null) + if (mobileInfo.Crushes == null) return false; var crushable = building.TraitsImplementing(); if (crushable.Count() == 0) return false; - if (!crushable.Any(b => b.CrushClasses.Intersect(Info.Crushes).Any())) + if (!crushable.Any(b => b.CrushClasses.Intersect(mobileInfo.Crushes).Any())) return false; } // Check mobile actors if (checkTransientActors && uim.AnyUnitsAt(cell)) { - var actors = uim.GetUnitsAt(cell).Where(a => a != self && a != ignoreActor).ToArray(); - var nonshareable = canShareCell ? actors : actors.Where(a => !a.HasTrait()).ToArray(); - - if (canShareCell) - { - var shareable = actors.Where(a => a.HasTrait()); - - // only allow 5 in a cell - if (shareable.Count() >= 5) - return false; - } - + var actors = uim.GetUnitsAt(cell).Where(a => a != ignoreActor).ToArray(); // We can enter a cell with nonshareable units only if we can crush all of them - if (Info.Crushes == null && nonshareable.Length > 0) + if (mobileInfo.Crushes == null && actors.Length > 0) return false; - if (nonshareable.Length > 0 && nonshareable.Any(a => !(a.HasTrait() && - a.TraitsImplementing().Any(b => b.CrushClasses.Intersect(Info.Crushes).Any())))) + if (actors.Length > 0 && actors.Any(a => !(a.HasTrait() && + a.TraitsImplementing().Any(b => b.CrushClasses.Intersect(mobileInfo.Crushes).Any())))) return false; } @@ -269,17 +264,22 @@ namespace OpenRA.Traits b.OnCrush(self); } } - - public virtual float MovementCostForCell(Actor self, int2 cell) + + public float MovementCostForCell( Actor self, int2 cell ) { - if (!self.World.Map.IsInMap(cell.X,cell.Y)) + return MovementCostForCell( Info, self.World, cell ); + } + + public static float MovementCostForCell(MobileInfo info, World world, int2 cell) + { + if (!world.Map.IsInMap(cell.X,cell.Y)) return float.PositiveInfinity; - var type = self.World.GetTerrainType(cell); - if (!Info.TerrainSpeeds.ContainsKey(type)) + var type = world.GetTerrainType(cell); + if (!info.TerrainSpeeds.ContainsKey(type)) return float.PositiveInfinity; - return Info.TerrainSpeeds[type].Cost; + return info.TerrainSpeeds[type].Cost; } public virtual float MovementSpeedForCell(Actor self, int2 cell) diff --git a/OpenRA.Game/Traits/Production.cs b/OpenRA.Game/Traits/Production.cs index 00577f47d0..23de0090dd 100755 --- a/OpenRA.Game/Traits/Production.cs +++ b/OpenRA.Game/Traits/Production.cs @@ -37,8 +37,13 @@ namespace OpenRA.Traits Info = info; } - public void DoProduction(Actor self, Actor newUnit, ExitInfo exitinfo) + public void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo) { + var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary + { + new OwnerInit( self.Owner ), + }); + var exit = self.Location + exitinfo.ExitCell; var spawn = self.CenterLocation + exitinfo.SpawnOffset; @@ -86,21 +91,17 @@ namespace OpenRA.Traits public virtual bool Produce( Actor self, ActorInfo producee ) { - var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary - { - new OwnerInit( self.Owner ), - }); - // Todo: remove assumption on Mobile; // required for 3-arg CanEnterCell - var mobile = newUnit.Trait(); + //var mobile = newUnit.Trait(); + var mobileInfo = producee.Traits.Get(); // Pick a spawn/exit point pair // Todo: Reorder in a synced random way foreach (var s in self.Info.Traits.WithInterface()) - if (mobile.CanEnterCell(self.Location + s.ExitCell,self,true)) + if( Mobile.CanEnterCell( mobileInfo, self.World, self.Location + s.ExitCell,self,true ) ) { - DoProduction(self, newUnit, s); + DoProduction(self, producee, s); return true; } return false; diff --git a/OpenRA.Mods.Cnc/ProductionAirdrop.cs b/OpenRA.Mods.Cnc/ProductionAirdrop.cs index 1378dd24f2..f5478502a2 100644 --- a/OpenRA.Mods.Cnc/ProductionAirdrop.cs +++ b/OpenRA.Mods.Cnc/ProductionAirdrop.cs @@ -52,11 +52,6 @@ namespace OpenRA.Mods.Cnc }); var cargo = a.Trait(); - var newUnit = self.World.CreateActor(false, producee.Name, new TypeDictionary - { - new OwnerInit( self.Owner ), - }); - cargo.Load(a, newUnit); a.QueueActivity(new Fly(self.Location + new int2(6,0))); a.QueueActivity(new Land(Target.FromActor(self))); a.QueueActivity(new CallFunc(() => @@ -64,7 +59,7 @@ namespace OpenRA.Mods.Cnc if (self.IsDead()) return; rb.PlayCustomAnimRepeating(self, "idle"); - self.World.AddFrameEndTask(ww => DoProduction(self, cargo.Unload(self), exit)); + self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit)); })); a.QueueActivity(new Fly(endPos)); a.QueueActivity(new RemoveSelf());