Decompiled source of Lurid Looming Lookers v1.0.0

tony4twentys-Lurid Looming Lookers.dll

Decompiled 3 weeks ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Lurid_Looming_Lookers;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
using Zorro.Core;
using Zorro.Settings;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyTitle("Lurid Looming Lookers")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Lurid Looming Lookers")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ce43d2ac-cbdc-4a78-b61b-eaabca5ceb3d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Lurid_Looming_Lookers
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Resource1
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					ResourceManager resourceManager = new ResourceManager("Lurid_Looming_Lookers.Resource1", typeof(Resource1).Assembly);
					resourceMan = resourceManager;
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] whisperaudio
		{
			get
			{
				object obj = ResourceManager.GetObject("whisperaudio", resourceCulture);
				return (byte[])obj;
			}
		}

		internal Resource1()
		{
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace LuridLoomingLookers
{
	[BepInPlugin("tony4twentys.Lurid_Looming_Lookers", "Lurid Looming Lookers", "1.0.0")]
	[BepInProcess("PEAK.exe")]
	public class LuridLoomingLookersPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "tony4twentys.Lurid_Looming_Lookers";

		public const string PluginName = "Lurid Looming Lookers";

		public const string PluginVersion = "1.0.0";

		internal const byte EventCode = 160;

		internal const int ProtocolVersion = 2;

		internal const string EventMagic = "tony4twentys.Lurid_Looming_Lookers";

		internal const int MaxLookers = 1000;

		public const float HideDistance = 1f;

		public const float StareTime = 1f;

		public const float DotProduct = 0.8f;

		public const float InjuryAmount = 0.01f;

		public const float InjuryCooldown = 1f;

		public const float CloseInjuryThreshold = 5f;

		public const float MaxActiveDistance = 40f;

		internal static LuridLoomingLookersPlugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<int> LookersShore;

		internal static ConfigEntry<int> LookersTropics;

		internal static ConfigEntry<int> LookersRoots;

		internal static ConfigEntry<int> LookersAlpine;

		internal static ConfigEntry<int> LookersMesa;

		internal static ConfigEntry<int> LookersGloom;

		internal static ConfigEntry<int> LookersCaldera;

		internal static ConfigEntry<int> LookersKiln;

		internal static ConfigEntry<int> LookersCitadel;

		internal static ConfigEntry<int> LookersPeak;

		internal static ConfigEntry<int> SpawnPerSecond;

		internal static ConfigEntry<bool> LookerInjury;

		internal static ConfigEntry<float> InjuryAmountConfig;

		internal static ConfigEntry<int> MaxLookersInjuring;

		internal static ConfigEntry<bool> SpawnOnPeak;

		internal static ConfigEntry<int> WhisperVolume;

		internal static AudioClip WhisperClip;

		private Harmony _harmony;

		private static bool _loggedTickError;

		private static bool _loggedInjuryError;

		private static bool _hostReady;

		private static bool _applyingHost;

		private static int _hostShore;

		private static int _hostTropics;

		private static int _hostRoots;

		private static int _hostAlpine;

		private static int _hostMesa;

		private static int _hostGloom;

		private static int _hostCaldera;

		private static int _hostKiln;

		private static int _hostCitadel;

		private static int _hostPeak;

		private static int _hostRate;

		private static bool _hostPeakSpawn;

		private static bool _hostInjury;

		private static float _hostInjuryAmount;

		private static int _hostMaxInjuring;

		internal static bool UsingHostConfig
		{
			get
			{
				try
				{
					return PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient && _hostReady;
				}
				catch
				{
					return false;
				}
			}
		}

		internal static int SpawnRate
		{
			get
			{
				int num = (UsingHostConfig ? _hostRate : Read(SpawnPerSecond, 25));
				return Mathf.Clamp(num, 1, 50);
			}
		}

		internal static bool PeakSpawnEnabled => UsingHostConfig ? _hostPeakSpawn : (SpawnOnPeak == null || SpawnOnPeak.Value);

		internal static bool InjuryEnabled => UsingHostConfig ? _hostInjury : (LookerInjury != null && LookerInjury.Value);

		internal static float InjuryPerTick
		{
			get
			{
				float num = (UsingHostConfig ? _hostInjuryAmount : ((InjuryAmountConfig == null) ? 0.01f : InjuryAmountConfig.Value));
				return Mathf.Clamp(num, 0f, 0.25f);
			}
		}

		internal static int MaxInjuringAtOnce
		{
			get
			{
				int num = (UsingHostConfig ? _hostMaxInjuring : Read(MaxLookersInjuring, 3));
				return Mathf.Clamp(num, 0, 50);
			}
		}

		internal static float WhisperScale => Mathf.Clamp01((float)Read(WhisperVolume, 100) / 100f);

		private void Awake()
		{
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			LookersShore = BindBiomeCount("LookersShore", "Shore", 200);
			LookersTropics = BindBiomeCount("LookersTropics", "Tropics", 200);
			LookersRoots = BindBiomeCount("LookersRoots", "Roots", 200);
			LookersAlpine = BindBiomeCount("LookersAlpine", "Alpine", 200);
			LookersMesa = BindBiomeCount("LookersMesa", "Mesa", 200);
			LookersGloom = BindBiomeCount("LookersGloom", "Gloom", 200);
			LookersCaldera = BindBiomeCount("LookersCaldera", "Caldera", 200);
			LookersKiln = BindBiomeCount("LookersKiln", "Kiln", 50);
			LookersCitadel = BindBiomeCount("LookersCitadel", "Citadel", 200);
			LookersPeak = BindBiomeCount("LookersPeak", "Peak", 50);
			SpawnPerSecond = BindCount("SpawnPerSecond", 25, "Minimum probe rate while planting extras. Each attempt waits 1/this seconds. Host value is used in multiplayer.", 1, 50);
			LookerInjury = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "LookerInjury", true, "Host-synced. When on, staring at a Looker or standing within 5m applies Injury. Off: extras still spawn and peek.");
			LookerInjury.SettingChanged += OnAnySettingChanged;
			InjuryAmountConfig = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "InjuryAmount", 0.01f, new ConfigDescription("Host-synced. Injury added by one Looker tick. Default 0.01.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.25f), Array.Empty<object>()));
			InjuryAmountConfig.SettingChanged += OnAnySettingChanged;
			MaxLookersInjuring = BindCount("MaxLookersInjuring", 3, "Host-synced. How many Lookers can apply injury in the same cooldown window. Closest ones win.", 0, 50, "Gameplay");
			SpawnOnPeak = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawning", "SpawnOnPeak", true, "Host-synced. When on, extras paint on Peak after the PEAK stinger.");
			SpawnOnPeak.SettingChanged += OnAnySettingChanged;
			WhisperVolume = BindCount("WhisperVolume", 100, "Local whisper loudness, 0-100. Stacks with game Master Volume (not Voices). 100 with Master at 50% is quieter; 50 with Master at 50% is nearly silent. Not host-synced.", 0, 100, "Audio");
			_harmony = new Harmony("tony4twentys.Lurid_Looming_Lookers");
			_harmony.PatchAll();
			LoadWhisper();
			LookerNet.Ensure();
			SceneManager.sceneLoaded += OnSceneLoaded;
			Log.LogInfo((object)("Loaded v1.0.0 — raycast spawns, host sync on event " + (byte)160 + "."));
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
			LookerAudio.Tick();
		}

		private void LateUpdate()
		{
			LuridLoomingLookers.LookerInjury.Flush();
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			LookerSpawner.OnSceneLoaded(((Scene)(ref scene)).name);
		}

		private ConfigEntry<int> BindBiomeCount(string key, string biome, int defaultValue)
		{
			return BindCount(key, defaultValue, "Extra Lookers on " + biome + ". 0 skips this biome. Host-synced. 1000 is the cap. Default " + defaultValue + ".");
		}

		private ConfigEntry<int> BindCount(string key, int defaultValue, string description, int min = 0, int max = 1000, string section = "Spawning")
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>()));
			val.SettingChanged += OnAnySettingChanged;
			return val;
		}

		private static void OnAnySettingChanged(object sender, EventArgs e)
		{
			if (!_applyingHost && sender != WhisperVolume)
			{
				LuridLoomingLookers.LookerInjury.OnEnabledChanged(InjuryEnabled);
				LookerNet.OnLocalSettingChanged();
			}
		}

		internal static int SpawnCountFor(string biome)
		{
			int num = (UsingHostConfig ? HostBiomeRaw(biome) : LocalBiomeRaw(biome));
			if (num < 0)
			{
				return DefaultForBiome(biome);
			}
			return ClampCount(num, 0);
		}

		internal static object[] BuildConfigPayload(byte sub)
		{
			return new object[18]
			{
				"tony4twentys.Lurid_Looming_Lookers",
				2,
				sub,
				Read(LookersShore, 200),
				Read(LookersTropics, 200),
				Read(LookersRoots, 200),
				Read(LookersAlpine, 200),
				Read(LookersMesa, 200),
				Read(LookersGloom, 200),
				Read(LookersCaldera, 200),
				Read(LookersKiln, 50),
				Read(LookersCitadel, 200),
				Read(LookersPeak, 50),
				Read(SpawnPerSecond, 25),
				SpawnOnPeak != null && SpawnOnPeak.Value,
				LookerInjury != null && LookerInjury.Value,
				(InjuryAmountConfig != null) ? InjuryAmountConfig.Value : 0.01f,
				Read(MaxLookersInjuring, 3)
			};
		}

		internal static void ApplyRemoteConfig(object[] arr)
		{
			if (arr == null || arr.Length < 18)
			{
				return;
			}
			_applyingHost = true;
			try
			{
				_hostShore = ClampCount(ToInt(arr[3]), 0);
				_hostTropics = ClampCount(ToInt(arr[4]), 0);
				_hostRoots = ClampCount(ToInt(arr[5]), 0);
				_hostAlpine = ClampCount(ToInt(arr[6]), 0);
				_hostMesa = ClampCount(ToInt(arr[7]), 0);
				_hostGloom = ClampCount(ToInt(arr[8]), 0);
				_hostCaldera = ClampCount(ToInt(arr[9]), 0);
				_hostKiln = ClampCount(ToInt(arr[10]), 0);
				_hostCitadel = ClampCount(ToInt(arr[11]), 0);
				_hostPeak = ClampCount(ToInt(arr[12]), 0);
				_hostRate = Mathf.Clamp(ToInt(arr[13]), 1, 50);
				_hostPeakSpawn = ToBool(arr[14]);
				_hostInjury = ToBool(arr[15]);
				_hostInjuryAmount = Mathf.Clamp(ToFloat(arr[16]), 0f, 0.25f);
				_hostMaxInjuring = Mathf.Clamp(ToInt(arr[17]), 0, 50);
				_hostReady = true;
				LuridLoomingLookers.LookerInjury.OnEnabledChanged(InjuryEnabled);
			}
			finally
			{
				_applyingHost = false;
			}
		}

		internal static void ClearHostConfig()
		{
			_hostReady = false;
			LuridLoomingLookers.LookerInjury.OnEnabledChanged(InjuryEnabled);
		}

		private static int LocalBiomeRaw(string biome)
		{
			return Read(EntryForBiome(biome), DefaultForBiome(biome));
		}

		private static int DefaultForBiome(string biome)
		{
			if (biome == "Kiln" || biome == "Peak")
			{
				return 50;
			}
			return 200;
		}

		private static int HostBiomeRaw(string biome)
		{
			return biome switch
			{
				"Shore" => _hostShore, 
				"Tropics" => _hostTropics, 
				"Roots" => _hostRoots, 
				"Alpine" => _hostAlpine, 
				"Mesa" => _hostMesa, 
				"Gloom" => _hostGloom, 
				"Caldera" => _hostCaldera, 
				"Kiln" => _hostKiln, 
				"Citadel" => _hostCitadel, 
				"Peak" => _hostPeak, 
				_ => DefaultForBiome(biome), 
			};
		}

		private static ConfigEntry<int> EntryForBiome(string biome)
		{
			if (string.IsNullOrEmpty(biome))
			{
				return null;
			}
			return (ConfigEntry<int>)(biome switch
			{
				"Shore" => LookersShore, 
				"Tropics" => LookersTropics, 
				"Roots" => LookersRoots, 
				"Alpine" => LookersAlpine, 
				"Mesa" => LookersMesa, 
				"Gloom" => LookersGloom, 
				"Caldera" => LookersCaldera, 
				"Kiln" => LookersKiln, 
				"Citadel" => LookersCitadel, 
				"Peak" => LookersPeak, 
				_ => null, 
			});
		}

		private static int Read(ConfigEntry<int> entry, int fallback)
		{
			return entry?.Value ?? fallback;
		}

		private static int ClampCount(int value, int min)
		{
			return Mathf.Clamp(value, min, 1000);
		}

		private static int ToInt(object value)
		{
			if (value is int result)
			{
				return result;
			}
			if (value is byte result2)
			{
				return result2;
			}
			if (value is short result3)
			{
				return result3;
			}
			if (value is float num)
			{
				return Mathf.RoundToInt(num);
			}
			return Convert.ToInt32(value);
		}

		private static float ToFloat(object value)
		{
			if (value is float result)
			{
				return result;
			}
			if (value is double num)
			{
				return (float)num;
			}
			if (value is int num2)
			{
				return num2;
			}
			return Convert.ToSingle(value);
		}

		private static bool ToBool(object value)
		{
			if (value is bool result)
			{
				return result;
			}
			return ToInt(value) != 0;
		}

		internal static void LogTickError(Exception ex)
		{
			if (!_loggedTickError)
			{
				_loggedTickError = true;
				Log.LogError((object)("[Lurid Looming Lookers] Looker tick failed once: " + ex));
			}
		}

		internal static void LogInjuryError(Exception ex)
		{
			if (!_loggedInjuryError)
			{
				_loggedInjuryError = true;
				Log.LogError((object)("[Lurid Looming Lookers] Injury apply failed once: " + ex));
			}
		}

		private static void LoadWhisper()
		{
			try
			{
				byte[] whisperaudio = Resource1.whisperaudio;
				if (whisperaudio != null && whisperaudio.Length != 0)
				{
					AssetBundle val = AssetBundle.LoadFromMemory(whisperaudio);
					if (!((Object)(object)val == (Object)null))
					{
						WhisperClip = val.LoadAsset<AudioClip>("ScoutWhispers");
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Whisper audio failed to load: " + ex.Message));
			}
		}
	}
	internal sealed class LookerNet : MonoBehaviourPunCallbacks, IOnEventCallback
	{
		internal const byte SubSpawn = 1;

		internal const byte SubRequest = 2;

		internal const byte SubClear = 3;

		internal const byte SubBegin = 4;

		internal const byte SubAdd = 5;

		internal const byte SubConfig = 6;

		private int _lastSegment = int.MinValue;

		private readonly List<Vector3> _lastPositions = new List<Vector3>(64);

		private Coroutine _configDebounce;

		internal static LookerNet Instance { get; private set; }

		internal static void Ensure()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("LuridLookers_Net");
				Object.DontDestroyOnLoad((Object)(object)val);
				Instance = val.AddComponent<LookerNet>();
			}
		}

		public override void OnEnable()
		{
			((MonoBehaviourPunCallbacks)this).OnEnable();
			PhotonNetwork.AddCallbackTarget((object)this);
		}

		public override void OnDisable()
		{
			PhotonNetwork.RemoveCallbackTarget((object)this);
			((MonoBehaviourPunCallbacks)this).OnDisable();
		}

		public override void OnJoinedRoom()
		{
			if (PhotonNetwork.IsMasterClient)
			{
				LuridLoomingLookersPlugin.ClearHostConfig();
				BroadcastConfig();
			}
			else
			{
				RequestSync();
			}
		}

		public override void OnLeftRoom()
		{
			_lastSegment = int.MinValue;
			_lastPositions.Clear();
			LuridLoomingLookersPlugin.ClearHostConfig();
			LookerSpawner.ResetRun();
		}

		public override void OnMasterClientSwitched(Player newMasterClient)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				LuridLoomingLookersPlugin.ClearHostConfig();
				BroadcastConfig();
			}
			else
			{
				LuridLoomingLookersPlugin.ClearHostConfig();
				RequestSync();
			}
		}

		public override void OnPlayerEnteredRoom(Player newPlayer)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				((MonoBehaviour)this).StartCoroutine(BroadcastAfterJoin());
			}
		}

		public void OnEvent(EventData photonEvent)
		{
			//IL_01b5: 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_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			if (photonEvent == null || photonEvent.Code != 160 || !(photonEvent.CustomData is object[] array) || array.Length < 3 || !(array[0] is string text) || text != "tony4twentys.Lurid_Looming_Lookers" || ToInt(array[1]) != 2)
			{
				return;
			}
			byte b = ToByte(array[2]);
			if (b == 2 && PhotonNetwork.IsMasterClient)
			{
				BroadcastConfig();
				BroadcastCached();
			}
			else if (b == 6)
			{
				if (!PhotonNetwork.IsMasterClient)
				{
					LuridLoomingLookersPlugin.ApplyRemoteConfig(array);
					LuridLoomingLookersPlugin.Log.LogInfo((object)("Host config applied — injury " + (LuridLoomingLookersPlugin.InjuryEnabled ? "on" : "off") + "."));
				}
			}
			else
			{
				if (PhotonNetwork.IsMasterClient)
				{
					return;
				}
				switch (b)
				{
				case 3:
					_lastSegment = int.MinValue;
					_lastPositions.Clear();
					LookerSpawner.ClearSpawned();
					return;
				case 4:
					if (array.Length >= 4)
					{
						_lastSegment = ToInt(array[3]);
						_lastPositions.Clear();
						LookerSpawner.BeginRemote(_lastSegment);
						return;
					}
					break;
				}
				if (b == 5 && array.Length >= 5)
				{
					int num = ToInt(array[3]);
					if (array[4] is Vector3 val)
					{
						_lastSegment = num;
						_lastPositions.Add(val);
						LookerSpawner.AddRemotePoint(num, val);
					}
				}
				else if (b == 1 && array.Length >= 5)
				{
					int num2 = ToInt(array[3]);
					Vector3[] array2 = array[4] as Vector3[];
					if (array2 == null)
					{
						array2 = Array.Empty<Vector3>();
					}
					_lastSegment = num2;
					_lastPositions.Clear();
					_lastPositions.AddRange(array2);
					LookerSpawner.ApplyHostSpawn(num2, array2);
				}
			}
		}

		internal void NotifyClear()
		{
			_lastSegment = int.MinValue;
			_lastPositions.Clear();
			RaiseToOthers(3);
		}

		internal void BeginSegment(int segment)
		{
			_lastSegment = segment;
			_lastPositions.Clear();
			RaiseToOthers(4, segment);
		}

		internal void AddPoint(int segment, Vector3 position)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			_lastSegment = segment;
			_lastPositions.Add(position);
			RaiseToOthers(5, segment, position);
		}

		private void BroadcastCached()
		{
			if (_lastSegment != int.MinValue)
			{
				RaiseToOthers(1, _lastSegment, _lastPositions.ToArray());
			}
		}

		internal static void OnLocalSettingChanged()
		{
			if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && !((Object)(object)Instance == (Object)null))
			{
				if (Instance._configDebounce != null)
				{
					((MonoBehaviour)Instance).StopCoroutine(Instance._configDebounce);
				}
				Instance._configDebounce = ((MonoBehaviour)Instance).StartCoroutine(Instance.DebounceConfig());
			}
		}

		internal static void RequestSync()
		{
			if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
			{
				Raise((ReceiverGroup)2, 2);
			}
		}

		private void RaiseToOthers(byte sub, params object[] extra)
		{
			if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				Raise((ReceiverGroup)0, sub, extra);
			}
		}

		private static void Raise(ReceiverGroup group, byte sub, params object[] extra)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_005c: Expected O, but got Unknown
			object[] array = new object[3 + extra.Length];
			array[0] = "tony4twentys.Lurid_Looming_Lookers";
			array[1] = 2;
			array[2] = sub;
			for (int i = 0; i < extra.Length; i++)
			{
				array[3 + i] = extra[i];
			}
			PhotonNetwork.RaiseEvent((byte)160, (object)array, new RaiseEventOptions
			{
				Receivers = group
			}, SendOptions.SendReliable);
		}

		private IEnumerator BroadcastAfterJoin()
		{
			yield return (object)new WaitForSeconds(0.5f);
			BroadcastConfig();
			BroadcastCached();
		}

		private IEnumerator DebounceConfig()
		{
			yield return (object)new WaitForSeconds(0.25f);
			BroadcastConfig();
			_configDebounce = null;
		}

		private static void BroadcastConfig()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				PhotonNetwork.RaiseEvent((byte)160, (object)LuridLoomingLookersPlugin.BuildConfigPayload(6), new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)0
				}, SendOptions.SendReliable);
			}
		}

		private static int ToInt(object value)
		{
			if (value is int result)
			{
				return result;
			}
			if (value is byte result2)
			{
				return result2;
			}
			if (value is short result3)
			{
				return result3;
			}
			return Convert.ToInt32(value);
		}

		private static byte ToByte(object value)
		{
			if (value is byte result)
			{
				return result;
			}
			return (byte)ToInt(value);
		}
	}
	internal sealed class ModLooker : MonoBehaviour
	{
		internal AudioSource Audio;
	}
	internal static class LookerSpawner
	{
		private enum VerticalZone
		{
			None,
			Basin,
			Shaft,
			Summit
		}

		private struct VerticalColumn
		{
			public Vector3 Center;

			public float Y0;

			public float Y1;

			public float Radius;
		}

		private struct Ribbon
		{
			public int Index;

			public Vector3 Start;

			public Vector3 Along;

			public Vector3 Across;

			public float Length;

			public float Width;

			public float YTop;
		}

		private const float RayStartAbove = 80f;

		private const float RayLength = 800f;

		private const float CampfireExclusion = 18f;

		private const float ShoreCampfireExclusion = 28f;

		private const float CorridorInset = 0.04f;

		private const float ShoreInset = 0.06f;

		private const int ShoreBands = 12;

		private const float CorridorWidthFraction = 0.5f;

		private const float MinCorridorWidth = 24f;

		private const float MaxCorridorWidth = 72f;

		private const float ShoreMaxWidth = 28f;

		private const float ShoreWaterClear = 100f;

		private const float CorridorWiden = 60f;

		private const float CorridorSpacing = 3f;

		private const float PeakBelowFlag = 32f;

		private const float MaxSlope = 75f;

		private const float VerticalSlope = 85f;

		private const float VerticalBand = 160f;

		private const float VerticalSliceHeight = 14f;

		private const int JitterTries = 4;

		private const int DestroysPerFrame = 40;

		private const float CitadelRoofExtra = 36f;

		private const float PeakAboveExtra = 8f;

		private const float PeakAroundFlag = 52f;

		private const float PeakFlagExclusion = 12f;

		private const float PeakBoxExclusion = 10f;

		private const float PeakWalkNormal = 0.35f;

		private const int PeakRaycastsPerFrame = 12;

		private const int PeakSpawnsPerFrame = 2;

		private const float CalderaRayLength = 280f;

		private const float KilnWallRay = 130f;

		private const float KilnMinRing = 10f;

		private const float KilnMinSpacing = 12f;

		private static int _matLogs;

		private static int _missDetail;

		private static int _missNoHit;

		private static int _missBad;

		private static int _missSlope;

		private static int _missCrowd;

		private static int _missOther;

		private static float _peakRoofYCached = float.NaN;

		private static bool _peakCollidersReady;

		private static readonly List<Collider> PeakColliders = new List<Collider>(64);

		private static readonly List<Collider> CalderaPads = new List<Collider>(64);

		private static Looker[] _vanillaCache;

		private static Transform[] _segmentRoots;

		private static float _peakScatterR = 52f;

		internal static readonly List<ModLooker> Spawned = new List<ModLooker>(64);

		private static readonly Dictionary<int, Bounds> BoundsCache = new Dictionary<int, Bounds>(8);

		private static readonly Dictionary<int, VerticalColumn> ColumnCache = new Dictionary<int, VerticalColumn>(8);

		private static readonly HashSet<int> BoundsTried = new HashSet<int>();

		private static readonly Queue<Vector3> RemoteQueue = new Queue<Vector3>(64);

		private static readonly RaycastHit[] PeakHits = (RaycastHit[])(object)new RaycastHit[48];

		private static readonly RaycastHit[] GroundHits = (RaycastHit[])(object)new RaycastHit[32];

		private static Ribbon _ribbon;

		private static Coroutine _boot;

		private static Coroutine _pending;

		private static GameObject _prototype;

		private static GameObject _cachedTemplate;

		private static Looker _cachedLooker;

		private static int _inFlightSegment = int.MinValue;

		private static int _completedSegment = int.MinValue;

		private static int _remoteSegment = int.MinValue;

		private static bool _paintingPeak;

		private static bool _peakPainted;

		private static Transform _citadelEntry;

		private static Transform _citadelExit;

		private static Transform _peakGround;

		private static Transform _peakFlag;

		private static Transform _peakBox;

		private static Transform _kilnCliff;

		private static Transform _volcanoCliff;

		private static Transform _peakKilnGround;

		private static Transform _shoreStartFire;

		private static bool _anchorsWalked;

		internal static void OnSceneLoaded(string sceneName)
		{
			ResetRun();
			if (IsClimbScene(sceneName))
			{
				LuridLoomingLookersPlugin.Log.LogInfo((object)("Climb scene '" + sceneName + "' — waiting for map/room."));
				if ((Object)(object)LuridLoomingLookersPlugin.Instance != (Object)null)
				{
					_boot = ((MonoBehaviour)LuridLoomingLookersPlugin.Instance).StartCoroutine(BootScene());
				}
			}
		}

		internal static void ResetRun()
		{
			StopBoot();
			StopPending();
			ClearSpawned();
			ClearTemplateCache();
			BoundsCache.Clear();
			ColumnCache.Clear();
			BoundsTried.Clear();
			RemoteQueue.Clear();
			CalderaPads.Clear();
			_vanillaCache = null;
			_segmentRoots = null;
			_ribbon = default(Ribbon);
			_ribbon.Index = int.MinValue;
			_peakScatterR = 52f;
			_completedSegment = int.MinValue;
			_inFlightSegment = int.MinValue;
			_remoteSegment = int.MinValue;
			_paintingPeak = false;
			_peakPainted = false;
			ClearAnchors();
		}

		internal static void RequestStinger(ProgressPoint point)
		{
			if (!CanHostRequest() || point == null)
			{
				return;
			}
			if (IsPeakStinger(point))
			{
				if (!LuridLoomingLookersPlugin.PeakSpawnEnabled)
				{
					LuridLoomingLookersPlugin.Log.LogInfo((object)"Stinger 'PEAK' — SpawnOnPeak is off, skipping.");
					return;
				}
				LuridLoomingLookersPlugin.Log.LogInfo((object)"Stinger 'PEAK' — paint Peak ground around Flag Pole, at Exit/Cliff height and up.");
				RequestPeak();
				return;
			}
			int num = FindSegmentForStinger(point);
			if (num >= 0)
			{
				LuridLoomingLookersPlugin.Log.LogInfo((object)("Stinger '" + (point.title ?? ((object)Unsafe.As<BiomeType, BiomeType>(ref point.biome)/*cast due to .constrained prefix*/).ToString()) + "' — paint " + DescribeSegment(num) + "."));
				RequestSegment(num);
			}
		}

		internal static void RequestCurrentSegment()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			if (!CanHostRequest())
			{
				return;
			}
			MapHandler instance = Singleton<MapHandler>.Instance;
			if (!((Object)(object)instance == (Object)null) && instance.segments != null)
			{
				int currentSegment = instance.currentSegment;
				if (currentSegment != 5 && (int)instance.GetCurrentSegment() != 5)
				{
					RequestSegment(currentSegment);
				}
			}
		}

		internal static void RequestPeak()
		{
			if (LuridLoomingLookersPlugin.PeakSpawnEnabled && CanHostRequest() && !_peakPainted && !_paintingPeak)
			{
				int index = PeakSlotIndex();
				StopPending();
				InvalidateVerticalCache(index);
				ClearAnchors();
				_paintingPeak = true;
				LookerNet.Instance?.NotifyClear();
				_pending = ((MonoBehaviour)LuridLoomingLookersPlugin.Instance).StartCoroutine(ScatterWhenReady(index));
			}
		}

		private static bool CanHostRequest()
		{
			//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)
			if ((Object)(object)LuridLoomingLookersPlugin.Instance == (Object)null)
			{
				return false;
			}
			if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient)
			{
				return false;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			return IsClimbScene(((Scene)(ref activeScene)).name);
		}

		private static void RequestSegment(int index)
		{
			if (index != _inFlightSegment && index != _completedSegment && (!IsPeakSegment(index) || _paintingPeak))
			{
				if (_inFlightSegment != int.MinValue)
				{
					LuridLoomingLookersPlugin.Log.LogInfo((object)("Campfire stop — aborting " + DescribeSegment(_inFlightSegment) + ", wipe extras, paint " + DescribeSegment(index) + "."));
				}
				StopPending();
				LookerNet.Instance?.NotifyClear();
				_pending = ((MonoBehaviour)LuridLoomingLookersPlugin.Instance).StartCoroutine(ScatterWhenReady(index));
			}
		}

		private static bool IsPeakStinger(ProgressPoint point)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)point.biome == 5)
			{
				return true;
			}
			return point.title != null && point.title.Equals("PEAK", StringComparison.OrdinalIgnoreCase);
		}

		private static int FindSegmentForStinger(ProgressPoint point)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			MapHandler instance = Singleton<MapHandler>.Instance;
			if ((Object)(object)instance == (Object)null || instance.segments == null)
			{
				return -1;
			}
			string text = point.title ?? "";
			if (text.IndexOf("CITADEL", StringComparison.OrdinalIgnoreCase) >= 0 || (int)point.biome == 9)
			{
				return FindNamedSegment(instance, "Temple", "Citadel");
			}
			if (text.IndexOf("KILN", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return FindNamedSegment(instance, "Kiln", "Volcano_Segment");
			}
			if (text.IndexOf("GLOOM", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return FindNamedSegment(instance, "Swamp_Segment", "Gloom");
			}
			if (text.IndexOf("CALDERA", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return FindNamedSegment(instance, "Caldera", "Volcano");
			}
			if (text.IndexOf("ROOTS", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return FindNamedSegment(instance, "Roots", "Tropics");
			}
			for (int i = 0; i < instance.segments.Length; i++)
			{
				MapSegment val = instance.segments[i];
				if (val != null && val.biome == point.biome && !IsPeakSegment(i))
				{
					return i;
				}
			}
			int currentSegment = instance.currentSegment;
			if (currentSegment >= 0 && currentSegment < instance.segments.Length && !IsPeakSegment(currentSegment))
			{
				return currentSegment;
			}
			return -1;
		}

		private static int FindNamedSegment(MapHandler map, string tokenA, string tokenB)
		{
			for (int i = 0; i < map.segments.Length; i++)
			{
				if (!IsPeakSegment(i))
				{
					GameObject segmentParent = GetSegmentParent(map, i);
					string name = (((Object)(object)segmentParent != (Object)null) ? ((Object)segmentParent).name : "");
					if (NameContains(name, tokenA) || NameContains(name, tokenB))
					{
						return i;
					}
				}
			}
			return -1;
		}

		internal static void ApplyHostSpawn(int segment, Vector3[] positions)
		{
			if (!((Object)(object)LuridLoomingLookersPlugin.Instance == (Object)null))
			{
				StopPending();
				_paintingPeak = IsPeakSegment(segment);
				_pending = ((MonoBehaviour)LuridLoomingLookersPlugin.Instance).StartCoroutine(SpawnWhenReady(segment, positions));
			}
		}

		internal static void BeginRemote(int segment)
		{
			if (!((Object)(object)LuridLoomingLookersPlugin.Instance == (Object)null))
			{
				StopPending();
				_paintingPeak = IsPeakSegment(segment);
				RemoteQueue.Clear();
				_remoteSegment = segment;
				_pending = ((MonoBehaviour)LuridLoomingLookersPlugin.Instance).StartCoroutine(BeginRemoteRoutine(segment));
			}
		}

		internal static void AddRemotePoint(int segment, Vector3 position)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (segment != _remoteSegment || (Object)(object)_prototype == (Object)null)
			{
				if (segment == _remoteSegment || _remoteSegment == int.MinValue)
				{
					RemoteQueue.Enqueue(position);
				}
			}
			else
			{
				SpawnOne(segment, position, default(RaycastHit), hasHit: false);
			}
		}

		internal static void ClearSpawned()
		{
			for (int num = Spawned.Count - 1; num >= 0; num--)
			{
				ModLooker modLooker = Spawned[num];
				if ((Object)(object)modLooker != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)modLooker).gameObject);
				}
			}
			Spawned.Clear();
			DestroyPrototype();
			LookerAudio.Reset();
			LookerInjury.Reset();
		}

		private static IEnumerator BootScene()
		{
			float timeout = 60f;
			while (timeout > 0f && ((Object)(object)Singleton<MapHandler>.Instance == (Object)null || !MapHandler.ExistsAndInitialized || !PhotonNetwork.InRoom || (Object)(object)Character.localCharacter == (Object)null || IsLoadingScreen()))
			{
				yield return (object)new WaitForSeconds(0.25f);
				timeout -= 0.25f;
			}
			if (!PhotonNetwork.InRoom || (Object)(object)Singleton<MapHandler>.Instance == (Object)null || IsLoadingScreen())
			{
				ManualLogSource log = LuridLoomingLookersPlugin.Log;
				Scene activeScene = SceneManager.GetActiveScene();
				log.LogInfo((object)("Boot skipped on '" + ((Scene)(ref activeScene)).name + "' — no room, map, or still loading."));
				_boot = null;
				yield break;
			}
			yield return (object)new WaitForSeconds(0.75f);
			if (IsLoadingScreen())
			{
				_boot = null;
				yield break;
			}
			if (PhotonNetwork.IsMasterClient)
			{
				RequestCurrentSegment();
			}
			else
			{
				LookerNet.RequestSync();
			}
			_boot = null;
		}

		private static IEnumerator ScatterWhenReady(int index)
		{
			_inFlightSegment = index;
			yield return ClearSpawnedRoutine();
			CacheFirstLooker();
			yield return WaitForSegment(index);
			EnableVanillaLookers(index);
			LookerNet.Instance?.BeginSegment(index);
			yield return DripPlaceAndSpawn(index);
			if (_paintingPeak)
			{
				_peakPainted = true;
			}
			_paintingPeak = false;
			_completedSegment = index;
			_inFlightSegment = int.MinValue;
			_pending = null;
		}

		private static IEnumerator SpawnWhenReady(int segment, Vector3[] positions)
		{
			yield return ClearSpawnedRoutine();
			CacheFirstLooker();
			yield return WaitForSegment(segment);
			EnableVanillaLookers(segment);
			yield return DripKnownPositions(segment, positions);
			_pending = null;
		}

		private static IEnumerator BeginRemoteRoutine(int segment)
		{
			yield return ClearSpawnedRoutine();
			CacheFirstLooker();
			yield return WaitForSegment(segment);
			EnableVanillaLookers(segment);
			if (!PreparePrototype(segment))
			{
				_pending = null;
				yield break;
			}
			while (RemoteQueue.Count > 0)
			{
				SpawnOne(segment, RemoteQueue.Dequeue(), default(RaycastHit), hasHit: false);
				yield return null;
			}
			_pending = null;
		}

		private static IEnumerator WaitForSegment(int index)
		{
			float timeout = 40f;
			while (timeout > 0f && IsLoadingScreen())
			{
				yield return (object)new WaitForSeconds(0.25f);
				timeout -= 0.25f;
			}
			for (timeout = 40f; timeout > 0f; timeout -= 0.25f)
			{
				if (WantsPeakColumn(index))
				{
					ResolveAnchors();
					if (PeakAnchorsReady())
					{
						break;
					}
				}
				else
				{
					MapHandler map = Singleton<MapHandler>.Instance;
					GameObject parent = GetSegmentParent(map, index);
					if ((Object)(object)parent != (Object)null && parent.activeInHierarchy)
					{
						break;
					}
				}
				yield return (object)new WaitForSeconds(0.25f);
			}
			yield return (object)new WaitForSeconds(WantsPeakColumn(index) ? 0.2f : 1.25f);
			if (WantsPeakColumn(index) && !PeakAnchorsReady())
			{
				LuridLoomingLookersPlugin.Log.LogWarning((object)"Peak paint has no Flag Pole / Rock_Platform or Kiln Cliff yet — looking again.");
				ClearAnchors();
				ResolveAnchors();
			}
		}

		private static IEnumerator ClearSpawnedRoutine()
		{
			int n = 0;
			for (int i = Spawned.Count - 1; i >= 0; i--)
			{
				ModLooker extra = Spawned[i];
				if ((Object)(object)extra != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)extra).gameObject);
				}
				n++;
				if (n % 40 == 0)
				{
					yield return null;
				}
			}
			Spawned.Clear();
			DestroyPrototype();
			LookerAudio.Reset();
			LookerInjury.Reset();
		}

		private static IEnumerator DripPlaceAndSpawn(int index)
		{
			if (UseVerticalFill(index) || WantsPeakColumn(index))
			{
				ResolveAnchors();
			}
			int target = TargetCount(index);
			if (target <= 0 || !PreparePrototype(index))
			{
				yield break;
			}
			List<Vector3> origins = BuildOrigins(index, target);
			List<Vector3> placed = new List<Vector3>(target);
			int rate = LuridLoomingLookersPlugin.SpawnRate;
			float interval = 1f / (float)rate;
			bool area = UseAreaFill(index);
			float maxSlope = 75f;
			if (IsKilnPaint(index) || IsShorePaint(index))
			{
				maxSlope = 89f;
			}
			else if (IsCalderaPaint(index))
			{
				maxSlope = 75f;
			}
			else if (area)
			{
				maxSlope = 85f;
			}
			_matLogs = 0;
			ResetMissStats();
			float started = Time.realtimeSinceStartup;
			if (WantsPeakColumn(index))
			{
				yield return PeakGatherAndSpawn(index, target, origins, area, maxSlope);
				yield break;
			}
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Placing " + target + " extras in " + DescribeSegment(index) + " (" + CountKey(index) + ", " + (IsKilnPaint(index) ? "kiln walls" : (IsCalderaPaint(index) ? "caldera crossing" : (UseVerticalFill(index) ? "vertical column" : "random ribbon"))) + ", " + origins.Count + " probes) at " + rate + " attempts/s."));
			int attempts = 0;
			for (int i = 0; i < origins.Count; i++)
			{
				if (placed.Count >= target)
				{
					break;
				}
				attempts++;
				LogPlaceProgress(index, placed.Count, target, attempts);
				PlaceAndAnnounce(index, origins[i], area, maxSlope, placed);
				if (placed.Count < target)
				{
					yield return (object)new WaitForSeconds(interval);
				}
			}
			int extra = (IsKilnPaint(index) ? Mathf.Min(Mathf.Max(400, target), (target - placed.Count) * 4) : ((target - placed.Count) * 20));
			while (placed.Count < target && extra > 0)
			{
				extra--;
				attempts++;
				LogPlaceProgress(index, placed.Count, target, attempts);
				if (TryRandomOrigin(index, area, placed, out var origin))
				{
					PlaceAndAnnounce(index, origin, area, maxSlope, placed);
				}
				if (placed.Count < target)
				{
					yield return (object)new WaitForSeconds(interval);
				}
			}
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Finished " + placed.Count + "/" + target + " extras for " + DescribeSegment(index) + " after " + attempts + " probes in " + (Time.realtimeSinceStartup - started).ToString("0.0") + "s."));
			LogMissSummary(index, placed.Count, target, attempts);
		}

		private static IEnumerator PeakGatherAndSpawn(int index, int target, List<Vector3> origins, bool area, float maxSlope)
		{
			if (origins == null || origins.Count == 0)
			{
				LuridLoomingLookersPlugin.Log.LogWarning((object)"Peak paint skipped — no Rock_Platform / Peak_Kiln origins.");
				yield break;
			}
			List<Vector3> placed = new List<Vector3>(target);
			List<RaycastHit> landed = new List<RaycastHit>(target);
			int attempts = 0;
			float minFps = 999f;
			float started = Time.realtimeSinceStartup;
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Gathering Peak hits on " + DescribeSegment(index) + " (" + origins.Count + " probes, " + 12 + " raycasts/frame, " + 2 + " spawns/frame). FPS " + ReadFps().ToString("0") + "."));
			for (int i = 0; i < origins.Count; i++)
			{
				if (placed.Count >= target)
				{
					break;
				}
				attempts++;
				if (TryPlace(origins[i], index, area, maxSlope, placed, out var hit))
				{
					placed.Add(((RaycastHit)(ref hit)).point);
					landed.Add(hit);
				}
				if ((i + 1) % 12 == 0)
				{
					yield return null;
					minFps = Mathf.Min(minFps, ReadFps());
				}
			}
			int extra = Mathf.Min(Mathf.Max(160, target), (target - placed.Count) * 3);
			while (placed.Count < target && extra > 0)
			{
				extra--;
				attempts++;
				if (TryRandomPeakOrigin(placed, out var origin) && TryPlace(origin, index, area, maxSlope, placed, out var hit2))
				{
					placed.Add(((RaycastHit)(ref hit2)).point);
					landed.Add(hit2);
				}
				if (attempts % 12 == 0)
				{
					yield return null;
					minFps = Mathf.Min(minFps, ReadFps());
				}
			}
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Peak gathered " + landed.Count + "/" + target + " after " + attempts + " probes. FPS " + ReadFps().ToString("0") + " (min " + minFps.ToString("0") + "). Spawning..."));
			minFps = 999f;
			for (int j = 0; j < landed.Count; j++)
			{
				RaycastHit val = landed[j];
				SpawnOne(index, ((RaycastHit)(ref val)).point, landed[j], hasHit: true);
				LookerNet instance = LookerNet.Instance;
				if (instance != null)
				{
					val = landed[j];
					instance.AddPoint(index, ((RaycastHit)(ref val)).point);
				}
				if ((j + 1) % 2 == 0)
				{
					yield return null;
					minFps = Mathf.Min(minFps, ReadFps());
				}
				if ((j + 1) % 50 == 0)
				{
					LuridLoomingLookersPlugin.Log.LogInfo((object)("Peak spawn " + (j + 1) + "/" + landed.Count + " FPS " + ReadFps().ToString("0") + " (min " + minFps.ToString("0") + ")."));
				}
			}
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Finished " + landed.Count + "/" + target + " extras for " + DescribeSegment(index) + " after " + attempts + " probes in " + (Time.realtimeSinceStartup - started).ToString("0.0") + "s. FPS " + ReadFps().ToString("0") + " (spawn min " + minFps.ToString("0") + ")."));
			LogMissSummary(index, landed.Count, target, attempts);
		}

		private static float ReadFps()
		{
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			if (unscaledDeltaTime < 0.0001f)
			{
				return 0f;
			}
			return 1f / unscaledDeltaTime;
		}

		private static void LogPlaceProgress(int index, int have, int target, int attempts)
		{
			if (attempts % 50 == 0)
			{
				LuridLoomingLookersPlugin.Log.LogInfo((object)("Still placing " + DescribeSegment(index) + ": " + have + "/" + target + " after " + attempts + " probes."));
			}
		}

		private static void PlaceAndAnnounce(int index, Vector3 origin, bool area, float maxSlope, List<Vector3> placed)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_006d: 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)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (!TryPlace(origin, index, area, maxSlope, placed, out var hit))
			{
				return;
			}
			Vector3 val = ((RaycastHit)(ref hit)).point;
			if (IsKilnPaint(index) && TryGetColumn(index, out var column))
			{
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(column.Center.x - ((RaycastHit)(ref hit)).point.x, 0f, column.Center.z - ((RaycastHit)(ref hit)).point.z);
				if (((Vector3)(ref val2)).sqrMagnitude > 0.01f)
				{
					val = ((RaycastHit)(ref hit)).point + ((Vector3)(ref val2)).normalized * 0.9f;
				}
			}
			SpawnOne(index, val, hit, hasHit: true);
			placed.Add(val);
			LookerNet.Instance?.AddPoint(index, val);
		}

		private static IEnumerator DripKnownPositions(int segment, Vector3[] positions)
		{
			if (positions == null || positions.Length == 0 || !PreparePrototype(segment))
			{
				yield break;
			}
			float interval = 1f / (float)LuridLoomingLookersPlugin.SpawnRate;
			for (int i = 0; i < positions.Length; i++)
			{
				SpawnOne(segment, positions[i], default(RaycastHit), hasHit: false);
				if (i + 1 < positions.Length)
				{
					yield return (object)new WaitForSeconds(interval);
				}
			}
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Finished " + Spawned.Count + " host-synced extras for " + DescribeSegment(segment) + "."));
		}

		private static bool PreparePrototype(int segment)
		{
			Looker val = FindTemplate();
			if ((Object)(object)val == (Object)null)
			{
				LuridLoomingLookersPlugin.Log.LogWarning((object)("No Looker template for " + DescribeSegment(segment) + "."));
				return false;
			}
			Transform spawnParent = GetSpawnParent(segment, ((Component)val).transform.parent);
			return (Object)(object)CreatePrototype(((Component)val).gameObject, spawnParent) != (Object)null;
		}

		private static void SpawnOne(int segment, Vector3 position, RaycastHit hit, bool hasHit)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00a0: 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)
			if (!((Object)(object)_prototype == (Object)null))
			{
				Transform spawnParent = GetSpawnParent(segment, _prototype.transform.parent);
				Quaternion val = Quaternion.Euler(0f, Random.Range(0f, 360f), 0f);
				GameObject val2 = Object.Instantiate<GameObject>(_prototype, position, val, spawnParent);
				((Object)val2).name = "LLL_Looker_" + Spawned.Count;
				val2.SetActive(true);
				if (!hasHit)
				{
					hasHit = TryRaycastGround(position + Vector3.up * 6f, UseAreaFill(segment), out hit);
				}
				if (hasHit)
				{
					ApplySurfaceMaterials(val2, hit, segment);
				}
				LookerInjury.Hide(val2.GetComponent<Looker>(), sleepAnimator: false);
				ModLooker modLooker = val2.AddComponent<ModLooker>();
				LookerAudio.Setup(modLooker);
				Spawned.Add(modLooker);
			}
		}

		private static void ApplySurfaceMaterials(GameObject looker, RaycastHit hit, int segment)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Renderer val = PickSurfaceRenderer(hit, segment);
			if ((Object)(object)val == (Object)null || (Object)(object)looker == (Object)null)
			{
				return;
			}
			Material[] sharedMaterials = val.sharedMaterials;
			if (sharedMaterials == null || sharedMaterials.Length == 0)
			{
				return;
			}
			if (_matLogs < 8)
			{
				_matLogs++;
				string text = (((Object)(object)sharedMaterials[0] != (Object)null) ? ((Object)sharedMaterials[0]).name : "?");
				string text2 = (((Object)(object)((RaycastHit)(ref hit)).collider != (Object)null) ? ((Object)((RaycastHit)(ref hit)).collider).name : "?");
				LuridLoomingLookersPlugin.Log.LogInfo((object)("Surface mat " + DescribeSegment(segment) + ": " + text + " from " + ((Object)val).name + " (hit " + text2 + ")."));
			}
			Looker component = looker.GetComponent<Looker>();
			Transform guy = (((Object)(object)component != (Object)null && (Object)(object)component.guy != (Object)null) ? component.guy.transform : looker.transform.Find("guy"));
			Renderer[] componentsInChildren = looker.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 == (Object)null || IsGuyRenderer(val2, guy))
				{
					continue;
				}
				if (val2.sharedMaterials != null && val2.sharedMaterials.Length == sharedMaterials.Length)
				{
					val2.sharedMaterials = sharedMaterials;
					continue;
				}
				Material[] sharedMaterials2 = val2.sharedMaterials;
				if (sharedMaterials2 == null || sharedMaterials2.Length == 0)
				{
					val2.sharedMaterials = (Material[])(object)new Material[1] { sharedMaterials[0] };
					continue;
				}
				for (int j = 0; j < sharedMaterials2.Length; j++)
				{
					sharedMaterials2[j] = sharedMaterials[0];
				}
				val2.sharedMaterials = sharedMaterials2;
			}
		}

		private static bool IsGuyRenderer(Renderer renderer, Transform guy)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return false;
			}
			if (renderer is SkinnedMeshRenderer)
			{
				return true;
			}
			if ((Object)(object)guy == (Object)null)
			{
				return ((Object)renderer).name.IndexOf("guy", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return (Object)(object)((Component)renderer).transform == (Object)(object)guy || ((Component)renderer).transform.IsChildOf(guy);
		}

		private static Renderer PickSurfaceRenderer(RaycastHit hit, int segment)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (WantsPeakColumn(segment))
			{
				return BestSurfaceRenderer(hit);
			}
			return RendererOn(((RaycastHit)(ref hit)).collider);
		}

		private static Renderer BestSurfaceRenderer(RaycastHit hit)
		{
			Renderer val = RendererOn(((RaycastHit)(ref hit)).collider);
			if ((Object)(object)val != (Object)null && !RendererLooksLikeSalt(val))
			{
				return val;
			}
			if (WantsPeakColumn(_inFlightSegment) && (Object)(object)_peakGround != (Object)null)
			{
				Renderer val2 = ((Component)_peakGround).GetComponent<Renderer>();
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = RendererOn(((Component)_peakGround).GetComponent<Collider>());
				}
				if ((Object)(object)val2 != (Object)null && !RendererLooksLikeSalt(val2))
				{
					return val2;
				}
			}
			return val;
		}

		private static bool RendererLooksLikeSalt(Renderer renderer)
		{
			Material[] sharedMaterials = renderer.sharedMaterials;
			for (int i = 0; i < sharedMaterials.Length; i++)
			{
				if ((Object)(object)sharedMaterials[i] != (Object)null && NameContains(((Object)sharedMaterials[i]).name, "Salt"))
				{
					return true;
				}
			}
			return NameContains(((Object)renderer).name, "Salt");
		}

		private static Renderer RendererOn(Collider collider)
		{
			if ((Object)(object)collider == (Object)null)
			{
				return null;
			}
			Renderer component = ((Component)collider).GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			return ((Component)collider).GetComponentInParent<Renderer>();
		}

		private static List<Vector3> BuildOrigins(int index, int target)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>(target * 3);
			Vector3 start;
			Vector3 end;
			if (WantsPeakColumn(index))
			{
				AddPeakPlatformOrigins(list, index, Mathf.Max(target * 3, target));
			}
			else if (IsKilnPaint(index))
			{
				AddKilnWallOrigins(list, index, Mathf.Max(target * 3, target));
			}
			else if (UseVerticalFill(index))
			{
				AddVerticalOrigins(list, index, Mathf.Max(target * 3, target));
			}
			else if (IsCalderaPaint(index))
			{
				AddCalderaOrigins(list, index, Mathf.Max(target * 3, target));
			}
			else if (TryGetCorridor(Singleton<MapHandler>.Instance, index, out start, out end))
			{
				AddCorridorOrigins(list, start, end, target, index);
			}
			return list;
		}

		private static void AddCorridorOrigins(List<Vector3> origins, Vector3 start, Vector3 end, int target, int index)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			OrientClimb(ref start, ref end);
			if (!TryGetLawn(start, end, index, out var along, out var across, out var length, out var width))
			{
				return;
			}
			float num = (IsShorePaint(index) ? 0.06f : 0.04f);
			float num2 = Mathf.Max(start.y, end.y) + 80f;
			RememberRibbon(index, start, along, across, length, width, num2);
			int num3 = Mathf.Max(target * 3, 240);
			bool flag = IsShorePaint(index);
			float num4 = (flag ? ShoreThinLength(length) : 0f);
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Random ribbon " + DescribeSegment(index) + ": " + length.ToString("0") + "m x " + width.ToString("0") + "m, startY=" + start.y.ToString("0") + " endY=" + end.y.ToString("0") + (flag ? (", thin " + 28f.ToString("0") + "m for first " + num4.ToString("0") + "m then " + width.ToString("0") + "m ribbon, open surfaces") : "") + ", " + num3 + (flag ? " banded" : " random") + " probes start→end."));
			for (int i = 0; i < num3; i++)
			{
				float num6;
				if (flag)
				{
					int num5 = i % 12;
					num6 = ((float)num5 + Random.value) / 12f;
					num6 = Mathf.Lerp(num, 1f - num, num6);
				}
				else
				{
					num6 = Random.Range(num, 1f - num);
				}
				float num7 = Random.Range(-0.5f, 0.5f);
				float num8 = (flag ? ShorePaintWidth(num6 * length, width) : width);
				Vector3 val = start + along * (num6 * length) + across * (num7 * num8);
				origins.Add(new Vector3(val.x, num2, val.z));
			}
		}

		private static float ShoreThinLength(float length)
		{
			return Mathf.Clamp(100f, 70f, Mathf.Max(80f, length * 0.45f));
		}

		private static float ShorePaintWidth(float alongDist, float wide)
		{
			float num = ShoreThinLength((_ribbon.Length > 8f) ? _ribbon.Length : (alongDist + 100f));
			if (alongDist <= num)
			{
				return 28f;
			}
			float num2 = Mathf.InverseLerp(num, num + 20f, alongDist);
			return Mathf.Lerp(28f, wide, num2);
		}

		private static bool TryGetLawn(Vector3 start, Vector3 end, int index, out Vector3 along, out Vector3 across, out float length, out float width)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0061: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			along = end - start;
			along.y = 0f;
			length = ((Vector3)(ref along)).magnitude;
			across = Vector3.right;
			width = 24f;
			if (length < 8f)
			{
				return false;
			}
			along /= length;
			across = Vector3.Cross(Vector3.up, along);
			if (((Vector3)(ref across)).sqrMagnitude < 0.01f)
			{
				across = Vector3.right;
			}
			else
			{
				((Vector3)(ref across)).Normalize();
			}
			float num = AcrossFromBounds(index, start, across);
			if (num < 16f)
			{
				num = Mathf.Max(48f, length * 0.55f);
			}
			width = num * 0.5f;
			width = Mathf.Clamp(width, 24f, 72f);
			width += 60f;
			return true;
		}

		private static float AcrossFromBounds(int index, Vector3 start, Vector3 across)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_004c: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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)
			if (!TryGetCachedBoundsRaw(index, out var bounds))
			{
				return 0f;
			}
			float num = float.MaxValue;
			float num2 = float.MinValue;
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3 extents = ((Bounds)(ref bounds)).extents;
			Vector3 val = default(Vector3);
			for (int i = -1; i <= 1; i += 2)
			{
				for (int j = -1; j <= 1; j += 2)
				{
					((Vector3)(ref val))..ctor(center.x + extents.x * (float)i, 0f, center.z + extents.z * (float)j);
					Vector3 val2 = val - new Vector3(start.x, 0f, start.z);
					float num3 = Vector3.Dot(val2, across);
					if (num3 < num)
					{
						num = num3;
					}
					if (num3 > num2)
					{
						num2 = num3;
					}
				}
			}
			return (num2 > num) ? (num2 - num) : 0f;
		}

		private static void OrientClimb(ref Vector3 start, ref Vector3 end)
		{
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			if (start.y > end.y + 8f)
			{
				Vector3 val = start;
				start = end;
				end = val;
			}
		}

		private static void RememberRibbon(int index, Vector3 start, Vector3 along, Vector3 across, float length, float width, float yTop)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			_ribbon.Index = index;
			_ribbon.Start = start;
			_ribbon.Along = along;
			_ribbon.Across = across;
			_ribbon.Length = length;
			_ribbon.Width = width;
			_ribbon.YTop = yTop;
		}

		private static bool TryGetRibbon(int index, out Vector3 start, out Vector3 along, out Vector3 across, out float length, out float width, out float yTop)
		{
			//IL_0030: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_00a7: 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_00b2: 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_0101: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if (_ribbon.Index == index && _ribbon.Length >= 8f)
			{
				start = _ribbon.Start;
				along = _ribbon.Along;
				across = _ribbon.Across;
				length = _ribbon.Length;
				width = _ribbon.Width;
				yTop = _ribbon.YTop;
				return true;
			}
			yTop = 80f;
			if (!TryGetCorridor(Singleton<MapHandler>.Instance, index, out start, out var end))
			{
				along = Vector3.forward;
				across = Vector3.right;
				length = 0f;
				width = 24f;
				return false;
			}
			OrientClimb(ref start, ref end);
			if (!TryGetLawn(start, end, index, out along, out across, out length, out width))
			{
				return false;
			}
			yTop = Mathf.Max(start.y, end.y) + 80f;
			RememberRibbon(index, start, along, across, length, width, yTop);
			return true;
		}

		private static void AddVerticalOrigins(List<Vector3> origins, int index, int count)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetColumn(index, out var column))
			{
				return;
			}
			Vector3 center = column.Center;
			float y = column.Y0;
			float y2 = column.Y1;
			float radius = column.Radius;
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Vertical column for " + DescribeSegment(index) + ": center=(" + center.x.ToString("0") + "," + center.z.ToString("0") + ") y=" + y.ToString("0") + "-" + y2.ToString("0") + " r=" + radius.ToString("0") + "."));
			float num = Mathf.Max(16f, y2 - y);
			int num2 = Mathf.Max(8, Mathf.RoundToInt(num / 14f));
			int num3 = Mathf.Max(4, Mathf.CeilToInt((float)count / (float)num2));
			for (int i = 0; i < num3; i++)
			{
				for (int j = 0; j < num2; j++)
				{
					float num4 = ((num2 == 1) ? 0.5f : (((float)j + 0.5f) / (float)num2));
					float num5 = Mathf.Lerp(y, y2, num4) + 4f;
					float num6 = ((float)i + (float)j * 0.37f) / (float)num3 * (float)Math.PI * 2f;
					float num7 = radius * (0.45f + 0.5f * (float)((i + j) % 3) / 2f);
					origins.Add(new Vector3(center.x + Mathf.Cos(num6) * num7, num5, center.z + Mathf.Sin(num6) * num7));
				}
			}
		}

		private static void AddKilnWallOrigins(List<Vector3> origins, int index, int count)
		{
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetColumn(index, out var column))
			{
				return;
			}
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Kiln walls for " + DescribeSegment(index) + ": center=(" + column.Center.x.ToString("0") + "," + column.Center.z.ToString("0") + ") y=" + column.Y0.ToString("0") + "-" + column.Y1.ToString("0") + " (cliff), 3 passes bottom→top, outward " + 130f.ToString("0") + "m."));
			int num = 14;
			int num2 = 10;
			for (int i = 0; i < 3; i++)
			{
				for (int j = 0; j < num; j++)
				{
					float num3 = ((num == 1) ? 1f : ((float)j / (float)(num - 1)));
					float num4 = Mathf.Lerp(column.Y0 + 6f, column.Y1, num3);
					float num5 = ((num3 > 0.8f) ? 6f : 2f);
					for (int k = 0; k < num2; k++)
					{
						float num6 = ((float)k + 0.5f + (float)i * 0.5f + (float)j * 0.17f) / (float)num2 * (float)Math.PI * 2f;
						origins.Add(new Vector3(column.Center.x + Mathf.Cos(num6) * num5, num4, column.Center.z + Mathf.Sin(num6) * num5));
					}
				}
			}
		}

		private static float KilnSpacingSqr(int index, float y)
		{
			if (!TryGetColumn(index, out var column) || column.Y1 <= column.Y0 + 1f)
			{
				return 144f;
			}
			float num = Mathf.InverseLerp(column.Y0, column.Y1, y);
			float num2 = Mathf.Lerp(12f, 6f, num);
			return num2 * num2;
		}

		private static void AddCalderaOrigins(List<Vector3> origins, int index, int count)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_012c: Unknown result type (might be due to invalid IL or missing references)
			float num = CalderaRayOriginY(index);
			CollectCalderaPads(index);
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Caldera pads " + CalderaPads.Count + " at ray y=" + num.ToString("0") + " (LavaPillar / Plartform / rock_Ring / LavaTemple / Rock_Hold2; skip River and Middle)."));
			if (CalderaPads.Count == 0)
			{
				return;
			}
			int num2 = Mathf.Max(4, Mathf.CeilToInt((float)count / (float)CalderaPads.Count));
			for (int i = 0; i < CalderaPads.Count; i++)
			{
				Collider val = CalderaPads[i];
				if (!((Object)(object)val == (Object)null))
				{
					Bounds bounds = val.bounds;
					for (int j = 0; j < num2; j++)
					{
						float num3 = Random.Range(0.2f, 0.8f);
						float num4 = Random.Range(0.2f, 0.8f);
						origins.Add(new Vector3(Mathf.Lerp(((Bounds)(ref bounds)).min.x, ((Bounds)(ref bounds)).max.x, num3), num, Mathf.Lerp(((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z, num4)));
					}
				}
			}
		}

		private static void CollectCalderaPads(int index)
		{
			if (CalderaPads.Count > 0)
			{
				return;
			}
			GameObject val = GetSegmentParent(Singleton<MapHandler>.Instance, index);
			if ((Object)(object)val == (Object)null)
			{
				val = GameObject.Find("Caldera_Segment");
				if ((Object)(object)val == (Object)null)
				{
					val = GameObject.Find("Map/Biome_4/Caldera");
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && val2.enabled && !val2.isTrigger && !IsCalderaBlocked(((Component)val2).transform) && IsCalderaAllowedTransform(((Component)val2).transform))
				{
					CalderaPads.Add(val2);
				}
			}
		}

		private static float CalderaRayOriginY(int index)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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)
			float num = 80f;
			if (index > 0 && TryGetCampfirePosition(Singleton<MapHandler>.Instance, index - 1, out var position) && CampfireLooksValid(position))
			{
				num = Mathf.Max(num, position.y + 40f);
			}
			if (TryGetCampfirePosition(Singleton<MapHandler>.Instance, index, out position) && CampfireLooksValid(position))
			{
				num = Mathf.Max(num, position.y + 40f);
			}
			return num;
		}

		private static void AddPeakPlatformOrigins(List<Vector3> origins, int index, int count)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0173: 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)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetPeakClimb(out var from, out var to) || (Object)(object)_peakGround == (Object)null)
			{
				LuridLoomingLookersPlugin.Log.LogWarning((object)"Peak paint skipped — need Central Tower Exit, Flag Pole, and Rock_Platform.");
				return;
			}
			EnsurePeakColliders();
			float num = PeakRoofY(to);
			float num2 = PeakFloorY(from.y, to);
			_peakScatterR = 52f;
			LuridLoomingLookersPlugin.Log.LogInfo((object)("Peak scatter for " + DescribeSegment(index) + ": " + ((Object)_peakFlag).name + " (" + to.x.ToString("0") + "," + to.y.ToString("0") + "," + to.z.ToString("0") + ") floorY=" + num2.ToString("0") + " roofY=" + num.ToString("0") + " r=" + _peakScatterR.ToString("0") + " pads=" + PeakColliders.Count + "."));
			for (int i = 0; i < count; i++)
			{
				Vector2 val = Random.insideUnitCircle * _peakScatterR;
				origins.Add(new Vector3(to.x + val.x, num, to.z + val.y));
			}
		}

		private static float PeakFloorY(float exitY, Vector3 flag)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Mathf.Max(exitY, flag.y - 32f);
		}

		private static float PeakRoofY(Vector3 flag)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!float.IsNaN(_peakRoofYCached))
			{
				return _peakRoofYCached;
			}
			float num = flag.y + 16f;
			if ((Object)(object)_peakGround != (Object)null && !NameContains(((Object)_peakGround).name, "Peak_Kiln"))
			{
				Collider component = ((Component)_peakGround).GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					float num2 = num;
					Bounds bounds = component.bounds;
					num = Mathf.Max(num2, Mathf.Min(((Bounds)(ref bounds)).max.y + 10f, flag.y + 40f));
				}
			}
			_peakRoofYCached = num;
			return num;
		}

		private static bool TryGetColumn(int index, out VerticalColumn column)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (ColumnCache.TryGetValue(index, out column))
			{
				return true;
			}
			if (TryBuildNamedColumn(index, out column))
			{
				ColumnCache[index] = column;
				return true;
			}
			if (!TryGetCachedBoundsRaw(index, out var bounds))
			{
				column = default(VerticalColumn);
				return false;
			}
			ComputeVerticalColumn(index, bounds, out var center, out var y, out var radius);
			column = new VerticalColumn
			{
				Center = center,
				Y0 = y,
				Y1 = VerticalTop(index, bounds, y),
				Radius = radius
			};
			ColumnCache[index] = column;
			return true;
		}

		private static bool TryBuildNamedColumn(int index, out VerticalColumn column)
		{
			column = default(VerticalColumn);
			ResolveAnchors();
			if (WantsPeakColumn(index))
			{
				return TryBuildPeakColumn(out column);
			}
			if (GetPlaceZone(index) == VerticalZone.Shaft)
			{
				return TryBuildShaftColumn(out column);
			}
			return false;
		}

		private static bool TryBuildShaftColumn(out VerticalColumn column)
		{
			//IL_0030: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0060: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			column = default(VerticalColumn);
			if ((Object)(object)_citadelEntry != (Object)null && (Object)(object)_citadelExit != (Object)null)
			{
				Vector3 position = _citadelEntry.position;
				Vector3 position2 = _citadelExit.position;
				column.Center = new Vector3((position.x + position2.x) * 0.5f, 0f, (position.z + position2.z) * 0.5f);
				column.Y0 = Mathf.Min(position.y, position2.y);
				column.Y1 = Mathf.Max(position.y, position2.y) + 36f;
				column.Radius = ModestRadius(_citadelEntry, _citadelExit, 24f, 36f);
				return column.Y1 > column.Y0 + 8f;
			}
			return TryBuildKilnColumn(out column);
		}

		private static bool TryBuildKilnColumn(out VerticalColumn column)
		{
			//IL_0029: 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_002f: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			column = default(VerticalColumn);
			ResolveAnchors();
			if ((Object)(object)_volcanoCliff == (Object)null)
			{
				return false;
			}
			Vector3 position = _volcanoCliff.position;
			float num = position.y + 180f;
			if ((Object)(object)_kilnCliff != (Object)null)
			{
				num = Mathf.Max(num, _kilnCliff.position.y);
			}
			if ((Object)(object)_peakKilnGround != (Object)null)
			{
				num = Mathf.Max(num, _peakKilnGround.position.y);
			}
			if ((Object)(object)_peakFlag != (Object)null && NameContains(((Object)_peakFlag.root).name, "Kiln"))
			{
				num = Mathf.Max(num, _peakFlag.position.y - 40f);
			}
			column.Center = new Vector3(position.x, 0f, position.z);
			column.Y0 = position.y;
			column.Y1 = Mathf.Max(position.y + 16f, num);
			column.Radius = 64f;
			return column.Y1 > column.Y0 + 8f;
		}

		private static bool TryBuildPeakColumn(out VerticalColumn column)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			column = default(VerticalColumn);
			if (!TryGetPeakClimb(out var from, out var to))
			{
				return false;
			}
			column.Center = new Vector3(to.x, 0f, to.z);
			column.Y0 = from.y;
			column.Y1 = to.y + 8f;
			column.Radius = 52f;
			return true;
		}

		private static void ComputeVerticalColumn(int index, Bounds bounds, out Vector3 center, out float y0, out float radius)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0068: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00d5: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_0106: 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)
			Vector3 position = Vector3.zero;
			Vector3 position2 = Vector3.zero;
			bool flag = index > 0 && TryGetCampfirePosition(Singleton<MapHandler>.Instance, index - 1, out position);
			bool flag2 = TryGetCampfirePosition(Singleton<MapHandler>.Instance, index, out position2);
			if (flag && flag2)
			{
				center = new Vector3((position.x + position2.x) * 0.5f, 0f, (position.z + position2.z) * 0.5f);
				y0 = Mathf.Min(position.y, position2.y);
				radius = Mathf.Clamp(HorizontalDist(position, position2) * 0.4f + 16f, 14f, 36f);
			}
			else if (flag)
			{
				center = new Vector3(position.x, 0f, position.z);
				y0 = position.y;
				radius = 24f;
			}
			else if (flag2)
			{
				center = new Vector3(position2.x, 0f, position2.z);
				y0 = position2.y;
				radius = 24f;
			}
			else
			{
				center = new Vector3(((Bounds)(ref bounds)).center.x, 0f, ((Bounds)(ref bounds)).center.z);
				y0 = ((Bounds)(ref bounds)).min.y + 4f;
				radius = 24f;
			}
		}

		private static float VerticalTop(int index, Bounds bounds, float y0)
		{
			//IL_001b: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			float num = y0 + 80f;
			if (TryGetCampfirePosition(Singleton<MapHandler>.Instance, index, out var position))
			{
				num = Mathf.Max(num, position.y + 24f);
			}
			if (IsPeakSegment(index))
			{
				GameObject val = TryGetPeakRoot();
				if ((Object)(object)val != (Object)null)
				{
					num = Mathf.Max(num, val.transform.position.y + 40f);
				}
			}
			else
			{
				num = Mathf.Max(num, Mathf.Min(((Bounds)(ref bounds)).max.y, y0 + 220f));
			}
			return num;
		}

		private static bool InVerticalColumn(Vector3 point, int index)
		{
			//IL_001a: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			if (!TryGetColumn(index, out var column))
			{
				return false;
			}
			if (point.y < column.Y0 - 8f || point.y > column.Y1 + 16f)
			{
				return false;
			}
			float num = point.x - column.Center.x;
			float num2 = point.z - column.Center.z;
			float num3 = column.Radius + 8f;
			if (IsKilnPaint(index))
			{
				num3 = Mathf.Max(num3, 130f);
			}
			return num * num + num2 * num2 <= num3 * num3;
		}

		private static bool TryRaycastVerticalBand(Vector3 origin, int index, out RaycastHit hit)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			hit = default(RaycastHit);
			int num = LayerMask.op_Implicit(HelperFunctions.terrainMapMask);
			if (Physics.Raycast(origin, Vector3.down, ref hit, 160f, num) && (Object)(object)((RaycastHit)(ref hit)).transform != (Object)null)
			{
				return true;
			}
			if (TryRaycastTowardColumn(origin, index, out hit) && origin.y - ((RaycastHit)(ref hit)).point.y <= 168f && ((RaycastHit)(ref hit)).point.y - origin.y <= 8f)
			{
				return true;
			}
			hit = HelperFunctions.GetGroundPosRaycast(origin, (LayerType)5, 0.35f);
			return (Object)(object)((RaycastHit)(ref hit)).transform != (Object)null && !IsBadSurface(hit) && origin.y - ((RaycastHit)(ref hit)).point.y <= 168f && origin.y - ((RaycastHit)(ref hit)).point.y >= -4f;
		}

		private static bool TryRaycastPeak(Vector3 origin, out RaycastHit hit)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: 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_00c6: 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_0181: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			hit = default(RaycastHit);
			if (!TryGetPeakClimb(out var from, out var to) || (Object)(object)_peakGround == (Object)null)
			{
				return false;
			}
			float num = PeakFloorY(from.y, to);
			float y = PeakRoofY(to);
			origin.y = y;
			float num2 = origin.y - num + 0.2f;
			if (num2 < 4f)
			{
				num2 = 4f;
			}
			EnsurePeakColliders();
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(origin, Vector3.down);
			float num3 = float.MaxValue;
			bool flag = false;
			RaycastHit val3 = default(RaycastHit);
			for (int i = 0; i < PeakColliders.Count; i++)
			{
				Collider val2 = PeakColliders[i];
				if (!((Object)(object)val2 == (Object)null) && val2.enabled && val2.Raycast(val, ref val3, num2) && PeakPlatformHitOk(val3, num, to) && !(((RaycastHit)(ref val3)).distance >= num3))
				{
					num3 = ((RaycastHit)(ref val3)).distance;
					hit = val3;
					flag = true;
				}
			}
			if (flag)
			{
				return true;
			}
			int num4 = LayerMask.op_Implicit(HelperFunctions.terrainMapMask);
			int num5 = Physics.RaycastNonAlloc(origin, Vector3.down, PeakHits, num2, num4);
			for (int j = 0; j < num5; j++)
			{
				RaycastHit val4 = PeakHits[j];
				if (PeakPlatformHitOk(val4, num, to) && !IsBadSurface(val4) && !(((RaycastHit)(ref val4)).distance >= num3))
				{
					num3 = ((RaycastHit)(ref val4)).distance;
					hit = val4;
					flag = true;
				}
			}
			return flag;
		}

		private static bool PeakPlatformHitOk(RaycastHit hit, float exitY, Vector3 flag)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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)
			if ((Object)(object)((RaycastHit)(ref hit)).transform == (Object)null || (Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
			{
				return false;
			}
			if (((RaycastHit)(ref hit)).point.y < exitY - 0.2f)
			{
				return false;
			}
			if (((RaycastHit)(ref hit)).normal.y < 0.35f)
			{
				return false;
			}
			if (!IsPeakWalkHit(hit))
			{
				return false;
			}
			if (IsPeakReserved(hit))
			{
				return false;
			}
			if (HorizontalDist(((RaycastHit)(ref hit)).point, flag) > _peakScatterR + 8f)
			{
				return false;
			}
			return true;
		}

		private static bool IsPeakWalkHit(RaycastHit hit)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null)
			{
				return false;
			}
			if (IsRockPlatformHit(hit))
			{
				return true;
			}
			Transform val = PeakSearchRoot();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			return IsUnderRoot(((Component)((RaycastHit)(ref hit)).collider).transform, val);
		}

		private static bool IsRockPlatformHit(RaycastHit hit)
		{
			Transform val = ((Component)((RaycastHit)(ref hit)).collider).transform;
			while ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)val == (Object)(object)_peakGround || (Object)(object)val == (Object)(object)_peakKilnGround)
				{
					return true;
				}
				string name = ((Object)val).name;
				if (name.Equals("Rock_Platform", StringComparison.OrdinalIgnoreCase) || NameContains(name, "Peak_Kiln"))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static Transform PeakSearchRoot()
		{
			if ((Object)(object)_peakGround != (Object)null && (Object)(object)_peakGround.parent != (Object)null)
			{
				return _peakGround.parent;
			}
			return _peakGround;
		}

		private static bool TryRaycastKilnWall(Vector3 origin, int index, out RaycastHit hit)
		{
			//IL_0002: 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_002a: 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_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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: 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_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			hit = default(RaycastHit);
			if (!TryGetColumn(index, out var column))
			{
				return false;
			}
			Vector3 right = default(Vector3);
			((Vector3)(ref right))..ctor(origin.x - column.Center.x, 0f, origin.z - column.Center.z);
			if (((Vector3)(ref right)).sqrMagnitude < 0.01f)
			{
				right = Vector3.right;
			}
			else
			{
				((Vector3)(ref right)).Normalize();
			}
			float num = ((column.Y1 > column.Y0 + 1f) ? Mathf.InverseLerp(column.Y0, column.Y1, origin.y) : 0f);
			float num2 = ((num > 0.75f) ? 0.35f : 0.08f);
			Vector3 val = right + Vector3.down * num2;
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			int num3 = LayerMask.op_Implicit(HelperFunctions.terrainMapMask);
			int num4 = Physics.RaycastNonAlloc(origin, normalized, PeakHits, 130f, num3);
			float num5 = float.MaxValue;
			bool result = false;
			float num6 = ((num > 0.75f) ? 4f : 10f);
			Vector3 val3 = default(Vector3);
			for (int i = 0; i < num4; i++)
			{
				RaycastHit val2 = PeakHits[i];
				if ((Object)(object)((RaycastHit)(ref val2)).transform == (Object)null || ((RaycastHit)(ref val2)).distance < 0.4f || IsBadSurface(val2) || ((RaycastHit)(ref val2)).point.y < column.Y0 - 4f || ((RaycastHit)(ref val2)).point.y > column.Y1 + 12f)
				{
					continue;
				}
				float num7 = HorizontalDist(((RaycastHit)(ref val2)).point, column.Center);
				if (num7 < num6)
				{
					continue;
				}
				((Vector3)(ref val3))..ctor(column.Center.x - ((RaycastHit)(ref val2)).point.x, 0f, column.Center.z - ((RaycastHit)(ref val2)).point.z);
				if (!(((Vector3)(ref val3)).sqrMagnitude < 1f))
				{
					Vector3 normal = ((RaycastHit)(ref val2)).normal;
					normal.y = 0f;
					if ((!(((Vector3)(ref normal)).sqrMagnitude >= 0.05f) || !(Vector3.Dot(((Vector3)(ref normal)).normalized, ((Vector3)(ref val3)).normalized) < -0.1f)) && !(((RaycastHit)(ref val2)).distance >= num5))
					{
						num5 = ((RaycastHit)(ref val2)).distance;
						hit = val2;
						result = true;
					}
				}
			}
			return result;
		}

		private static bool TryRaycastCaldera(Vector3 origin, out RaycastHit hit)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result t