Merge pull request #12370 from pchote/heightmap-shroud-reveal
Implement heightmap-visibility blocking
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user