public override void Generate(Map map, GenStepParams parms) { List <NeededRoad> neededRoads = CalculateNeededRoads(map); if (neededRoads.Count == 0) { return; } List <DrawCommand> list = new List <DrawCommand>(); DeepProfiler.Start("RebuildAllRegions"); map.regionAndRoomUpdater.RebuildAllRegionsAndRooms(); DeepProfiler.End(); TerrainDef rockDef = BaseGenUtility.RegionalRockTerrainDef(map.Tile, beautiful: false); IntVec3 centerpoint = CellFinderLoose.TryFindCentralCell(map, 3, 10); RoadDef bestRoadType = DefDatabase <RoadDef> .AllDefs.Where((RoadDef rd) => neededRoads.Count((NeededRoad nr) => nr.road == rd) >= 2).MaxByWithFallback((RoadDef rd) => rd.priority); DrawCommand item; if (bestRoadType != null) { NeededRoad neededRoad = neededRoads[neededRoads.FindIndex((NeededRoad nr) => nr.road == bestRoadType)]; neededRoads.RemoveAt(neededRoads.FindIndex((NeededRoad nr) => nr.road == bestRoadType)); NeededRoad neededRoad2 = neededRoads[neededRoads.FindIndex((NeededRoad nr) => nr.road == bestRoadType)]; neededRoads.RemoveAt(neededRoads.FindIndex((NeededRoad nr) => nr.road == bestRoadType)); RoadPathingDef pathingDef = neededRoad.road.pathingMode; IntVec3 intVec = FindRoadExitCell(map, neededRoad.angle, centerpoint, ref pathingDef); IntVec3 end = FindRoadExitCell(map, neededRoad2.angle, intVec, ref pathingDef); Action action = PrepDrawRoad(map, rockDef, intVec, end, neededRoad.road, pathingDef, out centerpoint); item = new DrawCommand { action = action, roadDef = bestRoadType }; list.Add(item); } foreach (NeededRoad item2 in neededRoads) { RoadPathingDef pathingDef2 = item2.road.pathingMode; IntVec3 intVec2 = FindRoadExitCell(map, item2.angle, centerpoint, ref pathingDef2); if (!(intVec2 == IntVec3.Invalid)) { item = new DrawCommand { action = PrepDrawRoad(map, rockDef, centerpoint, intVec2, item2.road, pathingDef2), roadDef = item2.road }; list.Add(item); } } foreach (DrawCommand item3 in list.OrderBy((DrawCommand dc) => dc.roadDef.priority)) { if (item3.action != null) { item3.action(); } } }
public override void Generate(Map map) { List <GenStep_Roads.NeededRoad> neededRoads = this.CalculateNeededRoads(map); if (neededRoads.Count == 0) { return; } List <GenStep_Roads.DrawCommand> list = new List <GenStep_Roads.DrawCommand>(); DeepProfiler.Start("RebuildAllRegions"); map.regionAndRoomUpdater.RebuildAllRegionsAndRooms(); DeepProfiler.End(); TerrainDef rockDef = BaseGenUtility.RegionalRockTerrainDef(map.Tile, false); IntVec3 intVec = CellFinderLoose.TryFindCentralCell(map, 3, 10, null); RoadDef bestRoadType = (from rd in DefDatabase <RoadDef> .AllDefs where neededRoads.Count((GenStep_Roads.NeededRoad nr) => nr.road == rd) >= 2 select rd).MaxByWithFallback((RoadDef rd) => rd.priority, null); if (bestRoadType != null) { GenStep_Roads.NeededRoad neededRoad = neededRoads[neededRoads.FindIndex((GenStep_Roads.NeededRoad nr) => nr.road == bestRoadType)]; neededRoads.RemoveAt(neededRoads.FindIndex((GenStep_Roads.NeededRoad nr) => nr.road == bestRoadType)); GenStep_Roads.NeededRoad neededRoad2 = neededRoads[neededRoads.FindIndex((GenStep_Roads.NeededRoad nr) => nr.road == bestRoadType)]; neededRoads.RemoveAt(neededRoads.FindIndex((GenStep_Roads.NeededRoad nr) => nr.road == bestRoadType)); RoadPathingDef pathingMode = neededRoad.road.pathingMode; IntVec3 intVec2 = this.FindRoadExitCell(map, neededRoad.angle, intVec, ref pathingMode); IntVec3 end = this.FindRoadExitCell(map, neededRoad2.angle, intVec2, ref pathingMode); Action action = this.PrepDrawRoad(map, rockDef, intVec2, end, neededRoad.road, pathingMode, out intVec); list.Add(new GenStep_Roads.DrawCommand { action = action, roadDef = bestRoadType }); } foreach (GenStep_Roads.NeededRoad current in neededRoads) { RoadPathingDef pathingMode2 = current.road.pathingMode; IntVec3 intVec3 = this.FindRoadExitCell(map, current.angle, intVec, ref pathingMode2); if (!(intVec3 == IntVec3.Invalid)) { list.Add(new GenStep_Roads.DrawCommand { action = this.PrepDrawRoad(map, rockDef, intVec, intVec3, current.road, pathingMode2), roadDef = current.road }); } } foreach (GenStep_Roads.DrawCommand current2 in from dc in list orderby dc.roadDef.priority select dc) { if (current2.action != null) { current2.action(); } } }
private IntVec3 FindRoadExitCell(Map map, float angle, IntVec3 crossroads, ref RoadPathingDef pathingDef) { Predicate <IntVec3> tileValidator = delegate(IntVec3 pos) { foreach (IntVec3 current in GenRadial.RadialCellsAround(pos, 8f, true)) { if (current.InBounds(map) && current.GetTerrain(map).HasTag("Water")) { return(false); } } return(true); }; float validAngleSpan; for (validAngleSpan = 10f; validAngleSpan < 90f; validAngleSpan += 10f) { Predicate <IntVec3> angleValidator = (IntVec3 pos) => GenGeo.AngleDifferenceBetween((pos - map.Center).AngleFlat, angle) < validAngleSpan; IntVec3 result; if (CellFinder.TryFindRandomEdgeCellWith((IntVec3 x) => angleValidator(x) && tileValidator(x) && map.reachability.CanReach(crossroads, x, PathEndMode.OnCell, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false)), map, 0f, out result)) { return(result); } } if (pathingDef == RoadPathingDefOf.Avoid) { pathingDef = RoadPathingDefOf.Bulldoze; } float validAngleSpan2; for (validAngleSpan2 = 10f; validAngleSpan2 < 90f; validAngleSpan2 += 10f) { Predicate <IntVec3> angleValidator = (IntVec3 pos) => GenGeo.AngleDifferenceBetween((pos - map.Center).AngleFlat, angle) < validAngleSpan2; IntVec3 result; if (CellFinder.TryFindRandomEdgeCellWith((IntVec3 x) => angleValidator(x) && tileValidator(x) && map.reachability.CanReach(crossroads, x, PathEndMode.OnCell, TraverseParms.For(TraverseMode.PassAllDestroyableThings, Danger.Deadly, false)), map, 0f, out result)) { return(result); } } Log.Error(string.Format("Can't find exit from map from {0} to angle {1}", crossroads, angle)); return(IntVec3.Invalid); }
private void ApplyDistanceField(DistanceElement[,] distance, Map map, TerrainDef rockDef, RoadDef roadDef, RoadPathingDef pathingDef) { int num = 0; while (true) { int num2 = num; IntVec3 size = map.Size; if (num2 >= size.x) { break; } int num3 = 0; while (true) { int num4 = num3; IntVec3 size2 = map.Size; if (num4 >= size2.z) { break; } DistanceElement distanceElement = distance[num, num3]; if (distanceElement.touched) { float b = Mathf.Abs(distanceElement.fromRoad + Rand.Value - 0.5f); for (int i = 0; i < roadDef.roadGenSteps.Count; i++) { RoadDefGenStep roadDefGenStep = roadDef.roadGenSteps[i]; float x = Mathf.LerpUnclamped(distanceElement.fromRoad, b, roadDefGenStep.antialiasingMultiplier); float num5 = roadDefGenStep.chancePerPositionCurve.Evaluate(x); if (!(num5 <= 0f) && (roadDefGenStep.periodicSpacing == 0 || !(distanceElement.alongPath / (float)roadDefGenStep.periodicSpacing % 1f * (float)roadDefGenStep.periodicSpacing >= 1f))) { IntVec3 position = new IntVec3(num, 0, num3); if (Rand.Value < num5) { roadDefGenStep.Place(map, position, rockDef, distanceElement.origin, distance); } } } } num3++; } num++; } }
private void DrawCurveSegment(DistanceElement[,] distance, List <IntVec3> path, int pathStartIndex, int pathEndIndex, RoadPathingDef pathing, Map map, int centerpointIndex, ref IntVec3 centerpoint) { if (pathStartIndex == pathEndIndex) { Log.ErrorOnce("Zero-length segment drawn in road routine", 78187971); } else { GenMath.BezierCubicControls bcc = GenerateBezierControls(path, pathStartIndex, pathEndIndex); List <Vector3> list = new List <Vector3>(); int num = (pathEndIndex - pathStartIndex) * 4; for (int i = 0; i <= num; i++) { list.Add(GenMath.BezierCubicEvaluate((float)i / (float)num, bcc)); } int num2 = 0; for (int j = pathStartIndex; j <= pathEndIndex; j++) { if (j > 0 && j < path.Count && path[j].InBounds(map) && path[j].GetTerrain(map).IsWater) { num2++; } } if (pathStartIndex + 1 < pathEndIndex) { for (int k = 0; k < list.Count; k++) { IntVec3 intVec = list[k].ToIntVec3(); bool flag = intVec.InBounds(map) && intVec.Impassable(map); int num3 = 0; for (int l = 0; l < GenAdj.CardinalDirections.Length; l++) { if (flag) { break; } IntVec3 c = intVec + GenAdj.CardinalDirections[l]; if (c.InBounds(map)) { flag |= (pathing == RoadPathingDefOf.Avoid && c.Impassable(map)); if (c.GetTerrain(map).IsWater) { num3++; } if (flag) { break; } } } if (flag || (float)num3 > (float)num2 * 1.5f + 2f) { DrawCurveSegment(distance, path, pathStartIndex, (pathStartIndex + pathEndIndex) / 2, pathing, map, centerpointIndex, ref centerpoint); DrawCurveSegment(distance, path, (pathStartIndex + pathEndIndex) / 2, pathEndIndex, pathing, map, centerpointIndex, ref centerpoint); return; } } } for (int m = 0; m < list.Count; m++) { Vector3 vector = list[m]; float x = vector.x; Vector3 vector2 = list[m]; FillDistanceField(distance, x, vector2.z, GenMath.LerpDouble(0f, (float)(list.Count - 1), (float)pathStartIndex, (float)pathEndIndex, (float)m), 10f, map); } if (centerpointIndex >= pathStartIndex && centerpointIndex < pathEndIndex) { centerpointIndex = Mathf.Clamp(Mathf.RoundToInt(GenMath.LerpDouble((float)pathStartIndex, (float)pathEndIndex, 0f, (float)list.Count, (float)centerpointIndex)), 0, list.Count - 1); centerpoint = list[centerpointIndex].ToIntVec3(); } } }
private Action PrepDrawRoad(Map map, TerrainDef rockDef, IntVec3 start, IntVec3 end, RoadDef roadDef, RoadPathingDef pathingDef, out IntVec3 centerpoint) { centerpoint = IntVec3.Invalid; PawnPath pawnPath = map.pathFinder.FindPath(start, end, TraverseParms.For(TraverseMode.NoPassClosedDoorsOrWater)); if (pawnPath == PawnPath.NotFound) { pawnPath = map.pathFinder.FindPath(start, end, TraverseParms.For(TraverseMode.NoPassClosedDoors)); } if (pawnPath == PawnPath.NotFound) { pawnPath = map.pathFinder.FindPath(start, end, TraverseParms.For(TraverseMode.PassAllDestroyableThingsNotWater)); } if (pawnPath == PawnPath.NotFound) { pawnPath = map.pathFinder.FindPath(start, end, TraverseParms.For(TraverseMode.PassAllDestroyableThings)); } if (pawnPath == PawnPath.NotFound) { return(null); } List <IntVec3> list = RefinePath(pawnPath.NodesReversed, map); pawnPath.ReleaseToPool(); IntVec3 size = map.Size; int x = size.x; IntVec3 size2 = map.Size; DistanceElement[,] distance = new DistanceElement[x, size2.z]; for (int i = 0; i < distance.GetLength(0); i++) { for (int j = 0; j < distance.GetLength(1); j++) { distance[i, j].origin = IntVec3.Invalid; } } int count = list.Count; int centerpointIndex = Mathf.RoundToInt(Rand.Range(0.3f, 0.7f) * (float)count); int num = Mathf.Max(1, GenMath.RoundRandom((float)count / (float)roadDef.tilesPerSegment)); for (int k = 0; k < num; k++) { int pathStartIndex = Mathf.RoundToInt((float)(count - 1) / (float)num * (float)k); int pathEndIndex = Mathf.RoundToInt((float)(count - 1) / (float)num * (float)(k + 1)); DrawCurveSegment(distance, list, pathStartIndex, pathEndIndex, pathingDef, map, centerpointIndex, ref centerpoint); } return(delegate { ApplyDistanceField(distance, map, rockDef, roadDef, pathingDef); }); }
private Action PrepDrawRoad(Map map, TerrainDef rockDef, IntVec3 start, IntVec3 end, RoadDef roadDef, RoadPathingDef pathingDef) { IntVec3 centerpoint; return(PrepDrawRoad(map, rockDef, start, end, roadDef, pathingDef, out centerpoint)); }
private Action PrepDrawRoad(Map map, TerrainDef rockDef, IntVec3 start, IntVec3 end, RoadDef roadDef, RoadPathingDef pathingDef) { IntVec3 intVec = default(IntVec3); return(this.PrepDrawRoad(map, rockDef, start, end, roadDef, pathingDef, out intVec)); }
private void ApplyDistanceField(DistanceElement[,] distance, Map map, TerrainDef rockDef, RoadDef roadDef, RoadPathingDef pathingDef) { for (int i = 0; i < map.Size.x; i++) { for (int j = 0; j < map.Size.z; j++) { DistanceElement distanceElement = distance[i, j]; if (!distanceElement.touched) { continue; } float b = Mathf.Abs(distanceElement.fromRoad + Rand.Value - 0.5f); for (int k = 0; k < roadDef.roadGenSteps.Count; k++) { RoadDefGenStep roadDefGenStep = roadDef.roadGenSteps[k]; float x = Mathf.LerpUnclamped(distanceElement.fromRoad, b, roadDefGenStep.antialiasingMultiplier); float num = roadDefGenStep.chancePerPositionCurve.Evaluate(x); if (!(num <= 0f) && (roadDefGenStep.periodicSpacing == 0 || !(distanceElement.alongPath / (float)roadDefGenStep.periodicSpacing % 1f * (float)roadDefGenStep.periodicSpacing >= 1f))) { IntVec3 position = new IntVec3(i, 0, j); if (Rand.Value < num) { roadDefGenStep.Place(map, position, rockDef, distanceElement.origin, distance); } } } } } }
private Action PrepDrawRoad(Map map, TerrainDef rockDef, IntVec3 start, IntVec3 end, RoadDef roadDef, RoadPathingDef pathingDef, out IntVec3 centerpoint) { centerpoint = IntVec3.Invalid; PawnPath pawnPath = map.pathFinder.FindPath(start, end, TraverseParms.For(TraverseMode.NoPassClosedDoorsOrWater, Danger.Deadly, false), PathEndMode.OnCell); if (pawnPath == PawnPath.NotFound) { pawnPath = map.pathFinder.FindPath(start, end, TraverseParms.For(TraverseMode.NoPassClosedDoors, Danger.Deadly, false), PathEndMode.OnCell); } if (pawnPath == PawnPath.NotFound) { pawnPath = map.pathFinder.FindPath(start, end, TraverseParms.For(TraverseMode.PassAllDestroyableThingsNotWater, Danger.Deadly, false), PathEndMode.OnCell); } if (pawnPath == PawnPath.NotFound) { pawnPath = map.pathFinder.FindPath(start, end, TraverseParms.For(TraverseMode.PassAllDestroyableThings, Danger.Deadly, false), PathEndMode.OnCell); } if (pawnPath == PawnPath.NotFound) { return(null); } List <IntVec3> list = this.RefinePath(pawnPath.NodesReversed, map); pawnPath.ReleaseToPool(); GenStep_Roads.DistanceElement[,] distance = new GenStep_Roads.DistanceElement[map.Size.x, map.Size.z]; int count = list.Count; int centerpointIndex = Mathf.RoundToInt(Rand.Range(0.3f, 0.7f) * (float)count); int num = Mathf.Max(1, GenMath.RoundRandom((float)count / (float)roadDef.tilesPerSegment)); for (int i = 0; i < num; i++) { int pathStartIndex = Mathf.RoundToInt((float)(count - 1) / (float)num * (float)i); int pathEndIndex = Mathf.RoundToInt((float)(count - 1) / (float)num * (float)(i + 1)); this.DrawCurveSegment(distance, list, pathStartIndex, pathEndIndex, pathingDef, map, centerpointIndex, ref centerpoint); } return(delegate { this.ApplyDistanceField(distance, map, rockDef, roadDef, pathingDef); }); }