Merge pull request #12370 from pchote/heightmap-shroud-reveal

Implement heightmap-visibility blocking
This commit is contained in:
reaperrr
2016-11-18 14:23:53 +01:00
committed by GitHub
12 changed files with 118 additions and 8 deletions

View File

@@ -241,6 +241,7 @@ namespace OpenRA
bool initializedCellProjection;
CellLayer<PPos[]> cellProjection;
CellLayer<List<MPos>> inverseCellProjection;
CellLayer<byte> projectedHeight;
public static string ComputeUID(IReadOnlyPackage package)
{
@@ -420,6 +421,7 @@ namespace OpenRA
cellProjection = new CellLayer<PPos[]>(this);
inverseCellProjection = new CellLayer<List<MPos>>(this);
projectedHeight = new CellLayer<byte>(this);
// Initialize collections
foreach (var cell in AllCells)
@@ -455,13 +457,54 @@ namespace OpenRA
// Remove old reverse projection
foreach (var puv in cellProjection[uv])
inverseCellProjection[(MPos)puv].Remove(uv);
{
var temp = (MPos)puv;
inverseCellProjection[temp].Remove(uv);
projectedHeight[temp] = ProjectedCellHeightInner(puv);
}
var projected = ProjectCellInner(uv);
cellProjection[uv] = projected;
foreach (var puv in projected)
inverseCellProjection[(MPos)puv].Add(uv);
{
var temp = (MPos)puv;
inverseCellProjection[temp].Add(uv);
var height = ProjectedCellHeightInner(puv);
projectedHeight[temp] = height;
// Propagate height up cliff faces
while (true)
{
temp = new MPos(temp.U, temp.V - 1);
if (!inverseCellProjection.Contains(temp) || inverseCellProjection[temp].Any())
break;
projectedHeight[temp] = height;
}
}
}
byte ProjectedCellHeightInner(PPos puv)
{
while (inverseCellProjection.Contains((MPos)puv))
{
var inverse = inverseCellProjection[(MPos)puv];
if (inverse.Any())
{
// The original games treat the top of cliffs the same way as the bottom
// This information isn't stored in the map data, so query the offset from the tileset
var temp = inverse.MaxBy(uv => uv.V);
var terrain = Tiles[temp];
return (byte)(Height[temp] - Rules.TileSet.Templates[terrain.Type][terrain.Index].Height);
}
// Try the next cell down if this is a cliff face
puv = new PPos(puv.U, puv.V + 1);
}
return 0;
}
PPos[] ProjectCellInner(MPos uv)
@@ -786,6 +829,11 @@ namespace OpenRA
return inverseCellProjection[uv];
}
public byte ProjectedHeight(PPos puv)
{
return projectedHeight[(MPos)puv];
}
public int FacingBetween(CPos cell, CPos towards, int fallbackfacing)
{
var delta = CenterOfCell(towards) - CenterOfCell(cell);

View File

@@ -115,7 +115,7 @@ namespace OpenRA.Traits
Hash += 1;
}
public static IEnumerable<PPos> ProjectedCellsInRange(Map map, WPos pos, WDist range)
public static IEnumerable<PPos> ProjectedCellsInRange(Map map, WPos pos, WDist range, int maxHeightDelta = -1)
{
// Account for potential extra half-cell from odd-height terrain
var r = (range.Length + 1023 + 512) / 1024;
@@ -124,15 +124,22 @@ namespace OpenRA.Traits
// Project actor position into the shroud plane
var projectedPos = pos - new WVec(0, pos.Z, pos.Z);
var projectedCell = map.CellContaining(projectedPos);
var projectedHeight = pos.Z / 512;
foreach (var c in map.FindTilesInCircle(projectedCell, r, true))
{
if ((map.CenterOfCell(c) - projectedPos).HorizontalLengthSquared <= limit)
yield return (PPos)c.ToMPos(map);
{
var puv = (PPos)c.ToMPos(map);
if (maxHeightDelta < 0 || map.ProjectedHeight(puv) < projectedHeight + maxHeightDelta)
yield return puv;
}
}
}
public static IEnumerable<PPos> ProjectedCellsInRange(Map map, CPos cell, WDist range)
public static IEnumerable<PPos> ProjectedCellsInRange(Map map, CPos cell, WDist range, int maxHeightDelta = -1)
{
return ProjectedCellsInRange(map, map.CenterOfCell(cell), range);
return ProjectedCellsInRange(map, map.CenterOfCell(cell), range, maxHeightDelta);
}
public void AddProjectedVisibility(object key, PPos[] visible)