Exemplo n.º 1
0
        public RiverDef GetRiverDef(int fromTile, int toTile, bool visibleOnly = true)
        {
            if (!IsNeighbor(fromTile, toTile))
            {
                Log.ErrorOnce("Tried to find river information between non-neighboring tiles", 12390444);
                return(null);
            }
            Tile tile = tiles[fromTile];
            List <Tile.RiverLink> list = (!visibleOnly) ? tile.potentialRivers : tile.Rivers;

            if (list == null)
            {
                return(null);
            }
            for (int i = 0; i < list.Count; i++)
            {
                Tile.RiverLink riverLink = list[i];
                if (riverLink.neighbor == toTile)
                {
                    Tile.RiverLink riverLink2 = list[i];
                    return(riverLink2.river);
                }
            }
            return(null);
        }
Exemplo n.º 2
0
        public void OverlayRiver(int fromTile, int toTile, RiverDef riverDef)
        {
            if (riverDef == null)
            {
                Log.ErrorOnce("Attempted to remove river with overlayRiver; not supported", 90292250);
                return;
            }
            RiverDef riverDef2 = GetRiverDef(fromTile, toTile, visibleOnly: false);

            if (riverDef2 == riverDef)
            {
                return;
            }
            Tile tile  = this[fromTile];
            Tile tile2 = this[toTile];

            if (riverDef2 != null)
            {
                if (riverDef2.degradeThreshold >= riverDef.degradeThreshold)
                {
                    return;
                }
                tile.potentialRivers.RemoveAll((Tile.RiverLink rl) => rl.neighbor == toTile);
                tile2.potentialRivers.RemoveAll((Tile.RiverLink rl) => rl.neighbor == fromTile);
            }
            if (tile.potentialRivers == null)
            {
                tile.potentialRivers = new List <Tile.RiverLink>();
            }
            if (tile2.potentialRivers == null)
            {
                tile2.potentialRivers = new List <Tile.RiverLink>();
            }
            List <Tile.RiverLink> potentialRivers = tile.potentialRivers;

            Tile.RiverLink item = new Tile.RiverLink
            {
                neighbor = toTile,
                river    = riverDef
            };
            potentialRivers.Add(item);
            List <Tile.RiverLink> potentialRivers2 = tile2.potentialRivers;

            item = new Tile.RiverLink
            {
                neighbor = fromTile,
                river    = riverDef
            };
            potentialRivers2.Add(item);
        }
Exemplo n.º 3
0
        private void TilesToRawData()
        {
            this.tileBiome       = DataSerializeUtility.SerializeUshort(this.TilesCount, (int i) => this.tiles[i].biome.shortHash);
            this.tileElevation   = DataSerializeUtility.SerializeUshort(this.TilesCount, (int i) => (ushort)Mathf.Clamp(Mathf.RoundToInt(((!this.tiles[i].WaterCovered) ? Mathf.Max(this.tiles[i].elevation, 1f) : this.tiles[i].elevation) + 8192f), 0, 65535));
            this.tileHilliness   = DataSerializeUtility.SerializeByte(this.TilesCount, (int i) => (byte)this.tiles[i].hilliness);
            this.tileTemperature = DataSerializeUtility.SerializeUshort(this.TilesCount, (int i) => (ushort)Mathf.Clamp(Mathf.RoundToInt((this.tiles[i].temperature + 300f) * 10f), 0, 65535));
            this.tileRainfall    = DataSerializeUtility.SerializeUshort(this.TilesCount, (int i) => (ushort)Mathf.Clamp(Mathf.RoundToInt(this.tiles[i].rainfall), 0, 65535));
            this.tileSwampiness  = DataSerializeUtility.SerializeByte(this.TilesCount, (int i) => (byte)Mathf.Clamp(Mathf.RoundToInt(this.tiles[i].swampiness * 255f), 0, 255));
            this.tileFeature     = DataSerializeUtility.SerializeUshort(this.TilesCount, (int i) => (this.tiles[i].feature != null) ? ((ushort)this.tiles[i].feature.uniqueID) : ushort.MaxValue);
            List <int>    list  = new List <int>();
            List <byte>   list2 = new List <byte>();
            List <ushort> list3 = new List <ushort>();

            for (int m = 0; m < this.TilesCount; m++)
            {
                List <Tile.RoadLink> potentialRoads = this.tiles[m].potentialRoads;
                if (potentialRoads != null)
                {
                    for (int j = 0; j < potentialRoads.Count; j++)
                    {
                        Tile.RoadLink roadLink = potentialRoads[j];
                        if (roadLink.neighbor >= m)
                        {
                            byte b = (byte)this.GetNeighborId(m, roadLink.neighbor);
                            if (b < 0)
                            {
                                Log.ErrorOnce("Couldn't find valid neighbor for road piece", 81637014, false);
                            }
                            else
                            {
                                list.Add(m);
                                list2.Add(b);
                                list3.Add(roadLink.road.shortHash);
                            }
                        }
                    }
                }
            }
            this.tileRoadOrigins   = DataSerializeUtility.SerializeInt(list.ToArray());
            this.tileRoadAdjacency = DataSerializeUtility.SerializeByte(list2.ToArray());
            this.tileRoadDef       = DataSerializeUtility.SerializeUshort(list3.ToArray());
            List <int>    list4 = new List <int>();
            List <byte>   list5 = new List <byte>();
            List <ushort> list6 = new List <ushort>();

            for (int k = 0; k < this.TilesCount; k++)
            {
                List <Tile.RiverLink> potentialRivers = this.tiles[k].potentialRivers;
                if (potentialRivers != null)
                {
                    for (int l = 0; l < potentialRivers.Count; l++)
                    {
                        Tile.RiverLink riverLink = potentialRivers[l];
                        if (riverLink.neighbor >= k)
                        {
                            byte b2 = (byte)this.GetNeighborId(k, riverLink.neighbor);
                            if (b2 < 0)
                            {
                                Log.ErrorOnce("Couldn't find valid neighbor for river piece", 81637014, false);
                            }
                            else
                            {
                                list4.Add(k);
                                list5.Add(b2);
                                list6.Add(riverLink.river.shortHash);
                            }
                        }
                    }
                }
            }
            this.tileRiverOrigins   = DataSerializeUtility.SerializeInt(list4.ToArray());
            this.tileRiverAdjacency = DataSerializeUtility.SerializeByte(list5.ToArray());
            this.tileRiverDef       = DataSerializeUtility.SerializeUshort(list6.ToArray());
        }
Exemplo n.º 4
0
        protected override void FillTab()
        {
            Vector2 winSize  = WinSize;
            float   x        = winSize.x;
            Vector2 winSize2 = WinSize;
            Rect    outRect  = new Rect(0f, 0f, x, winSize2.y).ContractedBy(10f);
            Rect    rect     = new Rect(0f, 0f, outRect.width - 16f, Mathf.Max(lastDrawnHeight, outRect.height));

            Widgets.BeginScrollView(outRect, ref scrollPosition, rect);
            Rect rect2 = rect;
            Rect rect3 = rect2;

            Text.Font = GameFont.Medium;
            Widgets.Label(rect3, base.SelTile.biome.LabelCap);
            Rect rect4 = rect2;

            rect4.yMin  += 35f;
            rect4.height = 99999f;
            Text.Font    = GameFont.Small;
            Listing_Standard listing_Standard = new Listing_Standard();

            listing_Standard.verticalSpacing = 0f;
            listing_Standard.Begin(rect4);
            Tile selTile   = base.SelTile;
            int  selTileID = base.SelTileID;

            listing_Standard.Label(selTile.biome.description);
            listing_Standard.Gap(8f);
            listing_Standard.GapLine();
            if (!selTile.biome.implemented)
            {
                listing_Standard.Label(selTile.biome.LabelCap + " " + "BiomeNotImplemented".Translate());
            }
            listing_Standard.LabelDouble("Terrain".Translate(), selTile.hilliness.GetLabelCap());
            if (selTile.Roads != null)
            {
                listing_Standard.LabelDouble("Road".Translate(), (from roadlink in selTile.Roads
                                                                  select roadlink.road.label).Distinct().ToCommaList(useAnd: true).CapitalizeFirst());
            }
            if (selTile.Rivers != null)
            {
                Listing_Standard listing_Standard2 = listing_Standard;
                string           leftLabel         = "River".Translate();
                Tile.RiverLink   riverLink         = selTile.Rivers.MaxBy((Tile.RiverLink riverlink) => riverlink.river.degradeThreshold);
                listing_Standard2.LabelDouble(leftLabel, riverLink.river.LabelCap);
            }
            if (!Find.World.Impassable(selTileID))
            {
                StringBuilder stringBuilder   = new StringBuilder();
                int           tile            = selTileID;
                bool          perceivedStatic = false;
                StringBuilder explanation     = stringBuilder;
                string        rightLabel      = (WorldPathGrid.CalculatedMovementDifficultyAt(tile, perceivedStatic, null, explanation) * Find.WorldGrid.GetRoadMovementDifficultyMultiplier(selTileID, -1, stringBuilder)).ToString("0.#");
                if (WorldPathGrid.WillWinterEverAffectMovementDifficulty(selTileID) && WorldPathGrid.GetCurrentWinterMovementDifficultyOffset(selTileID) < 2f)
                {
                    stringBuilder.AppendLine();
                    stringBuilder.AppendLine();
                    stringBuilder.Append(" (");
                    stringBuilder.Append("MovementDifficultyOffsetInWinter".Translate("+" + 2f.ToString("0.#")));
                    stringBuilder.Append(")");
                }
                listing_Standard.LabelDouble("MovementDifficulty".Translate(), rightLabel, stringBuilder.ToString());
            }
            if (selTile.biome.canBuildBase)
            {
                listing_Standard.LabelDouble("StoneTypesHere".Translate(), (from rt in Find.World.NaturalRockTypesIn(selTileID)
                                                                            select rt.label).ToCommaList(useAnd: true).CapitalizeFirst());
            }
            listing_Standard.LabelDouble("Elevation".Translate(), selTile.elevation.ToString("F0") + "m");
            listing_Standard.GapLine();
            listing_Standard.LabelDouble("AvgTemp".Translate(), GenTemperature.GetAverageTemperatureLabel(selTileID));
            listing_Standard.LabelDouble("OutdoorGrowingPeriod".Translate(), Zone_Growing.GrowingQuadrumsDescription(selTileID));
            listing_Standard.LabelDouble("Rainfall".Translate(), selTile.rainfall.ToString("F0") + "mm");
            if (selTile.biome.foragedFood != null && selTile.biome.forageability > 0f)
            {
                listing_Standard.LabelDouble("Forageability".Translate(), selTile.biome.forageability.ToStringPercent() + " (" + selTile.biome.foragedFood.label + ")");
            }
            else
            {
                listing_Standard.LabelDouble("Forageability".Translate(), "0%");
            }
            listing_Standard.LabelDouble("AnimalsCanGrazeNow".Translate(), (!VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsNowAt(selTileID)) ? "No".Translate() : "Yes".Translate());
            listing_Standard.GapLine();
            listing_Standard.LabelDouble("AverageDiseaseFrequency".Translate(), string.Format("{0} {1}", (60f / selTile.biome.diseaseMtbDays).ToString("F1"), "PerYear".Translate()));
            Listing_Standard listing_Standard3 = listing_Standard;
            string           leftLabel2        = "TimeZone".Translate();
            Vector2          vector            = Find.WorldGrid.LongLatOf(selTileID);

            listing_Standard3.LabelDouble(leftLabel2, GenDate.TimeZoneAt(vector.x).ToStringWithSign());
            StringBuilder stringBuilder2 = new StringBuilder();
            Rot4          rot            = Find.World.CoastDirectionAt(selTileID);

            if (rot.IsValid)
            {
                stringBuilder2.AppendWithComma(("HasCoast" + rot.ToString()).Translate());
            }
            if (Find.World.HasCaves(selTileID))
            {
                stringBuilder2.AppendWithComma("HasCaves".Translate());
            }
            if (stringBuilder2.Length > 0)
            {
                listing_Standard.LabelDouble("SpecialFeatures".Translate(), stringBuilder2.ToString().CapitalizeFirst());
            }
            if (Prefs.DevMode)
            {
                listing_Standard.LabelDouble("Debug world tile ID", selTileID.ToString());
            }
            lastDrawnHeight = rect4.y + listing_Standard.CurHeight;
            listing_Standard.End();
            Widgets.EndScrollView();
        }
Exemplo n.º 5
0
 private static int <FillTab> m__1(Tile.RiverLink riverlink)
 {
     return(riverlink.river.degradeThreshold);
 }
        public override IEnumerable Regenerate()
        {
            IEnumerator enumerator = base.Regenerate().GetEnumerator();

            try
            {
                if (enumerator.MoveNext())
                {
                    object result = enumerator.Current;
                    yield return(result);

                    /*Error: Unable to find new state assignment for yield return*/;
                }
            }
            finally
            {
                IDisposable disposable;
                IDisposable disposable2 = disposable = (enumerator as IDisposable);
                if (disposable != null)
                {
                    disposable2.Dispose();
                }
            }
            LayerSubMesh           subMesh       = base.GetSubMesh(WorldMaterials.Rivers);
            LayerSubMesh           subMeshBorder = base.GetSubMesh(WorldMaterials.RiversBorder);
            WorldGrid              grid          = Find.WorldGrid;
            List <OutputDirection> outputs       = new List <OutputDirection>();
            List <OutputDirection> outputsBorder = new List <OutputDirection>();

            for (int i = 0; i < grid.TilesCount; i++)
            {
                if (i % 1000 == 0)
                {
                    yield return((object)null);

                    /*Error: Unable to find new state assignment for yield return*/;
                }
                if (subMesh.verts.Count > 60000)
                {
                    subMesh       = base.GetSubMesh(WorldMaterials.Rivers);
                    subMeshBorder = base.GetSubMesh(WorldMaterials.RiversBorder);
                }
                Tile tile = grid[i];
                if (tile.rivers != null)
                {
                    outputs.Clear();
                    outputsBorder.Clear();
                    for (int j = 0; j < tile.rivers.Count; j++)
                    {
                        List <OutputDirection> list      = outputs;
                        OutputDirection        item      = default(OutputDirection);
                        Tile.RiverLink         riverLink = tile.rivers[j];
                        item.neighbor = riverLink.neighbor;
                        Tile.RiverLink riverLink2 = tile.rivers[j];
                        item.width = (float)(riverLink2.river.widthOnWorld - 0.20000000298023224);
                        list.Add(item);
                        List <OutputDirection> list2      = outputsBorder;
                        OutputDirection        item2      = default(OutputDirection);
                        Tile.RiverLink         riverLink3 = tile.rivers[j];
                        item2.neighbor = riverLink3.neighbor;
                        Tile.RiverLink riverLink4 = tile.rivers[j];
                        item2.width = riverLink4.river.widthOnWorld;
                        list2.Add(item2);
                    }
                    base.GeneratePaths(subMesh, i, outputs, this.riverColor, true);
                    base.GeneratePaths(subMeshBorder, i, outputsBorder, this.riverColor, true);
                }
            }
            base.FinalizeMesh(MeshParts.All);
            yield break;
IL_0335:
            /*Error near IL_0336: Unexpected return in MoveNext()*/;
        }
Exemplo n.º 7
0
        private void RawDataToTiles()
        {
            if (tiles.Count != TilesCount)
            {
                tiles.Clear();
                for (int j = 0; j < TilesCount; j++)
                {
                    tiles.Add(new Tile());
                }
            }
            else
            {
                for (int k = 0; k < TilesCount; k++)
                {
                    tiles[k].potentialRoads  = null;
                    tiles[k].potentialRivers = null;
                }
            }
            DataSerializeUtility.LoadUshort(tileBiome, TilesCount, delegate(int i, ushort data)
            {
                tiles[i].biome = DefDatabase <BiomeDef> .GetByShortHash(data) ?? BiomeDefOf.TemperateForest;
            });
            DataSerializeUtility.LoadUshort(tileElevation, TilesCount, delegate(int i, ushort data)
            {
                tiles[i].elevation = data - 8192;
            });
            DataSerializeUtility.LoadByte(tileHilliness, TilesCount, delegate(int i, byte data)
            {
                tiles[i].hilliness = (Hilliness)data;
            });
            DataSerializeUtility.LoadUshort(tileTemperature, TilesCount, delegate(int i, ushort data)
            {
                tiles[i].temperature = (float)(int)data / 10f - 300f;
            });
            DataSerializeUtility.LoadUshort(tileRainfall, TilesCount, delegate(int i, ushort data)
            {
                tiles[i].rainfall = (int)data;
            });
            DataSerializeUtility.LoadByte(tileSwampiness, TilesCount, delegate(int i, byte data)
            {
                tiles[i].swampiness = (float)(int)data / 255f;
            });
            int[]    array  = DataSerializeUtility.DeserializeInt(tileRoadOrigins);
            byte[]   array2 = DataSerializeUtility.DeserializeByte(tileRoadAdjacency);
            ushort[] array3 = DataSerializeUtility.DeserializeUshort(tileRoadDef);
            for (int l = 0; l < array.Length; l++)
            {
                int     num          = array[l];
                int     tileNeighbor = GetTileNeighbor(num, array2[l]);
                RoadDef byShortHash  = DefDatabase <RoadDef> .GetByShortHash(array3[l]);

                if (byShortHash != null)
                {
                    if (tiles[num].potentialRoads == null)
                    {
                        tiles[num].potentialRoads = new List <Tile.RoadLink>();
                    }
                    if (tiles[tileNeighbor].potentialRoads == null)
                    {
                        tiles[tileNeighbor].potentialRoads = new List <Tile.RoadLink>();
                    }
                    List <Tile.RoadLink> potentialRoads = tiles[num].potentialRoads;
                    Tile.RoadLink        item           = new Tile.RoadLink
                    {
                        neighbor = tileNeighbor,
                        road     = byShortHash
                    };
                    potentialRoads.Add(item);
                    List <Tile.RoadLink> potentialRoads2 = tiles[tileNeighbor].potentialRoads;
                    item = new Tile.RoadLink
                    {
                        neighbor = num,
                        road     = byShortHash
                    };
                    potentialRoads2.Add(item);
                }
            }
            int[]    array4 = DataSerializeUtility.DeserializeInt(tileRiverOrigins);
            byte[]   array5 = DataSerializeUtility.DeserializeByte(tileRiverAdjacency);
            ushort[] array6 = DataSerializeUtility.DeserializeUshort(tileRiverDef);
            for (int m = 0; m < array4.Length; m++)
            {
                int      num2          = array4[m];
                int      tileNeighbor2 = GetTileNeighbor(num2, array5[m]);
                RiverDef byShortHash2  = DefDatabase <RiverDef> .GetByShortHash(array6[m]);

                if (byShortHash2 != null)
                {
                    if (tiles[num2].potentialRivers == null)
                    {
                        tiles[num2].potentialRivers = new List <Tile.RiverLink>();
                    }
                    if (tiles[tileNeighbor2].potentialRivers == null)
                    {
                        tiles[tileNeighbor2].potentialRivers = new List <Tile.RiverLink>();
                    }
                    List <Tile.RiverLink> potentialRivers = tiles[num2].potentialRivers;
                    Tile.RiverLink        item2           = new Tile.RiverLink
                    {
                        neighbor = tileNeighbor2,
                        river    = byShortHash2
                    };
                    potentialRivers.Add(item2);
                    List <Tile.RiverLink> potentialRivers2 = tiles[tileNeighbor2].potentialRivers;
                    item2 = new Tile.RiverLink
                    {
                        neighbor = num2,
                        river    = byShortHash2
                    };
                    potentialRivers2.Add(item2);
                }
            }
        }
        protected override void FillTab()
        {
            Vector2 winSize  = WITab_Terrain.WinSize;
            float   x        = winSize.x;
            Vector2 winSize2 = WITab_Terrain.WinSize;
            Rect    rect     = new Rect(0f, 0f, x, winSize2.y).ContractedBy(10f);
            Rect    rect2    = rect;

            Text.Font = GameFont.Medium;
            Widgets.Label(rect2, base.SelTile.biome.LabelCap);
            Rect rect3 = rect;

            rect3.yMin += 35f;
            Text.Font   = GameFont.Small;
            Listing_Standard listing_Standard = new Listing_Standard();

            listing_Standard.verticalSpacing = 0f;
            listing_Standard.Begin(rect3);
            Tile    selTile   = base.SelTile;
            int     selTileID = base.SelTileID;
            Vector2 vector    = Find.WorldGrid.LongLatOf(selTileID);
            float   y         = vector.y;

            listing_Standard.Label(selTile.biome.description, -1f);
            listing_Standard.Gap(8f);
            listing_Standard.GapLine(12f);
            if (!selTile.biome.implemented)
            {
                listing_Standard.Label(selTile.biome.LabelCap + " " + "BiomeNotImplemented".Translate(), -1f);
            }
            listing_Standard.LabelDouble("Terrain".Translate(), selTile.hilliness.GetLabelCap());
            if (selTile.VisibleRoads != null)
            {
                listing_Standard.LabelDouble("Road".Translate(), GenText.ToCommaList((from roadlink in selTile.VisibleRoads
                                                                                      select roadlink.road.label).Distinct(), true).CapitalizeFirst());
            }
            if (selTile.VisibleRivers != null)
            {
                Listing_Standard listing_Standard2 = listing_Standard;
                string           leftLabel         = "River".Translate();
                Tile.RiverLink   riverLink         = selTile.VisibleRivers.MaxBy((Tile.RiverLink riverlink) => riverlink.river.degradeThreshold);
                listing_Standard2.LabelDouble(leftLabel, riverLink.river.LabelCap);
            }
            if (!Find.World.Impassable(selTileID))
            {
                int num      = 2500;
                int numTicks = Mathf.Min(num + WorldPathGrid.CalculatedCostAt(selTileID, false, -1f), 120000);
                listing_Standard.LabelDouble("MovementTimeNow".Translate(), numTicks.ToStringTicksToPeriod(true, false, true));
                int numTicks2 = Mathf.Min(num + WorldPathGrid.CalculatedCostAt(selTileID, false, Season.Summer.GetMiddleYearPct(y)), 120000);
                listing_Standard.LabelDouble("MovementTimeSummer".Translate(), numTicks2.ToStringTicksToPeriod(true, false, true));
                int numTicks3 = Mathf.Min(num + WorldPathGrid.CalculatedCostAt(selTileID, false, Season.Winter.GetMiddleYearPct(y)), 120000);
                listing_Standard.LabelDouble("MovementTimeWinter".Translate(), numTicks3.ToStringTicksToPeriod(true, false, true));
            }
            if (selTile.biome.canBuildBase)
            {
                listing_Standard.LabelDouble("StoneTypesHere".Translate(), GenText.ToCommaList(from rt in Find.World.NaturalRockTypesIn(selTileID)
                                                                                               select rt.label, true).CapitalizeFirst());
            }
            listing_Standard.LabelDouble("Elevation".Translate(), selTile.elevation.ToString("F0") + "m");
            listing_Standard.GapLine(12f);
            listing_Standard.LabelDouble("AvgTemp".Translate(), selTile.temperature.ToStringTemperature("F1"));
            float celsiusTemp = GenTemperature.AverageTemperatureAtTileForTwelfth(selTileID, Season.Winter.GetMiddleTwelfth(y));

            listing_Standard.LabelDouble("AvgWinterTemp".Translate(), celsiusTemp.ToStringTemperature("F1"));
            float celsiusTemp2 = GenTemperature.AverageTemperatureAtTileForTwelfth(selTileID, Season.Summer.GetMiddleTwelfth(y));

            listing_Standard.LabelDouble("AvgSummerTemp".Translate(), celsiusTemp2.ToStringTemperature("F1"));
            listing_Standard.LabelDouble("OutdoorGrowingPeriod".Translate(), Zone_Growing.GrowingQuadrumsDescription(selTileID));
            listing_Standard.LabelDouble("Rainfall".Translate(), selTile.rainfall.ToString("F0") + "mm");
            listing_Standard.LabelDouble("AnimalsCanGrazeNow".Translate(), (!VirtualPlantsUtility.EnvironmentAllowsEatingVirtualPlantsNowAt(selTileID)) ? "No".Translate() : "Yes".Translate());
            listing_Standard.GapLine(12f);
            listing_Standard.LabelDouble("AverageDiseaseFrequency".Translate(), string.Format("{0} {1}", ((float)(60.0 / selTile.biome.diseaseMtbDays)).ToString("F1"), "PerYear".Translate()));
            Listing_Standard listing_Standard3 = listing_Standard;
            string           leftLabel2        = "TimeZone".Translate();
            Vector2          vector2           = Find.WorldGrid.LongLatOf(selTileID);

            listing_Standard3.LabelDouble(leftLabel2, GenDate.TimeZoneAt(vector2.x).ToStringWithSign());
            StringBuilder stringBuilder = new StringBuilder();
            Rot4          rot           = Find.World.CoastDirectionAt(selTileID);

            if (rot.IsValid)
            {
                stringBuilder.AppendWithComma(("HasCoast" + rot.ToString()).Translate());
            }
            if (Find.World.HasCaves(selTileID))
            {
                stringBuilder.AppendWithComma("HasCaves".Translate());
            }
            if (stringBuilder.Length > 0)
            {
                listing_Standard.LabelDouble("SpecialFeatures".Translate(), stringBuilder.ToString().CapitalizeFirst());
            }
            if (Prefs.DevMode)
            {
                listing_Standard.LabelDouble("Debug world tile ID", selTileID.ToString());
            }
            listing_Standard.End();
        }