Decompiled source of Pages Of The Peak v0.1.1

Pages Of The Peak.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Playables;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PagesOfThePeak")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1")]
[assembly: AssemblyProduct("PagesOfThePeak")]
[assembly: AssemblyTitle("PagesOfThePeak")]
[assembly: AssemblyVersion("0.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PagesOfThePeak
{
	internal sealed class DrowsyVisualSuppressor : MonoBehaviour
	{
		private Plugin plugin;

		private FieldInfo drowsyFxField;

		private MethodInfo disableMethod;

		private object lastFx;

		private float nextClear;

		private bool logged;

		public void Initialize(Plugin owner)
		{
			plugin = owner;
			ResolveMembers();
		}

		private void ResolveMembers()
		{
			if (drowsyFxField == null)
			{
				drowsyFxField = AccessTools.Field(typeof(GUIManager), "drowsyFX");
			}
			if (drowsyFxField != null && disableMethod == null)
			{
				disableMethod = AccessTools.Method(drowsyFxField.FieldType, "Disable", Type.EmptyTypes, (Type[])null);
			}
		}

		private bool ShouldSuppress()
		{
			if ((Object)(object)plugin != (Object)null && plugin.IsCurseActive && plugin.State != null && plugin.State.phase == "Watching" && plugin.SuppressDrowsyCameraFX != null)
			{
				return plugin.SuppressDrowsyCameraFX.Value;
			}
			return false;
		}

		private void Update()
		{
			if (!ShouldSuppress())
			{
				logged = false;
				lastFx = null;
			}
			else if (!(Time.unscaledTime < nextClear))
			{
				nextClear = Time.unscaledTime + 0.15f;
				ClearCurrentEffect();
			}
		}

		private void ClearCurrentEffect()
		{
			ResolveMembers();
			GUIManager instance = GUIManager.instance;
			if (!Object.op_Implicit((Object)(object)instance) || drowsyFxField == null || disableMethod == null)
			{
				return;
			}
			try
			{
				object value = drowsyFxField.GetValue(instance);
				if (value != null)
				{
					disableMethod.Invoke(value, null);
					lastFx = value;
					if (!logged)
					{
						logged = true;
						plugin.Trace("Drowsy camera FX suppressed through GUIManager.drowsyFX ScreenVFX.Disable(); Drowsy status/meter remains active.");
					}
				}
			}
			catch (Exception ex)
			{
				plugin.InternalWarn("Drowsy camera FX clear failed safely: " + ex.GetBaseException().Message);
			}
		}

		public void Dispose()
		{
			plugin = null;
			lastFx = null;
		}

		private void OnDestroy()
		{
			Dispose();
		}
	}
	internal sealed class FlashlightController : MonoBehaviour
	{
		private Plugin plugin;

		private GameObject lightObject;

		private Light spot;

		private Camera attachedCamera;

		private bool isOn;

		private float nextCameraCheck;

		private float nextSettingsRefresh;

		private bool lastDesiredEnabled;

		public bool IsOn => isOn;

		public void Initialize(Plugin owner)
		{
			plugin = owner;
			isOn = plugin.FlashlightStartOn.Value;
			EnsureLight();
			ApplySettings();
			SetEnabled(isOn);
		}

		private void EnsureLight()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			Camera main = Camera.main;
			if (Object.op_Implicit((Object)(object)main) && (!Object.op_Implicit((Object)(object)lightObject) || !((Object)(object)attachedCamera == (Object)(object)main)))
			{
				if (Object.op_Implicit((Object)(object)lightObject))
				{
					Object.Destroy((Object)(object)lightObject);
				}
				attachedCamera = main;
				lightObject = new GameObject("POTP_CameraFlashlight");
				lightObject.transform.SetParent(((Component)main).transform, false);
				spot = lightObject.AddComponent<Light>();
				spot.type = (LightType)0;
				spot.renderMode = (LightRenderMode)1;
				ApplyTransform();
				ApplySettings();
				SetEnabled(isOn);
			}
		}

		private void ApplyTransform()
		{
			//IL_0057: 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)
			if (Object.op_Implicit((Object)(object)lightObject) && !((Object)(object)plugin == (Object)null))
			{
				lightObject.transform.localPosition = new Vector3(plugin.FlashlightHorizontalOffset.Value, plugin.FlashlightVerticalOffset.Value, plugin.FlashlightForwardOffset.Value);
				lightObject.transform.localRotation = Quaternion.identity;
			}
		}

		private void ApplySettings()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)spot) && !((Object)(object)plugin == (Object)null))
			{
				float value = plugin.FlashlightColorTemperature.Value;
				spot.color = Mathf.CorrelatedColorTemperatureToRGB(value);
				spot.intensity = plugin.FlashlightIntensity.Value;
				spot.range = plugin.FlashlightRange.Value;
				spot.spotAngle = plugin.FlashlightSpotAngle.Value;
				spot.innerSpotAngle = Mathf.Min(plugin.FlashlightInnerSpotAngle.Value, Mathf.Max(1f, spot.spotAngle - 1f));
				spot.shadows = (LightShadows)(plugin.FlashlightShadows.Value ? 2 : 0);
				spot.shadowStrength = plugin.FlashlightShadowStrength.Value;
				spot.shadowBias = plugin.FlashlightShadowBias.Value;
				spot.shadowNormalBias = plugin.FlashlightShadowNormalBias.Value;
			}
		}

		private void SetEnabled(bool value)
		{
			isOn = value;
			if (Object.op_Implicit((Object)(object)spot))
			{
				((Behaviour)spot).enabled = value && (Object)(object)plugin != (Object)null && plugin.EnableBuiltInFlashlight.Value;
			}
		}

		private void Update()
		{
			if ((Object)(object)plugin == (Object)null)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)lightObject) || !Object.op_Implicit((Object)(object)attachedCamera) || Time.unscaledTime >= nextCameraCheck)
			{
				nextCameraCheck = Time.unscaledTime + 1f;
				EnsureLight();
			}
			if (Time.unscaledTime >= nextSettingsRefresh)
			{
				nextSettingsRefresh = Time.unscaledTime + 0.25f;
				ApplyTransform();
				ApplySettings();
			}
			Keyboard current = Keyboard.current;
			if (current != null && plugin.EnableBuiltInFlashlight.Value && ((ButtonControl)current.lKey).wasPressedThisFrame)
			{
				SetEnabled(!isOn);
				plugin.Trace("Flashlight " + (isOn ? "ON" : "OFF"));
			}
			if (Object.op_Implicit((Object)(object)spot))
			{
				bool flag = plugin.EnableBuiltInFlashlight.Value && isOn;
				if (flag != lastDesiredEnabled || ((Behaviour)spot).enabled != flag)
				{
					lastDesiredEnabled = flag;
					((Behaviour)spot).enabled = flag;
				}
			}
		}

		private void LateUpdate()
		{
			if (!Object.op_Implicit((Object)(object)lightObject) || !Object.op_Implicit((Object)(object)attachedCamera))
			{
				EnsureLight();
			}
		}

		public float BeamExposureAt(Vector3 worldPoint)
		{
			//IL_0060: 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_0066: 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_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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)plugin == (Object)null || !plugin.EnableBuiltInFlashlight.Value || !isOn || !Object.op_Implicit((Object)(object)spot) || !((Behaviour)spot).enabled || !Object.op_Implicit((Object)(object)lightObject))
			{
				return 0f;
			}
			Vector3 position = lightObject.transform.position;
			Vector3 val = worldPoint - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude <= 0.01f || magnitude > spot.range)
			{
				return 0f;
			}
			Vector3 val2 = val / magnitude;
			float num = Vector3.Angle(lightObject.transform.forward, val2);
			float num2 = Mathf.Max(1f, spot.spotAngle * 0.5f);
			float num3 = Mathf.Clamp(spot.innerSpotAngle * 0.5f, 0f, num2 - 0.01f);
			if (num >= num2)
			{
				return 0f;
			}
			float num4 = ((num <= num3) ? 1f : (1f - Mathf.InverseLerp(num3, num2, num)));
			float num5 = Mathf.Clamp01(magnitude / Mathf.Max(0.01f, spot.range));
			float num6 = 1f - num5 * num5;
			if (!World.ClearSight(position, worldPoint))
			{
				return 0f;
			}
			return Mathf.Clamp01(num4 * num6);
		}

		public void Dispose()
		{
			if (Object.op_Implicit((Object)(object)lightObject))
			{
				Object.Destroy((Object)(object)lightObject);
			}
			lightObject = null;
			spot = null;
			attachedCamera = null;
		}

		private void OnDestroy()
		{
			Dispose();
		}
	}
	internal sealed class PagePromptController : MonoBehaviour
	{
		private Plugin plugin;

		private GameObject root;

		private TextMeshProUGUI text;

		private bool wanted;

		private bool peakFontApplied;

		private float nextFontSearch;

		private float lastFontSize = -1f;

		public void Initialize(Plugin owner)
		{
			plugin = owner;
			BuildUI();
		}

		private void BuildUI()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_006e: 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_0099: Expected O, but got Unknown
			//IL_00c1: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)root))
			{
				root = new GameObject("POTP_PagePromptCanvas");
				root.transform.SetParent(((Component)this).transform, false);
				Canvas obj = root.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 250;
				CanvasScaler obj2 = root.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				obj2.matchWidthOrHeight = 0.5f;
				root.AddComponent<GraphicRaycaster>();
				GameObject val = new GameObject("PagePrompt");
				val.transform.SetParent(root.transform, false);
				RectTransform obj3 = val.AddComponent<RectTransform>();
				obj3.anchorMin = new Vector2(0.5f, 0.35f);
				obj3.anchorMax = new Vector2(0.5f, 0.35f);
				obj3.pivot = new Vector2(0.5f, 0.5f);
				obj3.anchoredPosition = Vector2.zero;
				obj3.sizeDelta = new Vector2(900f, 90f);
				text = val.AddComponent<TextMeshProUGUI>();
				((TMP_Text)text).text = "[F] Grab Page";
				((TMP_Text)text).alignment = (TextAlignmentOptions)514;
				((TMP_Text)text).fontSize = plugin.PagePromptFontSize.Value;
				((TMP_Text)text).fontStyle = (FontStyles)1;
				((Graphic)text).color = Color.white;
				((Graphic)text).raycastTarget = false;
				((TMP_Text)text).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)text).overflowMode = (TextOverflowModes)0;
				root.SetActive(false);
				TryCopyPeakFont();
			}
		}

		private TMP_Text FindPeakPromptText()
		{
			GUIManager instance = GUIManager.instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return null;
			}
			string[] array = new string[5] { "interactPromptText", "promptText", "interactText", "interactNameText", "secondaryInteractPromptText" };
			foreach (string text in array)
			{
				try
				{
					FieldInfo fieldInfo = AccessTools.Field(typeof(GUIManager), text);
					if (!(fieldInfo == null))
					{
						object? value = fieldInfo.GetValue(instance);
						TMP_Text val = (TMP_Text)((value is TMP_Text) ? value : null);
						if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.font))
						{
							return val;
						}
					}
				}
				catch
				{
				}
			}
			return ((IEnumerable<TMP_Text>)((Component)instance).GetComponentsInChildren<TMP_Text>(true)).FirstOrDefault((Func<TMP_Text, bool>)((TMP_Text t) => Object.op_Implicit((Object)(object)t) && Object.op_Implicit((Object)(object)t.font)));
		}

		private void TryCopyPeakFont()
		{
			if (!Object.op_Implicit((Object)(object)text) || peakFontApplied)
			{
				return;
			}
			TMP_Text val = FindPeakPromptText();
			if (Object.op_Implicit((Object)(object)val))
			{
				((TMP_Text)text).font = val.font;
				peakFontApplied = true;
				if (Object.op_Implicit((Object)(object)val.fontSharedMaterial))
				{
					((TMP_Text)text).fontSharedMaterial = val.fontSharedMaterial;
				}
				plugin.Trace("Page interaction prompt is using PEAK TMP font: " + ((Object)val.font).name);
			}
		}

		public void SetVisible(bool value)
		{
			wanted = value;
			if (!Object.op_Implicit((Object)(object)root))
			{
				BuildUI();
			}
			if (Object.op_Implicit((Object)(object)root) && root.activeSelf != wanted)
			{
				root.SetActive(wanted);
			}
		}

		private void Update()
		{
			if (!Object.op_Implicit((Object)(object)root))
			{
				return;
			}
			if (Time.unscaledTime >= nextFontSearch)
			{
				nextFontSearch = Time.unscaledTime + 1f;
				TryCopyPeakFont();
			}
			if (Object.op_Implicit((Object)(object)text))
			{
				float value = plugin.PagePromptFontSize.Value;
				if (Mathf.Abs(value - lastFontSize) > 0.01f)
				{
					lastFontSize = value;
					((TMP_Text)text).fontSize = value;
				}
			}
		}

		public void Dispose()
		{
			if (Object.op_Implicit((Object)(object)root))
			{
				Object.Destroy((Object)(object)root);
			}
			root = null;
			text = null;
		}

		private void OnDestroy()
		{
			Dispose();
		}
	}
	internal sealed class PageVisualController : MonoBehaviour
	{
		private Plugin plugin;

		private readonly Dictionary<Material, Color> baseColors = new Dictionary<Material, Color>();

		private float currentVisibility = 1f;

		private float targetVisibility = 1f;

		private float nextExposureSample;

		private float lastAppliedVisibility = -1f;

		private bool lastRevealEnabled;

		public void Initialize(Plugin owner)
		{
			plugin = owner;
			CaptureColors();
		}

		public void SetRevealEnabled(bool value)
		{
			if (!value)
			{
				targetVisibility = 1f;
				currentVisibility = 1f;
				ApplyVisibility(1f, force: true);
				((Behaviour)this).enabled = false;
			}
			else
			{
				((Behaviour)this).enabled = true;
				nextExposureSample = 0f;
				lastAppliedVisibility = -1f;
			}
		}

		private void CaptureColors()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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)
			baseColors.Clear();
			Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				foreach (Material val2 in sharedMaterials)
				{
					if (Object.op_Implicit((Object)(object)val2) && !baseColors.ContainsKey(val2))
					{
						Color value = Color.white;
						if (val2.HasProperty("_BaseColor"))
						{
							value = val2.GetColor("_BaseColor");
						}
						else if (val2.HasProperty("_Color"))
						{
							value = val2.GetColor("_Color");
						}
						baseColors[val2] = value;
					}
				}
			}
		}

		private void ApplyVisibility(float visibility, bool force = false)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0098: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (!force && lastAppliedVisibility >= 0f && Mathf.Abs(visibility - lastAppliedVisibility) < 0.004f)
			{
				return;
			}
			lastAppliedVisibility = visibility;
			Color val = default(Color);
			foreach (KeyValuePair<Material, Color> baseColor in baseColors)
			{
				Material key = baseColor.Key;
				if (Object.op_Implicit((Object)(object)key))
				{
					Color value = baseColor.Value;
					((Color)(ref val))..ctor(value.r * visibility, value.g * visibility, value.b * visibility, value.a);
					if (key.HasProperty("_BaseColor"))
					{
						key.SetColor("_BaseColor", val);
					}
					if (key.HasProperty("_Color"))
					{
						key.SetColor("_Color", val);
					}
					if (key.HasProperty("_EmissionColor"))
					{
						key.SetColor("_EmissionColor", Color.black);
					}
					key.DisableKeyword("_EMISSION");
				}
			}
		}

		private void Update()
		{
			//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_0074: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)plugin == (Object)null) && !(Time.unscaledTime < nextExposureSample))
			{
				float num = ((nextExposureSample <= 0f) ? 0.05f : Mathf.Max(0.001f, Time.unscaledTime - (nextExposureSample - 0.05f)));
				nextExposureSample = Time.unscaledTime + 0.05f;
				Vector3 worldPoint = ((Component)this).transform.position + Vector3.up * 0.15f;
				float num2 = plugin.FlashlightExposureAt(worldPoint);
				num2 = Mathf.Clamp01(num2 * plugin.PageFlashlightRevealBoost.Value);
				targetVisibility = Mathf.Lerp(plugin.PageDarkVisibility.Value, 1f, num2);
				currentVisibility = Mathf.MoveTowards(currentVisibility, targetVisibility, num * plugin.PageRevealFadeSpeed.Value);
				ApplyVisibility(currentVisibility);
			}
		}

		private void OnDestroy()
		{
			//IL_003b: 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)
			foreach (KeyValuePair<Material, Color> baseColor in baseColors)
			{
				Material key = baseColor.Key;
				if (Object.op_Implicit((Object)(object)key))
				{
					if (key.HasProperty("_BaseColor"))
					{
						key.SetColor("_BaseColor", baseColor.Value);
					}
					if (key.HasProperty("_Color"))
					{
						key.SetColor("_Color", baseColor.Value);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Scoutmaster), "Start")]
	internal static class EnemyStartPatch
	{
		private static void Prefix(Scoutmaster __instance)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			if (!((Object)(object)Plugin.Instance == (Object)null) && Plugin.Instance.IsOurEnemy(__instance) && Object.op_Implicit((Object)(object)__instance.mat))
			{
				__instance.mat = new Material(__instance.mat);
			}
		}

		private static void Postfix(Scoutmaster __instance)
		{
			if (!((Object)(object)Plugin.Instance == (Object)null) && Plugin.Instance.IsOurEnemy(__instance))
			{
				(AccessTools.Field(typeof(Scoutmaster), "AllScoutmasters").GetValue(null) as IList)?.Remove(__instance);
				Plugin.Instance.AttachCustomVisual(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Scoutmaster), "OnDestroy")]
	internal static class EnemyDestroyPatch
	{
		private static void Prefix(Scoutmaster __instance)
		{
			if ((Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.IsOurEnemy(__instance))
			{
				Plugin.Instance.DetachCustomVisual(__instance);
				if (Object.op_Implicit((Object)(object)__instance.mat))
				{
					Object.Destroy((Object)(object)__instance.mat);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Scoutmaster), "Update")]
	internal static class EnemyUpdatePatch
	{
		private static bool Prefix(Scoutmaster __instance)
		{
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null || !instance.IsOurEnemy(__instance))
			{
				return true;
			}
			instance.EnemyUpdate(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(Scoutmaster), "FixedUpdate")]
	internal static class EnemyPhysicsPatch
	{
		private static bool Prefix(Scoutmaster __instance)
		{
			if (!((Object)(object)Plugin.Instance == (Object)null))
			{
				return !Plugin.Instance.IsOurEnemy(__instance);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GUIManager), "DrowsyFX")]
	internal static class DrowsyCameraVisualPatch
	{
		private static bool Prefix()
		{
			Plugin instance = Plugin.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return true;
			}
			if (instance.IsCurseActive && instance.SuppressDrowsyCameraFX != null)
			{
				return !instance.SuppressDrowsyCameraFX.Value;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Character), "UpdateVariablesFixed")]
	internal static class RegenPatch
	{
		private static float Scale(float amount, Character character)
		{
			if (!((Object)(object)Plugin.Instance == (Object)null))
			{
				return Plugin.Instance.Regen(amount, character);
			}
			return amount;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo add = AccessTools.Method(typeof(Character), "AddStamina", new Type[1] { typeof(float) }, (Type[])null);
			if (list.Count((CodeInstruction val2) => CodeInstructionExtensions.Calls(val2, add)) != 1)
			{
				throw new InvalidOperationException("Natural regen hook changed: expected exactly one AddStamina call.");
			}
			foreach (CodeInstruction i in list)
			{
				if (CodeInstructionExtensions.Calls(i, add))
				{
					CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					CodeInstructionExtensions.MoveLabelsTo(i, val);
					yield return val;
					yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RegenPatch), "Scale", (Type[])null, (Type[])null));
				}
				yield return i;
			}
		}
	}
	internal enum SlenderContactOutcome
	{
		KnockoutOnly,
		AlwaysKill,
		FirstKnockoutThenKill
	}
	[BepInPlugin("CircusFriendsStudios.PagesOfThePeak", "Pages of the Peak", "0.1.1")]
	public sealed class Plugin : BaseUnityPlugin, IOnEventCallback
	{
		public const string Guid = "CircusFriendsStudios.PagesOfThePeak";

		public const string Version = "0.1.1";

		private const string PlayerKey = "CFS.POTP.Version";

		private const string PlayerUseKey = "CFS.POTP.Use";

		private const string RoomStateKey = "CFS.POTP.State";

		private const string NetworkBuild = "0.1.1-mpfix5";

		private const byte EventCode = 179;

		public static Plugin Instance;

		internal RunState State = new RunState();

		internal ConfigEntry<int> PageCount;

		internal ConfigEntry<int> HuntAt;

		internal ConfigEntry<float> Bonus;

		internal ConfigEntry<float> StaticStrength;

		internal ConfigEntry<float> WatchDrowsyPerSecond;

		internal ConfigEntry<float> WatchGazeThreshold;

		internal ConfigEntry<float> WatchEffectDistance;

		internal ConfigEntry<float> HuntMaxRunSpeed;

		internal ConfigEntry<float> HuntMaxClimbSpeed;

		internal ConfigEntry<int> HuntSprintAtPages;

		internal ConfigEntry<SlenderContactOutcome> HuntContactOutcome;

		internal ConfigEntry<float> EventCooldownMin;

		internal ConfigEntry<float> EventCooldownMax;

		internal ConfigEntry<float> EventCooldownReductionPerPage;

		internal ConfigEntry<float> EventCooldownFloor;

		internal ConfigEntry<bool> DebugKeys;

		internal ConfigEntry<bool> ShowDebugText;

		internal ConfigEntry<bool> VerboseNetworkLogging;

		internal ConfigEntry<bool> EnableStatic;

		internal ConfigEntry<bool> EnableWatchDrowsy;

		internal ConfigEntry<bool> SuppressDrowsyCameraFX;

		internal ConfigEntry<bool> EnableBuiltInFlashlight;

		internal ConfigEntry<bool> FlashlightStartOn;

		internal ConfigEntry<bool> FlashlightShadows;

		internal ConfigEntry<float> FlashlightIntensity;

		internal ConfigEntry<float> FlashlightRange;

		internal ConfigEntry<float> FlashlightSpotAngle;

		internal ConfigEntry<float> FlashlightInnerSpotAngle;

		internal ConfigEntry<float> FlashlightColorTemperature;

		internal ConfigEntry<float> FlashlightShadowStrength;

		internal ConfigEntry<float> FlashlightShadowBias;

		internal ConfigEntry<float> FlashlightShadowNormalBias;

		internal ConfigEntry<float> FlashlightHorizontalOffset;

		internal ConfigEntry<float> FlashlightVerticalOffset;

		internal ConfigEntry<float> FlashlightForwardOffset;

		internal ConfigEntry<bool> EnableCustomSlender;

		internal ConfigEntry<bool> HideNativeScoutmaster;

		internal ConfigEntry<bool> EnableSlenderAudio;

		internal ConfigEntry<bool> ForceSlenderLitMaterials;

		internal ConfigEntry<bool> DisableSlenderEmission;

		internal ConfigEntry<bool> SlenderAutoLighting;

		internal ConfigEntry<bool> SlenderFlashlightRevealMode;

		internal ConfigEntry<bool> DisableSlenderEnvironmentReflections;

		internal ConfigEntry<float> SlenderVisualScale;

		internal ConfigEntry<float> SlenderVisualYOffset;

		internal ConfigEntry<float> SlenderVisualYaw;

		internal ConfigEntry<float> SlenderAlbedoMultiplier;

		internal ConfigEntry<float> SlenderDarkVisibility;

		internal ConfigEntry<float> SlenderRevealFadeSpeed;

		internal ConfigEntry<float> SlenderFlashlightRevealBoost;

		internal ConfigEntry<float> SlenderHuntAudioVolume;

		internal ConfigEntry<float> SlenderHuntAudioMinDistance;

		internal ConfigEntry<float> SlenderHuntAudioMaxDistance;

		internal ConfigEntry<float> SlenderHuntAudioFadeSeconds;

		internal ConfigEntry<string> ScrollName;

		internal ConfigEntry<bool> EnableCustomPageModels;

		internal ConfigEntry<bool> ShowPageLabel;

		internal ConfigEntry<bool> RandomizePageYaw;

		internal ConfigEntry<bool> ForcePageLitMaterials;

		internal ConfigEntry<bool> DisablePageEmission;

		internal ConfigEntry<bool> DisablePageEnvironmentReflections;

		internal ConfigEntry<bool> PageFlashlightRevealMode;

		internal ConfigEntry<float> CustomPageScale;

		internal ConfigEntry<float> CustomPageVerticalOffset;

		internal ConfigEntry<float> CustomPagePitch;

		internal ConfigEntry<float> CustomPageYaw;

		internal ConfigEntry<float> CustomPageRoll;

		internal ConfigEntry<float> PageDarkVisibility;

		internal ConfigEntry<float> PageFlashlightRevealBoost;

		internal ConfigEntry<float> PageRevealFadeSpeed;

		internal ConfigEntry<float> PagePromptFontSize;

		internal ConfigEntry<float> PageFloatingLabelSize;

		internal ConfigEntry<float> PageFloatingLabelHeight;

		private Harmony harmony;

		private World world;

		private FlashlightController flashlight;

		private DrowsyVisualSuppressor drowsyVisualSuppressor;

		private PagePromptController pagePrompt;

		private float tick;

		private float broadcast;

		private float nextRequest;

		private float nextRoomPoll;

		private float nextNetworkHeartbeat;

		private float eventAt;

		private float eventEnd;

		private float pendingUntil;

		private float nextMapLookup;

		private float nextModRosterCheck;

		private float nextFallbackPoll;

		private float nextPromptProbe;

		private int mapId;

		private int masterId;

		private int lastSegment = -1;

		private MapHandler cachedMap;

		private bool cachedAllModded;

		private int useNonce;

		private int lastRemoteAttackSerial;

		private float lastSnapshot;

		private float moveCheck;

		private float attackGrace;

		private float watchDrowsyPending;

		private string huntDiagnostic = "";

		private Vector3 lastEnemyPosition;

		private readonly Dictionary<int, int> attempts = new Dictionary<int, int>();

		private readonly Dictionary<int, float> requests = new Dictionary<int, float>();

		private readonly Dictionary<int, string> lastUseFallback = new Dictionary<int, string>();

		private readonly HashSet<int> knocked = new HashSet<int>();

		private readonly HashSet<int> mercyUsedThisSegment = new HashSet<int>();

		private string notice = "Waiting for a climb";

		private string waitingReason = "";

		private bool active;

		private bool advertised;

		private bool watchEffectFaulted;

		private Scoutmaster localEnemy;

		private Character localTarget;

		private float lastWatchDot;

		private string watchGazeReason = "idle";

		private float nextGazeErrorLog;

		private AssetBundle slenderBundle;

		private GameObject slenderPrefab;

		private float nextSlenderLightingDetection;

		private bool cachedPitchBlackDetected;

		private bool? lastReportedSlenderBlackoutMode;

		private string slenderBundlePath = "";

		private readonly Dictionary<int, GameObject> slenderVisuals = new Dictionary<int, GameObject>();

		internal bool Host
		{
			get
			{
				if (PhotonNetwork.InRoom)
				{
					return PhotonNetwork.IsMasterClient;
				}
				return false;
			}
		}

		internal bool IsCurseActive => active;

		internal static bool Alive(Character c)
		{
			if (Object.op_Implicit((Object)(object)c) && c.IsInitialized && !c.isBot && !c.isScoutmaster && !c.isZombie && !c.IsGhost && !c.data.dead)
			{
				return !c.data.passedOut;
			}
			return false;
		}

		internal void Log(string s)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)s);
			notice = s;
		}

		internal void Trace(string s)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)s);
		}

		internal void InternalWarn(string s)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)s);
		}

		private void Awake()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Expected O, but got Unknown
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Expected O, but got Unknown
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Expected O, but got Unknown
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Expected O, but got Unknown
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Expected O, but got Unknown
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Expected O, but got Unknown
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Expected O, but got Unknown
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Expected O, but got Unknown
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Expected O, but got Unknown
			//IL_0479: Unknown result type (might be due to invalid IL or missing references)
			//IL_0483: Expected O, but got Unknown
			//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0503: Expected O, but got Unknown
			//IL_059a: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a4: Expected O, but got Unknown
			//IL_05d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e2: Expected O, but got Unknown
			//IL_0616: Unknown result type (might be due to invalid IL or missing references)
			//IL_0620: Expected O, but got Unknown
			//IL_0675: Unknown result type (might be due to invalid IL or missing references)
			//IL_067f: Expected O, but got Unknown
			//IL_06f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ff: Expected O, but got Unknown
			//IL_0733: Unknown result type (might be due to invalid IL or missing references)
			//IL_073d: Expected O, but got Unknown
			//IL_0771: Unknown result type (might be due to invalid IL or missing references)
			//IL_077b: Expected O, but got Unknown
			//IL_07f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fb: Expected O, but got Unknown
			//IL_082f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0839: Expected O, but got Unknown
			//IL_086d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0877: Expected O, but got Unknown
			//IL_08ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b5: Expected O, but got Unknown
			//IL_08e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f3: Expected O, but got Unknown
			//IL_0927: Unknown result type (might be due to invalid IL or missing references)
			//IL_0931: Expected O, but got Unknown
			//IL_0965: Unknown result type (might be due to invalid IL or missing references)
			//IL_096f: Expected O, but got Unknown
			//IL_09a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ad: Expected O, but got Unknown
			//IL_0a02: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a0c: Expected O, but got Unknown
			//IL_0a40: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a4a: Expected O, but got Unknown
			//IL_0a7e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a88: Expected O, but got Unknown
			//IL_0b65: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b6f: Expected O, but got Unknown
			//IL_0ba3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bad: Expected O, but got Unknown
			//IL_0be1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0beb: Expected O, but got Unknown
			//IL_0c1f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c29: Expected O, but got Unknown
			//IL_0c5d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c67: Expected O, but got Unknown
			//IL_0cdd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ce7: Expected O, but got Unknown
			//IL_0d1b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d25: Expected O, but got Unknown
			//IL_0ddd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0de7: Expected O, but got Unknown
			//IL_0e1b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e25: Expected O, but got Unknown
			//IL_0e59: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e63: Expected O, but got Unknown
			//IL_0e97: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ea1: Expected O, but got Unknown
			//IL_0f15: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f1f: Expected O, but got Unknown
			Instance = this;
			PageCount = ((BaseUnityPlugin)this).Config.Bind<int>("Pages", "PagesPerBiome", 24, new ConfigDescription("Pages placed in each mountain biome/segment. Progress and regen reset when the next segment becomes active. Increase this for larger multiplayer lobbies.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 48), Array.Empty<object>()));
			Bonus = ((BaseUnityPlugin)this).Config.Bind<float>("Reward", "RegenPerPage", 0.02f, new ConfigDescription("Additive natural stamina regeneration bonus to the collector for the current biome. Resets on segment transition.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.1f), Array.Empty<object>()));
			HuntAt = ((BaseUnityPlugin)this).Config.Bind<int>("Threat", "HuntsStartAtPages", 3, new ConfigDescription("Shared pages needed to enable hunts.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 30), Array.Empty<object>()));
			HuntMaxRunSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Hunt", "MaxRunSpeedMultiplier", 2f, new ConfigDescription("Ground chase speed multiplier reached at the biome page maximum. 1.0 = vanilla movement pace.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			HuntMaxClimbSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Hunt", "MaxClimbSpeedMultiplier", 2f, new ConfigDescription("Climbing speed multiplier reached at the biome page maximum.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			HuntSprintAtPages = ((BaseUnityPlugin)this).Config.Bind<int>("Hunt", "ForceSprintAtPages", 6, new ConfigDescription("At this many collected pages, Hunt mode holds Scoutmaster sprint while chasing. This is editable independently of PagesPerBiome.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 48), Array.Empty<object>()));
			HuntContactOutcome = ((BaseUnityPlugin)this).Config.Bind<SlenderContactOutcome>("Hunt", "ContactOutcome", SlenderContactOutcome.FirstKnockoutThenKill, "What happens when Slenderman catches a player. KnockoutOnly always passes the player out; AlwaysKill uses PEAK's full death path; FirstKnockoutThenKill gives each player one knockout/mercy per biome, then later catches in that biome are fatal.");
			EventCooldownMin = ((BaseUnityPlugin)this).Config.Bind<float>("Threat", "CooldownMinSeconds", 20f, new ConfigDescription("Lower end of the encounter cooldown at low page counts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 90f), Array.Empty<object>()));
			EventCooldownMax = ((BaseUnityPlugin)this).Config.Bind<float>("Threat", "CooldownMaxSeconds", 36f, new ConfigDescription("Upper end of the encounter cooldown at low page counts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 120f), Array.Empty<object>()));
			EventCooldownReductionPerPage = ((BaseUnityPlugin)this).Config.Bind<float>("Threat", "CooldownReductionPerPage", 1.25f, new ConfigDescription("Seconds removed from the encounter cooldown for each page after the first.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			EventCooldownFloor = ((BaseUnityPlugin)this).Config.Bind<float>("Threat", "CooldownFloorSeconds", 10f, new ConfigDescription("Hard minimum encounter cooldown at high page counts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 60f), Array.Empty<object>()));
			EnableCustomSlender = ((BaseUnityPlugin)this).Config.Bind<bool>("Slender Model", "EnableCustomModel", true, "Load pagesofthepeak_slender from the BepInEx plugins folder and use it as the visible enemy model.");
			HideNativeScoutmaster = ((BaseUnityPlugin)this).Config.Bind<bool>("Slender Model", "HideNativeScoutmaster", true, "Hide the PEAK Scoutmaster renderers after the custom Slender model attaches. Physics and AI remain active.");
			EnableSlenderAudio = ((BaseUnityPlugin)this).Config.Bind<bool>("Slender Audio", "EnableHuntAudio", true, "Play the custom Slender prefab audio only during Hunt mode. Audio is fully 3D/spatial and follows Slender, so distance and direction are audible.");
			SlenderHuntAudioVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Audio", "HuntAudioVolume", 0.7f, new ConfigDescription("Master volume for Slender Hunt audio.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			SlenderHuntAudioMinDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Audio", "MinDistance", 4f, new ConfigDescription("Distance in metres at which Hunt audio is at full volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), Array.Empty<object>()));
			SlenderHuntAudioMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Audio", "MaxDistance", 45f, new ConfigDescription("Distance in metres at which Hunt audio fades to effectively inaudible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 120f), Array.Empty<object>()));
			SlenderHuntAudioFadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Audio", "FadeSeconds", 0.35f, new ConfigDescription("Fade-in/fade-out time when Hunt starts or ends.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 3f), Array.Empty<object>()));
			SlenderVisualScale = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Model", "Scale", 1f, new ConfigDescription("Uniform scale of the custom Slender visual.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 4f), Array.Empty<object>()));
			SlenderVisualYOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Model", "VerticalOffset", 0f, new ConfigDescription("Vertical local offset of the custom Slender visual in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-3f, 3f), Array.Empty<object>()));
			SlenderVisualYaw = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Model", "YawOffset", 0f, new ConfigDescription("Local Y-axis rotation correction for the custom Slender visual.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
			ForceSlenderLitMaterials = ((BaseUnityPlugin)this).Config.Bind<bool>("Slender Model", "ForceLitMaterials", true, "Force every custom Slender material onto PEAK/URP Lit so blackout/night lighting and the built-in flashlight affect him normally.");
			DisableSlenderEmission = ((BaseUnityPlugin)this).Config.Bind<bool>("Slender Model", "DisableMaterialEmission", true, "Strip emission/self-illumination from the custom Slender materials so he cannot glow in darkness.");
			SlenderAlbedoMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Model", "AlbedoMultiplier", 1f, new ConfigDescription("Optional overall material darkness multiplier. 1.0 preserves the original colors; lower values darken the model while still allowing lights/flashlight to illuminate it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.15f, 1f), Array.Empty<object>()));
			DisableSlenderEnvironmentReflections = ((BaseUnityPlugin)this).Config.Bind<bool>("Slender Model", "DisableEnvironmentReflections", true, "When blackout rendering is active, suppress reflection/light probes and environment specular highlights so Slender cannot glow from ambient sky/probe lighting.");
			SlenderAutoLighting = ((BaseUnityPlugin)this).Config.Bind<bool>("Slender Model", "AutoLightingCompatibility", true, "Automatically use normal PEAK lighting for vanilla day/night gameplay and enable the special flashlight-only blackout treatment when a loaded BepInEx plugin is detected as Pitch Black/PitchBlack. Turn OFF to use FlashlightRevealMode manually.");
			SlenderFlashlightRevealMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Slender Model", "FlashlightRevealMode", true, "Manual blackout override used only when AutoLightingCompatibility is OFF. ON = flashlight-only blackout treatment; OFF = normal PEAK/URP lighting.");
			SlenderDarkVisibility = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Model", "DarkVisibility", 0.02f, new ConfigDescription("How visible Slender remains when FlashlightRevealMode is enabled but the beam is not on him. 0 = completely black, 0.01 = tiny silhouette.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.35f), Array.Empty<object>()));
			SlenderFlashlightRevealBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Model", "FlashlightRevealBoost", 2f, new ConfigDescription("How quickly the flashlight restores Slender to full material brightness inside the beam.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 4f), Array.Empty<object>()));
			SlenderRevealFadeSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Slender Model", "RevealFadeSpeed", 10f, new ConfigDescription("How quickly Slender fades between darkness and flashlight-lit appearance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f), Array.Empty<object>()));
			EnableStatic = ((BaseUnityPlugin)this).Config.Bind<bool>("Watching", "EnableStatic", true, "Show the static overlay only while directly looking at Slender during a Watching event. Never applies during a Hunt.");
			StaticStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Watching", "StaticOpacity", 0.12f, new ConfigDescription("Maximum Watching-mode static opacity. Also respects PEAK photosensitivity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.3f), Array.Empty<object>()));
			EnableWatchDrowsy = ((BaseUnityPlugin)this).Config.Bind<bool>("Watching", "EnableDrowsyOnGaze", true, "Fill the normal PEAK Drowsy/Sleepy status while directly staring at Slender during Watching events. Never applies during Hunts.");
			SuppressDrowsyCameraFX = ((BaseUnityPlugin)this).Config.Bind<bool>("Watching", "SuppressDrowsyCameraFX", true, "Keep the real PEAK Drowsy meter/status but suppress the vanilla sleepy camera/post-processing effect while Pages of the Peak is active.");
			WatchDrowsyPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("Watching", "DrowsyPerSecond", 0.08f, new ConfigDescription("Drowsiness added per second of direct Watching-mode eye contact. 0.08 is roughly 8% of the bar per second before PEAK's own reductions.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.25f), Array.Empty<object>()));
			WatchGazeThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Watching", "DirectLookThreshold", 0.93f, new ConfigDescription("How directly the camera must face Slender before Watching gaze effects apply. Higher is stricter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.75f, 0.995f), Array.Empty<object>()));
			WatchEffectDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Watching", "EffectDistance", 45f, new ConfigDescription("Maximum distance in metres for Watching gaze effects.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			EnableBuiltInFlashlight = ((BaseUnityPlugin)this).Config.Bind<bool>("Flashlight", "EnableBuiltInFlashlight", true, "Enable the built-in camera-centered flashlight. Press L to toggle.");
			FlashlightStartOn = ((BaseUnityPlugin)this).Config.Bind<bool>("Flashlight", "StartOn", false, "Start each game session with the built-in flashlight switched on.");
			FlashlightIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "Intensity", 12f, new ConfigDescription("Flashlight brightness.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 15f), Array.Empty<object>()));
			FlashlightRange = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "Range", 80f, new ConfigDescription("Flashlight beam range in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
			FlashlightSpotAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "SpotAngle", 90f, new ConfigDescription("Outer flashlight cone angle. Higher = wider beam.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(15f, 120f), Array.Empty<object>()));
			FlashlightInnerSpotAngle = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "InnerSpotAngle", 90f, new ConfigDescription("Bright inner flashlight cone angle.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 110f), Array.Empty<object>()));
			FlashlightColorTemperature = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "ColorTemperatureKelvin", 5000f, new ConfigDescription("Beam color temperature. Lower = warmer/yellower; higher = cooler/bluer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2500f, 9000f), Array.Empty<object>()));
			FlashlightHorizontalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "HorizontalOffset", 0f, new ConfigDescription("Camera-local horizontal beam origin offset.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0.5f), Array.Empty<object>()));
			FlashlightVerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "VerticalOffset", -0.015f, new ConfigDescription("Camera-local vertical beam origin offset.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0.5f), Array.Empty<object>()));
			FlashlightForwardOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "ForwardOffset", 0.08f, new ConfigDescription("Camera-local forward beam origin offset.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			FlashlightShadows = ((BaseUnityPlugin)this).Config.Bind<bool>("Flashlight", "EnableShadows", false, "Use soft realtime shadows for the flashlight. Disable if performance is poor.");
			FlashlightShadowStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "ShadowStrength", 0.72f, new ConfigDescription("Flashlight shadow darkness.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			FlashlightShadowBias = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "ShadowBias", 0.05f, new ConfigDescription("Shadow bias. Increase slightly if you see shadow acne.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
			FlashlightShadowNormalBias = ((BaseUnityPlugin)this).Config.Bind<float>("Flashlight", "ShadowNormalBias", 0.4f, new ConfigDescription("Shadow normal bias.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			DebugKeys = ((BaseUnityPlugin)this).Config.Bind<bool>("Development", "EnableDebugKeys", true, "Enable F6-F11 development/test shortcuts.");
			ShowDebugText = ((BaseUnityPlugin)this).Config.Bind<bool>("Development", "ShowDebugText", false, "Show the Pages of the Peak diagnostic/status text in the upper-left corner. Disabled by default for normal/release gameplay.");
			VerboseNetworkLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Development", "VerboseNetworkLogging", false, "Write frequent multiplayer publish/event/heartbeat diagnostics to LogOutput.log. Leave OFF for normal gameplay; F6 diagnostics still work.");
			ScrollName = ((BaseUnityPlugin)this).Config.Bind<string>("Pages", "ScrollPrefabName", "", "Optional exact native Item object name; blank searches names containing scroll. F6 logs candidates. Missing mesh uses a labeled paper placeholder.");
			EnableCustomPageModels = ((BaseUnityPlugin)this).Config.Bind<bool>("Page Model", "EnableCustomPageModels", true, "Load pagesofthepeak_pages from the PagesOfThePeak plugin folder and use the bundled Slenderman paper meshes instead of PEAK's scroll visual.");
			CustomPageScale = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "Scale", 10f, new ConfigDescription("Uniform scale of the custom paper model. The supplied Slendpg FBX is authored very small; around 10 works well in PEAK.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 20f), Array.Empty<object>()));
			CustomPageVerticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "VerticalOffset", 0f, new ConfigDescription("Additional vertical offset for the custom paper model. A small positive value gives the page a deliberate floating collectible look.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>()));
			CustomPagePitch = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "PitchOffset", 0f, new ConfigDescription("X-axis rotation correction for the custom paper model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
			CustomPageYaw = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "YawOffset", 0f, new ConfigDescription("Y-axis rotation correction for the custom paper model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
			CustomPageRoll = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "RollOffset", 0f, new ConfigDescription("Z-axis rotation correction for the custom paper model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-180f, 180f), Array.Empty<object>()));
			RandomizePageYaw = ((BaseUnityPlugin)this).Config.Bind<bool>("Page Model", "RandomizeYaw", true, "Give each page a deterministic random Y rotation so the papers do not all face exactly the same direction.");
			ShowPageLabel = ((BaseUnityPlugin)this).Config.Bind<bool>("Page Model", "ShowFloatingPAGELabel", true, "Show the old floating PAGE text above custom paper models. Disabled by default for immersion.");
			PageFloatingLabelSize = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "FloatingPAGELabelSize", 0.025f, new ConfigDescription("World-space size of the floating PAGE label. This is independent of the custom page model Scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.008f, 0.15f), Array.Empty<object>()));
			PageFloatingLabelHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "FloatingPAGELabelHeight", 0.55f, new ConfigDescription("World-space height of the floating PAGE label above the page origin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2.5f), Array.Empty<object>()));
			ForcePageLitMaterials = ((BaseUnityPlugin)this).Config.Bind<bool>("Page Model", "ForceLitMaterials", true, "Convert custom page materials to URP/Lit so darkness and the Pages of the Peak flashlight affect them normally.");
			DisablePageEmission = ((BaseUnityPlugin)this).Config.Bind<bool>("Page Model", "DisableMaterialEmission", true, "Remove emission/self-illumination from custom page materials.");
			DisablePageEnvironmentReflections = ((BaseUnityPlugin)this).Config.Bind<bool>("Page Model", "DisableEnvironmentReflections", true, "Disable light/reflection probes and specular environment highlights on custom pages so white paper does not glow in darkness.");
			PageFlashlightRevealMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Page Model", "FlashlightRevealMode", false, "Blackout helper: keep custom pages dark unless the built-in flashlight beam is hitting them. Turn this ON when using Pitch Black PEAK/night mods.");
			PageDarkVisibility = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "DarkVisibility", 0.03f, new ConfigDescription("How visible custom pages remain outside the flashlight when FlashlightRevealMode is enabled.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
			PageFlashlightRevealBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "FlashlightRevealBoost", 2f, new ConfigDescription("How strongly the built-in flashlight restores page brightness.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
			PageRevealFadeSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "RevealFadeSpeed", 12f, new ConfigDescription("How quickly pages fade between darkness and flashlight-lit appearance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f), Array.Empty<object>()));
			PagePromptFontSize = ((BaseUnityPlugin)this).Config.Bind<float>("Page Model", "PromptFontSize", 38f, new ConfigDescription("Size of the no-box '[F] Grab Page' PEAK-font interaction prompt.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(18f, 72f), Array.Empty<object>()));
			world = new World(this);
			flashlight = ((Component)this).gameObject.AddComponent<FlashlightController>();
			flashlight.Initialize(this);
			drowsyVisualSuppressor = ((Component)this).gameObject.AddComponent<DrowsyVisualSuppressor>();
			drowsyVisualSuppressor.Initialize(this);
			pagePrompt = ((Component)this).gameObject.AddComponent<PagePromptController>();
			pagePrompt.Initialize(this);
			LoadSlenderBundle();
			harmony = new Harmony("CircusFriendsStudios.PagesOfThePeak");
			harmony.PatchAll();
			PhotonNetwork.AddCallbackTarget((object)this);
			Log("Loaded Pages of the Peak 0.1.1 MULTIPLAYER FIX 5 PERFORMANCE [0.1.1-mpfix5]. L flashlight; F6 MP diagnostics; F7 pages; F8 debug reward; F9 watch; F10 hunt; F11 reset. F activates pages.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("POTP NETWORK BUILD=0.1.1-mpfix5 | protocol=CFS.PagesOfThePeak.3 | StateWire=v1 | eventCode=" + (byte)179));
		}

		private void OnDestroy()
		{
			//IL_0020: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_005d: 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_0077: Expected O, but got Unknown
			if (Host)
			{
				DestroyEnemy();
			}
			PhotonNetwork.RemoveCallbackTarget((object)this);
			if (PhotonNetwork.InRoom)
			{
				PhotonNetwork.LocalPlayer.SetCustomProperties(new Hashtable
				{
					[(object)"CFS.POTP.Version"] = null,
					[(object)"CFS.POTP.Use"] = null
				}, (Hashtable)null, (WebFlags)null);
				if (Host && PhotonNetwork.CurrentRoom != null)
				{
					PhotonNetwork.CurrentRoom.SetCustomProperties(new Hashtable { [(object)"CFS.POTP.State"] = null }, (Hashtable)null, (WebFlags)null);
				}
			}
			Harmony obj3 = harmony;
			if (obj3 != null)
			{
				obj3.UnpatchSelf();
			}
			world?.Dispose();
			flashlight?.Dispose();
			flashlight = null;
			drowsyVisualSuppressor?.Dispose();
			drowsyVisualSuppressor = null;
			pagePrompt?.Dispose();
			pagePrompt = null;
			foreach (GameObject value in slenderVisuals.Values)
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					Object.Destroy((Object)(object)value);
				}
			}
			slenderVisuals.Clear();
			if ((Object)(object)slenderBundle != (Object)null)
			{
				slenderBundle.Unload(false);
			}
			slenderBundle = null;
			slenderPrefab = null;
			Instance = null;
		}

		private bool AllModded()
		{
			object value;
			string[] array = (from p in PhotonNetwork.PlayerList
				where !((Dictionary<object, object>)(object)p.CustomProperties).TryGetValue((object)"CFS.POTP.Version", out value) || !object.Equals(value, "0.1.1-mpfix5")
				select p.NickName).ToArray();
			waitingReason = ((array.Length == 0) ? "" : ("Waiting for matching mod: " + string.Join(", ", array)));
			return array.Length == 0;
		}

		private bool InClimb()
		{
			if (PhotonNetwork.InRoom && MapHandler.ExistsAndInitialized && Object.op_Implicit((Object)(object)Character.localCharacter))
			{
				return !Character.localCharacter.inAirport;
			}
			return false;
		}

		private MapHandler ResolveMapFast()
		{
			if (Object.op_Implicit((Object)(object)cachedMap))
			{
				return cachedMap;
			}
			if (Time.unscaledTime < nextMapLookup)
			{
				return null;
			}
			nextMapLookup = Time.unscaledTime + 1f;
			cachedMap = Object.FindFirstObjectByType<MapHandler>();
			return cachedMap;
		}

		private void Update()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_041c: Expected I4, but got Unknown
			if (!PhotonNetwork.InRoom)
			{
				if (active)
				{
					ClearLocal();
				}
				advertised = false;
				cachedMap = null;
				cachedAllModded = false;
				masterId = 0;
				mapId = 0;
				return;
			}
			if (!advertised)
			{
				PhotonNetwork.LocalPlayer.SetCustomProperties(new Hashtable { [(object)"CFS.POTP.Version"] = "0.1.1-mpfix5" }, (Hashtable)null, (WebFlags)null);
				advertised = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("MP ADVERTISE actor=" + PhotonNetwork.LocalPlayer.ActorNumber + " build=0.1.1-mpfix5 master=" + PhotonNetwork.MasterClient.ActorNumber + " isMaster=" + PhotonNetwork.IsMasterClient));
			}
			int actorNumber = PhotonNetwork.MasterClient.ActorNumber;
			if (masterId != 0 && masterId != actorNumber)
			{
				if (Host)
				{
					DestroyEnemy();
				}
				ClearLocal();
				mapId = 0;
				Log("Host changed: curse progress restarts; PEAK match continues.");
			}
			masterId = actorNumber;
			if (VerboseNetworkLogging.Value && Time.unscaledTime >= nextNetworkHeartbeat)
			{
				nextNetworkHeartbeat = Time.unscaledTime + 5f;
				LogNetworkSummary("heartbeat");
			}
			if (!InClimb())
			{
				if (active)
				{
					if (Host)
					{
						DestroyEnemy();
					}
					ClearLocal();
				}
				mapId = 0;
				return;
			}
			MapHandler val = ResolveMapFast();
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			if (mapId != 0 && mapId != ((Object)val).GetInstanceID())
			{
				if (Host)
				{
					DestroyEnemy();
				}
				ClearLocal();
			}
			mapId = ((Object)val).GetInstanceID();
			if (Host && Time.unscaledTime >= nextModRosterCheck)
			{
				nextModRosterCheck = Time.unscaledTime + 0.5f;
				cachedAllModded = AllModded();
			}
			if (Host && !cachedAllModded)
			{
				if (active)
				{
					DestroyEnemy();
					ClearLocal();
				}
				notice = waitingReason;
				return;
			}
			if (Host && !active)
			{
				Begin();
			}
			if (!Host && Time.unscaledTime >= nextRoomPoll)
			{
				bool flag = !active || lastSnapshot <= 0f || Time.unscaledTime - lastSnapshot > 2.5f;
				nextRoomPoll = Time.unscaledTime + (flag ? 0.35f : 1.5f);
				if (flag)
				{
					TryApplyRoomSnapshot();
				}
			}
			if (Host && Time.unscaledTime >= nextFallbackPoll)
			{
				nextFallbackPoll = Time.unscaledTime + 0.1f;
				PollPageUseFallbacks();
			}
			if (!Host && Time.unscaledTime >= nextRequest)
			{
				nextRequest = Time.unscaledTime + 2f;
				Send(new Message
				{
					kind = "sync"
				}, (ReceiverGroup)2);
			}
			if (!Host && active && Time.unscaledTime - lastSnapshot > 5f)
			{
				ClearLocal();
			}
			if (DebugKeys.Value && Keyboard.current != null && ((ButtonControl)Keyboard.current.f6Key).wasPressedThisFrame)
			{
				LogNetworkSummary("F6");
				world.Diagnostics();
			}
			if (!active)
			{
				pagePrompt?.SetVisible(value: false);
				return;
			}
			world.Refresh(State);
			if (Time.unscaledTime >= nextPromptProbe)
			{
				nextPromptProbe = Time.unscaledTime + 1f / 15f;
				pagePrompt?.SetVisible(world.LookingAt(State) != null);
			}
			UpdateNetworkPresentation();
			if (Host)
			{
				if (Time.time >= tick)
				{
					tick = Time.time + 5f;
					int num = (int)MapHandler.CurrentSegmentNumber;
					if (num != lastSegment)
					{
						EnterSegment(num);
					}
					SeedPages(num);
				}
				Scoutmaster val2 = ResolveEnemy();
				if ((State.phase == "Watching" || State.phase == "Hunt") && !Object.op_Implicit((Object)(object)val2))
				{
					EndEvent();
				}
				else if (Object.op_Implicit((Object)(object)val2) && Time.time >= eventEnd)
				{
					EndEvent();
				}
				if (State.pages > 0 && !Object.op_Implicit((Object)(object)ResolveEnemy()) && Time.time >= eventAt)
				{
					StartEvent(forceHunt: false);
				}
				if (Time.unscaledTime >= broadcast)
				{
					broadcast = Time.unscaledTime + 2f;
					Publish();
				}
			}
			if (Keyboard.current != null && ((ButtonControl)Keyboard.current.fKey).wasPressedThisFrame && Time.unscaledTime >= pendingUntil)
			{
				Page page = world.LookingAt(State);
				if (page != null)
				{
					pendingUntil = Time.unscaledTime + 1f;
					if (Host)
					{
						Collect(page.id, PhotonNetwork.LocalPlayer.ActorNumber);
					}
					else
					{
						RequestPageUse(page.id);
					}
				}
			}
			if (DebugKeys.Value)
			{
				Keys();
			}
			SafeUpdateWatchGazeEffects();
		}

		private void Begin()
		{
			Scoutmaster[] array = Object.FindObjectsByType<Scoutmaster>((FindObjectsSortMode)0);
			foreach (Scoutmaster val in array)
			{
				if (IsOurEnemy(val))
				{
					DestroyEnemyObject(((Component)val).gameObject);
				}
			}
			localEnemy = null;
			localTarget = null;
			active = true;
			State = new RunState
			{
				run = System.Guid.NewGuid().ToString("N"),
				bonusPerPage = Bonus.Value
			};
			attempts.Clear();
			knocked.Clear();
			mercyUsedThisSegment.Clear();
			lastUseFallback.Clear();
			lastRemoteAttackSerial = 0;
			eventAt = Time.time + 12f;
			tick = 0f;
			lastSegment = -1;
			Log("New curse started. " + PageCount.Value + " pages per biome; page count and regen reset at each segment transition. F to activate.");
			Publish();
		}

		private void ClearLocal()
		{
			localEnemy = null;
			localTarget = null;
			active = false;
			State = new RunState();
			world.Clear();
			attempts.Clear();
			knocked.Clear();
			mercyUsedThisSegment.Clear();
			requests.Clear();
			lastUseFallback.Clear();
			lastRemoteAttackSerial = 0;
			lastSnapshot = 0f;
			watchDrowsyPending = 0f;
			watchEffectFaulted = false;
			lastSegment = -1;
		}

		private void EnterSegment(int segment)
		{
			if (Object.op_Implicit((Object)(object)ResolveEnemy()))
			{
				DestroyEnemy();
			}
			world.Clear();
			State.ResetSegment(segment);
			attempts.Clear();
			knocked.Clear();
			mercyUsedThisSegment.Clear();
			lastRemoteAttackSerial = 0;
			attackGrace = 0f;
			moveCheck = 0f;
			huntDiagnostic = "";
			watchDrowsyPending = 0f;
			watchEffectFaulted = false;
			eventEnd = 0f;
			eventAt = Time.time + 12f;
			lastSegment = segment;
			Log("Entered segment " + segment + ": page count and stamina regen reset; seeding " + PageCount.Value + " pages.");
			Publish();
		}

		private void SeedPages(int segment)
		{
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: 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)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			if (!Alive(Character.localCharacter))
			{
				return;
			}
			int num = State.worldPages.Count((Page p) => p.segment == segment);
			if (num >= PageCount.Value || State.worldPages.Count >= 96)
			{
				return;
			}
			attempts.TryGetValue(segment, out var value);
			if (value >= 120)
			{
				return;
			}
			attempts[segment] = value + 1;
			MapSegment currentMapSegment = MapHandler.CurrentMapSegment;
			GameObject val = ((currentMapSegment != null) ? currentMapSegment.segmentParent : null);
			Transform root = (Object.op_Implicit((Object)(object)val) ? val.transform : null);
			Campfire currentCampfire = MapHandler.CurrentCampfire;
			List<Vector3> list = (from p in State.worldPages
				where p.segment == segment
				select p.position).ToList();
			if (Object.op_Implicit((Object)(object)currentCampfire))
			{
				list.Add(((Component)currentCampfire).transform.position);
			}
			float[] array = new float[3] { 12f, 9f, 6f };
			for (int num2 = 0; num2 < array.Length; num2++)
			{
				float spacing = array[num2];
				for (int num3 = 0; num3 < 60; num3++)
				{
					if (num >= PageCount.Value)
					{
						break;
					}
					if (world.BiomeGround(root, list, spacing, out var pos) && (!Object.op_Implicit((Object)(object)currentCampfire) || !(Vector3.Distance(pos, ((Component)currentCampfire).transform.position) < 8f)) && !State.worldPages.Any((Page p) => p.segment == segment && Vector3.Distance(p.position, pos) < spacing))
					{
						State.worldPages.Add(new Page
						{
							id = State.worldPages.Count + 1,
							segment = segment,
							position = pos
						});
						list.Add(pos);
						num++;
						((BaseUnityPlugin)this).Logger.LogInfo((object)("PAGE placed id=" + State.worldPages.Count + " segment=" + segment + " pos=" + ((object)Unsafe.As<Vector3, Vector3>(ref pos)/*cast due to .constrained prefix*/).ToString() + " spacingPass=" + spacing.ToString("0") + "m"));
					}
				}
				if (num >= PageCount.Value)
				{
					break;
				}
			}
			Log("Segment " + segment + ": " + num + "/" + PageCount.Value + " pages placed across biome.");
			Publish();
		}

		private void Collect(int id, int actor)
		{
			//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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			if (!Host || !active)
			{
				return;
			}
			Page page = State.worldPages.Find((Page x) => x.id == id);
			Character val = ((IEnumerable<Character>)Character.AllCharacters).FirstOrDefault((Func<Character, bool>)((Character x) => Alive(x) && ((MonoBehaviourPun)x).photonView.OwnerActorNr == actor));
			if (page != null && !page.used && Object.op_Implicit((Object)(object)val) && !(Vector3.Distance(val.Center, page.position) > 4f) && World.ClearSight(val.Head, page.position) && State.Collect(id, actor))
			{
				if (State.pages == 1)
				{
					eventAt = Time.time + Random.Range(6f, 12f);
				}
				Log("Page " + id + " activated. Shared threat: " + State.pages + "; collector regen +" + ((float)State.Owned(actor) * State.bonusPerPage * 100f).ToString("0") + "%.");
				Publish();
			}
		}

		private void SendJson(string json, ReceiverGroup group, int actor = 0)
		{
			//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_0022: 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_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (actor == 0)
			{
				obj = (object)new RaiseEventOptions
				{
					Receivers = group
				};
			}
			else
			{
				RaiseEventOptions val = new RaiseEventOptions();
				val.TargetActors = new int[1] { actor };
				obj = val;
			}
			RaiseEventOptions val2 = (RaiseEventOptions)obj;
			PhotonNetwork.RaiseEvent((byte)179, (object)json, val2, SendOptions.SendReliable);
		}

		private void Send(Message m, ReceiverGroup group, int actor = 0)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			SendJson(JsonUtility.ToJson((object)m), group, actor);
		}

		private void Publish(int actor = 0)
		{
			//IL_0083: 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_009d: Expected O, but got Unknown
			if (!Host || !active)
			{
				return;
			}
			State.revision++;
			string text = StateWire.Encode(State);
			if (string.IsNullOrEmpty(text))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"MP PUBLISH aborted: StateWire.Encode returned an empty payload.");
				return;
			}
			string text2 = JsonUtility.ToJson((object)new Message
			{
				kind = "state",
				run = State.run,
				payload = text
			});
			if (PhotonNetwork.CurrentRoom != null)
			{
				PhotonNetwork.CurrentRoom.SetCustomProperties(new Hashtable { [(object)"CFS.POTP.State"] = text2 }, (Hashtable)null, (WebFlags)null);
			}
			if (VerboseNetworkLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("MP PUBLISH rev=" + State.revision + " pages=" + State.pages + " worldPages=" + ((State.worldPages == null) ? (-1) : State.worldPages.Count) + " phase=" + State.phase + " enemy=" + State.enemy + " target=" + State.target + " payloadLen=" + text.Length + " jsonLen=" + text2.Length + " targetActor=" + actor));
			}
			SendJson(text2, (ReceiverGroup)0, actor);
		}

		private bool ApplyStateSnapshot(RunState incoming, string source)
		{
			if (incoming == null || incoming.worldPages == null || incoming.worldPages.Count > 96 || string.IsNullOrEmpty(incoming.run))
			{
				return false;
			}
			if (State.run == incoming.run && incoming.revision <= State.revision)
			{
				lastSnapshot = Time.unscaledTime;
				return false;
			}
			bool num = State.run != incoming.run;
			bool flag = State.segment != incoming.segment;
			if (num || flag)
			{
				world.Clear();
				lastRemoteAttackSerial = 0;
			}
			State = incoming;
			active = true;
			lastSnapshot = Time.unscaledTime;
			if (VerboseNetworkLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("MP STATE applied via " + source + " rev=" + State.revision + " segment=" + State.segment + " pages=" + State.pages + " worldPages=" + State.worldPages.Count + " phase=" + State.phase + " enemy=" + State.enemy + " target=" + State.target));
			}
			return true;
		}

		private void TryApplyRoomSnapshot()
		{
			if (Host || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null || !((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"CFS.POTP.State", out object value))
			{
				return;
			}
			if (!(value is string text))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("MP ROOM SNAPSHOT rejected: room property exists but is " + ((value == null) ? "null" : value.GetType().FullName)));
				return;
			}
			if (string.IsNullOrEmpty(text) || text.Length > 100000)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("MP ROOM SNAPSHOT rejected: invalid length=" + (text?.Length ?? (-1))));
				return;
			}
			Message message;
			try
			{
				message = JsonUtility.FromJson<Message>(text);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("MP ROOM SNAPSHOT JSON failed: " + ex.GetBaseException().Message));
				return;
			}
			if (message == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"MP ROOM SNAPSHOT rejected: deserialized message is null.");
				return;
			}
			if (message.mod != "CFS.PagesOfThePeak.3")
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("MP ROOM SNAPSHOT rejected: protocol=" + (message.mod ?? "<null>") + " expected=CFS.PagesOfThePeak.3"));
				return;
			}
			if (message.kind != "state")
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("MP ROOM SNAPSHOT rejected: kind=" + (message.kind ?? "<null>")));
				return;
			}
			if (string.IsNullOrEmpty(message.payload))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"MP ROOM SNAPSHOT rejected: payload is empty.");
				return;
			}
			RunState runState = StateWire.Decode(message.payload);
			if (runState == null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("MP ROOM SNAPSHOT rejected: StateWire decode failed. payloadLen=" + message.payload.Length));
			}
			else
			{
				ApplyStateSnapshot(runState, "room-cache");
			}
		}

		private void RequestPageUse(int pageId)
		{
			//IL_00a8: 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_00c2: Expected O, but got Unknown
			if (!Host && active && !string.IsNullOrEmpty(State.run))
			{
				Send(new Message
				{
					kind = "use",
					run = State.run,
					id = pageId
				}, (ReceiverGroup)2);
				useNonce++;
				string text = State.run + "|" + pageId + "|" + useNonce;
				PhotonNetwork.LocalPlayer.SetCustomProperties(new Hashtable { [(object)"CFS.POTP.Use"] = text }, (Hashtable)null, (WebFlags)null);
				if (VerboseNetworkLogging.Value)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("MP PAGE request id=" + pageId + " run=" + State.run + " nonce=" + useNonce));
				}
			}
		}

		private void PollPageUseFallbacks()
		{
			if (!Host || !active)
			{
				return;
			}
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (val != null && val.ActorNumber != PhotonNetwork.LocalPlayer.ActorNumber && ((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"CFS.POTP.Use", out object value) && value is string text && !string.IsNullOrEmpty(text) && (!lastUseFallback.TryGetValue(val.ActorNumber, out var value2) || !(value2 == text)))
				{
					lastUseFallback[val.ActorNumber] = text;
					string[] array = text.Split('|');
					if (array.Length == 3 && !(array[0] != State.run) && int.TryParse(array[1], out var result))
					{
						Collect(result, val.ActorNumber);
					}
				}
			}
		}

		private void UpdateNetworkPresentation()
		{
			if (!active)
			{
				return;
			}
			Scoutmaster val = ResolveEnemy();
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			AttachCustomVisual(val);
			if (!Host)
			{
				bool flag = State.phase == "Hunt";
				Character component = ((Component)val).GetComponent<Character>();
				bool runPreferred = flag && State.pages >= HuntSprintAtPages.Value && (!Object.op_Implicit((Object)(object)component) || (Object)(object)component.data == (Object)null || !component.data.isClimbingAnything);
				UpdateCustomVisualMotion(val, runPreferred);
				UpdateCustomVisualHuntAudio(val, flag);
				if (State.attackSerial > lastRemoteAttackSerial)
				{
					lastRemoteAttackSerial = State.attackSerial;
					TriggerCustomVisualAttack(val);
				}
			}
		}

		public void OnEvent(EventData e)
		{
			if (e.Code != 179 || !(e.CustomData is string { Length: <=100000 } text) || !PhotonNetwork.InRoom)
			{
				return;
			}
			if (VerboseNetworkLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("MP EVENT received sender=" + e.Sender + " bytes=" + text.Length + " host=" + Host));
			}
			Message message;
			try
			{
				message = JsonUtility.FromJson<Message>(text);
			}
			catch
			{
				return;
			}
			if (message == null || message.mod != "CFS.PagesOfThePeak.3")
			{
				return;
			}
			if (VerboseNetworkLogging.Value)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("MP MESSAGE parsed kind=" + (message.kind ?? "<null>") + " run=" + (message.run ?? "<null>") + " payloadLen=" + ((message.payload == null) ? (-1) : message.payload.Length)));
			}
			if (Host && (message.kind == "sync" || message.kind == "use"))
			{
				if (active && AllModded() && (!requests.TryGetValue(e.Sender, out var value) || !(Time.unscaledTime - value < 0.15f)))
				{
					requests[e.Sender] = Time.unscaledTime;
					if (message.kind == "sync")
					{
						Publish(e.Sender);
					}
					else if (message.run == State.run)
					{
						Collect(message.id, e.Sender);
					}
				}
			}
			else
			{
				if (e.Sender != PhotonNetwork.MasterClient.ActorNumber || Host || !InClimb())
				{
					return;
				}
				if (message.kind == "state")
				{
					if (string.IsNullOrEmpty(message.payload))
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)"MP EVENT state rejected: payload is empty.");
						return;
					}
					RunState runState = StateWire.Decode(message.payload);
					if (runState == null)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("MP EVENT state rejected: StateWire decode failed. payloadLen=" + message.payload.Length));
					}
					else
					{
						ApplyStateSnapshot(runState, "RaiseEvent");
					}
				}
				else
				{
					if ((!(message.kind == "down") && !(message.kind == "kill")) || !active || !(message.run == State.run))
					{
						return;
					}
					Character localCharacter = Character.localCharacter;
					if (!Alive(localCharacter) || !Object.op_Implicit((Object)(object)((MonoBehaviourPun)localCharacter).photonView) || ((MonoBehaviourPun)localCharacter).photonView.ViewID != message.id)
					{
						return;
					}
					if (message.kind == "kill")
					{
						if (!KillCharacterCompat(localCharacter))
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)"Full-death API was unavailable; falling back to knockout.");
							localCharacter.PassOutInstantly();
						}
					}
					else
					{
						localCharacter.PassOutInstantly();
					}
				}
			}
		}

		private void LogNetworkSummary(string reason)
		{
			try
			{
				bool inRoom = PhotonNetwork.InRoom;
				int num = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0);
				int num2 = ((inRoom && PhotonNetwork.MasterClient != null) ? PhotonNetwork.MasterClient.ActorNumber : 0);
				string text = "<none>";
				if (PhotonNetwork.LocalPlayer != null && ((Dictionary<object, object>)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"CFS.POTP.Version", out object value))
				{
					text = ((value == null) ? "<null>" : value.ToString());
				}
				bool flag = false;
				int num3 = 0;
				string text2 = "<none>";
				if (inRoom && PhotonNetwork.CurrentRoom != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).TryGetValue((object)"CFS.POTP.State", out object value2))
				{
					flag = true;
					text2 = ((value2 == null) ? "<null>" : value2.GetType().FullName);
					if (value2 is string text3)
					{
						num3 = text3.Length;
					}
				}
				List<string> list = new List<string>();
				if (inRoom)
				{
					Player[] playerList = PhotonNetwork.PlayerList;
					foreach (Player val in playerList)
					{
						string text4 = "<none>";
						if (((Dictionary<object, object>)(object)val.CustomProperties).TryGetValue((object)"CFS.POTP.Version", out object value3))
						{
							text4 = ((value3 == null) ? "<null>" : value3.ToString());
						}
						list.Add(val.ActorNumber + ":" + val.NickName + "=" + text4);
					}
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("MP DIAG [" + reason + "] build=0.1.1-mpfix5 inRoom=" + inRoom + " actor=" + num + " master=" + num2 + " isMaster=" + PhotonNetwork.IsMasterClient + " inClimb=" + InClimb() + " active=" + active + " advertised=" + advertised + " localProp=" + text + " roomState=" + flag + " roomStateType=" + text2 + " roomStateLen=" + num3 + " stateRun=" + (string.IsNullOrEmpty(State.run) ? "<none>" : State.run) + " rev=" + State.revision + " segment=" + State.segment + " pages=" + State.pages + " worldPages=" + ((State.worldPages == null) ? (-1) : State.worldPages.Count) + " phase=" + State.phase + " lastSnapshotAge=" + ((lastSnapshot <= 0f) ? "never" : ((Time.unscaledTime - lastSnapshot).ToString("0.00") + "s")) + " peers=[" + string.Join(", ", list) + "]"));
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("MP DIAG failed: " + ex.GetBaseException().Message));
			}
		}

		private Scoutmaster ResolveEnemy()
		{
			if (State.enemy != 0)
			{
				PhotonView val = PhotonView.Find(State.enemy);
				if (Object.op_Implicit((Object)(object)val))
				{
					Scoutmaster component = ((Component)val).GetComponent<Scoutmaster>();
					if (Object.op_Implicit((Object)(object)component) && IsOurEnemy(component))
					{
						return component;
					}
				}
			}
			if (Object.op_Implicit((Object)(object)localEnemy))
			{
				return localEnemy;
			}
			return null;
		}

		private Character ResolveTarget()
		{
			if (State.target != 0)
			{
				Character val = ((IEnumerable<Character>)Character.AllCharacters).FirstOrDefault((Func<Character, bool>)((Character c) => Alive(c) && Object.op_Implicit((Object)(object)((MonoBehaviourPun)c).photonView) && ((MonoBehaviourPun)c).photonView.ViewID == State.target));
				if (Object.op_Implicit((Object)(object)val))
				{
					return val;
				}
			}
			if (Object.op_Implicit((Object)(object)localTarget) && Alive(localTarget))
			{
				return localTarget;
			}
			if (PhotonNetwork.OfflineMode && Alive(Character.localCharacter))
			{
				return Character.localCharacter;
			}
			return null;
		}

		private bool HasEnemy()
		{
			return Object.op_Implicit((Object)(object)ResolveEnemy());
		}

		private void DestroyEnemyObject(GameObject go)
		{
			if (!Object.op_Implicit((Object)(object)go))
			{
				return;
			}
			try
			{
				PhotonView component = go.GetComponent<PhotonView>();
				if (PhotonNetwork.InRoom && Object.op_Implicit((Object)(object)component) && component.ViewID != 0)
				{
					PhotonNetwork.Destroy(go);
				}
				else
				{
					Object.Destroy((Object)(object)go);
				}
			}
			catch
			{
				if (Object.op_Implicit((Object)(object)go))
				{
					Object.Destroy((Object)(object)go);
				}
			}
		}

		private void LoadSlenderBundle()
		{
			if (!EnableCustomSlender.Value)
			{
				return;
			}
			try
			{
				string[] files = Directory.GetFiles(Paths.PluginPath, "pagesofthepeak_slender", SearchOption.AllDirectories);
				if (files == null || files.Length == 0)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Custom Slender model enabled, but pagesofthepeak_slender was not found under BepInEx/plugins. Native Scoutmaster visual will be used.");
					return;
				}
				slenderBundlePath = files[0];
				slenderBundle = AssetBundle.LoadFromFile(slenderBundlePath);
				if ((Object)(object)slenderBundle == (Object)null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not load Slender AssetBundle: " + slenderBundlePath + ". Native Scoutmaster visual will be used."));
					return;
				}
				string[] allAssetNames = slenderBundle.GetAllAssetNames();
				string text = allAssetNames.FirstOrDefault((string n) => n.EndsWith("/slender.prefab", StringComparison.OrdinalIgnoreCase));
				if (string.IsNullOrEmpty(text))
				{
					text = allAssetNames.FirstOrDefault((string n) => n.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase) && n.IndexOf("slender", StringComparison.OrdinalIgnoreCase) >= 0);
				}
				if (string.IsNullOrEmpty(text))
				{
					text = allAssetNames.FirstOrDefault((string n) => n.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase));
				}
				if (string.IsNullOrEmpty(text))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Slender AssetBundle loaded, but it contains no prefab. Assets: " + string.Join(", ", allAssetNames)));
					slenderBundle.Unload(false);
					slenderBundle = null;
					return;
				}
				slenderPrefab = slenderBundle.LoadAsset<GameObject>(text);
				if (!Object.op_Implicit((Object)(object)slenderPrefab))
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Slender prefab could not be loaded from AssetBundle entry: " + text));
					slenderBundle.Unload(false);
					slenderBundle = null;
					return;
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Custom Slender bundle ready: " + Path.GetFileName(slenderBundlePath) + " | prefab=" + text));
				Animator componentInChildren = slenderPrefab.GetComponentInChildren<Animator>(true);
				if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)componentInChildren.runtimeAnimatorController))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Slender animation clips: " + string.Join(", ", (from c in componentInChildren.runtimeAnimatorController.animationClips
						where Object.op_Implicit((Object)(object)c)
						select ((Object)c).name).Distinct().ToArray())));
					((BaseUnityPlugin)this).Logger.LogInfo((object)("Slender animator parameters: " + string.Join(", ", componentInChildren.parameters.Select((AnimatorControllerParameter p) => p.name + ":" + ((object)p.type/*cast due to .constrained prefix*/).ToString()).ToArray())));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Custom Slender bundle load failed; native Scoutmaster visual will be used. " + ex.GetBaseException().Message));
				slenderPrefab = null;
				if ((Object)(object)slenderBundle != (Object)null)
				{
					slenderBundle.Unload(false);
					slenderBundle = null;
				}
			}
		}

		private void FixSlenderMaterials(GameObject visual)
		{
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Expected O, but got Unknown
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Expected O, but got Unknown
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)visual))
			{
				return;
			}
			bool flag = UseSlenderBlackoutRendering();
			Shader val = Shader.Find("Universal Render Pipeline/Lit");
			if (!Object.op_Implicit((Object)(object)val))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"URP/Lit shader was not found. Slender materials could not be forced to scene lighting.");
				return;
			}
			Dictionary<int, Material> dictionary = new Dictionary<int, Material>();
			Renderer[] componentsInChildren = visual.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!Object.op_Implicit((Object)(object)val2))
				{
					continue;
				}
				val2.receiveShadows = true;
				val2.shadowCastingMode = (ShadowCastingMode)1;
				if (DisableSlenderEnvironmentReflections.Value && flag)
				{
					val2.reflectionProbeUsage = (ReflectionProbeUsage)0;
					val2.lightProbeUsage = (LightProbeUsage)0;
				}
				else
				{
					val2.reflectionProbeUsage = (ReflectionProbeUsage)1;
					val2.lightProbeUsage = (LightProbeUsage)1;
				}
				Material[] sharedMaterials = val2.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Material val3 = sharedMaterials[j];
					if (!Object.op_Implicit((Object)(object)val3))
					{
						continue;
					}
					if (dictionary.TryGetValue(((Object)val3).GetInstanceID(), out var value) && Object.op_Implicit((Object)(object)value))
					{
						sharedMaterials[j] = value;
						continue;
					}
					Texture val4 = null;
					Texture val5 = null;
					Texture val6 = null;
					Texture val7 = null;
					Color val8 = Color.white;
					float num = 0.35f;
					float num2 = 0f;
					if (val3.HasProperty("_BaseMap"))
					{
						val4 = val3.GetTexture("_BaseMap");
					}
					if (!Object.op_Implicit((Object)(object)val4) && val3.HasProperty("_MainTex"))
					{
						val4 = val3.GetTexture("_MainTex");
					}
					if (val3.HasProperty("_BumpMap"))
					{
						val5 = val3.GetTexture("_BumpMap");
					}
					if (val3.HasProperty("_MetallicGlossMap"))
					{
						val6 = val3.GetTexture("_MetallicGlossMap");
					}
					if (val3.HasProperty("_OcclusionMap"))
					{
						val7 = val3.GetTexture("_OcclusionMap");
					}
					if (val3.HasProperty("_BaseColor"))
					{
						val8 = val3.GetColor("_BaseColor");
					}
					else if (val3.HasProperty("_Color"))
					{
						val8 = val3.GetColor("_Color");
					}
					if (val3.HasProperty("_Smoothness"))
					{
						num = val3.GetFloat("_Smoothness");
					}
					else if (val3.HasProperty("_Glossiness"))
					{
						num = val3.GetFloat("_Glossiness");
					}
					if (val3.HasProperty("_Metallic"))
					{
						num2 = val3.GetFloat("_Metallic");
					}
					val8.r *= SlenderAlbedoMultiplier.Value;
					val8.g *= SlenderAlbedoMultiplier.Value;
					val8.b *= SlenderAlbedoMultiplier.Value;
					Material val9 = ((!ForceSlenderLitMaterials.Value) ? new Material(val3) : new Material(val));
					((Object)val9).name = ((Object)val3).name + "_POTP_Lit";
					if (val9.HasProperty("_BaseMap") && Object.op_Implicit((Object)(object)val4))
					{
						val9.SetTexture("_BaseMap", val4);
					}
					if (val9.HasProperty("_BaseColor"))
					{
						val9.SetColor("_BaseColor", val8);
					}
					if (val9.HasProperty("_Smoothness"))
					{
						val9.SetFloat("_Smoothness", Mathf.Clamp01(num));
					}
					if (val9.HasProperty("_Metallic"))
					{
						val9.SetFloat("_Metallic", (DisableSlenderEnvironmentReflections.Value && flag) ? 0f : Mathf.Clamp01(num2));
					}
					if (DisableSlenderEnvironmentReflections.Value && flag)
					{
						if (val9.HasProperty("_EnvironmentReflections"))
						{
							val9.SetFloat("_EnvironmentReflections", 0f);
						}
						if (val9.HasProperty("_SpecularHighlights"))
						{
							val9.SetFloat("_SpecularHighlights", 0f);
						}
						if (val9.HasProperty("_Smoothness"))
						{
							val9.SetFloat("_Smoothness", Mathf.Min(0.12f, val9.GetFloat("_Smoothness")));
						}
						val9.EnableKeyword("_ENVIRONMENTREFLECTIONS_OFF");
						val9.EnableKeyword("_SPECULARHIGHLIGHTS_OFF");
					}
					else
					{
						if (val9.HasProperty("_EnvironmentReflections"))
						{
							val9.SetFloat("_EnvironmentReflections", 1f);
						}
						if (val9.HasProperty("_SpecularHighlights"))
						{
							val9.SetFloat("_SpecularHighlights", 1f);
						}
						val9.DisableKeyword("_ENVIRONMENTREFLECTIONS_OFF");
						val9.DisableKeyword("_SPECULARHIGHLIGHTS_OFF");
					}
					if (Object.op_Implicit((Object)(object)val5) && val9.HasProperty("_BumpMap"))
					{
						val9.SetTexture("_BumpMap", val5);
						val9.EnableKeyword("_NORMALMAP");
					}
					if (Object.op_Implicit((Object)(object)val6) && val9.HasProperty("_MetallicGlossMap"))
					{
						val9.SetTexture("_MetallicGlossMap", val6);
						val9.EnableKeyword("_METALLICSPECGLOSSMAP");
					}
					if (Object.op_Implicit((Object)(object)val7) && val9.HasProperty("_OcclusionMap"))
					{
						val9.SetTexture("_OcclusionMap", val7);
						val9.EnableKeyword("_OCCLUSIONMAP");
					}
					if (DisableSlenderEmission.Value)
					{
						if (val9.HasProperty("_EmissionColor"))
						{
							val9.SetColor("_EmissionColor", Color.black);
						}
						if (val9.HasProperty("_EmissionMap"))
						{
							val9.SetTexture("_EmissionMap", (Texture)null);
						}
						val9.DisableKeyword("_EMISSION");
						val9.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)4;
					}
					if (val9.HasProperty("_Surface"))
					{
						val9.SetFloat("_Surface", 0f);
					}
					if (val9.HasProperty("_AlphaClip"))
					{
						val9.SetFloat("_AlphaClip", 0f);
					}
					val9.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
					val9.DisableKeyword("_ALPHATEST_ON");
					val9.renderQueue = -1;
					dictionary[((Object)val3).GetInstanceID()] = val9;
					sharedMaterials[j] = val9;
				}
				val2.sharedMaterials = sharedMaterials;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Custom Slender materials sanitized: " + dictionary.Count + " material(s), lit=" + ForceSlenderLitMaterials.Value + ", emissionOff=" + DisableSlenderEmission.Value + ", reflectionsOff=" + DisableSlenderEnvironmentReflections.Value + ", albedo=" + SlenderAlbedoMultiplier.Value.ToString("0.00")));
		}

		private bool DetectPitchBlackMod()
		{
			try
			{
				foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
				{
					PluginInfo value = pluginInfo.Value;
					BepInPlugin val = ((value != null) ? value.Metadata : null);
					string text = ((val != null) ? val.GUID : "");
					string text2 = ((val != null) ? val.Name : "");
					string text3 = pluginInfo.Key ?? "";
					if ((text + " " + text2 + " " + text3).Replace(" ", "").Replace("_", "").Replace("-", "")
						.ToLowerInvariant()
						.Contains("pitchblack"))
					{
						return true;
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Automatic Pitch Black detection failed safely: " + ex.GetBaseException().Message));
			}
			return false;
		}

		internal bool UseSlenderBlackoutRendering()
		{
			bool flag;
			if (SlenderAutoLighting != null && SlenderAutoLighting.Value)
			{
				if (Time.unscaledTime >= nextSlenderLightingDetection)
				{
					nextSlenderLightingDetection = Time.unscaledTime + 2f;
					cachedPitchBlackDetected = DetectPitchBlackMod();
				}
				flag = cachedPitchBlackDetected;
			}
			else
			{
				flag = SlenderFlashlightRevealMode != null && SlenderFlashlightRevealMode.Value;
			}
			if (!lastReportedSlenderBlackoutMode.HasValue || lastReportedSlenderBlackoutMode.Value != flag)
			{
				lastReportedSlenderBlackoutMode = flag;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Slender lighting mode: " + (flag ? "BLACKOUT / flashlight reveal" : "NORMAL PEAK day-night lighting") + " | Auto=" + (SlenderAutoLighting != null && SlenderAutoLighting.Value) + " | PitchBlackDetected=" + cachedPitchBlackDetected));
			}
			return flag;
		}

		internal float FlashlightExposureAt(Vector3 worldPoint)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)flashlight != (Object)null))
			{
				return 0f;
			}
			return flashlight.BeamExposureAt(worldPoint);
		}

		internal void AttachCustomVisual(Scoutmaster scout)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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)
			//IL_00c4: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if (!EnableCustomSlender.Value || !Object.op_Implicit((Object)(object)slenderPrefab) || !Object.op_Implicit((Object)(object)scout))
			{
				return;
			}
			int instanceID = ((Object)scout).GetInstanceID();
			if (slenderVisuals.TryGetValue(instanceID, out var value) && Object.op_Implicit((Object)(object)value))
			{
				return;
			}
			Renderer[] array = (from r in ((Component)scout).GetComponentsInChildren<Renderer>(true)
				where Object.op_Implicit((Object)(object)r)
				select r).ToArray();
			try
			{
				GameObject val = Object.Instantiate<GameObject>(slenderPrefab);
				if (!Object.op_Implicit((Object)(object)val))
				{
					throw new Exception("Instantiate returned null");
				}
				((Object)val).name = "POTP_CustomSlenderVisual";
				val.transform.position = ((Component)scout).transform.position + Vector3.up * SlenderVisualYOffset.Value;
				val.transform.rotation = ((Component)scout).transform.rotation * Quaternion.Euler(0f, SlenderVisualYaw.Value, 0f);
				val.transform.localScale = Vector3.one * SlenderVisualScale.Value;
				Collider[] componentsInChildren = val.GetComponentsInChildren<Collider>(true);
				foreach (Collider val2 in componentsInChildren)