Decompiled source of SakuraSanctuary v0.6.1

plugins/SakuraSanctuary/SakuraSanctuary.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using SakuraSanctuary.Core;
using SakuraSanctuary.Dev;
using SakuraSanctuary.Game;
using SakuraSanctuary.Gen;
using TMPro;
using TrueFinalAscent.Api;
using Unity.Profiling;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Zorro.Core.Runtime")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SakuraSanctuary
{
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(MapHandler), "InitializeMap")]
		private static void AfterInitializeMap()
		{
			SanctuaryRuntime.AfterInitializeMap();
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void Title(ProgressPoint __instance, ref string __result)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (SanctuaryRuntime.Active && !SanctuaryRuntime.Current.Tfa && __instance.biome == SanctuaryRuntime.Current.Biome)
			{
				__result = "SAKURA";
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Spawner), "GetObjectsToSpawn")]
		private static void SakuraLoot(Spawner __instance, ref List<GameObject> __result)
		{
			if (!(__instance is Luggage) || __result == null || __result.Count == 0 || !SanctuaryRuntime.Active)
			{
				return;
			}
			GameObject val = SanctuaryRuntime.Current?.Root;
			if (!((Object)(object)val == (Object)null) && ((Component)__instance).transform.IsChildOf(val.transform))
			{
				GameObject val2 = SakuraItems.LootPick();
				if (!((Object)(object)val2 == (Object)null))
				{
					__result[Random.Range(0, __result.Count)] = val2;
				}
			}
		}
	}
	[BepInPlugin("mirts.SakuraSanctuary", "Sakura Sanctuary", "0.6.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public enum Quality
		{
			Low,
			Medium,
			High,
			Ultra
		}

		public enum BiomePosition
		{
			Auto,
			SecondBiome,
			ThirdBiome
		}

		public const string Id = "mirts.SakuraSanctuary";

		public const string Name = "Sakura Sanctuary";

		public const string Version = "0.6.1";

		public const int GeneratorVersion = 9;

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		internal static string ConflictingPlugin;

		internal static bool TfaLinked;

		internal static bool DevMode;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<int> FixedSeed;

		internal static ConfigEntry<float> SpawnChance;

		internal static ConfigEntry<BiomePosition> Position;

		internal static ConfigEntry<float> Difficulty;

		internal static ConfigEntry<bool> BridgeHazards;

		internal static ConfigEntry<bool> WindHazards;

		internal static ConfigEntry<float> FogSpeed;

		internal static ConfigEntry<bool> AdditionalLoot;

		internal static ConfigEntry<bool> HostWarpKey;

		internal static ConfigEntry<Quality> Graphics;

		internal static ConfigEntry<float> PetalDensity;

		internal static ConfigEntry<float> ViewDistance;

		internal static ConfigEntry<bool> DepthPriming;

		internal static ConfigEntry<bool> SoftTextures;

		internal static ConfigEntry<bool> Ambience;

		internal static ConfigEntry<float> AmbientVolume;

		internal static ConfigEntry<float> WaterVolume;

		internal static ConfigEntry<float> WindVolume;

		internal static ConfigEntry<float> TempleVolume;

		internal static ConfigEntry<bool> KeepVanillaMusic;

		internal static ConfigEntry<string> AutoTest;

		internal static ConfigEntry<int> AutoTestLevel;

		internal static ConfigEntry<bool> AutoTestQuit;

		internal static ConfigEntry<bool> DevHotkeys;

		internal static ConfigEntry<bool> ShowRoute;

		internal static ConfigEntry<int> DevSlot;

		private static readonly string[] Conflicts = new string[6] { "PLL", "AllBiomes", "TerrainRandomiser", "TerrainCustomiser", "PeakWorkshop", "LostCity" };

		private void Awake()
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Expected O, but got Unknown
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Expected O, but got Unknown
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Expected O, but got Unknown
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Expected O, but got Unknown
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Expected O, but got Unknown
			//IL_0387: Unknown result type (might be due to invalid IL or missing references)
			//IL_0391: Expected O, but got Unknown
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Expected O, but got Unknown
			//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ed: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Replace the second biome (Tropics / Roots) with Sakura Sanctuary. In multiplayer the host's value counts.");
			FixedSeed = ((BaseUnityPlugin)this).Config.Bind<int>("General", "FixedSeed", 0, "0 = a new mountain with every daily island (the same for everyone on it). Any other number always builds that one variant. Host.");
			SpawnChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "SpawnChance", 1f, new ConfigDescription("Chance that an island gets the sanctuary at all (0..1). Decided per island, the same for everyone in the lobby. Host.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			Position = ((BaseUnityPlugin)this).Config.Bind<BiomePosition>("General", "Position", BiomePosition.SecondBiome, "Where the sanctuary appears: SecondBiome = instead of Tropics/Roots (tested). ThirdBiome / Auto (2nd or 3rd per island) are experimental. Host.");
			Difficulty = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "Difficulty", 1f, new ConfigDescription("Scales the climbing stamina cost on the sanctuary's cliffs (1 = as designed). Host.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 1.6f), Array.Empty<object>()));
			BridgeHazards = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "BridgeHazards", true, "Worn plank bridges creak and break once too many scouts have crossed them; broken temple boards fall when stood on. Host.");
			WindHazards = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "WindHazards", true, "Gusts on the exposed upper cliffs push climbers sideways (announced by rising wind and flying petals). Host.");
			FogSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "FogSpeedMultiplier", 0.75f, new ConfigDescription("How fast the rising fog closes in during the sanctuary, compared with vanilla. Host's fog is what everyone sees.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), Array.Empty<object>()));
			AdditionalLoot = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "ShrineOfferings", true, "Small shrines along the way hold a suitcase or an offering box with food. Host.");
			HostWarpKey = ((BaseUnityPlugin)this).Config.Bind<bool>("Host", "F6WarpToSanctuaryGate", true, "F6 (host only): bring every scout to the Shore campfire, the last one before the sanctuary.");
			Graphics = ((BaseUnityPlugin)this).Config.Bind<Quality>("Visuals", "GraphicsQuality", Quality.High, "Vegetation density, falling petals, small decoration and draw distance. Climbing routes and collisions are identical on every level.");
			PetalDensity = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "SakuraPetalDensity", 1f, new ConfigDescription("Multiplier for the falling cherry petals.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			ViewDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "ViewDistanceMultiplier", 1f, new ConfigDescription("Multiplier for the distance at which detail is hidden.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			DepthPriming = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "DepthPriming", true, "Inside the sakura biome the graphics card draws a quick depth pass first, so the stacked blossom crowns are shaded only once (much smoother when looking up the mountain, same picture). Turn off only if you see graphics glitches.");
			SoftTextures = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "PeakStyleTextures", true, "Softer textures closer to PEAK's painted look (the fine grain of the rock, wood and bark melts a few metres away). Off = the full detail.");
			Ambience = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "Ambience", true, "The sanctuary's own sounds: wind in the blossoms, water, creaking wood, wind chimes at the temple.");
			AmbientVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "AmbientVolume", 1f, new ConfigDescription("Master volume of the sanctuary's sounds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			WaterVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "WaterVolume", 1f, new ConfigDescription("Streams and waterfalls.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			WindVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "WindVolume", 1f, new ConfigDescription("Wind in the trees and on the cliffs.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			TempleVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "TempleAmbienceVolume", 1f, new ConfigDescription("Wind chimes and the temple bell.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			KeepVanillaMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "KeepVanillaMusic", false, "Play the replaced biome's climb music (Tropics/Roots or Alpine/Mesa) inside the sanctuary too. Off by default: it does not fit the cherry blossoms.");
			string text = Path.Combine(Paths.ConfigPath, "SakuraSanctuary.Dev.cfg");
			DevMode = File.Exists(text);
			ConfigFile val = new ConfigFile(text, false, ((BaseUnityPlugin)this).Info.Metadata)
			{
				SaveOnConfigSet = DevMode
			};
			AutoTest = val.Bind<string>("Dev", "AutoTest", "", "'' = off. 'survey' = dump the vanilla slot. 'tour' = screenshots of the sanctuary + route probes. 'play' = leave me at the Shore campfire.");
			AutoTestLevel = val.Bind<int>("Dev", "Level", 17, "Island (Level_N) used by AutoTest.");
			AutoTestQuit = val.Bind<bool>("Dev", "Quit", true, "Quit the game when the auto test is done.");
			DevHotkeys = val.Bind<bool>("Dev", "Hotkeys", true, "F7 warp to temple, F8 jump to slot 2 (host), F9 dump, F10 screenshot tour, F11 next route node.");
			DevSlot = val.Bind<int>("Dev", "Slot", 0, "Force the sanctuary into segment 1 (2nd biome) or 2 (3rd biome), ignoring the chance. 0 = normal rules.");
			ShowRoute = val.Bind<bool>("Dev", "ShowRoute", false, "Draw the planned climbing route (rest spots, climbs, jumps) as coloured markers.");
			if (DevMode)
			{
				MountainGenerator.Terrain2 = val.Bind<bool>("Dev", "Terrain2", true, "false = the 0.1.x pillar field (A/B tests only).").Value;
			}
			if (DevMode)
			{
				MistBuilder.NoStrata = val.Bind<bool>("Dev", "NoStrata", false, "true = no mist strata (A/B tests only).").Value;
			}
			if (DevMode)
			{
				MountainGenerator.NoEdgeFix = val.Bind<bool>("Dev", "NoEdgeFix", false, "true = the 0.2.5 map edge (A/B tests only).").Value;
			}
			if (DevMode)
			{
				WaterBuilder.NoErode = val.Bind<bool>("Dev", "NoWaterErode", false, "true = water over clefts as in 0.2.2 (A/B tests only).").Value;
			}
			foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
			{
				if (value2.Metadata.GUID == "mirts.SakuraSanctuary")
				{
					continue;
				}
				string text2 = value2.Metadata.GUID + " " + value2.Metadata.Name;
				string[] conflicts = Conflicts;
				foreach (string value in conflicts)
				{
					if (text2.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						ConflictingPlugin = value2.Metadata.Name;
					}
				}
			}
			LinkTrueFinalAscent();
			Harmony val2 = new Harmony("mirts.SakuraSanctuary");
			val2.PatchAll(typeof(Plugin).Assembly);
			if (DevMode && AutoTest.Value.Trim().ToLowerInvariant() != "perf")
			{
				RootMoveWatch.Install(val2);
			}
			SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode _)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				SanctuaryRuntime.OnSceneLoaded(scene);
			};
			((Component)this).gameObject.AddComponent<Handshake>();
			((Component)this).gameObject.AddComponent<HostWarp>();
			((Component)this).gameObject.AddComponent<FogPace>();
			((Component)this).gameObject.AddComponent<PocketCharms>();
			if (DevMode)
			{
				((Component)this).gameObject.AddComponent<DevTools>();
				if (!string.IsNullOrEmpty(AutoTest.Value))
				{
					((Component)this).gameObject.AddComponent<AutoDriver>();
				}
			}
			Log.LogInfo((object)("Sakura Sanctuary 0.6.1 loaded" + ((ConflictingPlugin != null) ? (" (inactive: " + ConflictingPlugin + " rewrites the map)") : "") + (TfaLinked ? " (FINAL ASCENT biome registered with True Final Ascent)" : "") + (DevMode ? " [dev mode]" : "")));
		}

		private static void LinkTrueFinalAscent()
		{
			if (!Chainloader.PluginInfos.TryGetValue("com.CptPICHU.peak.truefinalascent", out var value))
			{
				return;
			}
			Assembly assembly = (((Object)(object)value.Instance != (Object)null) ? ((object)value.Instance).GetType().Assembly : null);
			if (assembly == null)
			{
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly2 in assemblies)
				{
					if (assembly2.GetName().Name == "TrueFinalAscent")
					{
						assembly = assembly2;
					}
				}
			}
			if (assembly?.GetType("TrueFinalAscent.Api.TfaBiomes") == null)
			{
				ConflictingPlugin = value.Metadata.Name + " " + value.Metadata.Version?.ToString() + " (no biome API yet: update it to 2.10 or newer)";
				return;
			}
			try
			{
				TfaLinked = TfaBridge.Register();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not register with True Final Ascent: " + ex.Message));
			}
			if (!TfaLinked)
			{
				ConflictingPlugin = value.Metadata.Name + " (biome registration failed)";
			}
		}
	}
}
namespace SakuraSanctuary.Gen
{
	public static class MountainGenerator
	{
		private sealed class ColumnField
		{
			public float Size;

			public float Follow = 0.9f;

			public float MaxGradient = 6f;

			public ulong Seed;

			public readonly Dictionary<long, (Vector2 p, float top, Vector2 tilt)> Cells = new Dictionary<long, (Vector2, float, Vector2)>();
		}

		private sealed class Zones
		{
			public float F0 = 60f;

			public float F1;

			public float V1;

			public float G1;

			public float Ga1;

			public float End;

			public float ApproachY;

			public float FloorY = -55f;
		}

		private sealed class Massif
		{
			public readonly List<Vector2> Spine = new List<Vector2>();

			public readonly List<float> Half = new List<float>();

			public readonly List<float> Crest = new List<float>();

			public float Flank;

			public float Seed;

			public float Rugged = 1f;

			public string Name;

			public readonly List<Vector2> Notches = new List<Vector2>();
		}

		private sealed class Cut
		{
			public readonly List<Vector2> Line = new List<Vector2>();

			public readonly List<float> Floor = new List<float>();

			public float Half;

			public float Wall;

			public bool River;
		}

		private sealed class T2
		{
			public float Z0;

			public float CapY0;

			public float CapRate = 0.85f;

			public float StepSeed;

			public readonly List<Massif> Massifs = new List<Massif>();

			public readonly List<Cut> Cuts = new List<Cut>();

			public readonly List<Pillar> Needles = new List<Pillar>();
		}

		private sealed class Ctx
		{
			public GenInput In;

			public ulong Seed;

			public Rng Rng;

			public Noise2 N1;

			public Noise2 N2;

			public Noise2 N3;

			public MountainLayout L;

			public HeightGrid G;

			public float[] Levels;

			public float[] ProfZ;

			public float[] ProfY;

			public float RiverPhase;

			public float RiverPhase2;

			public float RiverX0;

			public float GorgeX;

			public List<Pillar> Pillars2 = new List<Pillar>();

			public T2 T2;

			public Zones Zn;

			public List<Vector2> EdgeSaddles;

			public Dictionary<int, Vector2> DropRims;

			public float LastSteps;

			public float LastCut;

			public bool[] NoTerrace;

			public List<Vector4> Mounds = new List<Vector4>();

			public bool[] KeepClear;

			public bool[] Water;

			public List<Vector4> WaterBodies = new List<Vector4>();

			public PassagePlan Passage;
		}

		private sealed class Body
		{
			public Vector2 C;

			public Vector2 Half;

			public float Cos = 1f;

			public float Sin;

			public float Round = 1f;

			public float Top;

			public float Sheer = 7f;

			public float Wobble;

			public float Bevel = 0.4f;

			public float Dome;

			public float Rough;

			public float NoiseSeed;

			public Vector2 Tilt;

			public Vector2 FaceDir;

			public float SideSheer;

			public bool Path;

			public string Name;

			public void SetYaw(float yaw)
			{
				Cos = Mathf.Cos(yaw);
				Sin = Mathf.Sin(yaw);
			}

			public static Body Segment(Vector3 a, Vector3 b, float halfWidth, float extend, string name)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00db: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(b.x - a.x, b.z - a.z);
				float num = Mathf.Max(0.5f, ((Vector2)(ref val)).magnitude);
				Vector2 val2 = val / num;
				return new Body
				{
					C = new Vector2((a.x + b.x) * 0.5f, (a.z + b.z) * 0.5f),
					Half = new Vector2(halfWidth, num * 0.5f + extend),
					Top = (a.y + b.y) * 0.5f,
					Tilt = val2 * ((b.y - a.y) / num),
					Round = Mathf.Min(halfWidth, 1.2f),
					Path = true,
					Name = name,
					Sin = 0f - val2.x,
					Cos = val2.y
				};
			}
		}

		private sealed class PassagePlan
		{
			public float Z0;

			public float Z1;

			public float X0 = -95f;

			public float X1 = 95f;

			public readonly List<Body> Bodies = new List<Body>();

			public readonly List<Vector3> PathPts = new List<Vector3>();

			public readonly List<(Vector3 pos, string kind)> Places = new List<(Vector3, string)>();

			public readonly List<Vector2> River = new List<Vector2>();

			public readonly List<(float z, float bed)> Bed = new List<(float, float)>();

			public float Side;

			public readonly List<(string, Vector3, Vector3)> WayViews = new List<(string, Vector3, Vector3)>();

			public float RiverZ0;

			public float RiverZ1;

			public float BankY;
		}

		public const float FlankFrom = 55f;

		public const float DropDepth = 7.5f;

		public const float FrameFrom = 5f;

		public const float FrameFace = 9f;

		public static bool Terrain2 = true;

		public static bool NoEdgeFix;

		public const float Cell = 1.25f;

		public const float GX0 = -172f;

		public const float GZ0 = 22f;

		public const float GX1 = 198f;

		private static (Vector2 p, float top, Vector2 tilt) ColumnCell(Ctx c, ColumnField f, int cx, int cz)
		{
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			long key = ((long)cx << 32) ^ (uint)cz;
			if (f.Cells.TryGetValue(key, out (Vector2, float, Vector2) value))
			{
				return value;
			}
			ulong num = Hash.Mix(f.Seed, (ulong)((long)(uint)cx * 2654435761L) ^ ((ulong)(uint)cz << 21), 0uL);
			float num2 = ((float)(num & 0xFFFF) / 65535f - 0.5f) * 0.8f;
			float num3 = ((float)((num >> 16) & 0xFFFF) / 65535f - 0.5f) * 0.8f;
			float num4 = (float)((num >> 32) & 0xFFFF) / 65535f - 0.5f;
			float num5 = ((float)((num >> 48) & 0xFF) / 255f - 0.5f) * 0.1f;
			float num6 = ((float)((num >> 56) & 0xFF) / 255f - 0.5f) * 0.1f;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(((float)cx + 0.5f + num2) * f.Size, ((float)cz + 0.5f + num3) * f.Size);
			float item = Raw(c, val.x, val.y) + num4 * 1.2f;
			Vector2 val2 = new Vector2(Raw(c, val.x + 1.5f, val.y) - Raw(c, val.x - 1.5f, val.y), Raw(c, val.x, val.y + 1.5f) - Raw(c, val.x, val.y - 1.5f)) / 3f;
			if (((Vector2)(ref val2)).magnitude > f.MaxGradient)
			{
				val2 = ((Vector2)(ref val2)).normalized * f.MaxGradient;
			}
			value = (val, item, val2 * f.Follow + new Vector2(num5, num6));
			f.Cells[key] = value;
			return value;
		}

		private static float ColumnAt(Ctx c, ColumnField f, float x, float z, out Vector2 toJoint, out float jointDist, out float step)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.FloorToInt(x / f.Size);
			int num2 = Mathf.FloorToInt(z / f.Size);
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(x, z);
			float num3 = float.MaxValue;
			float num4 = float.MaxValue;
			(Vector2, float, Vector2) tuple = default((Vector2, float, Vector2));
			(Vector2, float, Vector2) tuple2 = default((Vector2, float, Vector2));
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					(Vector2, float, Vector2) tuple3 = ColumnCell(c, f, num + j, num2 + i);
					Vector2 val2 = tuple3.Item1 - val;
					float sqrMagnitude = ((Vector2)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num3)
					{
						num4 = num3;
						tuple2 = tuple;
						num3 = sqrMagnitude;
						tuple = tuple3;
					}
					else if (sqrMagnitude < num4)
					{
						num4 = sqrMagnitude;
						tuple2 = tuple3;
					}
				}
			}
			Vector2 val3 = tuple2.Item1 - tuple.Item1;
			float magnitude = ((Vector2)(ref val3)).magnitude;
			Vector2 val4 = ((magnitude > 0.0001f) ? (val3 / magnitude) : Vector2.right);
			jointDist = (num4 - num3) / (2f * Mathf.Max(magnitude, 0.0001f));
			toJoint = val4;
			float num5 = tuple.Item2 + Vector2.Dot(tuple.Item3, val - tuple.Item1);
			float num6 = tuple2.Item2 + Vector2.Dot(tuple2.Item3, val - tuple2.Item1);
			step = num5 - num6;
			return num5;
		}

		private static void ShapeColumns(Ctx c)
		{
			HeightGrid g = c.G;
			string text = Environment.GetEnvironmentVariable("SAKURA_DEBUG") ?? "";
			float[] array = new float[g.W * g.H];
			float[] array2 = new float[g.W * g.H];
			float[] array3 = new float[g.W * g.H];
			for (int i = 0; i < g.H; i++)
			{
				for (int j = 0; j < g.W; j++)
				{
					c.LastSteps = 0f;
					c.LastCut = 0f;
					array[g.Idx(j, i)] = Raw(c, g.Xof(j), g.Zof(i));
					array2[g.Idx(j, i)] = c.LastSteps;
					array3[g.Idx(j, i)] = c.LastCut;
				}
			}
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			ColumnField columnField = new ColumnField
			{
				Size = 13f,
				Seed = Hash.Mix(c.Seed, "columns")
			};
			ColumnField f = new ColumnField
			{
				Size = 6.5f,
				Follow = 0.45f,
				MaxGradient = 0.9f,
				Seed = Hash.Mix(c.Seed, "footholds")
			};
			c.L.TerraceYY = new float[g.W * g.H];
			c.L.TerraceRiser = new float[g.W * g.H];
			c.L.TerraceLevels = c.Levels;
			c.L.ColumnSnap = (Vector2[])(object)new Vector2[g.W * g.H];
			Zones zn = c.Zn;
			int num4 = 0;
			for (int k = 0; k < g.H; k++)
			{
				for (int l = 0; l < g.W; l++)
				{
					int num5 = g.Idx(l, k);
					float num6 = g.Xof(l);
					float num7 = g.Zof(k);
					int num8 = Math.Max(l - 1, 0);
					int num9 = Math.Min(l + 1, g.W - 1);
					int num10 = Math.Max(k - 1, 0);
					int num11 = Math.Min(k + 1, g.H - 1);
					float num12 = (array[g.Idx(num9, k)] - array[g.Idx(num8, k)]) / ((float)(num9 - num8) * g.Cell);
					float num13 = (array[g.Idx(l, num11)] - array[g.Idx(l, num10)]) / ((float)(num11 - num10) * g.Cell);
					float x = Mathf.Sqrt(num12 * num12 + num13 * num13);
					float num14 = (c.L.ForestLifted ? 0f : (1f - Smooth(zn.F1 - 25f, zn.F1 - 5f, num7)));
					float num15 = Smooth(-0.35f, 0.45f, c.N1.Sample(num6 * 0.022f + 83f, num7 * 0.022f));
					float num16 = Smooth(0.85f, 2.2f, x) * (0.25f + 0.75f * num15) * (1f - num14);
					Vector2 toJoint;
					float jointDist;
					float step;
					float num17 = ColumnAt(c, columnField, num6, num7, out toJoint, out jointDist, out step);
					float num18 = Smooth(0f, g.Cell * 1.2f, jointDist);
					float num19 = Mathf.Clamp(num17 - array[num5], -2.4f, 2.4f);
					float num20 = ((c.T2 != null) ? Smooth(c.T2.Z0 - 18f, c.T2.Z0, num7) : 0f);
					float num21 = ((num20 > 0f) ? FractureNear(c, num6, num7) : 0f);
					num16 *= 1f - num20 * (1f - num21);
					if (text.Contains("noshape"))
					{
						g[l, k] = array[num5];
						continue;
					}
					g[l, k] = array[num5] + num19 * num16 * num18;
					if (num20 > 0f)
					{
						float num22 = Smooth(0.15f, 0.45f, c.N2.Sample(num6 * 0.02f + 211f, num7 * 0.02f - 5f));
						float num23 = Smooth(c.In.WallXMin - 2f, c.In.WallXMin + 12f, num6) * (1f - Smooth(c.In.WallXMax - 12f, c.In.WallXMax + 2f, num6));
						float num24 = num20 * Smooth(1f, 2f, x) * num22 * num23 * (1f - num21);
						if (!NoEdgeFix && Mathf.Abs(num6) > 60f)
						{
							num24 = 0f;
						}
						if (num24 > 0f)
						{
							g[l, k] = Mathf.Lerp(g[l, k], Bedding(c, array[num5], num6, num7), num24);
						}
						float num25 = (NoEdgeFix ? 0f : (num20 * (1f - array2[num5]) * (1f - Smooth(0.5f, 3f, array3[num5]))));
						if (num25 > 0.01f)
						{
							float num26 = AdaptiveSteps(c, array[num5], num6, num7, num12, num13);
							float num27 = num25;
							if (!NoEdgeFix && Mathf.Abs(num6) > 60f)
							{
								num26 = CliffBands(c, array[num5], num6, num7, num12, num13);
								num27 = Smooth(0.45f, 0.55f, num25);
								if (num27 > 0.5f)
								{
									num2++;
								}
							}
							g[l, k] += (num26 - array[num5]) * num27;
							if (num25 > 0.5f)
							{
								num++;
							}
						}
					}
					float num28 = RiverX(c, num7) * 0.35f + 12f * Mathf.Sin(num7 / 37f + c.RiverPhase);
					float x2 = Mathf.Min(Mathf.Abs(num6 - num28 - 24f), Mathf.Abs(num6 - num28 + 24f));
					float num29 = (1f - Smooth(15f, 24f, x2)) * Smooth(0.28f, 0.55f, x);
					if (c.T2 != null)
					{
						num29 *= 1f - Smooth(c.T2.Z0 - 18f, c.T2.Z0, num7) * (1f - FractureNear(c, num6, num7));
					}
					if (num29 > 0f)
					{
						g[l, k] = Mathf.Lerp(g[l, k], ColumnAt(c, f, num6, num7, out toJoint, out step, out var _), num29);
					}
					if (num16 > 0.5f)
					{
						num4++;
					}
					if (Mathf.Abs(num6) > 65f && num6 > c.In.WallXMin && num6 < c.In.WallXMax)
					{
						num3++;
					}
				}
			}
			c.L.Report.Add($"massif rock: {columnField.Cells.Count} fracture cells, {num4} exposed vertices; continuous slopes, bounded 2.4 m relief; {num} cells stepped off the route, outer flanks {num2}/{num3} cells in cliff bands");
		}

		private static void FlankCliffs(Ctx c)
		{
			if (NoEdgeFix)
			{
				return;
			}
			HeightGrid g = c.G;
			float[] array = (float[])g.Y.Clone();
			int num = 0;
			for (int i = 0; i < g.H; i++)
			{
				for (int j = 0; j < g.W; j++)
				{
					float num2 = g.Xof(j);
					float z = g.Zof(i);
					if (!(Mathf.Abs(num2) <= 60f) && !(num2 < c.In.WallXMin - 4f) && !(num2 > c.In.WallXMax + 4f))
					{
						int num3 = g.Idx(j, i);
						float num4 = array[num3];
						if (!float.IsNaN(num4) && !(num4 < 12f))
						{
							int num5 = Math.Max(j - 1, 0);
							int num6 = Math.Min(j + 1, g.W - 1);
							int num7 = Math.Max(i - 1, 0);
							int num8 = Math.Min(i + 1, g.H - 1);
							float sx = (array[g.Idx(num6, i)] - array[g.Idx(num5, i)]) / ((float)(num6 - num5) * g.Cell);
							float sz = (array[g.Idx(j, num8)] - array[g.Idx(j, num7)]) / ((float)(num8 - num7) * g.Cell);
							g.Y[num3] = Mathf.Lerp(num4, CliffBands(c, num4, num2, z, sx, sz), 1f);
							num++;
						}
					}
				}
			}
			c.L.Report.Add($"flank cliffs in front of the massifs: {num} cells");
		}

		private static float CliffBands(Ctx c, float y, float x, float z, float sx, float sz)
		{
			float seed = ((c.T2 != null) ? (c.T2.StepSeed + 53f) : 53f);
			float num = Off(x, z);
			float num2 = (y + num) / 11.5f;
			float num3 = Mathf.Floor(num2);
			float num4 = num2 - num3;
			float num5 = sx + (Off(x + 0.5f, z) - Off(x - 0.5f, z));
			float num6 = sz + (Off(x, z + 0.5f) - Off(x, z - 0.5f));
			float num7 = Mathf.Clamp(Mathf.Sqrt(num5 * num5 + num6 * num6) * 2f / 11.5f, 0.02f, 0.4f);
			float num8 = Smooth(1f - num7, 1f, num4) * 0.92f + num4 * 0.08f;
			return (num3 + num8) * 11.5f - num;
			float Off(float px, float pz)
			{
				return 1.6f * c.N1.Sample(px * 0.03f + seed, pz * 0.03f) + 1f * c.N2.Sample(px * 0.07f - seed, pz * 0.05f + 77f) + 0.4f * c.N3.Sample(px * 0.13f, pz * 0.13f + seed);
			}
		}

		private static float AdaptiveSteps(Ctx c, float y, float x, float z, float sx, float sz)
		{
			float seed = ((c.T2 != null) ? (c.T2.StepSeed + 17f) : 0f);
			float num = Off(x, z);
			float num2 = (y + num + 0.6f * Mathf.Sin(y * 0.37f + seed)) / 5.2f;
			float num3 = Mathf.Floor(num2);
			float num4 = num2 - num3;
			float num5 = sx + (Off(x + 0.5f, z) - Off(x - 0.5f, z));
			float num6 = sz + (Off(x, z + 0.5f) - Off(x, z - 0.5f));
			float num7 = Mathf.Clamp(Mathf.Sqrt(num5 * num5 + num6 * num6) * (1f + 0.22200002f * Mathf.Abs(Mathf.Cos(y * 0.37f + seed))) * 1.2f / 5.2f, 0.01f, 0.32f);
			float num8 = Smooth(1f - num7, 1f, num4) * 0.88f + num4 * 0.12f;
			return (num3 + num8) * 5.2f - num;
			float Off(float px, float pz)
			{
				return 3.2f * c.N1.Sample(px * 0.07f + seed, pz * 0.05f) + 2.5f * c.N2.Sample(px * 0.11f - seed, pz * 0.02f + 31f) + 0.6f * c.N3.Sample(px * 0.15f, pz * 0.15f + seed) + 0.16f * px;
			}
		}

		private static void ForestWalk(Ctx c)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			HeightGrid g = c.G;
			Vector3[] array = (Vector3[])(object)new Vector3[5]
			{
				new Vector3(-18f, 0f, 72f),
				new Vector3(22f, 0f, 96f),
				new Vector3(-22f, 0f, 120f),
				new Vector3(22f, 0f, 144f),
				new Vector3(0f, 0f, c.Zn.F1 + 10f)
			};
			for (int i = 0; i < array.Length; i++)
			{
				array[i].y = g.Sample(array[i].x, array[i].z);
			}
			int num = 0;
			Vector2 val = default(Vector2);
			Vector2 val2 = default(Vector2);
			for (int j = g.Jz(62f); j <= g.Jz(c.Zn.F1 + 18f); j++)
			{
				for (int k = g.Ix(-36f); k <= g.Ix(36f); k++)
				{
					((Vector2)(ref val))..ctor(g.Xof(k), g.Zof(j));
					float num2 = float.MaxValue;
					float num3 = g[k, j];
					Vector2 val4;
					for (int l = 1; l < array.Length; l++)
					{
						((Vector2)(ref val2))..ctor(array[l - 1].x, array[l - 1].z);
						Vector2 val3 = new Vector2(array[l].x, array[l].z) - val2;
						float num4 = Mathf.Clamp01(Vector2.Dot(val - val2, val3) / ((Vector2)(ref val3)).sqrMagnitude);
						val4 = val - (val2 + val3 * num4);
						float magnitude = ((Vector2)(ref val4)).magnitude;
						if (!(magnitude >= num2))
						{
							num2 = magnitude;
							num3 = Mathf.Lerp(array[l - 1].y, array[l].y, num4);
						}
					}
					if (num2 < 7f)
					{
						float num5 = 1f - Smooth(2.8f, 7f, num2);
						g[k, j] = Mathf.Lerp(g[k, j], num3, num5);
						num++;
					}
					val4 = val - new Vector2(-22f, 120f);
					float magnitude2 = ((Vector2)(ref val4)).magnitude;
					if (magnitude2 < 12f)
					{
						g[k, j] = Mathf.Lerp(g[k, j], array[2].y, 1f - Smooth(9f, 12f, magnitude2));
					}
				}
			}
			c.L.ForestRest = array[2] + new Vector3(4f, 0f, 0f);
			c.L.Views.Add(("18_switchback", array[1] + new Vector3(-7f, 5f, -10f), array[2] + Vector3.up * 1.5f));
			c.L.Views.Add(("19_forest_rest", array[2] + new Vector3(9f, 1.7f, -4f), array[2] + new Vector3(-3f, 1.5f, 2f)));
			c.L.Report.Add($"forest walk: local switchback, {num} grid vertices; 18 m turning terrace at {array[2]}");
		}

		private static Zones Z(Ctx c)
		{
			float frontZ;
			float approachY = RockFoot(c, out frontZ);
			float num = Mathf.Clamp(frontZ, c.In.Length * 0.62f, GZ1(c.In.Length) - 2f);
			Zones zones = new Zones
			{
				F1 = 155f,
				End = num,
				ApproachY = approachY
			};
			c.L.ApproachY = approachY;
			float num2 = num - zones.F1 - 6f;
			zones.V1 = zones.F1 + 0.3f * num2;
			zones.G1 = zones.V1 + 0.25f * num2;
			zones.Ga1 = zones.G1 + 0.3f * num2;
			return zones;
		}

		private static float RockFoot(Ctx c, out float frontZ)
		{
			List<float> list = new List<float>();
			List<float> list2 = new List<float>();
			float num = c.In.Length * 0.6f;
			for (float num2 = -40f; num2 <= 40f; num2 += 5f)
			{
				for (float num3 = num; num3 < c.In.Length; num3 += 1.25f)
				{
					float num4 = c.In.External(num2, num3);
					if (!float.IsNaN(num4))
					{
						list.Add(num4);
						list2.Add(num3);
						break;
					}
				}
			}
			float result = c.In.EndLocal.y - 75f;
			frontZ = c.In.Length - 71f;
			if (list.Count < 4)
			{
				return result;
			}
			list.Sort();
			list2.Sort();
			frontZ = list2[list2.Count / 2];
			return Mathf.Clamp(list[list.Count / 4] - 1.5f, c.In.EndLocal.y - 95f, c.In.EndLocal.y - 12f);
		}

		private static void Compose(Ctx c)
		{
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			Rng rng = c.Rng;
			MountainLayout l = c.L;
			Zones zones = (c.Zn = Z(c));
			l.ZForest = zones.F1;
			l.ZValley = zones.V1;
			l.ZGorge = zones.G1;
			l.ZGardens = zones.Ga1;
			l.ZEnd = zones.End;
			float yA = zones.ApproachY;
			float k = yA / Mathf.Max(60f, zones.End - 25f - 62f);
			float num = Mathf.Clamp01((k - 0.38f) / 0.3f);
			float[] array = new float[5] { -44f, -50f, -57f, -54f, -48f };
			float[] obj = new float[5] { 20f, 52f, 68f, 0f, 0f };
			obj[3] = zones.F1 - 5f;
			obj[4] = zones.F1 + 15f;
			float[] array2 = obj;
			for (int i = 0; i < 5; i++)
			{
				array[i] = Mathf.Lerp(array[i], Rise(array2[i]), num);
			}
			float yF = array[4];
			l.ForestLifted = num > 0.5f;
			if (num > 0f)
			{
				l.Report.Add($"steep slot (rise ratio {k:F2}): forest lifted {num * 100f:F0}%");
			}
			float[] obj2 = new float[11]
			{
				20f, 52f, 68f, 0f, 0f, 0f, 0f, 0f, 0f, 0f,
				0f
			};
			obj2[3] = zones.F1 - 5f;
			obj2[4] = zones.F1 + 15f;
			obj2[5] = zones.V1;
			obj2[6] = zones.G1;
			obj2[7] = zones.Ga1;
			obj2[8] = zones.End - 25f;
			obj2[9] = zones.End - 12f;
			obj2[10] = zones.End;
			c.ProfZ = obj2;
			c.ProfY = new float[11]
			{
				array[0],
				array[1],
				array[2],
				array[3],
				array[4],
				Hy(0.26f),
				Hy(0.52f),
				Hy(0.84f),
				yA - 5f,
				yA,
				yA + 8f
			};
			for (int j = 4; j < c.ProfZ.Length - 3; j++)
			{
				c.ProfZ[j] += rng.Range(-4f, 4f);
				c.ProfY[j] += rng.Range(-4f, 4f);
			}
			c.RiverPhase = rng.Range(0f, 6.28f);
			c.RiverPhase2 = rng.Range(0f, 6.28f);
			c.RiverX0 = rng.Range(-6f, 22f);
			c.GorgeX = rng.Range(-14f, 26f);
			l.Variant = $"river {c.RiverX0:F0}/{c.RiverPhase:F1}, gorge x {c.GorgeX:F0}, length {c.In.Length:F0}";
			int num2 = rng.Range(6, 10);
			for (int m = 0; m < num2; m++)
			{
				c.Mounds.Add(new Vector4(rng.Range(-110f, 135f), rng.Range(zones.F0 + 18f, zones.F1 - 8f), rng.Range(2f, 7f), rng.Range(10f, 22f)));
			}
			List<float> list = new List<float>();
			float num3 = -62f;
			float num4 = Mathf.Min(c.In.MaxClimb - 0.6f, 7.2f) * Mathf.Clamp(c.In.Difficulty, 0.8f, 1.1f);
			float a;
			float b;
			for (; num3 < c.In.EndLocal.y + 40f; num3 += rng.Range(a, b))
			{
				list.Add(num3);
				float num5 = Mathf.InverseLerp(-50f, yA, num3);
				a = Mathf.Lerp(2.8f, 5.8f, Mathf.Sqrt(num5));
				b = Mathf.Lerp(4.4f, num4, Mathf.Sqrt(num5));
			}
			c.Levels = list.ToArray();
			if (Terrain2)
			{
				LogPoolPlan(c);
				PlanMassifs(c);
			}
			else
			{
				Pillars(c);
				LogPoolPlan(c);
			}
			float Hy(float t)
			{
				return yF + t * (yA - yF);
			}
			float Rise(float z)
			{
				return Mathf.Max(-9f, (z - 62f) * k * 0.95f);
			}
		}

		private static void Pillars(Ctx c)
		{
			Rng rng = c.Rng;
			Zones zn = c.Zn;
			List<Pillar> list = c.Pillars2;
			float num = zn.V1 - 6f;
			float num2 = rng.Sign();
			for (; num < zn.End - 22f; num += rng.Range(16f, 24f))
			{
				float radius = rng.Range(9f, 15f);
				float num3 = RiverX(c, num) * 0.3f + num2 * rng.Range(12f, 30f);
				float top = Profile(c, num) + rng.Range(-2f, 6f);
				list.Add(new Pillar
				{
					X = num3,
					Z = num,
					Top = top,
					Radius = radius,
					Sheer = rng.Range(3.2f, 4.5f),
					Seed = rng.Range(0f, 100f),
					StairDir = Mathf.Atan2((0f - (num3 - RiverX(c, num - 14f) * 0.3f)) * 0.4f, -1f) + rng.Range(-0.5f, 0.5f),
					StairWidth = rng.Range(0.65f, 1f)
				});
				num2 = 0f - num2;
			}
			int num4 = list.Count + Mathf.RoundToInt((zn.End - zn.V1) * 0.22f);
			for (int i = 0; i < 900; i++)
			{
				float z = rng.Range(zn.V1 - 20f, zn.End - 10f);
				float x = rng.Range(c.In.WallXMin - 10f, c.In.WallXMax + 10f);
				float num5 = rng.Range(6f, 13f);
				if (Clear(x, z, num5))
				{
					float top2 = Profile(c, z) + rng.Range(-14f, 8f);
					list.Add(new Pillar
					{
						X = x,
						Z = z,
						Top = top2,
						Radius = num5,
						Sheer = rng.Range(3.5f, 5f),
						Seed = rng.Range(0f, 100f),
						StairDir = rng.Range(0f, 6.28f),
						StairWidth = rng.Range(0.4f, 0.8f)
					});
					if (list.Count >= num4)
					{
						break;
					}
				}
			}
			for (int j = 0; j < 26; j++)
			{
				float x2 = ((((j % 2 == 0) ? (-1f) : 1f) < 0f) ? rng.Range(-164f, c.In.WallXMin - 4f) : rng.Range(c.In.WallXMax + 4f, 190f));
				float z2 = rng.Range(zn.F1 - 30f, zn.End);
				float num6 = rng.Range(8f, 16f);
				if (Clear(x2, z2, num6))
				{
					float top3 = Profile(c, z2) + rng.Range(10f, 45f);
					list.Add(new Pillar
					{
						X = x2,
						Z = z2,
						Top = top3,
						Radius = num6,
						Sheer = rng.Range(4f, 6f),
						Seed = rng.Range(0f, 100f),
						StairDir = rng.Range(0f, 6.28f),
						StairWidth = 0.3f,
						Frame = true
					});
				}
			}
			c.L.Report.Add($"pillars: {list.Count} ({list.FindAll((Pillar p) => p.Frame).Count} backdrop)");
			bool Clear(float num7, float num8, float rad)
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				foreach (Pillar item in list)
				{
					Vector2 val = new Vector2(item.X - num7, item.Z - num8);
					if (((Vector2)(ref val)).magnitude < (item.Radius + rad) * 1.12f + 3f)
					{
						return false;
					}
				}
				return true;
			}
		}

		private static float Depth(Ctx c, float z)
		{
			Zones zn = c.Zn;
			if (z < zn.F1)
			{
				return 0f;
			}
			float num = Smooth(zn.F1, zn.F1 + 25f, z) * 12f;
			float num2 = Smooth(zn.V1 - 15f, zn.V1 + 15f, z) * 26f;
			float num3 = Smooth(zn.G1 - 10f, zn.G1 + 20f, z) * 12f;
			float num4 = 1f - Smooth(zn.End - 40f, zn.End - 10f, z);
			return (num + num2 + num3) * num4 + 6f * (1f - num4);
		}

		private static float PillarHeight(Ctx c, in Pillar p, float x, float z)
		{
			float num = x - p.X;
			float num2 = z - p.Z;
			float num3 = Mathf.Sqrt(num * num + num2 * num2);
			if (num3 > p.Radius * 1.4f + 40f)
			{
				return float.MinValue;
			}
			float num4 = Mathf.Atan2(num, num2);
			float num5 = 1f + 0.18f * Mathf.Sin(num4 * 3f + p.Seed) + 0.12f * Mathf.Sin(num4 * 5f + p.Seed * 1.7f) + 0.08f * c.N2.Sample(num * 0.15f + p.Seed, num2 * 0.15f);
			float num6 = p.Radius * num5;
			float num7 = 1.7f * (1f - Mathf.Min(1f, num3 / Mathf.Max(num6, 1f)) * Mathf.Min(1f, num3 / Mathf.Max(num6, 1f)));
			float num8 = 0.1f * (num * Mathf.Sin(p.Seed) + num2 * Mathf.Cos(p.Seed));
			float num9 = p.Top + num7 + num8 + 0.45f * c.N3.Sample(x * 0.1f, z * 0.1f);
			if (num3 <= num6)
			{
				return num9;
			}
			float num10 = num3 - num6;
			float x2 = Mathf.Abs(Mathf.DeltaAngle(num4 * 57.29578f, p.StairDir * 57.29578f)) * (MathF.PI / 180f);
			float num11 = 1f - Smooth(p.StairWidth * 0.75f, p.StairWidth, x2);
			float num12 = Mathf.Lerp(p.Sheer, 1.1f, num11);
			return num9 - num10 * num12;
		}

		private static float Profile(Ctx c, float z)
		{
			float[] profZ = c.ProfZ;
			float[] profY = c.ProfY;
			if (z <= profZ[0])
			{
				return profY[0];
			}
			for (int i = 0; i < profZ.Length - 1; i++)
			{
				if (!(z > profZ[i + 1]))
				{
					float num = (z - profZ[i]) / (profZ[i + 1] - profZ[i]);
					float num2 = ((i > 0) ? ((profY[i + 1] - profY[i - 1]) / (profZ[i + 1] - profZ[i - 1])) : ((profY[1] - profY[0]) / (profZ[1] - profZ[0])));
					float num3 = ((i + 2 < profZ.Length) ? ((profY[i + 2] - profY[i]) / (profZ[i + 2] - profZ[i])) : ((profY[i + 1] - profY[i]) / (profZ[i + 1] - profZ[i])));
					float num4 = profZ[i + 1] - profZ[i];
					float num5 = num * num;
					float num6 = num5 * num;
					return (2f * num6 - 3f * num5 + 1f) * profY[i] + (num6 - 2f * num5 + num) * num2 * num4 + (-2f * num6 + 3f * num5) * profY[i + 1] + (num6 - num5) * num3 * num4;
				}
			}
			return profY[^1];
		}

		public static float RiverX(float rx0, float ph, float ph2, float z)
		{
			return rx0 + 22f * Mathf.Sin(z / 46f + ph) + 7f * Mathf.Sin(z / 17f + ph2);
		}

		private static float RiverX(Ctx c, float z)
		{
			float num = RiverX(c.RiverX0, c.RiverPhase, c.RiverPhase2, z);
			PassagePlan passage = c.Passage;
			if (passage == null || z > passage.RiverZ1)
			{
				return num;
			}
			if (z >= passage.RiverZ0)
			{
				return PassageRiverX(passage, z);
			}
			return Mathf.Lerp(num, PassageRiverX(passage, passage.RiverZ0), Smooth(passage.RiverZ0 - 25f, passage.RiverZ0, z));
		}

		private static float Smooth(float a, float b, float x)
		{
			float num = Mathf.Clamp01((x - a) / (b - a));
			return num * num * (3f - 2f * num);
		}

		private static float SMax(float a, float b, float k)
		{
			float num = Mathf.Clamp01(0.5f + 0.5f * (a - b) / k);
			return b + (a - b) * num + k * num * (1f - num);
		}

		private static float Raw(Ctx c, float x, float z)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			Zones zn = c.Zn;
			float num = x + 7f * c.N1.Sample(x * 0.012f, z * 0.012f);
			float num2 = z + 7f * c.N1.Sample(x * 0.012f + 31f, z * 0.012f - 7f);
			float num3 = Profile(c, num2) - Depth(c, num2);
			float num4 = RiverX(c, num2);
			float x2 = Math.Abs(num - num4);
			float num5 = Smooth(zn.F1 - 10f, zn.F1 + 25f, num2) * (1f - Smooth(zn.V1 + 10f, zn.G1, num2)) * 10f;
			num3 -= num5 * (1f - Smooth(14f, 38f, x2));
			foreach (Vector4 mound in c.Mounds)
			{
				Vector2 val = new Vector2(num - mound.x, num2 - mound.y);
				float num6 = ((Vector2)(ref val)).magnitude / mound.w;
				if (num6 < 1.6f)
				{
					num3 += mound.z * Mathf.Max(0f, 1f - num6 * num6 * 0.45f) * (1f - Smooth(1.2f, 1.6f, num6));
				}
			}
			float num7 = (1f - Smooth(zn.F1 - 20f, zn.F1 + 30f, num2)) * Smooth(70f, 150f, Math.Abs(num - 12f)) * (20f + 0.15f * Mathf.Max(0f, num2 - 40f));
			num3 += num7;
			foreach (Pillar item in c.Pillars2)
			{
				Pillar p = item;
				if (!(Math.Abs(p.Z - num2) > p.Radius * 1.5f + 45f) && !(Math.Abs(p.X - num) > p.Radius * 1.5f + 45f))
				{
					float num8 = PillarHeight(c, in p, num, num2);
					if (num8 > num3)
					{
						num3 = num8;
					}
				}
			}
			float num9 = Smooth(zn.F1, zn.V1, num2);
			num3 += (c.N2.Fbm(num * 0.035f, num2 * 0.035f) * 2.4f + c.N3.Ridged(num * 0.05f, num2 * 0.05f) * 2.2f * num9) * (0.4f + 0.6f * num9);
			num3 += c.N3.Fbm(num * 0.09f, num2 * 0.09f, 3) * 0.6f;
			return FrameWalls(c, x, z, StartDrop(c, x, z, EdgeSaddles(c, x, z, (c.T2 != null) ? RawT2(c, x, z, num3) : num3)));
		}

		private static Vector2 DropRim(Ctx c, float x)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			int key = Mathf.RoundToInt(x * 4f);
			if (c.DropRims == null)
			{
				c.DropRims = new Dictionary<int, Vector2>();
			}
			if (c.DropRims.TryGetValue(key, out var value))
			{
				return value;
			}
			float num = c.In.External(x, 22f);
			float num2 = Mathf.Max(Profile(c, 22f), float.IsNaN(num) ? float.MinValue : (num + 0.25f));
			float num3 = 33f + 3f * c.N1.Sample(x * 0.04f + 7f, 1.3f);
			for (float num4 = num3; num4 < 70f; num4 += 0.625f)
			{
				float num5 = c.In.External(x, num4);
				if (float.IsNaN(num5) || num5 < num2 - 7.5f - 1.2f)
				{
					num3 = num4;
					break;
				}
				num3 = num4;
			}
			Dictionary<int, Vector2> dropRims = c.DropRims;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(num3, num2);
			dropRims[key] = val;
			return val;
		}

		private static float StartDrop(Ctx c, float x, float z, float y)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (NoEdgeFix || z > 110f || !c.L.ForestLifted)
			{
				return y;
			}
			float num = Smooth(c.In.WallXMin - 2f, c.In.WallXMin + 4f, x) * (1f - Smooth(c.In.WallXMax - 4f, c.In.WallXMax + 2f, x));
			if (num <= 0f)
			{
				return y;
			}
			Vector2 val = DropRim(c, x);
			float x2 = val.x;
			float y2 = val.y;
			float num2 = y;
			if (z <= x2)
			{
				y = Mathf.Max(y, y2 + 0.35f * c.N3.Sample(x * 0.2f, z * 0.2f));
			}
			float num3 = Smooth(x2, x2 + 1.1f, z) * (1f - Smooth(x2 + 16f, x2 + 34f, z));
			y = Mathf.Lerp(y, Mathf.Min(y, y2 - 7.5f), num3);
			return Mathf.Lerp(num2, y, num);
		}

		private static float FrameWalls(Ctx c, float x, float z, float y)
		{
			if (NoEdgeFix)
			{
				return y;
			}
			float num = Mathf.Max(c.In.WallXMin - x, x - c.In.WallXMax);
			if (num < 4f)
			{
				return y;
			}
			float num2 = ((x < 0f) ? (-1f) : 1f);
			float num3 = c.N2.Sample(z * 0.035f + num2 * 17f, 3.1f);
			float num4 = c.N3.Sample(z * 0.11f - num2 * 5f, num * 0.08f);
			float num5 = Profile(c, Mathf.Clamp(z, c.ProfZ[0], c.Zn.End));
			float num6 = Mathf.Max(num5, y) + 47f + 8f * num3 + 2.5f * num4;
			float num7 = Smooth(5f + 1.2f * num3, 14f + 1.2f * num3, num);
			float num8 = Mathf.Max(y, Mathf.Lerp(y, num6, num7));
			float x2 = ((num2 < 0f) ? (x - -172f) : (198f - x));
			float num9 = Smooth(15f, 2f, x2);
			return Mathf.Lerp(num8, num5 - 90f, num9);
		}

		private static float EdgeSaddles(Ctx c, float x, float z, float y)
		{
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			if (NoEdgeFix)
			{
				return y;
			}
			float num = Mathf.Max(c.In.WallXMin - x, x - c.In.WallXMax);
			if (c.T2 != null && z < c.T2.Z0 + 10f)
			{
				float num2 = Mathf.Max(c.In.WallXMin + 4f, -95f) - 6f;
				float num3 = Mathf.Min(c.In.WallXMax - 4f, 95f) + 6f;
				num = Mathf.Max(num, Mathf.Max(num2 - x, x - num3) * (1f - Smooth(c.T2.Z0 - 10f, c.T2.Z0 + 10f, z)));
			}
			if (num <= -1f)
			{
				return y;
			}
			if (c.EdgeSaddles == null)
			{
				c.EdgeSaddles = new List<Vector2>();
				Random random = new Random((int)(c.Seed & 0x7FFFFFFF) ^ 0x5ADD1E5);
				for (float num4 = 55f + (float)random.NextDouble() * 10f; num4 < c.Zn.End - 12f; num4 += 30f + (float)random.NextDouble() * 15f)
				{
					c.EdgeSaddles.Add(new Vector2(num4, 14f + (float)random.NextDouble() * 6f));
				}
			}
			float num5 = Smooth(-1f, 2.5f, num);
			foreach (Vector2 edgeSaddle in c.EdgeSaddles)
			{
				float num6 = Math.Abs(z - edgeSaddle.x);
				if (num6 < 9f)
				{
					y -= num5 * edgeSaddle.y * (1f - Smooth(3f, 3f + edgeSaddle.y / 3.7f, num6));
				}
			}
			return y;
		}

		private static void LogPoolPlan(Ctx c)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			Zones zn = c.Zn;
			float num = Mathf.Lerp(zn.F1 + 18f, zn.V1 - 12f, c.Rng.Range(0.35f, 0.6f));
			float num2 = RiverX(c, num);
			LogPool logPool = new LogPool
			{
				HalfWidth = c.Rng.Range(9f, 12f),
				HalfLength = c.Rng.Range(8f, 10f),
				Lanes = 3
			};
			logPool.Center = new Vector3(num2, 0f, num);
			c.L.Pool = logPool;
		}

		private static void Rivers(Ctx c)
		{
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			HeightGrid g = c.G;
			WaterPlan water = c.L.Water;
			Zones zn = c.Zn;
			float[] orig = (float[])g.Y.Clone();
			LogPool pool = c.L.Pool;
			float num = zn.V1 + 8f;
			Vector3? val = null;
			float num2 = float.MaxValue;
			for (float num3 = num; num3 >= 64f; num3 -= 1.5f)
			{
				float num4 = RiverX(c, num3);
				float num5 = Orig(num4, num3);
				if (pool != null && Math.Abs(num3 - pool.Center.z) < pool.HalfLength + 2f)
				{
					val = null;
				}
				else
				{
					float num6 = ((num3 > zn.F1) ? 7f : 5.5f);
					float num7 = num5 - 0.35f;
					CarveBowl(c, num4, num3, num6 * 0.5f + 0.6f, Mathf.Min(num7, num2), 1.5f);
					if (val.HasValue && num2 - num7 > 2.2f)
					{
						water.Falls.Add((new Vector3(val.Value.x, num2, val.Value.z), new Vector3(num4, num7, num3), num6 * 0.9f));
						if (Flat(num4, num3 - 2.5f, num6 * 0.9f + 1.5f))
						{
							water.Pools.Add((new Vector3(num4, num7, num3 - 2.5f), num6 * 0.9f + 1.5f));
							c.WaterBodies.Add(new Vector4(num4, num3 - 2.5f, num6 * 0.9f + 4f, num7));
							CarveBowl(c, num4, num3 - 2.5f, num6 * 0.9f + 1.2f, num7, 2.4f);
						}
					}
					if (num7 < num2 - 0.01f || !val.HasValue)
					{
						num2 = Mathf.Min(num2, num7);
					}
					water.River.Add(new Vector3(num4, num2, num3));
					water.Width.Add(num6);
					c.WaterBodies.Add(new Vector4(num4, num3, num6 * 0.5f + 3.5f, num2));
					val = new Vector3(num4, num2, num3);
					MarkWater(c, num4, num3, num6 * 0.5f);
				}
			}
			if (water.River.Count > 0)
			{
				Vector3 val2 = water.River[water.River.Count - 1];
				water.Pools.Add((val2 + new Vector3(0f, 0f, -6f), 9f));
				CarveBowl(c, val2.x, val2.z - 6f, 8.6f, val2.y, 2.2f);
				c.WaterBodies.Add(new Vector4(val2.x, val2.z - 6f, 12f, val2.y));
				MarkWater(c, val2.x, val2.z - 6f, 9f);
			}
			if (pool != null)
			{
				ShapePool(c, pool, Orig);
			}
			c.L.Report.Add($"river: {water.River.Count} points, {water.Falls.Count} waterfalls");
			bool Flat(float x, float z, float r)
			{
				float num8 = float.MaxValue;
				float num9 = float.MinValue;
				for (float num10 = 0f; num10 < 6.28f; num10 += 0.785f)
				{
					float val3 = Orig(x + Mathf.Cos(num10) * r, z + Mathf.Sin(num10) * r);
					num8 = Math.Min(num8, val3);
					num9 = Math.Max(num9, val3);
				}
				return num9 - num8 < 1.2f;
			}
			float Orig(float x, float z)
			{
				float num8 = (x - g.X0) / g.Cell;
				float num9 = (z - g.Z0) / g.Cell;
				int num10 = Mathf.Clamp((int)num8, 0, g.W - 2);
				int num11 = Mathf.Clamp((int)num9, 0, g.H - 2);
				float num12 = Mathf.Clamp01(num8 - (float)num10);
				float num13 = Mathf.Clamp01(num9 - (float)num11);
				return Mathf.Lerp(Mathf.Lerp(orig[g.Idx(num10, num11)], orig[g.Idx(num10 + 1, num11)], num12), Mathf.Lerp(orig[g.Idx(num10, num11 + 1)], orig[g.Idx(num10 + 1, num11 + 1)], num12), num13);
			}
		}

		private static void ShapePool(Ctx c, LogPool pool, Func<float, float, float> orig)
		{
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			HeightGrid g = c.G;
			float cx = pool.Center.x;
			float cz = pool.Center.z;
			float num = ((c.Passage != null) ? c.Passage.BankY : orig(cx, cz - pool.HalfLength - 3f));
			pool.Water = num - 0.7f;
			_ = pool.Water;
			float num2 = pool.Water + 6.5f;
			float num3 = pool.Water + 16f;
			float hw = pool.HalfWidth;
			float hl = pool.HalfLength;
			for (int i = g.Jz(cz - hl - 14f); i <= g.Jz(cz + hl + 16f); i++)
			{
				for (int j = g.Ix(cx - hw - 16f); j <= g.Ix(cx + hw + 16f); j++)
				{
					float num4 = g.Xof(j) - cx;
					float num5 = g.Zof(i) - cz;
					float num6 = Math.Abs(num4);
					float num7 = Rim(num4, num5);
					float num8 = g[j, i];
					float num9 = (num7 - 1f) * Mathf.Min(hw, hl);
					if (num7 <= 1f)
					{
						num8 = pool.Water - 0.6f - 5.4f * Smooth(1f, 0.7f, num7);
					}
					else if (num5 < 0f && num6 <= hw * 0.8f && num9 < 10f)
					{
						num8 = Mathf.Lerp(pool.Water - 0.2f, num, Smooth(0f, 9f, num9));
					}
					else if (num5 > hl * 0.6f && num5 < hl + 5f && num6 <= hw)
					{
						num8 = ((num6 < 3.5f) ? Math.Max(num8, num3 + 4f) : num2);
					}
					else if (num9 < 12f && num5 > 0f - hl - 2f)
					{
						num8 = Math.Max(num8, pool.Water + 1.2f + (num3 - pool.Water - 1.2f) * Smooth(1.2f, 4f, num9) + Smooth(4f, 12f, num9) * 6f);
					}
					g[j, i] = num8;
					c.NoTerrace[g.Idx(j, i)] = true;
					if (num7 <= 1f)
					{
						c.Water[g.Idx(j, i)] = true;
					}
				}
			}
			pool.Center = new Vector3(cx, pool.Water, cz);
			for (float num10 = 0f - hw; num10 <= hw; num10 += 3f)
			{
				for (float num11 = 0f - hl - 3f; num11 <= hl; num11 += 3f)
				{
					c.WaterBodies.Add(new Vector4(cx + num10, cz + num11, 3.2f, pool.Water));
				}
			}
			pool.Near = new Vector3(cx, pool.Water + 0.6f, cz - hl - 4f);
			pool.Far = new Vector3(cx + (c.Rng.Chance(0.5f) ? (-1f) : 1f) * (hw * 0.6f), num2, cz + hl + 2.5f);
			c.L.Water.Falls.Add((new Vector3(cx, num3 + 4f, cz + hl + 0.2f), new Vector3(cx, pool.Water, cz + hl - 1.6f), 6.5f));
			c.L.Report.Add($"log pool at z {cz:F0}: {2f * hw:F0} x {2f * hl:F0} m, water {pool.Water:F1}, ledge {num2:F1}");
			float Rim(float x, float z)
			{
				return Mathf.Pow(Mathf.Pow(Math.Abs(x) / hw, 4f) + Mathf.Pow(Math.Abs(z) / hl, 4f), 0.25f) * (1f + 0.09f * c.N2.Sample((cx + x) * 0.14f + 31f, (cz + z) * 0.14f - 7f));
			}
		}

		private static void PlanMassifs(Ctx c)
		{
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_0806: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0acf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ad4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0af1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0af6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0afb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b04: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b06: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b0d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b15: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b20: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b25: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b60: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bc8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c00: Unknown result type (might be due to invalid IL or missing references)
			//IL_06df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c44: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f8e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fa8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fcf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ff6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d7b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d80: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dca: Unknown result type (might be due to invalid IL or missing references)
			Zones zn = c.Zn;
			Rng rng = Rng.For(c.Seed, "massifs");
			T2 t = (c.T2 = new T2());
			LogPool pool = c.L.Pool;
			t.Z0 = ((pool != null) ? (pool.Center.z + pool.HalfLength + 4f) : (zn.F1 + 25f));
			float num = t.Z0 - 12f;
			float num2 = zn.End - 6f;
			float num3 = rng.Sign();
			float z = pool?.Center.z ?? zn.F1;
			t.CapY0 = Profile(c, z) - Depth(c, z) - 6f;
			float num4 = (zn.ApproachY - t.CapY0) / Mathf.Max(40f, zn.End - 16f - (t.Z0 - 6f));
			t.CapRate = Mathf.Max(0.85f, num4 * 1.08f);
			Massif massif = new Massif
			{
				Name = "route",
				Flank = rng.Range(1.8f, 2.6f),
				Seed = rng.Range(0f, 100f)
			};
			float num5 = rng.Range(0f, 6.28f);
			float num6 = rng.Range(0.45f, 0.65f);
			float num7 = rng.Range(26f, 30f);
			for (float num8 = num; num8 <= num2; num8 += 5f)
			{
				float num9 = Mathf.InverseLerp(num, num2, num8);
				float num10 = RiverX(c, Mathf.Min(num8, zn.V1 + 8f));
				float num11 = Smooth(zn.G1 + 34f, zn.G1 + 34f + Mathf.Lerp(25f, 45f, num6), num8);
				float num12 = Mathf.Lerp(num10 + num3 * num7, 6f * Mathf.Sin(num5), num11) + 9f * Mathf.Sin(num9 * 7.5f + num5) * (0.4f + 0.6f * num11);
				massif.Spine.Add(new Vector2(num12, num8));
				massif.Half.Add(Mathf.Lerp(11f, 19f, 0.5f + 0.5f * Mathf.Sin(num9 * 5.3f + num5 * 1.7f)) * (1f + 0.6f * Smooth(0.8f, 1f, num9)));
				massif.Crest.Add(1.2f + 2.5f * Mathf.Sin(num9 * 9f + num5 * 0.7f));
			}
			t.Massifs.Add(massif);
			Massif massif2 = new Massif
			{
				Name = "across",
				Flank = rng.Range(2.2f, 3.2f),
				Seed = rng.Range(0f, 100f)
			};
			float num13 = rng.Range(0f, 6.28f);
			float num14 = zn.G1 + rng.Range(10f, 30f);
			float num15 = rng.Range(30f, 36f);
			float num16 = rng.Range(2f, 9f);
			for (float num17 = num; num17 <= num14; num17 += 5f)
			{
				float num18 = Mathf.InverseLerp(num, num14, num17);
				float num19 = RiverX(c, Mathf.Min(num17, zn.V1 + 8f)) - num3 * num15 + 7f * Mathf.Sin(num18 * 6f + num13);
				massif2.Spine.Add(new Vector2(num19, num17));
				massif2.Half.Add(Mathf.Lerp(10f, 22f, 0.5f + 0.5f * Mathf.Sin(num18 * 4.1f + num13)));
				massif2.Crest.Add(0f - num16 + 4f * Mathf.Sin(num18 * 6.5f + num13));
			}
			t.Massifs.Add(massif2);
			float[] array = new float[2] { -1f, 1f };
			foreach (float num20 in array)
			{
				Massif massif3 = new Massif
				{
					Name = ((num20 < 0f) ? "wall left" : "wall right"),
					Flank = rng.Range(3.2f, 4.2f),
					Seed = rng.Range(0f, 100f),
					Rugged = 2.2f
				};
				float num21 = ((num20 < 0f) ? (c.In.WallXMin - rng.Range(4f, 14f)) : (c.In.WallXMax + rng.Range(4f, 14f)));
				float num22 = rng.Range(0f, 6.28f);
				float num23 = rng.Range(0f, 6.28f);
				float num24 = rng.Range(6f, 12f);
				for (float num25 = num; num25 <= zn.End; num25 += 6f)
				{
					float num26 = Mathf.InverseLerp(num, zn.End, num25);
					massif3.Spine.Add(new Vector2(num21 + num20 * 10f * Mathf.Sin(num26 * 5f + num22), num25));
					massif3.Half.Add(11f + 5f * Mathf.Sin(num26 * 3.3f + num23));
					massif3.Crest.Add(num24 + 8f + 12f * Mathf.Sin(num26 * 4f + num22) + 5f * Mathf.Sin(num26 * 11f + num23));
				}
				Random random = new Random((int)(massif3.Seed * 1000f) ^ ((num20 < 0f) ? 5954846 : 5954862));
				float num27 = num + 18f + (float)random.NextDouble() * 12f;
				while (!NoEdgeFix && num27 < zn.End - 12f)
				{
					massif3.Notches.Add(new Vector2(num27, 14f + (float)random.NextDouble() * 6f));
					num27 += 30f + (float)random.NextDouble() * 15f;
				}
				t.Massifs.Add(massif3);
			}
			Massif massif4 = new Massif
			{
				Name = "summit",
				Flank = rng.Range(2.4f, 3.2f),
				Seed = rng.Range(0f, 100f)
			};
			t.StepSeed = rng.Range(0f, 100f);
			float num28 = rng.Range(-10f, 10f);
			float num29 = rng.Range(-10f, 10f);
			for (float num30 = 0f; num30 <= 4f; num30 += 1f)
			{
				float num31 = Mathf.Lerp(zn.Ga1 + 5f, zn.End + 4f, num30 / 4f);
				massif4.Spine.Add(new Vector2(Mathf.Lerp(num28, num29, num30 / 4f), num31));
				massif4.Half.Add(Mathf.Lerp(18f, 34f, num30 / 4f));
				massif4.Crest.Add(Mathf.Lerp(-3f, 0f, num30 / 4f));
			}
			t.Massifs.Add(massif4);
			Cut cut = new Cut
			{
				Half = 6.5f,
				Wall = 1.5f,
				River = true
			};
			float num32 = num;
			float num33 = 0f;
			float num34 = Profile(c, zn.V1 + 10f) - 14f;
			for (float num35 = zn.V1 + 10f; num35 >= num; num35 -= 2f)
			{
				cut.Line.Add(new Vector2(RiverX(c, num35), num35));
				if (num32 - num35 > num33)
				{
					num34 -= rng.Range(2.6f, 5.5f);
					num33 = rng.Range(10f, 18f);
					num32 = num35;
				}
				cut.Floor.Add(Mathf.Min(num34, Profile(c, num35) - 10f));
			}
			t.Cuts.Add(cut);
			Cut cut2 = new Cut
			{
				Half = rng.Range(4f, 7f),
				Wall = 4.5f
			};
			float num36 = rng.Range(0f, 6.28f);
			for (float num37 = zn.V1 - 4f; num37 <= zn.G1 + 12f; num37 += 2f)
			{
				float num38 = Mathf.InverseLerp(zn.V1 - 4f, zn.G1 + 12f, num37);
				float num39 = RiverX(c, Mathf.Min(num37, zn.V1 + 8f)) + 6f * Mathf.Sin(num38 * 3.4f + num36);
				cut2.Line.Add(new Vector2(num39, num37));
				cut2.Floor.Add(Profile(c, num37) - Mathf.Lerp(30f, 38f, Mathf.Sin(num38 * MathF.PI)));
			}
			t.Cuts.Add(cut2);
			int num40 = rng.Range(3, 6);
			Vector2 val2;
			float f;
			for (int j = 0; j < num40; j++)
			{
				int num41 = rng.Range(4, massif.Spine.Count - 6);
				Vector2 val = massif.Spine[num41];
				val2 = massif.Spine[num41 + 1] - massif.Spine[num41 - 1];
				Vector2 normalized = ((Vector2)(ref val2)).normalized;
				Vector2 val3 = new Vector2(normalized.y, 0f - normalized.x) * rng.Sign();
				Cut cut3 = new Cut
				{
					Half = rng.Range(1.2f, 2.5f),
					Wall = rng.Range(1.2f, 2f)
				};
				float num42 = Profile(c, val.y) + massif.Crest[num41] - rng.Range(3f, 6f);
				float num43 = rng.Range(0.9f, 1.3f);
				float num44 = massif.Half[num41] * 1.3f + 3f;
				bool flag = false;
				for (float num45 = num44; num45 <= num44 + 26f; num45 += 2f)
				{
					Vector2 val4 = val + val3 * num45 + normalized * (3f * Mathf.Sin(num45 * 0.2f));
					int seg;
					float num46 = Nearest(massif.Spine, val4, out seg, out f);
					if (Math.Abs(seg - num41) > 3 && num46 < massif.Half[seg] * 1.3f + 6f)
					{
						flag = true;
						break;
					}
					cut3.Line.Add(val4);
					cut3.Floor.Add(num42 - (num45 - num44) * num43);
				}
				if (!flag && cut3.Line.Count >= 3)
				{
					t.Cuts.Add(cut3);
				}
			}
			int num47 = rng.Range(5, 9);
			for (int k = 0; k < 300; k++)
			{
				if (t.Needles.Count >= num47)
				{
					break;
				}
				float num48 = rng.Range(zn.G1 + 4f, zn.Ga1 + 10f);
				float num49 = rng.Range(c.In.WallXMin + 15f, c.In.WallXMax - 15f);
				float num50 = (rng.Chance(0.3f) ? rng.Range(14f, 22f) : rng.Range(6f, 11f));
				bool flag2 = true;
				foreach (Pillar needle in t.Needles)
				{
					val2 = new Vector2(needle.X - num49, needle.Z - num48);
					if (((Vector2)(ref val2)).magnitude < (needle.Radius + num50) * 1.2f + 6f)
					{
						flag2 = false;
						break;
					}
				}
				if (Nearest(massif.Spine, new Vector2(num49, num48), out var seg2, out f) < massif.Half[seg2] + num50 + 8f)
				{
					flag2 = false;
				}
				if (flag2)
				{
					float top = Profile(c, num48) + ((num50 > 13f) ? rng.Range(-4f, 6f) : rng.Range(2f, 16f));
					t.Needles.Add(new Pillar
					{
						X = num49,
						Z = num48,
						Top = top,
						Radius = num50,
						Sheer = rng.Range(3.5f, 5.5f),
						Seed = rng.Range(0f, 100f),
						StairDir = rng.Range(0f, 6.28f),
						StairWidth = rng.Range(0.45f, 0.9f)
					});
				}
			}
			c.Pillars2.AddRange(t.Needles);
			c.L.CragKind = (float x, float num51) => (!(num51 < t.Z0 - 8f)) ? ((FractureNear(c, x, num51) > 0.4f) ? 1 : 2) : 0;
			c.L.CragDensity = delegate(float x, float num52)
			{
				float num51 = Smooth(t.Z0 - 18f, t.Z0, num52);
				if (num51 <= 0f)
				{
					return 1f;
				}
				float num53 = Smooth(0.1f, 0.35f, c.N2.Sample(x * 0.028f + 57f, num52 * 0.028f - 13f));
				return Mathf.Lerp(1f, Mathf.Max(num53, FractureNear(c, x, num52)), num51);
			};
			foreach (Cut cut4 in t.Cuts)
			{
				c.L.Report.Add($"  cut from ({cut4.Line[0].x:F0}, {cut4.Line[0].y:F0}) to ({cut4.Line[cut4.Line.Count - 1].x:F0}, {cut4.Line[cut4.Line.Count - 1].y:F0}), half {cut4.Half:F1}, floor {cut4.Floor[0]:F0}..{cut4.Floor[cut4.Floor.Count - 1]:F0}");
			}
			c.L.Report.Add($"  zones: V1 {zn.V1:F0}, G1 {zn.G1:F0}, Ga1 {zn.Ga1:F0}, End {zn.End:F0}");
			c.L.Report.Add($"terrain 2.0: {t.Massifs.Count} massifs, {t.Cuts.Count} cuts ({num40} gullies), {t.Needles.Count} needles, from z {t.Z0:F0}");
		}

		private static float SMin(float a, float b, float k)
		{
			return 0f - SMax(0f - a, 0f - b, k);
		}

		private static float Nearest(List<Vector2> line, Vector2 p, out int seg, out float f)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			float num = float.MaxValue;
			seg = 0;
			f = 0f;
			for (int i = 0; i + 1 < line.Count; i++)
			{
				Vector2 val = line[i];
				Vector2 val2 = line[i + 1] - val;
				float num2 = Mathf.Clamp01(Vector2.Dot(p - val, val2) / Mathf.Max(0.0001f, ((Vector2)(ref val2)).sqrMagnitude));
				Vector2 val3 = val + val2 * num2 - p;
				float sqrMagnitude = ((Vector2)(ref val3)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					seg = i;
					f = num2;
				}
			}
			return Mathf.Sqrt(num);
		}

		private static float MassifHeight(Ctx c, Massif m, float x, float z)
		{
			float steps;
			return MassifHeight(c, m, x, z, out steps);
		}

		private static float MassifHeight(Ctx c, Massif m, float x, float z, out float steps)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			steps = 0f;
			Vector2 p = default(Vector2);
			((Vector2)(ref p))..ctor(x, z);
			int seg;
			float f;
			float num = Nearest(m.Spine, p, out seg, out f);
			float num2 = Mathf.Lerp(m.Half[seg], m.Half[seg + 1], f);
			float num3 = Mathf.Lerp(m.Crest[seg], m.Crest[seg + 1], f);
			Vector2 val = Vector2.Lerp(m.Spine[seg], m.Spine[seg + 1], f);
			float num4 = Profile(c, val.y) + num3;
			foreach (Vector2 notch in m.Notches)
			{
				float num5 = Mathf.Abs(z - notch.x);
				if (num5 < 9f)
				{
					num4 -= notch.y * (1f - Smooth(3f, 3f + notch.y / 3.7f, num5));
				}
			}
			if (m.Name == "route" || m.Name == "summit")
			{
				float num6 = c.T2.CapY0 + Mathf.Max(0f, Mathf.Min(val.y, z) - c.T2.Z0 + 6f) * c.T2.CapRate;
				num4 = Mathf.Max(num4, Mathf.Min(num6 - 2f, c.Zn.ApproachY));
				num4 = Mathf.Min(num4, num6);
				float x2 = num / Mathf.Max(1f, Mathf.Lerp(m.Half[seg], m.Half[seg + 1], f));
				steps = 1f - Smooth(0.95f, 1.25f, x2);
			}
			num2 *= 1f + 0.28f * c.N2.Sample(x * 0.03f + m.Seed, z * 0.03f);
			float num7 = (4.5f * c.N3.Ridged(x * 0.022f + m.Seed, z * 0.022f) + 3f * c.N1.Sample(x * 0.012f - m.Seed, z * 0.012f) - 2f) * m.Rugged;
			if (num <= num2)
			{
				float num8 = num / Mathf.Max(num2, 1f);
				return num4 + 1.6f * (1f - num8 * num8) + 0.05f * ((x - val.x) * Mathf.Sin(m.Seed)) + num7 * (1f - 0.5f * num8 * num8);
			}
			float num9 = m.Flank * (0.8f + 0.4f * (0.5f + 0.5f * c.N1.Sample(x * 0.02f - m.Seed, z * 0.02f)));
			return num4 + num7 * 0.5f - (num - num2) * num9;
		}

		private static float CutHeight(Cut cut, float x, float z)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			int seg;
			float f;
			float num = Nearest(cut.Line, new Vector2(x, z), out seg, out f);
			return Mathf.Lerp(cut.Floor[seg], cut.Floor[seg + 1], f) + Mathf.Max(0f, num - cut.Half) * cut.Wall;
		}

		private static float RawT2(Ctx c, float x, float z, float old)
		{
			T2 t = c.T2;
			float num = Smooth(t.Z0 - 18f, t.Z0, z);
			if (num <= 0f)
			{
				return old;
			}
			float num2 = x + 11f * c.N1.Sample(x * 0.008f + 17f, z * 0.008f);
			float num3 = z + 9f * c.N1.Sample(x * 0.008f - 41f, z * 0.008f + 5f);
			float num4 = Profile(c, num3) - Mathf.Lerp(34f, 18f, Smooth(c.Zn.Ga1, c.Zn.End, num3));
			float num5 = Mathf.Max(c.In.WallXMin - x, x - c.In.WallXMax) - 28f;
			if (num5 > 0f && !NoEdgeFix)
			{
				num4 -= num5 * 2.2f + num5 * num5 * 0.08f;
			}
			float num6 = 0f;
			foreach (Massif massif in t.Massifs)
			{
				num4 = SMax(num4, MassifHeight(c, massif, num2, num3, out var steps), 7f);
				num6 = Mathf.Max(num6, steps);
			}
			foreach (Pillar needle in t.Needles)
			{
				Pillar p = needle;
				if (!(Math.Abs(p.Z - num3) > p.Radius * 1.5f + 45f) && !(Math.Abs(p.X - num2) > p.Radius * 1.5f + 45f))
				{
					float num7 = PillarHeight(c, in p, num2, num3);
					if (num7 > float.MinValue)
					{
						num4 = SMax(num4, num7, 3.5f);
					}
				}
			}
			float num8 = float.MaxValue;
			foreach (Cut cut in t.Cuts)
			{
				float num9 = CutHeight(cut, num2, num3);
				if (cut.River)
				{
					num8 = num9;
				}
				num4 = SMin(num4, num9, 2.5f);
			}
			c.LastSteps = num6 * num;
			c.LastCut = ((num8 < float.MaxValue) ? (Mathf.Max(0f, num4 + 3f - num8) * ((num4 < num8 + 2.5f) ? 1f : 0f)) : 0f);
			if (num6 > 0f)
			{
				num4 = Mathf.Lerp(num4, RidgeSteps(c, num4, num2, num3, t.StepSeed), num6);
			}
			num4 += (c.N2.Fbm(num2 * 0.035f, num3 * 0.035f) * 2f + c.N3.Ridged(num2 * 0.05f, num3 * 0.05f) * 1.6f) * (1f - 0.5f * num6);
			num4 += c.N3.Fbm(num2 * 0.09f, num3 * 0.09f, 3) * 0.6f * (1f - 0.7f * num6);
			return Mathf.Lerp(old, num4, num);
		}

		private static float Bedding(Ctx c, float y, float x, float z)
		{
			float num = 5.2f + 1.8f * c.N2.Sample(x * 0.035f + 7f, z * 0.035f - 3f);
			float num2 = 9f * c.N1.Sample(x * 0.006f + 3f, z * 0.006f + 9f) + 0.09f * x + 2.5f * c.N3.Sample(x * 0.03f, z * 0.03f);
			float num3 = (y + num2) / num;
			float num4 = Mathf.Floor(num3);
			float num5 = num3 - num4;
			float num6 = 0.55f + 0.3f * (0.5f + 0.5f * c.N3.Sample(x * 0.05f + num4 * 3.1f, z * 0.05f));
			float num7 = Smooth(1f - num6, 1f, num5) * 0.6f + num5 * 0.4f;
			return (num4 + num7) * num - num2;
		}

		private static float RidgeSteps(Ctx c, float y, float x, float z, float seed)
		{
			float num = 3.2f * c.N1.Sample(x * 0.07f + seed, z * 0.05f) + 2.5f * c.N2.Sample(x * 0.11f - seed, z * 0.02f + 31f) + 0.6f * c.N3.Sample(x * 0.15f, z * 0.15f + seed) + 0.16f * x;
			float num2 = (y + num + 0.6f * Mathf.Sin(y * 0.37f + seed)) / 5.2f;
			float num3 = Mathf.Floor(num2);
			float num4 = num2 - num3;
			float num5 = Smooth(0.68f, 1f, num4) * 0.88f + num4 * 0.12f;
			return (num3 + num5) * 5.2f - num;
		}

		private static float FractureNear(Ctx c, float x, float z)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			T2 t = c.T2;
			float num = 0f;
			if (t.Cuts.Count > 1)
			{
				Cut cut = t.Cuts[1];
				int seg;
				float f;
				float x2 = Nearest(cut.Line, new Vector2(x, z), out seg, out f);
				num = 1f - Smooth(cut.Half + 6f, cut.Half + 18f, x2);
			}
			foreach (Pillar needle in t.Needles)
			{
				Vector2 val = new Vector2(x - needle.X, z - needle.Z);
				float magnitude = ((Vector2)(ref val)).magnitude;
				num = Mathf.Max(num, 1f - Smooth(needle.Radius + 3f, needle.Radius + 12f, magnitude));
			}
			return num;
		}

		private static void CrestProfile(Ctx c)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			if (c.T2 == null || !(Environment.GetEnvironmentVariable("SAKURA_DEBUG") ?? "").Contains("crest"))
			{
				return;
			}
			Massif massif = c.T2.Massifs[0];
			StringBuilder stringBuilder = new StringBuilder("  crest:");
			float num = float.NaN;
			foreach (Vector2 item in massif.Spine)
			{
				float num2 = c.G.Sample(item.x, item.y);
				stringBuilder.Append(string.Format(" {0:F0}@{1:F0}:{2:F0}{3}", item.y, item.x, num2, float.IsNaN(num) ? "" : $"({num2 - num:+0;-0})"));
				num = num2;
			}
			c.L.Report.Add(stringBuilder.ToString());
			string environmentVariable = Environment.GetEnvironmentVariable("SAKURA_PROBE");
			if (string.IsNullOrEmpty(environmentVariable))
			{
				return;
			}
			string[] array = environmentVariable.Split(',');
			float num3 = float.Parse(array[0], CultureInfo.InvariantCulture);
			float num4 = float.Parse(array[1], CultureInfo.InvariantCulture);
			for (int num5 = 6; num5 >= -6; num5--)
			{
				StringBuilder stringBuilder2 = new StringBuilder($"  probe z {num4 + (float)num5 * 2.5f,6:F1}:");
				for (int i = -6; i <= 6; i++)
				{
					stringBuilder2.Append($" {c.G.Sample(num3 + (float)i * 2.5f, num4 + (float)num5 * 2.5f),6:F1}");
				}
				c.L.Report.Add(stringBuilder2.ToString());
			}
			StringBuilder stringBuilder3 = new StringBuilder("  probe line:");
			for (float num6 = num4 - 15f; num6 <= num4 + 15f; num6 += 1.25f)
			{
				float num7 = c.G.Sample(num3, num6);
				float num8 = c.G.Sample(num3, num6 + 1.25f);
				float num9 = Raw(c, num3, num6);
				float num10 = Raw(c, num3, num6 + 1.25f);
				stringBuilder3.Append($" {num6:F0}:{num7:F0}/{Mathf.Atan2(num8 - num7, 1.25f) * 57.29578f:F0}(raw {num9:F0}/{Mathf.Atan2(num10 - num9, 1.25f) * 57.29578f:F0})");
			}
			c.L.Report.Add(stringBuilder3.ToString());
			for (int num11 = 6; num11 >= -6; num11--)
			{
				float num12 = num3;
				float num13 = num4 + (float)num11 * 2.5f;
				float x = num12 + 11f * c.N1.Sample(num12 * 0.008f + 17f, num13 * 0.008f);
				float num14 = num13 + 9f * c.N1.Sample(num12 * 0.008f - 41f, num13 * 0.008f + 5f);
				StringBuilder stringBuilder4 = new StringBuilder($"  massifs z {num13,6:F1}: abyss {Profile(c, num14) - Mathf.Lerp(34f, 18f, Smooth(c.Zn.Ga1, c.Zn.End, num14)),6:F1}");
				foreach (Massif massif2 in c.T2.Massifs)
				{
					float steps;
					float num15 = MassifHeight(c, massif2, x, num14, out steps);
					stringBuilder4.Append($" {massif2.Name} {num15,6:F1}(st {steps:F2} -> {RidgeSteps(c, num15, x, num14, c.T2.StepSeed):F1})");
				}
				stringBuilder4.Append($" | ground {c.G.Sample(num12, num13),6:F1}");
				c.L.Report.Add(stringBuilder4.ToString());
			}
		}

		private static void PoolExit(Ctx c)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			T2 t = c.T2;
			LogPool pool = c.L.Pool;
			if (t == null || pool == null || t.Massifs.Count == 0)
			{
				return;
			}
			HeightGrid g = c.G;
			Massif massif = t.Massifs[0];
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(pool.Far.x, pool.Far.z);
			int i;
			for (i = 0; i < massif.Spine.Count - 1 && massif.Spine[i].y < pool.Far.z + 30f; i++)
			{
			}
			Vector2 val2 = massif.Spine[i];
			Vector2 val3 = val2 - val;
			float magnitude = ((Vector2)(ref val3)).magnitude;
			if (magnitude < 5f)
			{
				return;
			}
			val3 /= magnitude;
			float y = pool.Far.y;
			float num = g.Sample(val2.x, val2.y);
			float num2 = Mathf.Clamp((num - y) / magnitude, -0.2f, 0.8f);
			int num3 = 0;
			for (float num4 = 0f; num4 <= magnitude; num4 += g.Cell * 0.5f)
			{
				Vector2 val4 = val + val3 * num4;
				float num5 = y + num2 * num4;
				for (float num6 = -4.5f; num6 <= 4.5f; num6 += g.Cell * 0.5f)
				{
					Vector2 val5 = val4 + new Vector2(val3.y, 0f - val3.x) * num6;
					int i2 = g.Ix(val5.x);
					int j = g.Jz(val5.y);
					if (g.In(i2, j) && !c.Water[g.Idx(i2, j)])
					{
						float num7 = Math.Abs(num6);
						float num8 = ((num7 <= 2.6f) ? num5 : Mathf.Lerp(num5, g[i2, j], Smooth(2.6f, 4.5f, num7)));
						if (Math.Abs(g[i2, j] - num8) > 0.05f)
						{
							g[i2, j] = num8;
							num3++;
						}
					}
				}
			}
			c.L.Report.Add($"terrain 2.0: crest cap from {t.CapY0:F1} rising {t.CapRate:F2} (ledge {y:F1})");
			c.L.Report.Add($"terrain 2.0: pool exit rib {magnitude:F0} m from the ledge ({y:F1}) to the route massif ({num:F1}), slope {num2:F2}, {num3} cells");
		}

		public static float GZ1(float length)
		{
			return length - 15f;
		}

		public static HeightGrid NewGrid(float length, float fill)
		{
			int w = (int)Math.Round(296.0) + 1;
			int h = (int)Math.Round((GZ1(length) - 22f) / 1.25f) + 1;
			return new HeightGrid(-172f, 22f, 1.25f, w, h, fill);
		}

		public static MountainLayout Generate(GenInput input, ulong seed)
		{
			MountainLayout mountainLayout = null;
			List<string> list = new List<string>();
			int num = ((Environment.GetEnvironmentVariable("SAKURA_DEBUG") ?? "").Contains("nofallback") ? 1 : 6);
			for (int i = 0; i < num; i++)
			{
				ulong num2 = ((i == 0) ? seed : Hash.Mix(seed, (ulong)i, 4195465924uL));
				MountainLayout mountainLayout2 = GenerateOnce(input, num2);
				if (i > 0)
				{
					mountainLayout2.Report.Insert(0, string.Format("fallback variant {0} (seed {1:X16}) after seed {2:X16} had no provable route; stuck at {3}", i, num2, seed, string.Join(" ", list)));
				}
				mountainLayout2.Seed = num2;
				if (mountainLayout2.RouteValid)
				{
					return mountainLayout2;
				}
				list.Add(((object)Unsafe.As<Vector3, Vector3>(ref mountainLayout2.StuckAt)/*cast due to .constrained prefix*/).ToString());
				if (mountainLayout == null)
				{
					mountainLayout = mountainLayout2;
				}
			}
			return mountainLayout;
		}

		private static MountainLayout GenerateOnce(GenInput input, ulong seed)
		{
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_040a: Unknown result type (might be due to invalid IL or missing references)
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			Ctx c = new Ctx
			{
				In = input,
				Seed = seed,
				Rng = Rng.For(seed, "layout"),
				N1 = new Noise2(Hash.Mix(seed, "n1")),
				N2 = new Noise2(Hash.Mix(seed, "n2")),
				N3 = new Noise2(Hash.Mix(seed, "n3")),
				L = new MountainLayout
				{
					Seed = seed
				}
			};
			c.G = NewGrid(input.Length, 0f);
			int w = c.G.W;
			int h = c.G.H;
			c.L.Terrain = c.G;
			c.L.Petals = new HeightGrid(-172f, 22f, 1.25f, w, h, 0f);
			PickTheme(c.L, seed);
			c.KeepClear = new bool[w * h];
			c.Water = new bool[w * h];
			c.NoTerrace = new bool[w * h];
			c.L.StartPoint = Vector3.zero;
			c.L.EndPoint = input.EndLocal;
			Compose(c);
			ShapeColumns(c);
			Passage(c);
			FlankCliffs(c);
			float[] array = (float[])c.G.Y.Clone();
			MergeExternal(c);
			GrandStair(c);
			Rivers(c);
			bool liftDbg = (Environment.GetEnvironmentVariable("SAKURA_DEBUG") ?? "").Contains("riverlift");
			float[] afterRivers = (liftDbg ? ((float[])c.G.Y.Clone()) : null);
			if (c.T2 != null)
			{
				PoolExit(c);
			}
			Lift("pool exit");
			CrestProfile(c);
			TempleResult temple = TemplePlan.Plan(c.L, input, Rng.For(seed, "temple"));
			RouteFinder.Solve(c.L, input, temple, Rng.For(seed, "route"), c.KeepClear);
			if (c.L.RouteValid)
			{
				c.L.Grotto = GrottoPlanner.Plan(c.L, input, c.KeepClear, c.Water);
			}
			Lift("route");
			Decorator.Decorate(c.L, input, Rng.For(seed, "decor"), c.KeepClear, c.Water, c.N3);
			if (c.L.Grotto != null)
			{
				GrottoPlanner.Clean(c.L);
				GrottoPlanner.Dress(c.L);
			}
			Lift("decor");
			FillWater(c);
			Views(c);
			c.L.Terraced = new bool[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				c.L.Terraced[i] = Math.Abs(array[i] - c.G.Y[i]) < 0.05f && (c.L.TerraceRiser[i] > 0f || c.L.ColumnSnap[i] != Vector2.zero);
			}
			return c.L;
			void Lift(string stage)
			{
				if (liftDbg)
				{
					int num = 0;
					StringBuilder stringBuilder = new StringBuilder();
					for (int j = 0; j < c.G.Y.Length; j++)
					{
						if (c.Water[j] && c.G.Y[j] > afterRivers[j] + 0.3f)
						{
							if (num < 12)
							{
								stringBuilder.Append($" ({c.G.Xof(j % c.G.W):F0},{c.G.Zof(j / c.G.W):F0} +{c.G.Y[j] - afterRivers[j]:F1})");
							}
							num++;
						}
					}
					c.L.Report.Add($"river lift after {stage}: {num} river cells raised >0.3 m:{stringBuilder}");
				}
			}
		}

		private static void PickTheme(MountainLayout L, ulong seed)
		{
			Rng rng = Rng.For(seed, "theme");
			float num = rng.Value();
			L.Theme = ((num < 0.3f) ? "spring" : ((num < 0.52f) ? "hanafubuki" : ((num < 0.72f) ? "lanterns" : ((num < 0.86f) ? "misty" : "bamboo"))));
			L.Onsen = rng.Chance(0.25f);
			L.Hardness = rng.Range(0.1f, 0.95f);
			L.Report.Add(string.Format("theme: {0}{1}, hardness {2:F2}", L.Theme, L.Onsen ? " + hot springs" : "", L.Hardness));
		}

		private static float Terrace(Ctx c, float y, float x, float z)
		{
			float yyOut;
			float riserOut;
			return Terrace(c, y, x, z, out yyOut, out riserOut);
		}

		private static float Terrace(Ctx c, float y, float x, float z, out float yyOut, out float riserOut)
		{
			float[] levels = c.Levels;
			yyOut = float.NaN;
			riserOut = 0f;
			float num = 5.5f * c.N1.Sample(x * 0.0045f + 50f, z * 0.0045f) + 1.8f * c.N2.Sample(x * 0.021f - 9f, z * 0.021f + 4f);
			float num2 = y + num;
			int num3 = Array.BinarySearch(levels, num2);
			if (num3 < 0)
			{
				num3 = ~num3 - 1;
			}
			if (num3 < 0 || num3 >= levels.Length - 1)
			{
				return y;
			}
			yyOut = num2;
			float num4 = levels[num3];
			float num5 = levels[num3 + 1];
			float num6 = (num2 - num4) / (num5 - num4);
			float num7 = Smooth(-56f, -40f, y);
			float num8 = Mathf.Lerp(0.55f, 0.09f, num7);
			float num9 = Mathf.Lerp(0.6f, 0.1f, num7);
			riserOut = ((num7 > 0.95f) ? num8 : 0f);
			float num10 = Smooth(1f - num8, 1f, num6) * (1f - num9) + num6 * num9;
			float num11 = num4 + num10 * (num5 - num4) - num;
			return Mathf.Lerp(y, num11, Mathf.Lerp(0.25f, 1f, num7));