diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 31102be6b4..3003c7fc8b 100755 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -1,4 +1,4 @@ - + Debug @@ -204,7 +204,6 @@ - diff --git a/OpenRA.Game/Traits/SharesCell.cs b/OpenRA.Game/Traits/SharesCell.cs deleted file mode 100755 index dc59764ced..0000000000 --- a/OpenRA.Game/Traits/SharesCell.cs +++ /dev/null @@ -1,64 +0,0 @@ -using OpenRA.FileFormats; -#region Copyright & License Information -/* - * Copyright 2007-2010 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see LICENSE. - */ -#endregion - -namespace OpenRA.Traits -{ - class SharesCellInfo : ITraitInfo - { - public object Create(ActorInitializer init) { return new SharesCell(init); } - } - - public class SharesCell : IOffsetCenterLocation, ISync - { - [Sync] - public int Position; - - public SharesCell(ActorInitializer init) - { - Position = init.Contains() ? init.Get() : 0; - } - - 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); - } - }} - } - - public class SubcellInit : IActorInit - { - [FieldFromYamlKey] - public readonly int value = 0; - - public SubcellInit() { } - - public SubcellInit( int init ) - { - value = init; - } - - public int Value( World world ) - { - return value; - } - } -} diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 73b9de1e94..5975f12cf6 100755 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -148,7 +148,6 @@ namespace OpenRA.Traits int InitialFacing { get; } } - public interface IOffsetCenterLocation { float2 CenterOffset { get; } } public interface ICrushable { void OnCrush(Actor crusher); diff --git a/OpenRA.Game/Traits/World/UnitInfluence.cs b/OpenRA.Game/Traits/World/UnitInfluence.cs index 9d7c776b69..04645bdc2a 100644 --- a/OpenRA.Game/Traits/World/UnitInfluence.cs +++ b/OpenRA.Game/Traits/World/UnitInfluence.cs @@ -49,6 +49,15 @@ namespace OpenRA.Traits for( var i = influence[ a.X, a.Y ] ; i != null ; i = i.next ) yield return i.actor; } + + public bool HasFreeSubCell(int2 a) + { + if (!AnyUnitsAt(a)) + return true; + + return new[]{SubCell.BottomLeft, SubCell.BottomRight, SubCell.Center, + SubCell.TopLeft, SubCell.TopRight}.Any(b => !AnyUnitsAt(a,b)); + } public bool AnyUnitsAt(int2 a) { @@ -60,7 +69,7 @@ namespace OpenRA.Traits var node = influence[ a.X, a.Y ]; while (node != null) { - if (node.subCell == sub) return true; + if (node.subCell == sub || node.subCell == SubCell.FullCell) return true; node = node.next; } return false; diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 4b8fd4df4e..e7cc75110a 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -40,6 +40,8 @@ namespace OpenRA.Mods.RA.Move public readonly int Speed = 1; [FieldLoader.Load] public readonly bool OnRails = false; + [FieldLoader.Load] + public readonly bool SharesCell = true; public virtual object Create(ActorInitializer init) { return new Mobile(init, this); } @@ -73,16 +75,29 @@ namespace OpenRA.Mods.RA.Move return TerrainSpeeds[type].Cost; } - + + public readonly Dictionary SubCellOffsets = new Dictionary() + { + {SubCell.TopLeft, new int2(-6,-6)}, + {SubCell.TopRight, new int2(6,6)}, + {SubCell.Center, new int2(0,0)}, + {SubCell.BottomLeft, new int2(-6,6)}, + {SubCell.BottomRight, new int2(6,6)}, + {SubCell.FullCell, new int2(0,0)}, + }; + public bool CanEnterCell(World world, UnitInfluence uim, int2 cell, Actor ignoreActor, bool checkTransientActors) { if (MovementCostForCell(world, cell) == int.MaxValue) return false; - + + if (SharesCell && uim.HasFreeSubCell(cell)) + return true; + var blockingActors = uim.GetUnitsAt(cell).Where(x => x != ignoreActor).ToList(); if (checkTransientActors && blockingActors.Count > 0) { - // We can enter a cell with nonshareable units only if we can crush all of them + // Non-sharable unit can enter a cell with shareable units only if it can crush all of them if (Crushes == null) return false; @@ -109,6 +124,8 @@ namespace OpenRA.Mods.RA.Move int __facing; int2 __fromCell, __toCell; + SubCell __fromSubCell, __toSubCell; + int __altitude; [Sync] @@ -159,11 +176,16 @@ namespace OpenRA.Mods.RA.Move this.Info = info; uim = self.World.WorldActor.Trait(); - + __toSubCell = __fromSubCell = info.SharesCell ? SubCell.Center : SubCell.FullCell; + if (init.Contains()) + { + this.__fromSubCell = this.__toSubCell = init.Get(); + } + if (init.Contains()) { this.__fromCell = this.__toCell = init.Get(); - this.PxPosition = Util.CenterOfCell(fromCell); + this.PxPosition = Util.CenterOfCell(fromCell) + info.SubCellOffsets[__fromSubCell]; } this.Facing = init.Contains() ? init.Get() : info.InitialFacing; @@ -173,7 +195,7 @@ namespace OpenRA.Mods.RA.Move public void SetPosition(Actor self, int2 cell) { SetLocation(cell, cell); - PxPosition = Util.CenterOfCell(fromCell); + PxPosition = Util.CenterOfCell(fromCell) + Info.SubCellOffsets[__fromSubCell]; FinishedMoving(self); } @@ -412,3 +434,24 @@ namespace OpenRA.Mods.RA.Move public IActivity MoveTo(Func> pathFunc) { return new Move(pathFunc); } } } + +namespace OpenRA.Traits +{ + public class SubCellInit : IActorInit + { + [FieldFromYamlKey] + public readonly int value = 0; + + public SubCellInit() { } + + public SubCellInit( int init ) + { + value = init; + } + + public SubCell Value( World world ) + { + return (SubCell)value; + } + } +} \ No newline at end of file