diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 3a894ecdb8..4cd3042b9a 100755 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -1,4 +1,4 @@ - + Debug @@ -240,6 +240,7 @@ + @@ -275,4 +276,7 @@ --> + + + \ No newline at end of file diff --git a/OpenRA.Game/PathSearch.cs b/OpenRA.Game/PathSearch.cs index 7efe42def8..4eead3e6ba 100755 --- a/OpenRA.Game/PathSearch.cs +++ b/OpenRA.Game/PathSearch.cs @@ -116,7 +116,7 @@ namespace OpenRA continue; var mobile = self.traits.Get(); - if (checkForBlocked && !mobile.CanEnterCell(newHere)) + if (checkForBlocked && !mobile.CanEnterCell(newHere, ignoreBuilding)) continue; if (customBlock != null && customBlock(newHere)) diff --git a/OpenRA.Game/Traits/Activities/Move.cs b/OpenRA.Game/Traits/Activities/Move.cs index dccdbdb656..e3ec8bd41d 100755 --- a/OpenRA.Game/Traits/Activities/Move.cs +++ b/OpenRA.Game/Traits/Activities/Move.cs @@ -168,7 +168,7 @@ namespace OpenRA.Traits.Activities { if( path.Count == 0 ) return null; var nextCell = path[ path.Count - 1 ]; - if( !mobile.CanEnterCell( nextCell ) ) + if( !mobile.CanEnterCell( nextCell, ignoreBuilding ) ) { if( ( mobile.toCell - destination.Value ).LengthSquared <= nearEnough ) { @@ -244,7 +244,6 @@ namespace OpenRA.Traits.Activities var frac = (float)moveFraction / moveFractionTotal; self.CenterLocation = float2.Lerp( from, to, frac ); - // + self.traits.WithInterface().Aggregate(float2.Zero, (a, x) => a + x.CenterOffset); if( moveFraction >= moveFractionTotal ) unit.Facing = toFacing & 0xFF; diff --git a/OpenRA.Game/Traits/Mobile.cs b/OpenRA.Game/Traits/Mobile.cs index 54c75357a7..84d32f361d 100644 --- a/OpenRA.Game/Traits/Mobile.cs +++ b/OpenRA.Game/Traits/Mobile.cs @@ -121,12 +121,28 @@ namespace OpenRA.Traits public bool CanEnterCell(int2 p) { - if (!self.World.WorldActor.traits.Get().CanMoveHere(p)) return false; + return CanEnterCell(p, null); + } + + public bool CanEnterCell(int2 p, Actor ignoreBuilding) + { + if (!self.World.WorldActor.traits.Get().CanMoveHere(p, ignoreBuilding)) return false; - if (self.World.WorldActor.traits.Get().GetUnitsAt(p).Any( - a => a != self && !self.World.IsActorCrushableByActor(a, self))) + var canShare = self.traits.Contains(); + var actors = self.World.WorldActor.traits.Get().GetUnitsAt(p); + var nonshareable = actors.Where(a => a != self && !(canShare && a.traits.Contains())); + var shareable = actors.Where(a => a != self && canShare && a.traits.Contains()); + + // only allow 5 in a cell + if (shareable.Count() >= 5) return false; + // We can enter a cell with nonshareable units if we can crush all of them + if (nonshareable.Any( + a => !self.World.IsActorCrushableByActor(a, self))) + return false; + + return self.World.Map.IsInMap(p.X, p.Y) && Rules.TerrainTypes[self.World.TileSet.GetTerrainType(self.World.Map.MapTiles[p.X, p.Y])] .GetCost(GetMovementType()) < float.PositiveInfinity; diff --git a/OpenRA.Game/Traits/SharesCell.cs b/OpenRA.Game/Traits/SharesCell.cs new file mode 100644 index 0000000000..7cee42b254 --- /dev/null +++ b/OpenRA.Game/Traits/SharesCell.cs @@ -0,0 +1,46 @@ +#region Copyright & License Information +/* + * Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford. + * This file is part of OpenRA. + * + * OpenRA is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * OpenRA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenRA. If not, see . + */ +#endregion + +namespace OpenRA.Traits +{ + class SharesCellInfo : TraitInfo {} + public class SharesCell : IOffsetCenterLocation + { + [Sync] + public int Position; + + public float2 CenterOffset + { get { + switch (Position) + { + case 1: + return new float2(-5f,-5f); + case 2: + return new float2(5f,-5f); + case 3: + return new float2(-5f,5f); + case 4: + return new float2(5f,5f); + default: + return new float2(-5f, -5f); + } + }} + } +} diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 5eb35fb76a..21a03e1c4a 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -103,6 +103,7 @@ namespace OpenRA.Traits IEnumerable GetCurrentPath(Actor self); } + public interface IOffsetCenterLocation { float2 CenterOffset { get; } } public interface ICrushable { void OnCrush(Actor crusher); diff --git a/mods/cnc/defaults.yaml b/mods/cnc/defaults.yaml index 0b167e693d..59bea365da 100644 --- a/mods/cnc/defaults.yaml +++ b/mods/cnc/defaults.yaml @@ -31,6 +31,7 @@ RevealsShroud: GainsExperience: GivesExperience: + SharesCell: ^Ship: Category: Ship