public int2 Expand( World world, float[][ , ] passableCost ) { var p = queue.Pop(); cellInfo[ p.Location.X, p.Location.Y ].Seen = true; var custom2 = world.customTerrain[p.Location.X, p.Location.Y]; var thisCost = (custom2 != null) ? custom2.GetCost(p.Location, umt) : passableCost[(int)umt][p.Location.X, p.Location.Y]; if (thisCost == float.PositiveInfinity) return p.Location; foreach( int2 d in directions ) { int2 newHere = p.Location + d; if (!world.Map.IsInMap(newHere.X, newHere.Y)) continue; if( cellInfo[ newHere.X, newHere.Y ].Seen ) continue; var custom = world.customTerrain[newHere.X, newHere.Y]; var costHere = (custom != null) ? custom.GetCost(newHere, umt) : passableCost[(int)umt][newHere.X, newHere.Y]; if (costHere == float.PositiveInfinity) continue; if (!buildingInfluence.CanMoveHere(newHere, ignoreBuilding)) continue; // Replicate real-ra behavior of not being able to enter a cell if there is a mixture of crushable and uncrushable units if (checkForBlocked && (unitInfluence.GetUnitsAt(newHere).Any(a => !world.IsActorPathableToCrush(a, umt)))) continue; if (customBlock != null && customBlock(newHere)) continue; var est = heuristic( newHere ); if( est == float.PositiveInfinity ) continue; float cellCost = ((d.X * d.Y != 0) ? 1.414213563f : 1.0f) * costHere; // directional bonuses for smoother flow! if (((newHere.X & 1) == 0) && d.Y < 0) cellCost -= .1f; else if (((newHere.X & 1) == 1) && d.Y > 0) cellCost -= .1f; if (((newHere.Y & 1) == 0) && d.X < 0) cellCost -= .1f; else if (((newHere.Y & 1) == 1) && d.X > 0) cellCost -= .1f; float newCost = cellInfo[ p.Location.X, p.Location.Y ].MinCost + cellCost; if( newCost >= cellInfo[ newHere.X, newHere.Y ].MinCost ) continue; cellInfo[ newHere.X, newHere.Y ].Path = p.Location; cellInfo[ newHere.X, newHere.Y ].MinCost = newCost; queue.Add( new PathDistance( newCost + est, newHere ) ); } return p.Location; }