Refactor footprint cell lookups and move them to Building
Removing FootprintUtils happens in the next commit for better reviewability.
This commit is contained in:
@@ -23,6 +23,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public class GivesBuildableAreaInfo : TraitInfo<GivesBuildableArea> { }
|
||||
public class GivesBuildableArea { }
|
||||
|
||||
public enum FootprintCellType
|
||||
{
|
||||
Empty = '_',
|
||||
OccupiedPassable = '=',
|
||||
Blocking = 'x'
|
||||
}
|
||||
|
||||
public class BuildingInfo : ITraitInfo, IOccupySpaceInfo, IPlaceBuildingDecorationInfo, UsesInit<LocationInit>
|
||||
{
|
||||
[Desc("Where you are allowed to place the building (Water, Clear, ...)")]
|
||||
@@ -31,8 +38,10 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Desc("The range to the next building it can be constructed. Set it higher for walls.")]
|
||||
public readonly int Adjacent = 2;
|
||||
|
||||
[Desc("x means space it blocks, _ is a part that is passable by actors.")]
|
||||
public readonly string Footprint = "x";
|
||||
[Desc("x means cell is blocked, = means part of the footprint but passable, ",
|
||||
"_ means completely empty.")]
|
||||
[FieldLoader.LoadUsing("LoadFootprint")]
|
||||
public readonly Dictionary<CVec, FootprintCellType> Footprint;
|
||||
|
||||
public readonly CVec Dimensions = new CVec(1, 1);
|
||||
|
||||
@@ -58,9 +67,90 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public virtual object Create(ActorInitializer init) { return new Building(init, this); }
|
||||
|
||||
protected static object LoadFootprint(MiniYaml yaml)
|
||||
{
|
||||
var footprintYaml = yaml.Nodes.FirstOrDefault(n => n.Key == "Footprint");
|
||||
var footprintChars = footprintYaml != null ? footprintYaml.Value.Value.Where(x => !char.IsWhiteSpace(x)).ToArray() : new[] { 'x' };
|
||||
|
||||
var dimensionsYaml = yaml.Nodes.FirstOrDefault(n => n.Key == "Dimensions");
|
||||
var dim = dimensionsYaml != null ? FieldLoader.GetValue<CVec>("Dimensions", dimensionsYaml.Value.Value) : new CVec(1, 1);
|
||||
|
||||
if (footprintChars.Length != dim.X * dim.Y)
|
||||
{
|
||||
var fp = footprintYaml.Value.Value.ToString();
|
||||
var dims = dim.X + "x" + dim.Y;
|
||||
throw new YamlException("Invalid footprint: {0} does not match dimensions {1}".F(fp, dims));
|
||||
}
|
||||
|
||||
var index = 0;
|
||||
var ret = new Dictionary<CVec, FootprintCellType>();
|
||||
for (var y = 0; y < dim.Y; y++)
|
||||
{
|
||||
for (var x = 0; x < dim.X; x++)
|
||||
{
|
||||
var c = footprintChars[index++];
|
||||
if (!Enum.IsDefined(typeof(FootprintCellType), (FootprintCellType)c))
|
||||
throw new YamlException("Invalid footprint cell type '{0}'".F(c));
|
||||
|
||||
ret[new CVec(x, y)] = (FootprintCellType)c;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> FootprintTiles(CPos location, FootprintCellType type)
|
||||
{
|
||||
return Footprint.Where(kv => kv.Value == type).Select(kv => location + kv.Key);
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> Tiles(CPos location)
|
||||
{
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.OccupiedPassable))
|
||||
yield return t;
|
||||
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.Blocking))
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> FrozenUnderFogTiles(CPos location)
|
||||
{
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.Empty))
|
||||
yield return t;
|
||||
|
||||
foreach (var t in Tiles(location))
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> UnpathableTiles(CPos location)
|
||||
{
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.Blocking))
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public IEnumerable<CPos> PathableTiles(CPos location)
|
||||
{
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.Empty))
|
||||
yield return t;
|
||||
|
||||
foreach (var t in FootprintTiles(location, FootprintCellType.OccupiedPassable))
|
||||
yield return t;
|
||||
}
|
||||
|
||||
public CVec LocationOffset()
|
||||
{
|
||||
return new CVec(Dimensions.X / 2, Dimensions.Y > 1 ? (Dimensions.Y + 1) / 2 : 0);
|
||||
}
|
||||
|
||||
public WVec CenterOffset(World w)
|
||||
{
|
||||
var off = (w.Map.CenterOfCell(new CPos(Dimensions.X, Dimensions.Y)) - w.Map.CenterOfCell(new CPos(1, 1))) / 2;
|
||||
return (off - new WVec(0, 0, off.Z)) + LocalCenterOffset;
|
||||
}
|
||||
|
||||
public Actor FindBaseProvider(World world, Player p, CPos topLeft)
|
||||
{
|
||||
var center = world.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(world, this);
|
||||
var center = world.Map.CenterOfCell(topLeft) + CenterOffset(world);
|
||||
var allyBuildEnabled = world.WorldActor.Trait<MapBuildRadius>().AllyBuildRadiusEnabled;
|
||||
|
||||
foreach (var bp in world.ActorsWithTrait<BaseProvider>())
|
||||
@@ -118,7 +208,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
}
|
||||
|
||||
var buildingTiles = FootprintUtils.Tiles(world.Map.Rules, buildingName, this, topLeft).ToList();
|
||||
var buildingTiles = Tiles(topLeft).ToList();
|
||||
return nearnessCandidates
|
||||
.Any(a => buildingTiles
|
||||
.Any(b => Math.Abs(a.X - b.X) <= Adjacent
|
||||
@@ -127,7 +217,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
|
||||
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos topLeft, SubCell subCell = SubCell.Any)
|
||||
{
|
||||
var occupied = FootprintUtils.UnpathableTiles(info.Name, this, topLeft)
|
||||
var occupied = UnpathableTiles(topLeft)
|
||||
.ToDictionary(c => c, c => SubCell.FullCell);
|
||||
|
||||
return new ReadOnlyDictionary<CPos, SubCell>(occupied);
|
||||
@@ -178,13 +268,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
topLeft = init.Get<LocationInit, CPos>();
|
||||
Info = info;
|
||||
|
||||
occupiedCells = FootprintUtils.UnpathableTiles(self.Info.Name, Info, TopLeft)
|
||||
occupiedCells = Info.UnpathableTiles(TopLeft)
|
||||
.Select(c => Pair.New(c, SubCell.FullCell)).ToArray();
|
||||
|
||||
targetableCells = FootprintUtils.UnpathableTiles(self.Info.Name, Info, TopLeft)
|
||||
targetableCells = Info.FootprintTiles(TopLeft, FootprintCellType.Blocking)
|
||||
.Select(c => Pair.New(c, SubCell.FullCell)).ToArray();
|
||||
|
||||
CenterPosition = init.World.Map.CenterOfCell(topLeft) + FootprintUtils.CenterOffset(init.World, Info);
|
||||
CenterPosition = init.World.Map.CenterOfCell(topLeft) + Info.CenterOffset(init.World);
|
||||
SkipMakeAnimation = init.Contains<SkipMakeAnimsInit>();
|
||||
}
|
||||
|
||||
@@ -258,7 +348,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var smudgeLayers = self.World.WorldActor.TraitsImplementing<SmudgeLayer>();
|
||||
|
||||
foreach (var smudgeLayer in smudgeLayers)
|
||||
foreach (var footprintTile in FootprintUtils.Tiles(self))
|
||||
foreach (var footprintTile in Info.Tiles(self.Location))
|
||||
smudgeLayer.RemoveSmudge(footprintTile);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user