From 43478dd500566ae96c43347e806be27c5ab6b4ba Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Tue, 29 Jul 2014 08:33:46 -0500 Subject: [PATCH 1/5] enum SubCell => int & Dictionary => WVec[] --- OpenRA.Game/Map/ActorInitializer.cs | 5 ++-- OpenRA.Game/Traits/TraitsInterfaces.cs | 2 +- OpenRA.Game/Traits/World/ActorMap.cs | 18 ++++++------- OpenRA.Mods.RA/Activities/UnloadCargo.cs | 2 +- OpenRA.Mods.RA/Air/Aircraft.cs | 4 +-- OpenRA.Mods.RA/Buildings/Building.cs | 6 ++--- OpenRA.Mods.RA/Crate.cs | 2 +- OpenRA.Mods.RA/Husk.cs | 2 +- OpenRA.Mods.RA/Immobile.cs | 8 +++--- OpenRA.Mods.RA/Move/Mobile.cs | 32 ++++++++++++------------ OpenRA.Mods.RA/Move/Move.cs | 2 +- OpenRA.Mods.RA/Move/PathFinder.cs | 2 +- OpenRA.Mods.RA/SpawnMPUnits.cs | 2 +- 13 files changed, 41 insertions(+), 46 deletions(-) diff --git a/OpenRA.Game/Map/ActorInitializer.cs b/OpenRA.Game/Map/ActorInitializer.cs index 1ce7eeb80f..f1811ec833 100755 --- a/OpenRA.Game/Map/ActorInitializer.cs +++ b/OpenRA.Game/Map/ActorInitializer.cs @@ -63,13 +63,12 @@ namespace OpenRA public CPos Value(World world) { return value; } } - public class SubCellInit : IActorInit + public class SubCellInit : IActorInit { [FieldFromYamlKey] public readonly int value = 0; public SubCellInit() { } public SubCellInit(int init) { value = init; } - public SubCellInit(SubCell init) { value = (int)init; } - public SubCell Value(World world) { return (SubCell)value; } + public int Value(World world) { return value; } } public class CenterPositionInit : IActorInit diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 0f4193a349..d4fbdf7b56 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -126,7 +126,7 @@ namespace OpenRA.Traits { WPos CenterPosition { get; } CPos TopLeft { get; } - IEnumerable> OccupiedCells(); + IEnumerable> OccupiedCells(); } public static class IOccupySpaceExts diff --git a/OpenRA.Game/Traits/World/ActorMap.cs b/OpenRA.Game/Traits/World/ActorMap.cs index b31f331077..e9f73b95ce 100644 --- a/OpenRA.Game/Traits/World/ActorMap.cs +++ b/OpenRA.Game/Traits/World/ActorMap.cs @@ -29,15 +29,11 @@ namespace OpenRA.Traits class InfluenceNode { public InfluenceNode Next; - public SubCell SubCell; + public int SubCell; public Actor Actor; } - static readonly SubCell[] SubCells = - { - SubCell.TopLeft, SubCell.TopRight, SubCell.Center, - SubCell.BottomLeft, SubCell.BottomRight - }; + static readonly int[] SubCells = { 1, 2, 3, 4, 5 }; readonly ActorMapInfo info; readonly Map map; @@ -79,13 +75,13 @@ namespace OpenRA.Traits yield return i.Actor; } - public IEnumerable GetUnitsAt(CPos a, SubCell sub) + public IEnumerable GetUnitsAt(CPos a, int sub) { if (!map.Contains(a)) yield break; for (var i = influence[a]; i != null; i = i.Next) - if (!i.Actor.Destroyed && (i.SubCell == sub || i.SubCell == SubCell.FullCell)) + if (!i.Actor.Destroyed && (i.SubCell == sub || i.SubCell == 0)) yield return i.Actor; } @@ -97,7 +93,7 @@ namespace OpenRA.Traits return SubCells.Any(b => !AnyUnitsAt(a, b)); } - public SubCell? FreeSubCell(CPos a) + public int? FreeSubCell(CPos a) { if (!HasFreeSubCell(a)) return null; @@ -110,10 +106,10 @@ namespace OpenRA.Traits return influence[a] != null; } - public bool AnyUnitsAt(CPos a, SubCell sub) + public bool AnyUnitsAt(CPos a, int sub) { for (var i = influence[a]; i != null; i = i.Next) - if (i.SubCell == sub || i.SubCell == SubCell.FullCell) + if (i.SubCell == sub || i.SubCell == 0) return true; return false; diff --git a/OpenRA.Mods.RA/Activities/UnloadCargo.cs b/OpenRA.Mods.RA/Activities/UnloadCargo.cs index d331c8c75e..7a28a47b2d 100644 --- a/OpenRA.Mods.RA/Activities/UnloadCargo.cs +++ b/OpenRA.Mods.RA/Activities/UnloadCargo.cs @@ -63,7 +63,7 @@ namespace OpenRA.Mods.RA.Activities var exitCell = ChooseExitCell(actor); if (exitCell == null) { - foreach (var blocker in BlockedExitCells(actor).SelectMany(self.World.ActorMap.GetUnitsAt)) + foreach (var blocker in BlockedExitCells(actor).SelectMany(p => self.World.ActorMap.GetUnitsAt(p))) { foreach (var nbm in blocker.TraitsImplementing()) nbm.OnNotifyBlockingMove(blocker, self); diff --git a/OpenRA.Mods.RA/Air/Aircraft.cs b/OpenRA.Mods.RA/Air/Aircraft.cs index ac8273845a..55964bdfee 100644 --- a/OpenRA.Mods.RA/Air/Aircraft.cs +++ b/OpenRA.Mods.RA/Air/Aircraft.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA.Air public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld { - static readonly Pair[] NoCells = { }; + static readonly Pair[] NoCells = { }; readonly AircraftInfo info; readonly Actor self; @@ -210,7 +210,7 @@ namespace OpenRA.Mods.RA.Air } } - public IEnumerable> OccupiedCells() { return NoCells; } + public IEnumerable> OccupiedCells() { return NoCells; } public WVec FlyStep(int facing) { diff --git a/OpenRA.Mods.RA/Buildings/Building.cs b/OpenRA.Mods.RA/Buildings/Building.cs index 209f6df6b7..2106094c75 100644 --- a/OpenRA.Mods.RA/Buildings/Building.cs +++ b/OpenRA.Mods.RA/Buildings/Building.cs @@ -133,14 +133,14 @@ namespace OpenRA.Mods.RA.Buildings this.Info = info; occupiedCells = FootprintUtils.UnpathableTiles( self.Info.Name, Info, TopLeft ) - .Select(c => Pair.New(c, SubCell.FullCell)).ToArray(); + .Select(c => Pair.New(c, 0)).ToArray(); CenterPosition = init.world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(init.world, Info); SkipMakeAnimation = init.Contains(); } - Pair[] occupiedCells; - public IEnumerable> OccupiedCells() { return occupiedCells; } + Pair[] occupiedCells; + public IEnumerable> OccupiedCells() { return occupiedCells; } public void Created(Actor self) { diff --git a/OpenRA.Mods.RA/Crate.cs b/OpenRA.Mods.RA/Crate.cs index f7df5848c6..30d57614f8 100644 --- a/OpenRA.Mods.RA/Crate.cs +++ b/OpenRA.Mods.RA/Crate.cs @@ -89,7 +89,7 @@ namespace OpenRA.Mods.RA } public CPos TopLeft { get { return Location; } } - public IEnumerable> OccupiedCells() { yield return Pair.New(Location, SubCell.FullCell); } + public IEnumerable> OccupiedCells() { yield return Pair.New(Location, 0); } public WPos CenterPosition { get; private set; } public void SetPosition(Actor self, WPos pos) { SetPosition(self, self.World.Map.CellContaining(pos)); } diff --git a/OpenRA.Mods.RA/Husk.cs b/OpenRA.Mods.RA/Husk.cs index aabf691e5a..42cc49e1af 100644 --- a/OpenRA.Mods.RA/Husk.cs +++ b/OpenRA.Mods.RA/Husk.cs @@ -52,7 +52,7 @@ namespace OpenRA.Mods.RA self.QueueActivity(new Drag(CenterPosition, finalPos, distance / speed)); } - public IEnumerable> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); } + public IEnumerable> OccupiedCells() { yield return Pair.New(TopLeft, 0); } public bool CanEnterCell(CPos cell, Actor ignoreActor, bool checkTransientActors) { if (!self.World.Map.Contains(cell)) diff --git a/OpenRA.Mods.RA/Immobile.cs b/OpenRA.Mods.RA/Immobile.cs index 63570e95a8..2042d31c44 100644 --- a/OpenRA.Mods.RA/Immobile.cs +++ b/OpenRA.Mods.RA/Immobile.cs @@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA { [Sync] readonly CPos location; [Sync] readonly WPos position; - readonly IEnumerable> occupied; + readonly IEnumerable> occupied; public Immobile(ActorInitializer init, ImmobileInfo info) { @@ -32,14 +32,14 @@ namespace OpenRA.Mods.RA position = init.world.Map.CenterOfCell(location); if (info.OccupiesSpace) - occupied = new [] { Pair.New(TopLeft, SubCell.FullCell) }; + occupied = new [] { Pair.New(TopLeft, 0) }; else - occupied = new Pair[0]; + occupied = new Pair[0]; } public CPos TopLeft { get { return location; } } public WPos CenterPosition { get { return position; } } - public IEnumerable> OccupiedCells() { return occupied; } + public IEnumerable> OccupiedCells() { return occupied; } public void AddedToWorld(Actor self) { diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 9050e7fe6f..fc334bc06c 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -133,14 +133,14 @@ namespace OpenRA.Mods.RA.Move return TilesetMovementClass[tileset]; } - public static readonly Dictionary SubCellOffsets = new Dictionary() + public static readonly WVec[] SubCellOffsets = { - {SubCell.TopLeft, new WVec(-299, -256, 0)}, - {SubCell.TopRight, new WVec(256, -256, 0)}, - {SubCell.Center, new WVec(0, 0, 0)}, - {SubCell.BottomLeft, new WVec(-299, 256, 0)}, - {SubCell.BottomRight, new WVec(256, 256, 0)}, - {SubCell.FullCell, new WVec(0, 0, 0)}, + new WVec(0, 0, 0), + new WVec(-299, -256, 0), + new WVec(256, -256, 0), + new WVec(0, 0, 0), + new WVec(-299, 256, 0), + new WVec(256, 256, 0), }; static bool IsMovingInMyDirection(Actor self, Actor other) @@ -208,7 +208,7 @@ namespace OpenRA.Mods.RA.Move int __facing; CPos __fromCell, __toCell; - public SubCell fromSubCell, toSubCell; + public int fromSubCell, toSubCell; //int __altitude; @@ -226,7 +226,7 @@ namespace OpenRA.Mods.RA.Move [Sync] public int PathHash; // written by Move.EvalPath, to temporarily debug this crap. - public void SetLocation(CPos from, SubCell fromSub, CPos to, SubCell toSub) + public void SetLocation(CPos from, int fromSub, CPos to, int toSub) { if (fromCell == from && toCell == to && fromSubCell == fromSub && toSubCell == toSub) return; @@ -248,10 +248,11 @@ namespace OpenRA.Mods.RA.Move this.self = init.self; this.Info = info; - toSubCell = fromSubCell = info.SharesCell ? SubCell.Center : SubCell.FullCell; + // TODO replace 3 w/ SubCellDefaultIndex + toSubCell = fromSubCell = info.SharesCell ? 3 : 0; if (init.Contains()) { - this.fromSubCell = this.toSubCell = init.Get(); + this.fromSubCell = this.toSubCell = init.Get(); } if (init.Contains()) @@ -414,7 +415,7 @@ namespace OpenRA.Mods.RA.Move public CPos TopLeft { get { return toCell; } } - public IEnumerable> OccupiedCells() + public IEnumerable> OccupiedCells() { if (fromCell == toCell) yield return Pair.New(fromCell, fromSubCell); @@ -427,14 +428,13 @@ namespace OpenRA.Mods.RA.Move } } - public SubCell GetDesiredSubcell(CPos a, Actor ignoreActor) + public int GetDesiredSubcell(CPos a, Actor ignoreActor) { if (!Info.SharesCell) - return SubCell.FullCell; + return 0; // Prioritise the current subcell - return new[]{ fromSubCell, SubCell.TopLeft, SubCell.TopRight, SubCell.Center, - SubCell.BottomLeft, SubCell.BottomRight}.First(b => + return new[]{ fromSubCell, 1, 2, 3, 4, 5}.First(b => { var blockingActors = self.World.ActorMap.GetUnitsAt(a, b).Where(c => c != ignoreActor); if (blockingActors.Any()) diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 265fdb3076..5dc077a58d 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -180,7 +180,7 @@ namespace OpenRA.Mods.RA.Move } } - Pair? PopPath(Actor self, Mobile mobile) + Pair? PopPath(Actor self, Mobile mobile) { if (path.Count == 0) return null; diff --git a/OpenRA.Mods.RA/Move/PathFinder.cs b/OpenRA.Mods.RA/Move/PathFinder.cs index abaeb49b74..ead53ad4f0 100644 --- a/OpenRA.Mods.RA/Move/PathFinder.cs +++ b/OpenRA.Mods.RA/Move/PathFinder.cs @@ -80,7 +80,7 @@ namespace OpenRA.Mods.RA.Move } } - public List FindUnitPathToRange(CPos src, SubCell srcSub, WPos target, WRange range, Actor self) + public List FindUnitPathToRange(CPos src, int srcSub, WPos target, WRange range, Actor self) { using (new PerfSample("Pathfinder")) { diff --git a/OpenRA.Mods.RA/SpawnMPUnits.cs b/OpenRA.Mods.RA/SpawnMPUnits.cs index f97f43a318..a0df13ee48 100644 --- a/OpenRA.Mods.RA/SpawnMPUnits.cs +++ b/OpenRA.Mods.RA/SpawnMPUnits.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.RA throw new InvalidOperationException("No cells available to spawn starting unit {0}".F(s)); var cell = validCells.Random(w.SharedRandom); - var subCell = mi.SharesCell ? w.ActorMap.FreeSubCell(cell).Value : SubCell.FullCell; + var subCell = mi.SharesCell ? w.ActorMap.FreeSubCell(cell).Value : 0; w.CreateActor(s.ToLowerInvariant(), new TypeDictionary { From 4b7537bb1339d5fc6e8a0c7ee28c6160ab2f7536 Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Tue, 29 Jul 2014 09:01:37 -0500 Subject: [PATCH 2/5] Moved MobileInfo.SubCellOffsets to Map (dropping static) & added Map.SubCellsDefaultIndex --- OpenRA.Game/Map/Map.cs | 11 +++++++++++ OpenRA.Mods.RA/Activities/Leap.cs | 2 +- OpenRA.Mods.RA/Move/Mobile.cs | 17 +++-------------- OpenRA.Mods.RA/Move/Move.cs | 10 +++++----- OpenRA.Mods.RA/Move/PathFinder.cs | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 9ad6248792..39cba9d30f 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -77,6 +77,17 @@ namespace OpenRA public Bitmap CustomPreview; public readonly TileShape TileShape; + [FieldLoader.Ignore] + public readonly WVec[] SubCellOffsets = + { + new WVec(0, 0, 0), + new WVec(-299, -256, 0), + new WVec(256, -256, 0), + new WVec(0, 0, 0), + new WVec(-299, 256, 0), + new WVec(256, 256, 0), + }; + public readonly int SubCellsDefaultIndex = 3; [FieldLoader.LoadUsing("LoadOptions")] public MapOptions Options; diff --git a/OpenRA.Mods.RA/Activities/Leap.cs b/OpenRA.Mods.RA/Activities/Leap.cs index 465d7247c5..b226ad19de 100644 --- a/OpenRA.Mods.RA/Activities/Leap.cs +++ b/OpenRA.Mods.RA/Activities/Leap.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Activities mobile.IsMoving = true; from = self.CenterPosition; - to = self.World.Map.CenterOfCell(targetMobile.fromCell) + MobileInfo.SubCellOffsets[targetMobile.fromSubCell]; + to = self.World.Map.CenterOfCell(targetMobile.fromCell) + self.World.Map.SubCellOffsets[targetMobile.fromSubCell]; length = Math.Max((to - from).Length / speed.Range, 1); self.Trait().Attacking(self, Target.FromActor(target)); diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index fc334bc06c..9c1992ca12 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -133,16 +133,6 @@ namespace OpenRA.Mods.RA.Move return TilesetMovementClass[tileset]; } - public static readonly WVec[] SubCellOffsets = - { - new WVec(0, 0, 0), - new WVec(-299, -256, 0), - new WVec(256, -256, 0), - new WVec(0, 0, 0), - new WVec(-299, 256, 0), - new WVec(256, 256, 0), - }; - static bool IsMovingInMyDirection(Actor self, Actor other) { if (!other.IsMoving()) return false; @@ -248,8 +238,7 @@ namespace OpenRA.Mods.RA.Move this.self = init.self; this.Info = info; - // TODO replace 3 w/ SubCellDefaultIndex - toSubCell = fromSubCell = info.SharesCell ? 3 : 0; + toSubCell = fromSubCell = info.SharesCell ? init.world.Map.SubCellsDefaultIndex : 0; if (init.Contains()) { this.fromSubCell = this.toSubCell = init.Get(); @@ -258,7 +247,7 @@ namespace OpenRA.Mods.RA.Move if (init.Contains()) { this.__fromCell = this.__toCell = init.Get(); - SetVisualPosition(self, init.world.Map.CenterOfCell(fromCell) + MobileInfo.SubCellOffsets[fromSubCell]); + SetVisualPosition(self, init.world.Map.CenterOfCell(fromCell) + self.World.Map.SubCellOffsets[fromSubCell]); } this.Facing = init.Contains() ? init.Get() : info.InitialFacing; @@ -272,7 +261,7 @@ namespace OpenRA.Mods.RA.Move public void SetPosition(Actor self, CPos cell) { SetLocation(cell, fromSubCell, cell, fromSubCell); - SetVisualPosition(self, self.World.Map.CenterOfCell(fromCell) + MobileInfo.SubCellOffsets[fromSubCell]); + SetVisualPosition(self, self.World.Map.CenterOfCell(fromCell) + self.World.Map.SubCellOffsets[fromSubCell]); FinishedMoving(self); } diff --git a/OpenRA.Mods.RA/Move/Move.cs b/OpenRA.Mods.RA/Move/Move.cs index 5dc077a58d..d58e100f88 100755 --- a/OpenRA.Mods.RA/Move/Move.cs +++ b/OpenRA.Mods.RA/Move/Move.cs @@ -150,8 +150,8 @@ namespace OpenRA.Mods.RA.Move mobile.SetLocation(mobile.fromCell, mobile.fromSubCell, nextCell.Value.First, nextCell.Value.Second); var move = new MoveFirstHalf( this, - self.World.Map.CenterOfCell(mobile.fromCell) + MobileInfo.SubCellOffsets[mobile.fromSubCell], - Util.BetweenCells(self.World, mobile.fromCell, mobile.toCell) + (MobileInfo.SubCellOffsets[mobile.fromSubCell] + MobileInfo.SubCellOffsets[mobile.toSubCell]) / 2, + self.World.Map.CenterOfCell(mobile.fromCell) + self.World.Map.SubCellOffsets[mobile.fromSubCell], + Util.BetweenCells(self.World, mobile.fromCell, mobile.toCell) + (self.World.Map.SubCellOffsets[mobile.fromSubCell] + self.World.Map.SubCellOffsets[mobile.toSubCell]) / 2, mobile.Facing, mobile.Facing, 0); @@ -347,15 +347,15 @@ namespace OpenRA.Mods.RA.Move protected override MovePart OnComplete(Actor self, Mobile mobile, Move parent) { - var fromSubcellOffset = MobileInfo.SubCellOffsets[mobile.fromSubCell]; - var toSubcellOffset = MobileInfo.SubCellOffsets[mobile.toSubCell]; + var fromSubcellOffset = self.World.Map.SubCellOffsets[mobile.fromSubCell]; + var toSubcellOffset = self.World.Map.SubCellOffsets[mobile.toSubCell]; var nextCell = parent.PopPath(self, mobile); if (nextCell != null) { if (IsTurn(mobile, nextCell.Value.First)) { - var nextSubcellOffset = MobileInfo.SubCellOffsets[nextCell.Value.Second]; + var nextSubcellOffset = self.World.Map.SubCellOffsets[nextCell.Value.Second]; var ret = new MoveFirstHalf( move, Util.BetweenCells(self.World, mobile.fromCell, mobile.toCell) + (fromSubcellOffset + toSubcellOffset) / 2, diff --git a/OpenRA.Mods.RA/Move/PathFinder.cs b/OpenRA.Mods.RA/Move/PathFinder.cs index ead53ad4f0..43e165d121 100644 --- a/OpenRA.Mods.RA/Move/PathFinder.cs +++ b/OpenRA.Mods.RA/Move/PathFinder.cs @@ -89,7 +89,7 @@ namespace OpenRA.Mods.RA.Move var rangeSquared = range.Range*range.Range; // Correct for SubCell offset - target -= MobileInfo.SubCellOffsets[srcSub]; + target -= self.World.Map.SubCellOffsets[srcSub]; // Select only the tiles that are within range from the requested SubCell // This assumes that the SubCell does not change during the path traversal From 9b30c21f936362fe076834f613ec97ec00ced3ba Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Thu, 31 Jul 2014 18:20:52 -0500 Subject: [PATCH 3/5] Load subcells and default subcell index from mod.yaml --- OpenRA.Game/Manifest.cs | 43 ++++++++++++++++++++++++++++ OpenRA.Game/Map/Map.cs | 14 +++------ OpenRA.Game/Traits/World/ActorMap.cs | 18 ++++++------ OpenRA.Mods.RA/Move/Mobile.cs | 39 +++++++++++++++---------- OpenRA.Mods.RA/SpawnMPUnits.cs | 2 +- mods/cnc/mod.yaml | 4 +++ mods/d2k/mod.yaml | 4 +++ mods/ra/mod.yaml | 4 +++ mods/ts/mod.yaml | 3 ++ 9 files changed, 95 insertions(+), 36 deletions(-) diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index 1d2ad01433..a1ae7d4612 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -37,6 +37,20 @@ namespace OpenRA public readonly Size TileSize = new Size(24, 24); public readonly TileShape TileShape = TileShape.Rectangle; + [Desc("(x,y,z) offset of the full cell and each sub-cell", "x & y: -512 ... 512, Z >= 0")] + public readonly WVec[] SubCellOffsets = + { + new WVec(0, 0, 0), // full cell - index 0 + new WVec(-299, -256, 0), // top left - index 1 + new WVec(256, -256, 0), // top right - index 2 + new WVec(0, 0, 0), // center - index 3 + new WVec(-299, 256, 0), // bottom left - index 4 + new WVec(256, 256, 0), // bottom right - index 5 + }; + + [Desc("Default subcell index used if SubCellInit is absent", "0 - full cell, 1 - first sub-cell")] + public readonly int SubCellDefaultIndex = 3; + public Manifest(string mod) { var path = new[] { "mods", mod, "mod.yaml" }.Aggregate(Path.Combine); @@ -87,6 +101,35 @@ namespace OpenRA if (yaml.ContainsKey("TileShape")) TileShape = FieldLoader.GetValue("TileShape", yaml["TileShape"].Value); + // Read subcell information + // sub-cell index 0 is the full cell + if (yaml.ContainsKey("SubCells")) + { + var subcells = yaml["SubCells"].ToDictionary(); + + // Read (x,y,z) offset (relative to cell center) pairs for positioning subcells + if (subcells.ContainsKey("Offsets")) + { + SubCellOffsets = FieldLoader.GetValue("Offsets", subcells["Offsets"].Value); + + foreach (var i in SubCellOffsets) + if (i.X < -512 || i.X > 512 || i.Y < -512 || i.Y > 512 || i.Z < 0) + throw new InvalidDataException("Subcell offsets must be in bounds (X & Y: -512 ... 512, Z > 0)"); + } + + // Read default subcell index used when creating actors that share cells without SubCellInit + if (subcells.ContainsKey("DefaultIndex")) + SubCellDefaultIndex = FieldLoader.GetValue("DefaultIndex", subcells ["DefaultIndex"].Value); + + // Otherwise set the default subcell index to the middle subcell entry + else + SubCellDefaultIndex = SubCellOffsets.Length / 2; // default is the middle subcell entry + } + + // validate default index - 0 for no subcells, otherwise > 1 & <= subcell count (offset triples count - 1) + if (SubCellDefaultIndex < (SubCellOffsets.Length > 1 ? 1 : 0) || SubCellDefaultIndex >= SubCellOffsets.Length) + throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells"); + // Allow inherited mods to import parent maps. var compat = new List(); compat.Add(mod); diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 39cba9d30f..2731ba7b4c 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -78,16 +78,8 @@ namespace OpenRA public readonly TileShape TileShape; [FieldLoader.Ignore] - public readonly WVec[] SubCellOffsets = - { - new WVec(0, 0, 0), - new WVec(-299, -256, 0), - new WVec(256, -256, 0), - new WVec(0, 0, 0), - new WVec(-299, 256, 0), - new WVec(256, 256, 0), - }; - public readonly int SubCellsDefaultIndex = 3; + public readonly WVec[] SubCellOffsets; + public readonly int SubCellDefaultIndex; [FieldLoader.LoadUsing("LoadOptions")] public MapOptions Options; @@ -257,6 +249,8 @@ namespace OpenRA MapTiles = Exts.Lazy(() => LoadMapTiles()); MapResources = Exts.Lazy(() => LoadResourceTiles()); TileShape = Game.modData.Manifest.TileShape; + SubCellOffsets = Game.modData.Manifest.SubCellOffsets; + SubCellDefaultIndex = Game.modData.Manifest.SubCellDefaultIndex; // The Uid is calculated from the data on-disk, so // format changes must be flushed to disk. diff --git a/OpenRA.Game/Traits/World/ActorMap.cs b/OpenRA.Game/Traits/World/ActorMap.cs index e9f73b95ce..3c028af924 100644 --- a/OpenRA.Game/Traits/World/ActorMap.cs +++ b/OpenRA.Game/Traits/World/ActorMap.cs @@ -33,8 +33,6 @@ namespace OpenRA.Traits public Actor Actor; } - static readonly int[] SubCells = { 1, 2, 3, 4, 5 }; - readonly ActorMapInfo info; readonly Map map; readonly CellLayer influence; @@ -87,18 +85,18 @@ namespace OpenRA.Traits public bool HasFreeSubCell(CPos a) { - if (!AnyUnitsAt(a)) - return true; - - return SubCells.Any(b => !AnyUnitsAt(a, b)); + return FreeSubCell(a) >= 0; } - public int? FreeSubCell(CPos a) + public int FreeSubCell(CPos a) { - if (!HasFreeSubCell(a)) - return null; + if (!AnyUnitsAt(a)) + return map.SubCellDefaultIndex; - return SubCells.First(b => !AnyUnitsAt(a, b)); + for (var i = 1; i < map.SubCellOffsets.Length; ++i) + if (!AnyUnitsAt(a, i)) + return i; + return -1; } public bool AnyUnitsAt(CPos a) diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index 9c1992ca12..f4419079bc 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -238,7 +238,7 @@ namespace OpenRA.Mods.RA.Move this.self = init.self; this.Info = info; - toSubCell = fromSubCell = info.SharesCell ? init.world.Map.SubCellsDefaultIndex : 0; + toSubCell = fromSubCell = info.SharesCell ? init.world.Map.SubCellDefaultIndex : 0; if (init.Contains()) { this.fromSubCell = this.toSubCell = init.Get(); @@ -417,27 +417,36 @@ namespace OpenRA.Mods.RA.Move } } + bool IsDesiredSubcellNotBlocked(CPos a, int b, Actor ignoreActor) + { + var blockingActors = self.World.ActorMap.GetUnitsAt(a, b).Where(c => c != ignoreActor); + if (blockingActors.Any()) + { + // Non-sharable unit can enter a cell with shareable units only if it can crush all of them + if (Info.Crushes == null) + return false; + + if (blockingActors.Any(c => !(c.HasTrait() && + c.TraitsImplementing().Any(d => d.CrushableBy(Info.Crushes, self.Owner))))) + return false; + } + return true; + } + public int GetDesiredSubcell(CPos a, Actor ignoreActor) { if (!Info.SharesCell) return 0; // Prioritise the current subcell - return new[]{ fromSubCell, 1, 2, 3, 4, 5}.First(b => - { - var blockingActors = self.World.ActorMap.GetUnitsAt(a, b).Where(c => c != ignoreActor); - if (blockingActors.Any()) - { - // Non-sharable unit can enter a cell with shareable units only if it can crush all of them - if (Info.Crushes == null) - return false; + if (IsDesiredSubcellNotBlocked(a, fromSubCell, ignoreActor)) + return fromSubCell; - if (blockingActors.Any(c => !(c.HasTrait() && - c.TraitsImplementing().Any(d => d.CrushableBy(Info.Crushes, self.Owner))))) - return false; - } - return true; - }); + for (var i = 1; i < self.World.Map.SubCellOffsets.Length; ++i) + if (IsDesiredSubcellNotBlocked(a, i, ignoreActor)) + return i; + + return -1; } public bool CanEnterCell(CPos p) diff --git a/OpenRA.Mods.RA/SpawnMPUnits.cs b/OpenRA.Mods.RA/SpawnMPUnits.cs index a0df13ee48..58b5a2b46e 100644 --- a/OpenRA.Mods.RA/SpawnMPUnits.cs +++ b/OpenRA.Mods.RA/SpawnMPUnits.cs @@ -61,7 +61,7 @@ namespace OpenRA.Mods.RA throw new InvalidOperationException("No cells available to spawn starting unit {0}".F(s)); var cell = validCells.Random(w.SharedRandom); - var subCell = mi.SharesCell ? w.ActorMap.FreeSubCell(cell).Value : 0; + var subCell = mi.SharesCell ? w.ActorMap.FreeSubCell(cell) : 0; w.CreateActor(s.ToLowerInvariant(), new TypeDictionary { diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 13479e27d0..6b6555c6c9 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -126,6 +126,10 @@ TileSets: mods/cnc/tilesets/temperat.yaml mods/cnc/tilesets/jungle.yaml +SubCells: + Offsets: 0,0,0, -299,-256,0, 256,-256,0, 0,0,0, -299,256,0, 256,256,0 + DefaultIndex: 3 + LoadScreen: CncLoadScreen Image: mods/cnc/uibits/chrome.png Text: Loading diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index e27ad056d8..b6c9c82605 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -100,6 +100,10 @@ Notifications: TileSets: mods/d2k/tilesets/arrakis.yaml +SubCells: + Offsets: 0,0,0, -299,-256,0, 256,-256,0, 0,0,0, -299,256,0, 256,256,0 + DefaultIndex: 3 + TileSize: 32,32 Music: diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 9043bd1e6e..221a7c0e0c 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -117,6 +117,10 @@ TileSets: mods/ra/tilesets/temperat.yaml mods/ra/tilesets/desert.yaml +SubCells: + Offsets: 0,0,0, -299,-256,0, 256,-256,0, 0,0,0, -299,256,0, 256,256,0 + DefaultIndex: 3 + Music: mods/ra/music.yaml diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index 64548b7bac..bd7ce9714d 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -145,6 +145,9 @@ TileSets: TileSize: 48,24 TileShape: Diamond +SubCells: + Offsets: 0,0,0, -256,128,0, 0,-128,0, 256,128,0 + DefaultIndex: 2 Music: mods/ts/music.yaml From 898bf4959a763f214666a40917dc04f62dc713ad Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Thu, 31 Jul 2014 19:30:18 -0500 Subject: [PATCH 4/5] Remove sub-cell offset bounds checking --- OpenRA.Game/Manifest.cs | 21 +++++---------------- OpenRA.Game/Traits/World/ActorMap.cs | 2 +- OpenRA.Mods.RA/Move/Mobile.cs | 2 +- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index a1ae7d4612..282ae968d1 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -37,7 +37,7 @@ namespace OpenRA public readonly Size TileSize = new Size(24, 24); public readonly TileShape TileShape = TileShape.Rectangle; - [Desc("(x,y,z) offset of the full cell and each sub-cell", "x & y: -512 ... 512, Z >= 0")] + [Desc("(x,y,z) offset of the full cell and each sub-cell", "X & Y should be between -512 ... 512 and Z >= 0")] public readonly WVec[] SubCellOffsets = { new WVec(0, 0, 0), // full cell - index 0 @@ -101,32 +101,21 @@ namespace OpenRA if (yaml.ContainsKey("TileShape")) TileShape = FieldLoader.GetValue("TileShape", yaml["TileShape"].Value); - // Read subcell information - // sub-cell index 0 is the full cell if (yaml.ContainsKey("SubCells")) { var subcells = yaml["SubCells"].ToDictionary(); // Read (x,y,z) offset (relative to cell center) pairs for positioning subcells if (subcells.ContainsKey("Offsets")) - { SubCellOffsets = FieldLoader.GetValue("Offsets", subcells["Offsets"].Value); - foreach (var i in SubCellOffsets) - if (i.X < -512 || i.X > 512 || i.Y < -512 || i.Y > 512 || i.Z < 0) - throw new InvalidDataException("Subcell offsets must be in bounds (X & Y: -512 ... 512, Z > 0)"); - } - - // Read default subcell index used when creating actors that share cells without SubCellInit if (subcells.ContainsKey("DefaultIndex")) - SubCellDefaultIndex = FieldLoader.GetValue("DefaultIndex", subcells ["DefaultIndex"].Value); - - // Otherwise set the default subcell index to the middle subcell entry - else - SubCellDefaultIndex = SubCellOffsets.Length / 2; // default is the middle subcell entry + SubCellDefaultIndex = FieldLoader.GetValue("DefaultIndex", subcells["DefaultIndex"].Value); + else // Otherwise set the default subcell index to the middle subcell entry + SubCellDefaultIndex = SubCellOffsets.Length / 2; } - // validate default index - 0 for no subcells, otherwise > 1 & <= subcell count (offset triples count - 1) + // Validate default index - 0 for no subcells, otherwise > 1 & <= subcell count (offset triples count - 1) if (SubCellDefaultIndex < (SubCellOffsets.Length > 1 ? 1 : 0) || SubCellDefaultIndex >= SubCellOffsets.Length) throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells"); diff --git a/OpenRA.Game/Traits/World/ActorMap.cs b/OpenRA.Game/Traits/World/ActorMap.cs index 3c028af924..32f927a706 100644 --- a/OpenRA.Game/Traits/World/ActorMap.cs +++ b/OpenRA.Game/Traits/World/ActorMap.cs @@ -93,7 +93,7 @@ namespace OpenRA.Traits if (!AnyUnitsAt(a)) return map.SubCellDefaultIndex; - for (var i = 1; i < map.SubCellOffsets.Length; ++i) + for (var i = 1; i < map.SubCellOffsets.Length; i++) if (!AnyUnitsAt(a, i)) return i; return -1; diff --git a/OpenRA.Mods.RA/Move/Mobile.cs b/OpenRA.Mods.RA/Move/Mobile.cs index f4419079bc..b83ea123cc 100755 --- a/OpenRA.Mods.RA/Move/Mobile.cs +++ b/OpenRA.Mods.RA/Move/Mobile.cs @@ -442,7 +442,7 @@ namespace OpenRA.Mods.RA.Move if (IsDesiredSubcellNotBlocked(a, fromSubCell, ignoreActor)) return fromSubCell; - for (var i = 1; i < self.World.Map.SubCellOffsets.Length; ++i) + for (var i = 1; i < self.World.Map.SubCellOffsets.Length; i++) if (IsDesiredSubcellNotBlocked(a, i, ignoreActor)) return i; From b6690291941072b9558310da9f3989a67c102e38 Mon Sep 17 00:00:00 2001 From: atlimit8 Date: Mon, 4 Aug 2014 18:12:14 -0500 Subject: [PATCH 5/5] reverted mod.yaml in cnc, d2k, & ra --- mods/cnc/mod.yaml | 4 ---- mods/d2k/mod.yaml | 4 ---- mods/ra/mod.yaml | 4 ---- 3 files changed, 12 deletions(-) diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 6b6555c6c9..13479e27d0 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -126,10 +126,6 @@ TileSets: mods/cnc/tilesets/temperat.yaml mods/cnc/tilesets/jungle.yaml -SubCells: - Offsets: 0,0,0, -299,-256,0, 256,-256,0, 0,0,0, -299,256,0, 256,256,0 - DefaultIndex: 3 - LoadScreen: CncLoadScreen Image: mods/cnc/uibits/chrome.png Text: Loading diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index b6c9c82605..e27ad056d8 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -100,10 +100,6 @@ Notifications: TileSets: mods/d2k/tilesets/arrakis.yaml -SubCells: - Offsets: 0,0,0, -299,-256,0, 256,-256,0, 0,0,0, -299,256,0, 256,256,0 - DefaultIndex: 3 - TileSize: 32,32 Music: diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 221a7c0e0c..9043bd1e6e 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -117,10 +117,6 @@ TileSets: mods/ra/tilesets/temperat.yaml mods/ra/tilesets/desert.yaml -SubCells: - Offsets: 0,0,0, -299,-256,0, 256,-256,0, 0,0,0, -299,256,0, 256,256,0 - DefaultIndex: 3 - Music: mods/ra/music.yaml