HPF is aware of map projection changes.

An event is added to Map to indicate when the cell projection is changed. This is important as this can mean Map.Contains(CPos) could now return different results for the cell. The HierarchicalPathFinder is made aware of these changes so it can rebuild any out-of-date information. This fixes prevent a crash if a cell that was previously outside the map changes height and becomes inside the map. The local path search will explore the cell as it is inside the map - but if the HPF was unaware if had been updated, it will still consider the cell to be outside the map and unreachable, resulting in a crash.
This commit is contained in:
RoosterDragon
2022-12-19 18:18:15 +00:00
committed by Paul Chote
parent d8ebb96077
commit 39e48d9e8d
2 changed files with 20 additions and 2 deletions

View File

@@ -243,6 +243,8 @@ namespace OpenRA
public CellRegion AllCells { get; private set; }
public List<CPos> AllEdgeCells { get; private set; }
public event Action<CPos> CellProjectionChanged;
// Internal data
readonly ModData modData;
CellLayer<short> cachedTerrainIndexes;
@@ -336,11 +338,12 @@ namespace OpenRA
Height = new CellLayer<byte>(Grid.Type, size);
Ramp = new CellLayer<byte>(Grid.Type, size);
Tiles.Clear(terrainInfo.DefaultTerrainTile);
if (Grid.MaximumTerrainHeight > 0)
{
Height.CellEntryChanged += UpdateProjection;
Tiles.CellEntryChanged += UpdateProjection;
Tiles.CellEntryChanged += UpdateRamp;
Tiles.CellEntryChanged += UpdateProjection;
Height.CellEntryChanged += UpdateProjection;
}
PostInit();
@@ -530,6 +533,7 @@ namespace OpenRA
var inverse = inverseCellProjection[uv];
inverse.Clear();
inverse.Add(uv);
CellProjectionChanged?.Invoke(cell);
return;
}
@@ -567,6 +571,8 @@ namespace OpenRA
projectedHeight[temp] = height;
}
}
CellProjectionChanged?.Invoke(cell);
}
byte ProjectedCellHeightInner(PPos puv)

View File

@@ -281,6 +281,10 @@ namespace OpenRA.Mods.Common.Pathfinder
// When we build the cost table, it depends on the movement costs of the cells at that time.
// When this changes, we must update the cost table.
locomotor.CellCostChanged += RequireCostRefreshInCell;
// If the map projection changes, the result of Map.Contains(CPos) may change.
// We need to rebuild grids to account for this possibility.
this.world.Map.CellProjectionChanged += RequireProjectionRefreshInCell;
}
public (
@@ -619,6 +623,14 @@ namespace OpenRA.Mods.Common.Pathfinder
}
}
/// <summary>
/// When map projection changes for a cell, marks the grid it belongs to as out of date.
/// </summary>
void RequireProjectionRefreshInCell(CPos cell)
{
dirtyGridIndexes.Add(GridIndex(cell));
}
/// <summary>
/// <see cref="BlockedByActor.Immovable"/> defines immovability based on the mobile trait. The blocking rules
/// in <see cref="Locomotor.CanMoveFreelyInto(Actor, CPos, SubCell, BlockedByActor, Actor)"/> allow units to