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