Decompiled source of Sense of Direction v1.1.5

SenseOfDirection.dll

Decompiled 18 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using SenseOfDirection.BelltowerIndicator;
using SenseOfDirection.CampfireIndicator;
using SenseOfDirection.Common;
using SenseOfDirection.Compass;
using SenseOfDirection.CompassItems;
using SenseOfDirection.Compatibility;
using SenseOfDirection.GhostFreeCam;
using SenseOfDirection.Indicators;
using SenseOfDirection.ItemPings;
using SenseOfDirection.Labels;
using SenseOfDirection.LuggagePing;
using SenseOfDirection.Pings;
using SenseOfDirection.PirateCompass;
using SenseOfDirection.ScoutStatueIndicator;
using SenseOfDirection.Ui;
using SenseOfDirection.Ui.Localization;
using TMPro;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Localization;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.ControllerSupport;
using Zorro.Core;
using Zorro.Settings;
using Zorro.Settings.UI;
using pworld.Scripts.Extensions;

[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("SenseOfDirection")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.5.0")]
[assembly: AssemblyInformationalVersion("1.1.5+44914b0cb212bb38e002814a20c7ca9853f11171")]
[assembly: AssemblyProduct("SenseOfDirection")]
[assembly: AssemblyTitle("SenseOfDirection")]
[assembly: AssemblyVersion("1.1.5.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[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 SenseOfDirection
{
	[BepInPlugin("OnlyCook.SenseOfDirection", "Sense of Direction", "1.1.5")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		internal PluginConfig Cfg { get; private set; }

		internal ManualLogSource Log => ((BaseUnityPlugin)this).Logger;

		private void Awake()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			Instance = this;
			Cfg = new PluginConfig(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("OnlyCook.SenseOfDirection");
			Wire("PlayerLabelPatches", delegate
			{
				PlayerLabelPatches.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("VanillaLabelSuppressionPatch", delegate
			{
				VanillaLabelSuppressionPatch.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("DeadLabelCullPatches", delegate
			{
				DeadLabelCullPatches.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("PointPingerPatches", delegate
			{
				PointPingerPatches.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("GhostFreeCamPatches", delegate
			{
				GhostFreeCamPatches.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("PauseSuppressPatch", delegate
			{
				PauseSuppressPatch.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("LuggageCompassSpawner", delegate
			{
				LuggageCompassSpawner.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("PingableRegistryPatches", delegate
			{
				PingableRegistryPatches.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("PirateCompassNeedlePatch", delegate
			{
				PirateCompassNeedlePatch.Apply(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("SleepTalkCompat", delegate
			{
				SleepTalkCompat.Initialize(_harmony, ((BaseUnityPlugin)this).Logger);
			});
			Wire("CampfireIndicatorController", delegate
			{
				_ = CampfireIndicatorController.Instance;
			});
			Wire("ScoutStatueIndicatorController", delegate
			{
				_ = ScoutStatueIndicatorController.Instance;
			});
			Wire("BelltowerIndicatorController", delegate
			{
				_ = BelltowerIndicatorController.Instance;
			});
			Wire("PingAudioTuner", delegate
			{
				_ = PingAudioTuner.Instance;
			});
			Wire("CompassManager", delegate
			{
				_ = CompassManager.Instance;
			});
			Wire("PirateCompassLuggageIndicatorController", delegate
			{
				_ = PirateCompassLuggageIndicatorController.Instance;
			});
			Wire("LuggagePingController", delegate
			{
				_ = LuggagePingController.Instance;
			});
			Wire("CampfireCompassSpawner", delegate
			{
				_ = CampfireCompassSpawner.Instance;
			});
			Wire("SceneResetCoordinator", delegate
			{
				_ = SceneResetCoordinator.Instance;
			});
			Wire("PingableRegistry", delegate
			{
				_ = PingableRegistry.Instance;
			});
			Wire("PingPrewarm", delegate
			{
				_ = PingPrewarm.Instance;
			});
			Wire("PreviewMenu", delegate
			{
				_ = PreviewMenu.Instance;
			});
			Wire("ZombieDebugEsp", delegate
			{
				_ = ZombieDebugEsp.Instance;
			});
			Wire("IndicatorTestHarness", delegate
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Expected O, but got Unknown
				if (Cfg.EnableIndicatorTestHarness.Value)
				{
					GameObject val = new GameObject("SenseOfDirection.IndicatorTestHarness");
					Object.DontDestroyOnLoad((Object)val);
					val.AddComponent<IndicatorTestHarness>();
				}
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Sense of Direction 1.1.5 loaded.");
		}

		private void Wire(string system, Action setup)
		{
			if (!Safe.Run("startup: " + system, setup))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)(system + " failed to initialise - that feature is disabled, the rest of the mod is unaffected."));
			}
		}
	}
	public class PluginConfig
	{
		public readonly ConfigEntry<IndicatorPlacement> PlayerLabelPlacement;

		public readonly ConfigEntry<IndicatorPlacement> CampfirePlacement;

		public readonly ConfigEntry<IndicatorPlacement> PingPlacement;

		public readonly ConfigEntry<IndicatorPlacement> ItemPingPlacement;

		public readonly ConfigEntry<IndicatorPlacement> PirateCompassLuggagePlacement;

		public readonly ConfigEntry<bool> EnableLabelOverlapAvoidance;

		public readonly ConfigEntry<float> AntiOverlapAnimationSpeedMultiplier;

		public readonly ConfigEntry<float> IndicatorIconSizeMultiplier;

		public readonly ConfigEntry<KeyCode> PreviewMenuKey;

		public readonly ConfigEntry<float> OnScreenNameFontScale;

		public readonly ConfigEntry<float> OnScreenDistanceFontScale;

		public readonly ConfigEntry<float> OffScreenNameFontScale;

		public readonly ConfigEntry<float> OffScreenDistanceFontScale;

		public readonly ConfigEntry<float> CompassNameFontScale;

		public readonly ConfigEntry<float> CompassDistanceFontScale;

		public readonly ConfigEntry<bool> EnablePlayerLabels;

		public readonly ConfigEntry<bool> EnablePlayerLabelOffScreenIndicator;

		public readonly ConfigEntry<KeyCode> PlayerLabelToggleKey;

		public readonly ConfigEntry<LabelDisplayMode> PlayerLabelDisplayMode;

		public readonly ConfigEntry<float> HoldShownDuration;

		public readonly ConfigEntry<float> PlayerLabelMaxDistanceMeters;

		public readonly ConfigEntry<float> PlayerLabelNameFontSize;

		public readonly ConfigEntry<float> PlayerLabelDistanceFontSize;

		public readonly ConfigEntry<bool> ShowPlayerLabelDistance;

		public readonly ConfigEntry<bool> ShowStatusBadges;

		public readonly ConfigEntry<float> PlayerLabelBadgeSizePixels;

		public readonly ConfigEntry<bool> UseCharacterColor;

		public readonly ConfigEntry<bool> ReplaceVanillaLabels;

		public readonly ConfigEntry<bool> ShowPlayerSkeleton;

		public readonly ConfigEntry<float> PlayerSkeletonLineThickness;

		public readonly ConfigEntry<bool> PlayerSkeletonUseCharacterColor;

		public readonly ConfigEntry<bool> ShowPlayerSkeletonJoints;

		public readonly ConfigEntry<bool> EnableCampfireIndicator;

		public readonly ConfigEntry<bool> ShowCampfireDistance;

		public readonly ConfigEntry<bool> HideCampfireName;

		public readonly ConfigEntry<bool> EnableScoutStatueIndicator;

		public readonly ConfigEntry<bool> HideScoutStatueIndicatorName;

		public readonly ConfigEntry<bool> EnableBelltowerIndicator;

		public readonly ConfigEntry<bool> RemoveVisibilityCutoff;

		public readonly ConfigEntry<bool> EnablePingScaling;

		public readonly ConfigEntry<float> PingScaleMultiplier;

		public readonly ConfigEntry<bool> EnablePingRipple;

		public readonly ConfigEntry<float> RippleScaleCounterMultiplier;

		public readonly ConfigEntry<bool> EnablePingOffScreenIndicator;

		public readonly ConfigEntry<bool> ShowPingDistanceLabel;

		public readonly ConfigEntry<bool> EnableGhostPing;

		public readonly ConfigEntry<bool> EnablePingAudioBoost;

		public readonly ConfigEntry<float> PingAudioRangeMeters;

		public readonly ConfigEntry<float> PingAudioMinDistanceMeters;

		public readonly ConfigEntry<float> PingAudioVolumeMultiplier;

		public readonly ConfigEntry<bool> EnablePingAntiSpam;

		public readonly ConfigEntry<int> PingAntiSpamFreeSpamCount;

		public readonly ConfigEntry<float> PingAntiSpamSlowModeIntervalSeconds;

		public readonly ConfigEntry<int> PingAntiSpamMaxQueueLength;

		public readonly ConfigEntry<float> PingAntiSpamResetSeconds;

		public readonly ConfigEntry<bool> EnableItemPings;

		public readonly ConfigEntry<float> ItemPingDurationSeconds;

		public readonly ConfigEntry<bool> EnableItemPingGrouping;

		public readonly ConfigEntry<bool> EnableCreaturePings;

		public readonly ConfigEntry<bool> UseNativeItemPingIcons;

		public readonly ConfigEntry<ItemPingNameMode> ItemPingNameMode;

		public readonly ConfigEntry<bool> ShowItemPingDistance;

		public readonly ConfigEntry<bool> EnableItemPingOffScreenIndicator;

		public readonly ConfigEntry<float> ItemPingDetectionRadiusMeters;

		public readonly ConfigEntry<float> ItemPingCrossKindRadiusMeters;

		public readonly ConfigEntry<float> LuggagePingDetectionRadiusMeters;

		public readonly ConfigEntry<bool> EnableItemPingHitAssist;

		public readonly ConfigEntry<float> ItemPingHitboxRadiusMeters;

		public readonly ConfigEntry<bool> EnableItemPingRayAssist;

		public readonly ConfigEntry<float> ItemPingRayAssistRadiusMeters;

		public readonly ConfigEntry<bool> EnableCompass;

		public readonly ConfigEntry<CompassDisplayMode> CompassDisplayMode;

		public readonly ConfigEntry<PirateCompassDisplayMode> PirateCompassDisplayMode;

		public readonly ConfigEntry<float> CompassWidthPixels;

		public readonly ConfigEntry<float> CompassMarkerGapPixels;

		public readonly ConfigEntry<float> CompassVerticalOffsetPixels;

		public readonly ConfigEntry<float> CompassHorizontalOffsetPixels;

		public readonly ConfigEntry<float> CompassFovDegrees;

		public readonly ConfigEntry<float> CompassIconSizePixels;

		public readonly ConfigEntry<float> CompassElevationThresholdMeters;

		public readonly ConfigEntry<bool> CompassShowDegreeNumbers;

		public readonly ConfigEntry<bool> CompassShowNames;

		public readonly ConfigEntry<bool> CompassShowDistances;

		public readonly ConfigEntry<CompassLineColor> CompassLineColor;

		public readonly ConfigEntry<float> CompassLineThicknessMultiplier;

		public readonly ConfigEntry<bool> CompassClampIconsToEdge;

		public readonly ConfigEntry<bool> CompassColorPlayerLabels;

		public readonly ConfigEntry<bool> EnablePirateCompassLuggageIndicator;

		public readonly ConfigEntry<bool> PirateCompassClownLuggageOnly;

		public readonly ConfigEntry<PirateCompassLuggageDisplayMode> PirateCompassLuggageDisplayMode;

		public readonly ConfigEntry<bool> ShowPirateCompassLuggageName;

		public readonly ConfigEntry<bool> ShowPirateCompassLuggageDistance;

		public readonly ConfigEntry<bool> EnablePirateCompassLuggageOffScreenIndicator;

		public readonly ConfigEntry<bool> EnableCompassAtCampfires;

		public readonly ConfigEntry<bool> CampfireCompassOnlyWhenNeeded;

		public readonly ConfigEntry<bool> EnableCompassFromLuggage;

		public readonly ConfigEntry<float> CompassFromLuggageChancePercent;

		public readonly ConfigEntry<bool> EnablePirateCompassFromLuggage;

		public readonly ConfigEntry<float> PirateCompassFromLuggageChancePercent;

		public readonly ConfigEntry<bool> EnableLuggagePing;

		public readonly ConfigEntry<KeyCode> LuggagePingKey;

		public readonly ConfigEntry<float> LuggagePingRadiusMeters;

		public readonly ConfigEntry<float> LuggagePingDurationSeconds;

		public readonly ConfigEntry<float> LuggagePingCooldownSeconds;

		public readonly ConfigEntry<bool> EnableGhostFreeCam;

		public readonly ConfigEntry<float> GhostFreeCamMaxDistanceMeters;

		public readonly ConfigEntry<bool> GhostFreeCamUnlimitedRange;

		public readonly ConfigEntry<KeyCode> GhostFreeCamToggleKey;

		public readonly ConfigEntry<float> GhostFreeCamMoveSpeedMetersPerSecond;

		public readonly ConfigEntry<float> GhostFreeCamSprintMultiplier;

		public readonly ConfigEntry<bool> GhostFreeCamShowCrosshair;

		public readonly ConfigEntry<bool> GhostFreeCamShowKeyHint;

		public readonly ConfigEntry<KeyCode> GhostFreeCamAscendKey;

		public readonly ConfigEntry<KeyCode> GhostFreeCamDescendKey;

		public readonly ConfigEntry<bool> HideAllGhosts;

		public readonly ConfigEntry<bool> EnableDebugLogging;

		public readonly ConfigEntry<bool> EnableIndicatorTestHarness;

		public readonly ConfigEntry<bool> EnableZombieDebugEsp;

		public readonly ConfigEntry<bool> EnableGhostFreeCamKeyHintPreview;

		public PluginConfig(ConfigFile config)
		{
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Expected O, but got Unknown
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Expected O, but got Unknown
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Expected O, but got Unknown
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Expected O, but got Unknown
			//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Expected O, but got Unknown
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Expected O, but got Unknown
			//IL_04da: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Expected O, but got Unknown
			//IL_062b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0635: Expected O, but got Unknown
			//IL_0680: Unknown result type (might be due to invalid IL or missing references)
			//IL_068a: Expected O, but got Unknown
			//IL_0729: Unknown result type (might be due to invalid IL or missing references)
			//IL_0733: Expected O, but got Unknown
			//IL_0762: Unknown result type (might be due to invalid IL or missing references)
			//IL_076c: Expected O, but got Unknown
			//IL_079b: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a5: Expected O, but got Unknown
			//IL_07e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ef: Expected O, but got Unknown
			//IL_081e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0828: Expected O, but got Unknown
			//IL_084c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0856: Expected O, but got Unknown
			//IL_0885: Unknown result type (might be due to invalid IL or missing references)
			//IL_088f: Expected O, but got Unknown
			//IL_08da: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e4: Expected O, but got Unknown
			//IL_09bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c5: Expected O, but got Unknown
			//IL_09f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_09fe: Expected O, but got Unknown
			//IL_0a2d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a37: Expected O, but got Unknown
			//IL_0a82: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a8c: Expected O, but got Unknown
			//IL_0ad7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae1: Expected O, but got Unknown
			//IL_0b64: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b6e: Expected O, but got Unknown
			//IL_0b9d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba7: Expected O, but got Unknown
			//IL_0bd6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0be0: Expected O, but got Unknown
			//IL_0c0f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c19: Expected O, but got Unknown
			//IL_0c48: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c52: Expected O, but got Unknown
			//IL_0c81: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c8b: Expected O, but got Unknown
			//IL_0cba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc4: Expected O, but got Unknown
			//IL_0d63: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d6d: Expected O, but got Unknown
			//IL_0ed0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0eda: Expected O, but got Unknown
			//IL_0f25: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f2f: Expected O, but got Unknown
			//IL_0f97: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fa1: Expected O, but got Unknown
			//IL_0fd0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fda: Expected O, but got Unknown
			//IL_1009: Unknown result type (might be due to invalid IL or missing references)
			//IL_1013: Expected O, but got Unknown
			//IL_105e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1068: Expected O, but got Unknown
			//IL_10d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_10da: Expected O, but got Unknown
			//IL_1109: Unknown result type (might be due to invalid IL or missing references)
			//IL_1113: Expected O, but got Unknown
			PlayerLabelPlacement = config.Bind<IndicatorPlacement>("General", "player-label-placement", IndicatorPlacement.Both, "Where player labels are drawn. Both: as the on-screen label and as a marker on the compass tape at once. OffScreenOnly: only the label on the screen. CompassOnly: only the compass marker.");
			CampfirePlacement = config.Bind<IndicatorPlacement>("General", "campfire-placement", IndicatorPlacement.OffScreenOnly, "Where the campfire indicator is drawn, using the same OffScreenOnly/CompassOnly/Both choice as player-label-placement.");
			PingPlacement = config.Bind<IndicatorPlacement>("General", "ping-placement", IndicatorPlacement.OffScreenOnly, "Where pings are drawn, using the same OffScreenOnly/CompassOnly/Both choice as player-label-placement.");
			ItemPingPlacement = config.Bind<IndicatorPlacement>("General", "item-ping-placement", IndicatorPlacement.OffScreenOnly, "Where item/luggage/creature ping highlights are drawn, using the same OffScreenOnly/CompassOnly/Both choice as player-label-placement.");
			PirateCompassLuggagePlacement = config.Bind<IndicatorPlacement>("General", "pirate-compass-luggage-placement", IndicatorPlacement.Both, "Where the Pirate's Compass luggage indicator is drawn, using the same OffScreenOnly/CompassOnly/Both choice as player-label-placement.");
			EnableLabelOverlapAvoidance = config.Bind<bool>("General", "enable-label-overlap-avoidance", true, "Nudges overlapping player/ping/item-ping/campfire labels (and compass markers) apart so they stay readable when several land on top of each other, instead of stacking illegibly. Off restores every label/marker to its exact tracked position with no nudging at all.");
			AntiOverlapAnimationSpeedMultiplier = config.Bind<float>("General", "anti-overlap-animation-speed-multiplier", 1f, new ConfigDescription("How fast overlapping labels/markers slide apart and back together (enable-label-overlap-avoidance above). 1 keeps the shipped speed; lower both slows the motion and adds a short delay before a label starts reacting to a newly created/resolved overlap, for anyone who finds this mod's labels moving around distracting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
			IndicatorIconSizeMultiplier = config.Bind<float>("General", "indicator-icon-size-multiplier", 1f, new ConfigDescription("Scales the size of every on-/off-screen indicator icon: the ping hand's off-screen arrow, item pings' on-screen crosshair/off-screen arrow (native item icons included) and the campfire icon. 1 keeps the shipped size. Does not affect the compass (its own icon-size-pixels) or player label badges (their own badge-size-pixels below).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			PreviewMenuKey = config.Bind<KeyCode>("General", "preview-menu-key", (KeyCode)289, "Key that opens the in-game settings menu: every visual setting in this mod, laid out over a live preview of what it actually does (player labels, pings, item pings, the campfire indicator and the compass, all drawn on a real screenshot and updating as you change them). Changes there are written straight to this config file. Set to None to disable the key entirely.");
			OnScreenNameFontScale = config.Bind<float>("Fonts", "on-screen-name-scale", 1f, new ConfigDescription("Scales every name label drawn on a thing you can actually see (player labels, item/creature pings). 1 keeps the shipped sizes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			OnScreenDistanceFontScale = config.Bind<float>("Fonts", "on-screen-distance-scale", 1f, new ConfigDescription("Same, for the distance sub-line under an on-screen label.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			OffScreenNameFontScale = config.Bind<float>("Fonts", "off-screen-name-scale", 1f, new ConfigDescription("Scales every name label on a thing that's currently off-screen, i.e. clamped to the edge with an arrow. Set this below on-screen-name-scale to keep a crowded screen edge quieter without shrinking the labels on things you're actually looking at.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			OffScreenDistanceFontScale = config.Bind<float>("Fonts", "off-screen-distance-scale", 1f, new ConfigDescription("Same, for the distance sub-line under an off-screen (edge-clamped) label.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			CompassNameFontScale = config.Bind<float>("Fonts", "compass-name-scale", 1f, new ConfigDescription("Scales the name label above each compass-tape marker (only shown at all when Compass/show-names is on).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			CompassDistanceFontScale = config.Bind<float>("Fonts", "compass-distance-scale", 1f, new ConfigDescription("Scales the distance sub-label under each compass-tape marker.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			EnablePlayerLabels = config.Bind<bool>("Player-Labels", "enable-player-labels", true, "Master switch for Sense of Direction's player labels. Off hides them entirely (vanilla's own name labels are unaffected either way).");
			EnablePlayerLabelOffScreenIndicator = config.Bind<bool>("Player-Labels", "enable-offscreen-indicator", true, "Keep a player's label visible, clamped to the screen edge, once they go off-screen. Off hides the label entirely instead, so it only shows while the player is actually in view. Does nothing while player-label-placement is CompassOnly, which hides the whole widget anyway.");
			PlayerLabelToggleKey = config.Bind<KeyCode>("Player-Labels", "toggle-key", (KeyCode)103, "Key that shows/hides player labels, per display-mode below. Only a single key can be bound here, not a combination like Ctrl+G.");
			PlayerLabelDisplayMode = config.Bind<LabelDisplayMode>("Player-Labels", "display-mode", LabelDisplayMode.Toggle, "Toggle: press toggle-key to show/hide labels. AlwaysOn: labels are always visible (toggle-key does nothing). Hold: labels show while toggle-key is held down.");
			HoldShownDuration = config.Bind<float>("Player-Labels", "hold-shown-duration", 1.5f, new ConfigDescription("Hold mode only: how many seconds labels stay visible after the key is released (also covers a quick tap).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			PlayerLabelMaxDistanceMeters = config.Bind<float>("Player-Labels", "max-distance-meters", 1000f, new ConfigDescription("A player's label stops showing beyond this distance. Lower it if you'd rather only track teammates who are actually nearby, or raise it to cover longer sightlines.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 2000f), Array.Empty<object>()));
			PlayerLabelNameFontSize = config.Bind<float>("Player-Labels", "name-font-size", 28f, new ConfigDescription("Base font size of each player's name label, before the Fonts section's on-screen/off-screen name scale is applied on top.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 60f), Array.Empty<object>()));
			PlayerLabelDistanceFontSize = config.Bind<float>("Player-Labels", "distance-font-size", 18f, new ConfigDescription("Base font size of the distance sub-line under each name label, before the Fonts section's distance scale is applied on top.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 40f), Array.Empty<object>()));
			ShowPlayerLabelDistance = config.Bind<bool>("Player-Labels", "show-distance", true, "Show the distance sub-line under each name label.");
			ShowStatusBadges = config.Bind<bool>("Player-Labels", "show-status-badges", true, "Show the host crown / unconscious / dead badges on each label.");
			PlayerLabelBadgeSizePixels = config.Bind<float>("Player-Labels", "badge-size-pixels", 26f, new ConfigDescription("Size of the host crown / unconscious / dead badges below the player label.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(16f, 44f), Array.Empty<object>()));
			UseCharacterColor = config.Bind<bool>("Player-Labels", "use-character-color", true, "Color each label's name with that player's own character color instead of the vanilla name-label color.");
			ReplaceVanillaLabels = config.Bind<bool>("Player-Labels", "replace-vanilla-labels", false, "Hide the game's own close-range player name labels entirely, so Sense of Direction's labels are the only ones ever shown. Normally the two systems hand off to each other instead.");
			ShowPlayerSkeleton = config.Bind<bool>("Player-Labels", "show-skeleton", false, "Draw each player's skeleton over the world, visible through walls and terrain. Shows and hides together with the labels themselves, so the display-mode and toggle-key above apply to it too. Off by default: it gives away a lot more than a name label does.");
			PlayerSkeletonLineThickness = config.Bind<float>("Player-Labels", "skeleton-line-thickness", 2f, new ConfigDescription("How thick the skeleton's bones are drawn. Thickness stays the same on screen at any distance, so a far-off player is still a readable stick figure rather than a hairline.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), Array.Empty<object>()));
			PlayerSkeletonUseCharacterColor = config.Bind<bool>("Player-Labels", "skeleton-use-character-color", true, "Color each skeleton with that player's own character color. Off draws them all in the vanilla name-label color instead. Separate from use-character-color above, so the skeletons and the name labels can be colored differently.");
			ShowPlayerSkeletonJoints = config.Bind<bool>("Player-Labels", "skeleton-show-joints", true, "Draw a dot at each joint of the skeleton, on top of the bones.");
			EnableCampfireIndicator = config.Bind<bool>("Campfire", "enable-campfire-indicator", true, "Show an always-on indicator pointing at the current segment's campfire (the one you're trying to reach next), so you always know which way to go. Turn it off if you'd rather find your own way up and keep the rest of the mod.");
			ShowCampfireDistance = config.Bind<bool>("Campfire", "show-distance", true, "Show the distance sub-line under the campfire indicator.");
			HideCampfireName = config.Bind<bool>("Campfire", "hide-name", true, "Never show the campfire's name label (\"Campfire\") on the compass. On by default since the icon alone already makes it obvious which marker is the campfire.");
			EnableScoutStatueIndicator = config.Bind<bool>("Campfire", "enable-scout-statue-indicator", false, "Show an indicator pointing at the nearest scout statue (one of the 4 randomly-placed statues in the first 4 biomes, each holding a Scout's Amulet) for as long as its amulet hasn't been picked up yet. Uses the same campfire-placement setting as the campfire indicator above.");
			HideScoutStatueIndicatorName = config.Bind<bool>("Campfire", "hide-scout-statue-indicator-name", true, "Never show the scout statue indicator's amulet name label (e.g. \"SCOUT'S TENACITY\"). On by default since those names run quite long.");
			EnableBelltowerIndicator = config.Bind<bool>("Campfire", "enable-belltower-indicator", false, "Show an indicator pointing at the nearest not-yet-lit Belltower (Gloom biome only). Uses the same campfire-placement setting as the campfire indicator above.");
			RemoveVisibilityCutoff = config.Bind<bool>("Pings", "remove-visibility-cutoff", true, "Vanilla silently refuses to even spawn a ping's visual once its pinging player is more than ~45m from you; turning this on makes far pings still show up at all. Most of the other Pings settings only matter once this is on.");
			EnablePingScaling = config.Bind<bool>("Pings", "enable-scaling", true, "Scale ping visuals up the further away they are, well past vanilla's own hard-capped scale, so far pings stay easy to spot.");
			PingScaleMultiplier = config.Bind<float>("Pings", "scale-multiplier", 1f, new ConfigDescription("Extra multiplier applied on top of vanilla's own (uncapped, see remove-visibility-cutoff) ping scale. 1x is vanilla's own uncapped size; higher makes every ping bigger regardless of distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
			EnablePingRipple = config.Bind<bool>("Pings", "enable-ripple", true, "Show an expanding ring in the pinging player's own character color at the ping location, so it reads against similarly-colored terrain. Press your ping key to preview this here.");
			RippleScaleCounterMultiplier = config.Bind<float>("Pings", "ripple-scale-counter-multiplier", 0.8f, new ConfigDescription("The ripple grows together with the ping's own distance-scaling (see enable-scaling above), which can end up huge on a very far ping. This counteracts that growth: 1x leaves it untouched, lower values increasingly hold the ripple back the bigger it would otherwise get, while a nearby ping's already-small ripple barely changes at any value. Only affects the ripple, not the ping marker itself.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			EnablePingOffScreenIndicator = config.Bind<bool>("Pings", "enable-offscreen-indicator", true, "Show an edge-of-screen arrow pointing toward an active ping when it's off-screen, same mechanism as the player-label/campfire indicators. Only the arrow; the distance line below is show-distance's own call. Does nothing while General/ping-placement is CompassOnly, which hides the whole widget anyway.");
			ShowPingDistanceLabel = config.Bind<bool>("Pings", "show-distance", true, "Show a distance sub-line under the ping indicator.");
			EnableGhostPing = config.Bind<bool>("Pings", "enable-ghost-ping", true, "Let dead or unconscious players keep pinging (vanilla blocks pinging once passed out, well before actual death), colored using their own character color same as when alive. Requires both sides to have this mod installed.");
			EnablePingAudioBoost = config.Bind<bool>("Ping-Audio", "enable-audio-boost", true, "Drastically reduce the ping sound's distance falloff so it's audible from much further away, while sounding unchanged up close. The rest of this section does nothing while this is off.");
			PingAudioRangeMeters = config.Bind<float>("Ping-Audio", "range-meters", 600f, new ConfigDescription("Ping sound's max audible range (vanilla is 150).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(150f, 2000f), Array.Empty<object>()));
			PingAudioMinDistanceMeters = config.Bind<float>("Ping-Audio", "min-distance-meters", 10f, new ConfigDescription("Distance under which the ping sound plays at full volume before it starts falling off toward range-meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			PingAudioVolumeMultiplier = config.Bind<float>("Ping-Audio", "volume-multiplier", 0.85f, new ConfigDescription("Multiplier on the ping sound's own base (close-range) volume. The far-range audibility boost also makes it slightly too loud up close, so this trims that back down.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 1.5f), Array.Empty<object>()));
			EnablePingAntiSpam = config.Bind<bool>("Ping-Anti-Spam", "enable-anti-spam", true, "Rate-limits how often *other* players' pings actually render/play once they're pinging rapidly, so spamming the ping key isn't more disruptive than vanilla now that pings are bigger/louder. A short burst always goes through instantly; only once someone keeps spamming does \"slow mode\" kick in, queueing further pings to arrive at a throttled rate instead (never silently dropped, unless the queue itself is full; see max-queue-length). Never applies to your own pings.");
			PingAntiSpamFreeSpamCount = config.Bind<int>("Ping-Anti-Spam", "free-spam-count", 3, new ConfigDescription("How many pings in a row from the same player always show up instantly before slow mode kicks in.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			PingAntiSpamSlowModeIntervalSeconds = config.Bind<float>("Ping-Anti-Spam", "slow-mode-interval-seconds", 0.5f, new ConfigDescription("Once slow mode kicks in, queued pings from that player are spaced at least this far apart before they're actually shown to you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			PingAntiSpamMaxQueueLength = config.Bind<int>("Ping-Anti-Spam", "max-queue-length", 2, new ConfigDescription("How many of a spamming player's pings can be queued up waiting to show at once while in slow mode. Any further ping while the queue's already full is dropped entirely rather than queued.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
			PingAntiSpamResetSeconds = config.Bind<float>("Ping-Anti-Spam", "reset-seconds", 2f, new ConfigDescription("How long a player has to go without pinging (with their queue fully drained) before slow mode fully resets to normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			EnableItemPings = config.Bind<bool>("Item-Pings", "enable-item-pings", true, "Highlight nearby items/luggage when you ping near them, with a name and distance label, as a native replacement for the (broken/unmaintained) PingItems mod by memiczny.");
			ItemPingDurationSeconds = config.Bind<float>("Item-Pings", "duration-seconds", 6f, new ConfigDescription("How long an item/luggage highlight stays visible before fading out (ends early regardless if the item is picked up or the luggage is opened).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 20f), Array.Empty<object>()));
			EnableItemPingGrouping = config.Bind<bool>("Item-Pings", "enable-grouping", true, "Group multiple nearby items of the same kind into a single highlight showing a count (e.g. \"3x Coconut\") instead of one highlight per item.");
			EnableCreaturePings = config.Bind<bool>("Item-Pings", "enable-creature-pings", true, "Also highlight creatures (beetles, spiders, zombies, ...) when pinged, same as items/luggage. OFF leaves creature pings behaving like vanilla (so it won't work for them).");
			UseNativeItemPingIcons = config.Bind<bool>("Item-Pings", "use-native-icons", true, "Show the item's own in-game icon (the art its inventory slot uses, e.g. an actual bandage for a pinged bandage) as the highlight's crosshair and its compass marker, instead of the mod's generic item-ping icon. Only items (and the campfire) have an icon in the game at all; luggage, creatures and hazards keep the generic icon either way. Works with custom modded items as well.");
			ItemPingNameMode = config.Bind<ItemPingNameMode>("Item-Pings", "name-mode", SenseOfDirection.ItemPings.ItemPingNameMode.Always, "Always: every highlight shows what it is. HideWhenIconShown: anything already showing its own in-game icon (see use-native-icons) drops its name, since the icon says what it is (luggage, creatures and hazards have no icon, so they keep theirs). Never: no names at all. A grouped ping keeps its count regardless (a hidden name still shows \"3x\").");
			ShowItemPingDistance = config.Bind<bool>("Item-Pings", "show-distance", true, "Show a distance sub-line under the item/luggage highlight.");
			EnableItemPingOffScreenIndicator = config.Bind<bool>("Item-Pings", "enable-offscreen-indicator", true, "Show an edge-of-screen arrow pointing toward a highlighted item/luggage when it's off-screen, same mechanism as the ping indicator. Does nothing while General/item-ping-placement is CompassOnly, which hides the whole widget anyway.");
			ItemPingDetectionRadiusMeters = config.Bind<float>("Item-Ping-Detection", "item-radius-meters", 2f, new ConfigDescription("How close a ping needs to land to an item for it to get highlighted.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>()));
			ItemPingCrossKindRadiusMeters = config.Bind<float>("Item-Ping-Detection", "cross-kind-radius-meters", 0.75f, new ConfigDescription("How close a *different* kind of item has to be to the item you actually pinged before it also gets highlighted. Items of the same kind still group together across the full item-radius-meters (that's what makes a \"2x COCONUT\" grouping), but a different item only counts if it was pretty much directly aimed at too, so pinging one item in a luggage doesn't drag in an unrelated one sitting next to it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			LuggagePingDetectionRadiusMeters = config.Bind<float>("Item-Ping-Detection", "luggage-radius-meters", 3.5f, new ConfigDescription("Same as item-radius-meters, but for luggage, which is a bigger target.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 15f), Array.Empty<object>()));
			EnableItemPingHitAssist = config.Bind<bool>("Item-Ping-Detection", "enable-hit-assist", true, "Widen the ping's own aim raycast so it can land directly on an item/luggage's own collider (not just terrain/ground), instead of phasing through to whatever's behind it. Fixes hard-to-ping items like a coconut up a tree or a small dropped item. Off falls back to vanilla's own terrain-only ping raycast.");
			ItemPingHitboxRadiusMeters = config.Bind<float>("Item-Ping-Detection", "hitbox-radius-meters", 0.35f, new ConfigDescription("Only used when enable-hit-assist is on. Treats the ping raycast as a sphere of this radius instead of an infinitely-thin line, so aiming near (not pixel-perfect on) an item's collider still hits it. 0 disables the sphere, falling back to a plain (still item-widened) raycast.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1.5f), Array.Empty<object>()));
			EnableItemPingRayAssist = config.Bind<bool>("Item-Ping-Detection", "enable-ray-assist", true, "Also count an item/luggage as pinged if it's close enough to your aim line, independent of physics entirely. Needed for items that aren't pushable/hittable until first picked up (an unpicked coconut on a tree, berries on a bush, something freshly spawned from opened luggage); their collider is disabled until then, so no physics raycast (not even enable-hit-assist's) can ever land on them.");
			ItemPingRayAssistRadiusMeters = config.Bind<float>("Item-Ping-Detection", "ray-assist-radius-meters", 0.6f, new ConfigDescription("Only used when enable-ray-assist is on. How far off your exact aim line an item/luggage can be and still count as pinged.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			EnableCompass = config.Bind<bool>("Compass", "enable-compass", true, "Master switch for the top-of-screen compass tape. Off hides it entirely regardless of any individual mechanic's placement setting.");
			CompassDisplayMode = config.Bind<CompassDisplayMode>("Compass", "display-mode", SenseOfDirection.Compass.CompassDisplayMode.AlwaysOn, "When the compass tape is shown, from least to most restrictive: ALWAYS ON shows it regardless of inventory. CARRIED needs a compass item somewhere in your inventory or stashed in a worn backpack. MAIN INVENTORY only counts ones in your inventory slots. HOLDING ITEM needs a compass item actively equipped in your hand right now. Only regular compasses count here.");
			PirateCompassDisplayMode = config.Bind<PirateCompassDisplayMode>("Compass", "pirate-display-mode", SenseOfDirection.Compass.PirateCompassDisplayMode.MatchDisplayMode, "The same levels as display-mode above, but for Pirate's Compasses only. The tape shows whenever either setting's own condition is met. MATCH DISPLAY MODE keeps Pirate's Compasses on whatever display-mode itself is set to. Only about the compass tape: the Pirate's Compass luggage indicator has its own separate luggage-indicator-display-mode.");
			CompassWidthPixels = config.Bind<float>("Compass", "width-pixels", 640f, new ConfigDescription("Width of the compass tape, in pixels at the 1920-wide reference resolution (scales with actual resolution same as everything else). Wider shows more of the horizon at once.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(300f, 1400f), Array.Empty<object>()));
			CompassMarkerGapPixels = config.Bind<float>("Compass", "marker-gap-pixels", 40f, new ConfigDescription("Vertical gap between the tick row and the marker baseline below it, on top of a small fixed minimum. Raise this for more breathing room (e.g. after turning on show-names).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(40f, 200f), Array.Empty<object>()));
			CompassVerticalOffsetPixels = config.Bind<float>("Compass", "vertical-offset-pixels", 28f, new ConfigDescription("Gap between the top of the screen and the compass tape.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
			CompassHorizontalOffsetPixels = config.Bind<float>("Compass", "horizontal-offset-pixels", 0f, new ConfigDescription("Horizontal offset from top-center. 0 keeps it centered; positive shifts right, negative shifts left (e.g. to dodge another HUD mod's own top-of-screen element).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-800f, 800f), Array.Empty<object>()));
			CompassFovDegrees = config.Bind<float>("Compass", "fov-degrees", 150f, new ConfigDescription("How much of the horizon (in degrees) is visible on the tape at once before a heading/marker slides off the edge. Lower feels closer to your actual field of view; higher gives more lead time for things approaching from the side.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 180f), Array.Empty<object>()));
			CompassIconSizePixels = config.Bind<float>("Compass", "icon-size-pixels", 26f, new ConfigDescription("Size of each marker's icon on the compass.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(12f, 64f), Array.Empty<object>()));
			CompassElevationThresholdMeters = config.Bind<float>("Compass", "elevation-threshold-meters", 3f, new ConfigDescription("A marker only gets an up/down elevation arrow once its target is at least this many meters above/below you, which avoids a flickering arrow for things that are roughly level with you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f), Array.Empty<object>()));
			CompassShowDegreeNumbers = config.Bind<bool>("Compass", "show-degree-numbers", false, "Show a numeric heading (e.g. \"105\") at every non-cardinal tick instead of leaving it as a plain unlabeled line. N/E/S/W are always lettered either way.");
			CompassShowNames = config.Bind<bool>("Compass", "show-names", false, "Show a name label above each compass marker that has one (players, item/creature pings, the campfire). Distances still show independently of this setting.");
			CompassShowDistances = config.Bind<bool>("Compass", "show-distances", true, "Show a distance sub-label under each compass marker.");
			CompassLineColor = config.Bind<CompassLineColor>("Compass", "line-color", SenseOfDirection.Compass.CompassLineColor.White, "Base color of the compass tape's heading ticks/labels and baseline stripe (true north keeps its own dark red accent regardless).");
			CompassLineThicknessMultiplier = config.Bind<float>("Compass", "line-thickness-multiplier", 1f, new ConfigDescription("Scales the thickness of the compass tape's tick lines (both cardinal and minor) and its baseline stripe. 1 keeps the shipped thickness; higher values make the lines bolder.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
			CompassClampIconsToEdge = config.Bind<bool>("Compass", "clamp-icons-to-edge", false, "Markers that would otherwise not be visible (outside the compass FOV window) are instead clamped to the nearest left/right edge of the tape and shown dimmed, like a mini radar, instead of not appearing at all.");
			CompassColorPlayerLabels = config.Bind<bool>("Compass", "color-player-labels", false, "Tint a player's name/distance labels on the compass in their own character color instead of plain white, matching how ping/item ping labels are already colored.");
			EnablePirateCompassLuggageIndicator = config.Bind<bool>("Pirate-Compass", "enable-pirate-compass-luggage-indicator", true, "With a Pirate's Compass on you, show an indicator with a distance label pointing at the nearest unopened Luggage, the same target its own in-game needle points at. How close to hand the compass has to be is up to luggage-indicator-display-mode below. NOTE: as the host you can increase the chance to get a Pirate's Compass or even another regular Compass from Luggage in this mod's config.");
			PirateCompassClownLuggageOnly = config.Bind<bool>("Pirate-Compass", "clown-luggage-only", false, "Make the Pirate's Compass only ever target unopened Clown Luggage, ignoring every other kind of Luggage.");
			PirateCompassLuggageDisplayMode = config.Bind<PirateCompassLuggageDisplayMode>("Pirate-Compass", "luggage-indicator-display-mode", SenseOfDirection.PirateCompass.PirateCompassLuggageDisplayMode.RequireHolding, "How close to hand a Pirate's Compass has to be for its luggage indicator to show, from least to most restrictive: CARRIED needs one somewhere in your inventory or stashed in a worn backpack. MAIN INVENTORY only counts ones in your inventory slots. HOLDING ITEM needs one actively equipped in your hand right now.");
			ShowPirateCompassLuggageName = config.Bind<bool>("Pirate-Compass", "show-luggage-name", true, "Show a name label (\"LUGGAGE\") above the Pirate's Compass indicator.");
			ShowPirateCompassLuggageDistance = config.Bind<bool>("Pirate-Compass", "show-luggage-distance", true, "Show a distance sub-label under the Pirate's Compass indicator.");
			EnablePirateCompassLuggageOffScreenIndicator = config.Bind<bool>("Pirate-Compass", "enable-off-screen-indicator", true, "Show an off-screen arrow pointing toward the nearest unopened luggage while it isn't in view. Off shows the indicator only once it's actually on screen.");
			EnableCompassAtCampfires = config.Bind<bool>("Compass-Items", "enable-compass-at-campfires", true, "Host-only: whenever a campfire is lit, place an extra regular Compass on the ground next to that campfire's backpack. Vanilla only ever gives out one compass per run (right at the start), which leaves everyone else in a co-op run without one - this is the top-up. See only-when-needed below, which limits when this actually happens. Only the host's value matters: items are spawned by the host alone.");
			CampfireCompassOnlyWhenNeeded = config.Bind<bool>("Compass-Items", "campfire-compass-only-when-needed", true, "Only place the campfire compass above when it's actually of use: in a co-op run (solo, the run's own starting compass is already yours) whose host doesn't have Compass/display-mode set to AlwaysOn (on AlwaysOn the compass tape shows without anyone having to hold a compass item at all). Turn this off to have one spawn at every campfire unconditionally. Does nothing if enable-compass-at-campfires above is off.");
			EnableCompassFromLuggage = config.Bind<bool>("Compass-Items", "enable-compass-from-empty-luggage", false, "Host-only: gives opened Luggage a chance (see add-compass-chance-percent below) to also contain a regular Compass. This never replaces or removes anything the game itself rolled - it only fills a slot the game left empty - and it never changes the game's own spawn odds. A small Luggage holds 1-2 items and a big one 2-3, so roughly two opens in three leave a slot free; that free slot is what a compass can go into. Explorer's Luggage always fills every slot and Ancient (cursed) Luggage is left alone entirely, so neither is affected. Only the host's value matters: luggage contents are spawned by the host alone.");
			CompassFromLuggageChancePercent = config.Bind<float>("Compass-Items", "add-compass-chance-percent", 3f, new ConfigDescription("Chance, in percent, that opening a Luggage gets you a regular Compass. This is the real chance per luggage opened, not per luggage that happened to have a free slot - 3 means 3 luggage in 100. The cap is the odds of a free slot existing at all (about 66%, i.e. two opens in three), so setting it that high means every luggage that can take a compass gets one. Only rolled when enable-compass-from-empty-luggage is on, and only after the Pirate's Compass roll below missed (if that one is enabled too - the two shares don't eat into each other, but together they can't exceed the cap).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 66f), Array.Empty<object>()));
			EnablePirateCompassFromLuggage = config.Bind<bool>("Compass-Items", "enable-pirate-compass-from-empty-luggage", false, "Host-only: same as enable-compass-from-empty-luggage above, but for the Pirate's Compass (the one whose needle points at the nearest unopened luggage). Rolled first when both are enabled - a hit here spawns a Pirate's Compass and skips the regular Compass roll entirely, so at most one extra compass is ever added per luggage.");
			PirateCompassFromLuggageChancePercent = config.Bind<float>("Compass-Items", "add-pirate-compass-chance-percent", 0.5f, new ConfigDescription("Chance, in percent, that opening a Luggage gets you a Pirate's Compass. Same scale as add-compass-chance-percent above: the real chance per luggage opened, capped by the roughly 66% odds of a free slot existing. Kept low by default - it's a much stronger find than a regular Compass. Only rolled when enable-pirate-compass-from-empty-luggage is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 66f), Array.Empty<object>()));
			EnableLuggagePing = config.Bind<bool>("Luggage-Ping", "enable-luggage-ping", true, "Master switch: press LUGGAGE PING KEY below to highlight every unopened luggage within the set radius (100m by default) of you, visible only to yourself. Comes with a cooldown by default (15s) which is able to be changed through the mod's config, the same goes for the radius.");
			LuggagePingKey = config.Bind<KeyCode>("Luggage-Ping", "key", (KeyCode)116, "Key that triggers a luggage ping (see above) if enabled and not on a cooldown.");
			LuggagePingRadiusMeters = config.Bind<float>("Luggage-Ping", "radius-meters", 100f, new ConfigDescription("How far around you luggage gets highlighted. Capped well below the level's own size so this can't turn into a full map-wide luggage ESP.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 250f), Array.Empty<object>()));
			LuggagePingDurationSeconds = config.Bind<float>("Luggage-Ping", "duration-seconds", 6f, new ConfigDescription("How long each highlighted luggage stays visible before fading out (ends early regardless if it's opened first).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 20f), Array.Empty<object>()));
			LuggagePingCooldownSeconds = config.Bind<float>("Luggage-Ping", "cooldown-seconds", 15f, new ConfigDescription("How long you have to wait between luggage pings. Trying to ping again while this is still running shows a brief on-screen reminder instead of doing nothing silently. 0 disables the cooldown entirely.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>()));
			EnableGhostFreeCam = config.Bind<bool>("Ghost-Free-Cam", "enable-ghost-free-cam", true, "Lets dead players fly a free camera instead of being stuck in vanilla's third-person spectate view. Unlike every other setting in this mod, this one and the two below it are host-controlled: only the room host's own value for these three settings ever takes effect for every player, the same way enable-ghost-ping requires both sides to have this mod installed. That's because letting each client fly unlimited distances would be an unfair, effectively ESP-like advantage other players in the same run never agreed to. If the host doesn't have this mod installed, ghost free-cam simply doesn't work for anyone, same as ghost pinging. Your own value here still matters if you end up being the host.");
			GhostFreeCamMaxDistanceMeters = config.Bind<float>("Ghost-Free-Cam", "max-distance-meters", 50f, new ConfigDescription("Host-controlled, see enable-ghost-free-cam. How far a ghost's free camera can scout from whichever living player they're currently spectating before being pulled back, like a chain of this length. Ignored entirely when unlimited-range is on.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 500f), Array.Empty<object>()));
			GhostFreeCamUnlimitedRange = config.Bind<bool>("Ghost-Free-Cam", "unlimited-range", false, "Host-controlled, see enable-ghost-free-cam. Removes max-distance-meters' leash entirely, letting ghosts free-cam anywhere on the map. Note that the leash is what keeps this mechanic from being overpowered.");
			GhostFreeCamToggleKey = config.Bind<KeyCode>("Ghost-Free-Cam", "toggle-key", (KeyCode)98, "Purely local. Key that toggles free-fly camera mode on/off while you're dead and spectating; each player binds their own. Only does anything while enable-ghost-free-cam ends up effectively on (see that setting for how that's decided).");
			GhostFreeCamMoveSpeedMetersPerSecond = config.Bind<float>("Ghost-Free-Cam", "move-speed-meters-per-second", 15f, new ConfigDescription("Purely local. How fast the free camera flies. PEAK's own built-in dev free-camera controller (reused for the first pass of this feature) turned out to feel unusably slow in practice, so this mod drives its own movement directly in real-world meters/second instead of relying on that controller's tuning. Movement, sprint and up/down keys all follow your own PEAK control bindings - rebind those in the game's own Controls settings, not here.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			GhostFreeCamSprintMultiplier = config.Bind<float>("Ghost-Free-Cam", "sprint-multiplier", 3f, new ConfigDescription("Purely local. Speed multiplier while holding your own sprint key (whatever you've bound it to in PEAK's own Controls settings).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			GhostFreeCamShowCrosshair = config.Bind<bool>("Ghost-Free-Cam", "show-crosshair", true, "Purely local. Shows a small reticle at the center of the screen while free-cam is engaged, so you have something to aim regular pings at (spectate mode otherwise has no crosshair at all).");
			GhostFreeCamShowKeyHint = config.Bind<bool>("Ghost-Free-Cam", "show-key-hint", true, "Purely local. Shows a key badge + short label near vanilla's own \"you are a ghost\" panel reminding you which key toggles free-cam (and whether it'll engage or disengage), since vanilla's UI never mentions this mod's keybind at all.");
			GhostFreeCamAscendKey = config.Bind<KeyCode>("Ghost-Free-Cam", "ascend-key", (KeyCode)101, "Purely local. Extra key that flies the free camera straight up, on top of your own jump key (which also works). Ignored while merely unconscious (not yet dead), same as descend-key below, since E/Q are vanilla's own keys to speed up dying right next to each other. Set to None to disable.");
			GhostFreeCamDescendKey = config.Bind<KeyCode>("Ghost-Free-Cam", "descend-key", (KeyCode)113, "Purely local. Extra key that flies the free camera straight down, on top of your own crouch key (which also works). Ignored while merely unconscious (not yet dead), see ascend-key above. Set to None to disable.");
			HideAllGhosts = config.Bind<bool>("Ghost-Free-Cam", "hide-all-ghosts", false, "Purely local. Hides every dead player's ghost body from your own view entirely. Doesn't affect anyone else, and doesn't affect your own ability to spectate/free-cam while dead yourself.");
			EnableDebugLogging = config.Bind<bool>("Debug", "enable-debug-logging", false, "Log extra diagnostic detail to the BepInEx console/log file.");
			EnableIndicatorTestHarness = config.Bind<bool>("Debug", "enable-indicator-test-harness", false, "Spawn a handful of fixed dummy world points around the camera to visually verify the edge-of-screen indicator framework. Dev/QA tool only; leave off for normal play.");
			EnableZombieDebugEsp = config.Bind<bool>("Debug", "enable-zombie-debug-esp", false, "Dev/QA aid: always-visible label for every naturally-spawned zombie in the level, through walls, to speed up testing zombie-ping detection without hunting a whole level for a rare spawn. Not a real feature; leave off for normal play.");
			EnableGhostFreeCamKeyHintPreview = config.Bind<bool>("Debug", "enable-ghost-free-cam-key-hint-preview", false, "Dev/QA aid: always shows the ghost free-cam key hint badge/label (toggle-key still flips it between its 'go into'/'leave' text), even while alive, to check its look without dying first. Not a real feature; leave off for normal play.");
		}
	}
	public static class PluginInfo
	{
		public const string Guid = "OnlyCook.SenseOfDirection";

		public const string Name = "Sense of Direction";

		public const string Version = "1.1.5";
	}
}
namespace SenseOfDirection.Ui
{
	internal interface IConfigBoundSetting
	{
		string DisplayName { get; }

		string Tooltip { get; }

		string DefaultValueText { get; }

		Setting Setting { get; }

		void ResetToDefault();

		void RefreshFromConfig();
	}
	internal class ConfigSettingHandler : ISettingHandler
	{
		public void SaveSetting(Setting setting)
		{
		}

		public T GetSetting<T>() where T : Setting
		{
			return default(T);
		}

		public IEnumerable<Setting> GetAllSettings()
		{
			return Array.Empty<Setting>();
		}
	}
	internal static class ConfigSettingNaming
	{
		internal static string DisplayName(ConfigEntryBase entry)
		{
			if (!ConfigLocalizationTable.TryGet(entry, out var result))
			{
				return entry.Definition.Key.Replace('-', ' ').ToUpperInvariant();
			}
			return result.Name;
		}

		internal static string Tooltip(ConfigEntryBase entry)
		{
			object obj;
			if (!ConfigLocalizationTable.TryGet(entry, out var result))
			{
				ConfigDescription description = entry.Description;
				obj = ((description != null) ? description.Description : null);
				if (obj == null)
				{
					return string.Empty;
				}
			}
			else
			{
				obj = DescriptionPlaceholders.Resolve(result.Description);
			}
			return (string)obj;
		}

		internal static string EnumDisplayName(Enum value)
		{
			string fallback = Regex.Replace(value.ToString(), "(?<!^)([A-Z])", " $1").ToUpperInvariant();
			return EnumLocalizationTable.Get(value.GetType(), value.ToString(), fallback);
		}
	}
	internal class ConfigFloatSetting : FloatSetting, IConfigBoundSetting
	{
		private readonly ConfigEntry<float> _entry;

		private readonly ISettingHandler _handler;

		public string DisplayName { get; }

		public string Tooltip { get; }

		public string DefaultValueText { get; private set; }

		public Setting Setting => (Setting)(object)this;

		internal ConfigFloatSetting(ConfigEntry<float> entry, ISettingHandler handler)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			_entry = entry;
			_handler = handler;
			DisplayName = ConfigSettingNaming.DisplayName((ConfigEntryBase)(object)entry);
			Tooltip = ConfigSettingNaming.Tooltip((ConfigEntryBase)(object)entry);
			float2 minMaxValue = ((FloatSetting)this).GetMinMaxValue();
			((FloatSetting)this).MinValue = minMaxValue.x;
			((FloatSetting)this).MaxValue = minMaxValue.y;
			((FloatSetting)this).Value = Mathf.Clamp(entry.Value, ((FloatSetting)this).MinValue, ((FloatSetting)this).MaxValue);
			DefaultValueText = ((FloatSetting)this).Expose((float)((ConfigEntryBase)entry).DefaultValue);
		}

		public override void ApplyValue()
		{
			_entry.Value = ((FloatSetting)this).Value;
		}

		public override void Save(ISettingsSaveLoad saver)
		{
		}

		public override void Load(ISettingsSaveLoad loader)
		{
			RefreshFromConfig();
		}

		protected override float GetDefaultValue()
		{
			return (float)((ConfigEntryBase)_entry).DefaultValue;
		}

		protected override float2 GetMinMaxValue()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			ConfigDescription description = ((ConfigEntryBase)_entry).Description;
			if (((description != null) ? description.AcceptableValues : null) is AcceptableValueRange<float> val)
			{
				return new float2(val.MinValue, val.MaxValue);
			}
			float num = (float)((ConfigEntryBase)_entry).DefaultValue;
			return new float2(0f, Mathf.Max(1f, num * 2f));
		}

		public override string Expose(float result)
		{
			if (!(((FloatSetting)this).MaxValue - ((FloatSetting)this).MinValue > 20f))
			{
				return result.ToString("0.00");
			}
			return Mathf.RoundToInt(result).ToString();
		}

		public void ResetToDefault()
		{
			((FloatSetting)this).SetValue(((FloatSetting)this).GetDefaultValue(), _handler, false);
		}

		public void RefreshFromConfig()
		{
			((FloatSetting)this).SetValue(_entry.Value, _handler, false);
		}
	}
	internal class ConfigBoolSetting : OffOnSetting, IConfigBoundSetting, ICustomLocalizedEnumSetting
	{
		private readonly ConfigEntry<bool> _entry;

		private readonly ISettingHandler _handler;

		public string DisplayName { get; }

		public string Tooltip { get; }

		public string DefaultValueText { get; }

		public Setting Setting => (Setting)(object)this;

		internal ConfigBoolSetting(ConfigEntry<bool> entry, ISettingHandler handler)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			_entry = entry;
			_handler = handler;
			DisplayName = ConfigSettingNaming.DisplayName((ConfigEntryBase)(object)entry);
			Tooltip = ConfigSettingNaming.Tooltip((ConfigEntryBase)(object)entry);
			DefaultValueText = ConfigSettingNaming.EnumDisplayName((Enum)(object)((EnumSetting<OffOnMode>)(object)this).GetDefaultValue());
			((EnumSetting<OffOnMode>)this).Value = (OffOnMode)(entry.Value ? 1 : 0);
		}

		public override void ApplyValue()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			_entry.Value = (int)((EnumSetting<OffOnMode>)this).Value == 1;
		}

		public override void Save(ISettingsSaveLoad saver)
		{
		}

		public override void Load(ISettingsSaveLoad loader)
		{
			RefreshFromConfig();
		}

		protected override OffOnMode GetDefaultValue()
		{
			if ((bool)((ConfigEntryBase)_entry).DefaultValue)
			{
				return (OffOnMode)1;
			}
			return (OffOnMode)0;
		}

		public override List<LocalizedString> GetLocalizedChoices()
		{
			return null;
		}

		public List<string> GetCustomLocalizedChoices()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			string[] names = Enum.GetNames(typeof(OffOnMode));
			foreach (string value in names)
			{
				list.Add(ConfigSettingNaming.EnumDisplayName((Enum)(object)(OffOnMode)Enum.Parse(typeof(OffOnMode), value)));
			}
			return list;
		}

		public void RegisterCustomLocalized(Action action)
		{
		}

		public void DeregisterCustomLocalized(Action action)
		{
		}

		public void ResetToDefault()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected I4, but got Unknown
			((EnumSetting<OffOnMode>)(object)this).SetValue((int)((EnumSetting<OffOnMode>)(object)this).GetDefaultValue(), _handler, false);
		}

		public void RefreshFromConfig()
		{
			((EnumSetting<OffOnMode>)(object)this).SetValue(_entry.Value ? 1 : 0, _handler, false);
		}
	}
	internal class ConfigEnumSetting<T> : EnumSetting<T>, IConfigBoundSetting, ICustomLocalizedEnumSetting where T : unmanaged, Enum
	{
		private readonly ConfigEntry<T> _entry;

		private readonly ISettingHandler _handler;

		public string DisplayName { get; }

		public string Tooltip { get; }

		public string DefaultValueText { get; }

		public Setting Setting => (Setting)(object)this;

		internal ConfigEnumSetting(ConfigEntry<T> entry, ISettingHandler handler)
		{
			_entry = entry;
			_handler = handler;
			DisplayName = ConfigSettingNaming.DisplayName((ConfigEntryBase)(object)entry);
			Tooltip = ConfigSettingNaming.Tooltip((ConfigEntryBase)(object)entry);
			DefaultValueText = ConfigSettingNaming.EnumDisplayName((T)((ConfigEntryBase)entry).DefaultValue);
			base.Value = entry.Value;
		}

		public override void ApplyValue()
		{
			_entry.Value = base.Value;
		}

		public override void Save(ISettingsSaveLoad saver)
		{
		}

		public override void Load(ISettingsSaveLoad loader)
		{
			RefreshFromConfig();
		}

		protected override T GetDefaultValue()
		{
			return (T)((ConfigEntryBase)_entry).DefaultValue;
		}

		public override List<LocalizedString> GetLocalizedChoices()
		{
			return null;
		}

		public List<string> GetCustomLocalizedChoices()
		{
			List<string> list = new List<string>();
			string[] names = Enum.GetNames(typeof(T));
			foreach (string value in names)
			{
				list.Add(ConfigSettingNaming.EnumDisplayName((T)Enum.Parse(typeof(T), value)));
			}
			return list;
		}

		public void RegisterCustomLocalized(Action action)
		{
		}

		public void DeregisterCustomLocalized(Action action)
		{
		}

		public void ResetToDefault()
		{
			((EnumSetting<T>)this).SetValue(Convert.ToInt32(((EnumSetting<T>)this).GetDefaultValue()), _handler, false);
		}

		public void RefreshFromConfig()
		{
			((EnumSetting<T>)this).SetValue(Convert.ToInt32(_entry.Value), _handler, false);
		}
	}
	internal static class ConfigSettingFactory
	{
		internal static IConfigBoundSetting Create(ConfigEntryBase entry, ISettingHandler handler)
		{
			if (!(entry is ConfigEntry<float> entry2))
			{
				if (entry is ConfigEntry<bool> entry3)
				{
					return new ConfigBoolSetting(entry3, handler);
				}
				Type settingType = entry.SettingType;
				if (settingType.IsEnum)
				{
					return (IConfigBoundSetting)Activator.CreateInstance(typeof(ConfigEnumSetting<>).MakeGenericType(settingType), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[2] { entry, handler }, null);
				}
				return null;
			}
			return new ConfigFloatSetting(entry2, handler);
		}
	}
	internal class DropdownOverlayFix : MonoBehaviour
	{
		private const string DropdownListName = "Dropdown List";

		private const string BlockerName = "Blocker";

		private const int ListSortingOrder = 30100;

		private const int BlockerSortingOrder = 30099;

		private TMP_Dropdown _dropdown;

		private RectTransform _rootCanvas;

		internal static void Attach(GameObject control, RectTransform rootCanvas)
		{
			TMP_Dropdown componentInChildren = control.GetComponentInChildren<TMP_Dropdown>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				DropdownOverlayFix dropdownOverlayFix = control.AddComponent<DropdownOverlayFix>();
				dropdownOverlayFix._dropdown = componentInChildren;
				dropdownOverlayFix._rootCanvas = rootCanvas;
			}
		}

		private void LateUpdate()
		{
			if ((Object)(object)_dropdown == (Object)null)
			{
				return;
			}
			RaiseBlocker();
			Transform val = ((Component)_dropdown).transform.Find("Dropdown List");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			val.SetParent((Transform)(object)_rootCanvas, true);
			val.SetAsLastSibling();
			Canvas component = ((Component)val).GetComponent<Canvas>();
			if ((Object)(object)component != (Object)null)
			{
				component.overrideSorting = true;
				component.sortingOrder = 30100;
				if ((Object)(object)((Component)val).GetComponent<GraphicRaycaster>() == (Object)null)
				{
					((Component)val).gameObject.AddComponent<GraphicRaycaster>();
				}
			}
		}

		private void RaiseBlocker()
		{
			Transform val = ((Transform)_rootCanvas).Find("Blocker");
			if (!((Object)(object)val == (Object)null))
			{
				Canvas component = ((Component)val).GetComponent<Canvas>();
				if (!((Object)(object)component == (Object)null) && component.sortingOrder != 30099)
				{
					component.overrideSorting = true;
					component.sortingOrder = 30099;
				}
			}
		}
	}
	internal class JaggedPanel : MonoBehaviour
	{
		private Image _fillImage;

		private Image _grainImage;

		private RectTransform _rect;

		private int _jagFrame;

		private float _jagFrameTimer;

		private Vector2 _bakedSize = Vector2.zero;

		internal float Alpha { get; set; } = 1f;

		internal static JaggedPanel Create(RectTransform parent, string name, Vector2 size)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			val2.sizeDelta = size;
			JaggedPanel jaggedPanel = val.AddComponent<JaggedPanel>();
			jaggedPanel._rect = val2;
			jaggedPanel._fillImage = val.GetComponent<Image>();
			jaggedPanel._fillImage.type = (Type)0;
			((Graphic)jaggedPanel._fillImage).raycastTarget = true;
			GameObject val3 = new GameObject("GrainMask", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Mask)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = new Vector2(11f, 11f);
			val4.offsetMax = new Vector2(-11f, -11f);
			Image component = val3.GetComponent<Image>();
			component.sprite = PanelChrome.MaskSprite(128, Mathf.Max(1f, 15f));
			component.type = (Type)1;
			((Graphic)component).raycastTarget = false;
			val3.GetComponent<Mask>().showMaskGraphic = false;
			GameObject val5 = new GameObject("Grain", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform val6 = (RectTransform)val5.transform;
			((Transform)val6).SetParent((Transform)(object)val4, false);
			val6.anchorMin = Vector2.zero;
			val6.anchorMax = Vector2.one;
			val6.offsetMin = Vector2.zero;
			val6.offsetMax = Vector2.zero;
			jaggedPanel._grainImage = val5.GetComponent<Image>();
			Texture2D val7 = PanelChrome.GrainTexture();
			jaggedPanel._grainImage.sprite = Sprite.Create(val7, new Rect(0f, 0f, (float)((Texture)val7).width, (float)((Texture)val7).height), new Vector2(0.5f, 0.5f), 100f);
			((Graphic)jaggedPanel._grainImage).raycastTarget = false;
			jaggedPanel.Rebake();
			return jaggedPanel;
		}

		private void Update()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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)
			_jagFrameTimer += Time.unscaledDeltaTime;
			if (_jagFrameTimer >= 0.5f)
			{
				_jagFrameTimer = 0f;
				_jagFrame = (_jagFrame + 1) % 3;
				ApplyFrame();
			}
			Rect rect = _rect.rect;
			if (((Rect)(ref rect)).size != _bakedSize)
			{
				Rebake();
			}
			ApplyAlpha();
		}

		private void Rebake()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = _rect.rect;
			_bakedSize = ((Rect)(ref rect)).size;
			ApplyFrame();
			ApplyAlpha();
		}

		private void ApplyFrame()
		{
			int width = Mathf.Max(1, Mathf.RoundToInt(_bakedSize.x));
			int height = Mathf.Max(1, Mathf.RoundToInt(_bakedSize.y));
			_fillImage.sprite = PanelChrome.PanelSprite(width, height, _jagFrame);
		}

		private void ApplyAlpha()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)_fillImage).color = new Color(1f, 1f, 1f, Alpha);
			((Graphic)_grainImage).color = new Color(1f, 1f, 1f, Alpha);
		}
	}
	internal static class NativeResolutionCamera
	{
		private static readonly HashSet<Camera> _registered = new HashSet<Camera>();

		private static bool _subscribed;

		private static float _savedRenderScale;

		private static bool _overrodeThisRender;

		internal static void Register(Camera camera)
		{
			if (!((Object)(object)camera == (Object)null))
			{
				_registered.Add(camera);
				StripUnneededWork(camera);
				if (!_subscribed)
				{
					RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
					RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
					_subscribed = true;
				}
			}
		}

		private static void StripUnneededWork(Camera camera)
		{
			UniversalAdditionalCameraData universalAdditionalCameraData = CameraExtensions.GetUniversalAdditionalCameraData(camera);
			universalAdditionalCameraData.renderPostProcessing = false;
			universalAdditionalCameraData.renderShadows = false;
			universalAdditionalCameraData.antialiasing = (AntialiasingMode)0;
			universalAdditionalCameraData.requiresDepthOption = (CameraOverrideOption)0;
			universalAdditionalCameraData.requiresColorOption = (CameraOverrideOption)0;
			universalAdditionalCameraData.dithering = false;
			universalAdditionalCameraData.stopNaN = false;
		}

		internal static void Unregister(Camera camera)
		{
			_registered.Remove(camera);
		}

		private static void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
		{
			_overrodeThisRender = false;
			if (_registered.Contains(camera))
			{
				RenderPipelineAsset currentRenderPipeline = GraphicsSettings.currentRenderPipeline;
				UniversalRenderPipelineAsset val = (UniversalRenderPipelineAsset)(object)((currentRenderPipeline is UniversalRenderPipelineAsset) ? currentRenderPipeline : null);
				if (val != null && val.renderScale != 1f)
				{
					_savedRenderScale = val.renderScale;
					val.renderScale = 1f;
					_overrodeThisRender = true;
				}
			}
		}

		private static void OnEndCameraRendering(ScriptableRenderContext context, Camera camera)
		{
			if (_overrodeThisRender && _registered.Contains(camera))
			{
				RenderPipelineAsset currentRenderPipeline = GraphicsSettings.currentRenderPipeline;
				UniversalRenderPipelineAsset val = (UniversalRenderPipelineAsset)(object)((currentRenderPipeline is UniversalRenderPipelineAsset) ? currentRenderPipeline : null);
				if (val != null)
				{
					val.renderScale = _savedRenderScale;
				}
				_overrodeThisRender = false;
			}
		}
	}
	internal static class NativeSettingCells
	{
		private const float LabelInset = 18f;

		private const float LabelHeight = 30f;

		private const float LabelTopPadding = 8f;

		private const float ControlHeight = 52f;

		private const float ControlBottomPadding = 12f;

		internal const float RowHeight = 108f;

		private const float DropdownBoxPadding = 4f;

		private const float RowCornerRadius = 12f;

		private static bool _dumpedOneDropdown;

		private static readonly Color RowPlateColor = new Color(14f / 85f, 0.21960784f, 42f / 85f, 0.92f);

		internal static bool TryFindPrefab()
		{
			InputCellMapper instance = SingletonAsset<InputCellMapper>.Instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)instance.EnumSettingCell != (Object)null)
			{
				return (Object)(object)instance.FloatSettingCell != (Object)null;
			}
			return false;
		}

		internal static GameObject CreateRow(RectTransform parent, IConfigBoundSetting bound, ISettingHandler handler, Action<string, string> onHover, RectTransform rootCanvas)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0044: Expected O, but got Unknown
			GameObject settingUICell = bound.Setting.GetSettingUICell();
			if ((Object)(object)settingUICell == (Object)null)
			{
				return null;
			}
			GameObject obj = CreatePlate(parent, bound.DisplayName);
			RectTransform val = (RectTransform)obj.transform;
			BuildLabel(val, bound.DisplayName);
			AttachHoverDescription(dropdown: BuildControl(val, settingUICell, bound, handler, rootCanvas), rowGo: obj, tooltip: bound.Tooltip, defaultValueText: bound.DefaultValueText, onHover: onHover);
			return obj;
		}

		internal static GameObject CreateKeyBindRow(RectTransform parent, ConfigEntry<KeyCode> entry, Action<string, string> onHover)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			string displayName = ConfigSettingNaming.DisplayName((ConfigEntryBase)(object)entry);
			GameObject obj = CreatePlate(parent, displayName);
			RectTransform val = (RectTransform)obj.transform;
			BuildLabel(val, displayName);
			BuildKeyBindControl(val, entry);
			AttachHoverDescription(obj, ConfigSettingNaming.Tooltip((ConfigEntryBase)(object)entry), ((ConfigEntryBase)entry).DefaultValue.ToString().ToUpperInvariant(), onHover, null);
			return obj;
		}

		private static GameObject CreatePlate(RectTransform parent, string displayName)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			GameObject val = new GameObject("SoD.SettingRow." + displayName, new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			((Transform)(RectTransform)val.transform).SetParent((Transform)(object)parent, false);
			Image component = val.GetComponent<Image>();
			component.sprite = PanelChrome.MakeRoundedSprite(64, 12f, 0f, Color.white, Color.white);
			component.type = (Type)1;
			((Graphic)component).color = RowPlateColor;
			((Graphic)component).raycastTarget = true;
			return val;
		}

		private static void BuildKeyBindControl(RectTransform row, ConfigEntry<KeyCode> entry)
		{
			//IL_0018: 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_0028: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: 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_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Expected O, but got Unknown
			RectTransform val = (RectTransform)new GameObject("Control", new Type[1] { typeof(RectTransform) }).transform;
			((Transform)val).SetParent((Transform)(object)row, false);
			val.anchorMin = new Vector2(0f, 0f);
			val.anchorMax = new Vector2(1f, 0f);
			val.pivot = new Vector2(0.5f, 0f);
			val.offsetMin = new Vector2(18f, 12f);
			val.offsetMax = new Vector2(-18f, 64f);
			InputCellMapper instance = SingletonAsset<InputCellMapper>.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.FloatSettingCell == (Object)null)
			{
				return;
			}
			GameObject val2 = Object.Instantiate<GameObject>(instance.FloatSettingCell, (Transform)(object)val);
			val2.SetActive(true);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			val3.offsetMin = Vector2.zero;
			val3.offsetMax = Vector2.zero;
			FloatSettingUI component = val2.GetComponent<FloatSettingUI>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.inputField == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return;
			}
			TMP_InputField inputField = component.inputField;
			GameObject gameObject = ((Component)inputField).gameObject;
			TMP_Text textComponent = inputField.textComponent;
			if ((Object)(object)inputField.placeholder != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)inputField.placeholder).gameObject);
			}
			if ((Object)(object)component.slider != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)((Component)component.slider).gameObject);
			}
			Object.DestroyImmediate((Object)(object)inputField);
			Object.DestroyImmediate((Object)(object)component);
			RectTransform val4 = (RectTransform)gameObject.transform;
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = new Vector2(20f, 4f);
			val4.offsetMax = new Vector2(-20f, -4f);
			if ((Object)(object)textComponent != (Object)null)
			{
				RectTransform val5 = (RectTransform)textComponent.transform;
				val5.anchorMin = Vector2.zero;
				val5.anchorMax = Vector2.one;
				val5.offsetMin = new Vector2(14f, 0f);
				val5.offsetMax = new Vector2(-14f, 0f);
				textComponent.alignment = (TextAlignmentOptions)514;
				textComponent.enableWordWrapping = false;
				textComponent.enableAutoSizing = true;
				textComponent.fontSizeMin = 14f;
				textComponent.fontSizeMax = 26f;
				((Graphic)textComponent).raycastTarget = false;
			}
			KeyRebindControl keyRebindControl = gameObject.AddComponent<KeyRebindControl>();
			keyRebindControl.Entry = entry;
			keyRebindControl.Label = textComponent;
			keyRebindControl.ShowCurrentKey();
			Button val6 = gameObject.GetComponent<Button>();
			if ((Object)(object)val6 == (Object)null)
			{
				val6 = gameObject.AddComponent<Button>();
			}
			((UnityEvent)val6.onClick).AddListener(new UnityAction(keyRebindControl.BeginListening));
		}

		private static void BuildLabel(RectTransform row, string displayName)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Label", new Type[2]
			{
				typeof(RectTransform),
				typeof(TextMeshProUGUI)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)row, false);
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.pivot = new Vector2(0.5f, 1f);
			val2.offsetMin = new Vector2(18f, -38f);
			val2.offsetMax = new Vector2(-18f, -8f);
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = displayName;
			((TMP_Text)component).fontSize = 21f;
			((Graphic)component).color = PanelChrome.BodyColor;
			((TMP_Text)component).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)component).enableWordWrapping = false;
			((TMP_Text)component).overflowMode = (TextOverflowModes)3;
			((TMP_Text)component).enableAutoSizing = true;
			((TMP_Text)component).fontSizeMin = 14f;
			((TMP_Text)component).fontSizeMax = 21f;
			((Graphic)component).raycastTarget = false;
			if ((Object)(object)NativeAssets.Font != (Object)null)
			{
				((TMP_Text)component).font = NativeAssets.Font;
			}
			if ((Object)(object)NativeAssets.OutlineMaterial != (Object)null)
			{
				((TMP_Text)component).fontSharedMaterial = NativeAssets.OutlineMaterial;
			}
		}

		private static TMP_Dropdown BuildControl(RectTransform row, GameObject controlPrefab, IConfigBoundSetting bound, ISettingHandler handler, RectTransform rootCanvas)
		{
			//IL_0018: 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_0028: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)new GameObject("Control", new Type[1] { typeof(RectTransform) }).transform;
			((Transform)val).SetParent((Transform)(object)row, false);
			val.anchorMin = new Vector2(0f, 0f);
			val.anchorMax = new Vector2(1f, 0f);
			val.pivot = new Vector2(0.5f, 0f);
			val.offsetMin = new Vector2(18f, 12f);
			val.offsetMax = new Vector2(-18f, 64f);
			SettingInputUICell component = Object.Instantiate<GameObject>(controlPrefab, (Transform)(object)val).GetComponent<SettingInputUICell>();
			((Component)component).gameObject.SetActive(true);
			RectTransform val2 = (RectTransform)((Component)component).transform;
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = Vector2.zero;
			TMP_Dropdown componentInChildren = ((Component)component).GetComponentInChildren<TMP_Dropdown>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				FitDropdownBox(componentInChildren);
			}
			component.Setup(bound.Setting, handler);
			DropdownOverlayFix.Attach(((Component)component).gameObject, rootCanvas);
			if ((Object)(object)componentInChildren != (Object)null && !_dumpedOneDropdown)
			{
				_dumpedOneDropdown = true;
				UiDebugDump.DumpDeferred(((Component)row).gameObject, "dropdown row: " + bound.DisplayName);
			}
			return componentInChildren;
		}

		private static void FitDropdownBox(TMP_Dropdown dropdown)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)((Component)dropdown).transform;
			val.sizeDelta = new Vector2(val.sizeDelta.x, -8f);
			val.anchoredPosition = new Vector2(val.anchoredPosition.x, 0f);
			TMP_Text captionText = dropdown.captionText;
			if (!((Object)(object)captionText == (Object)null))
			{
				((Component)captionText).gameObject.SetActive(true);
				RectTransform val2 = (RectTransform)captionText.transform;
				val2.anchorMin = Vector2.zero;
				val2.anchorMax = Vector2.one;
				val2.offsetMin = new Vector2(14f, 0f);
				val2.offsetMax = new Vector2(-34f, 0f);
				captionText.alignment = (TextAlignmentOptions)4097;
				captionText.enableWordWrapping = false;
				captionText.enableAutoSizing = true;
				captionText.fontSizeMin = 14f;
				captionText.fontSizeMax = 26f;
			}
		}

		private static void AttachHoverDescription(GameObject rowGo, string tooltip, string defaultValueText, Action<string, string> onHover, TMP_Dropdown dropdown)
		{
			if (!string.IsNullOrEmpty(tooltip) && onHover != null)
			{
				SettingRowHover settingRowHover = rowGo.AddComponent<SettingRowHover>();
				settingRowHover.Tooltip = tooltip;
				settingRowHover.DefaultValueText = defaultValueText;
				settingRowHover.OnHover = onHover;
				settingRowHover.Dropdown = dropdown;
			}
		}
	}
	internal class KeyRebindControl : MonoBehaviour
	{
		internal ConfigEntry<KeyCode> Entry;

		internal TMP_Text Label;

		internal static bool IsCapturing { get; private set; }

		internal void BeginListening()
		{
			IsCapturing = true;
			SetCaption(PreviewMenuLocalization.Current.PressAKey);
		}

		internal void ShowCurrentKey()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			SetCaption(((object)Entry.Value/*cast due to .constrained prefix*/).ToString().ToUpperInvariant());
		}

		private void SetCaption(string caption)
		{
			if ((Object)(object)Label != (Object)null)
			{
				Label.text = caption;
			}
		}

		private void OnGUI()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!IsCapturing || (Object)(object)Label == (Object)null)
			{
				return;
			}
			Event current = Event.current;
			if (current != null && (int)current.type == 4 && (int)current.keyCode != 0)
			{
				IsCapturing = false;
				if ((int)current.keyCode != 27)
				{
					Entry.Value = current.keyCode;
				}
				ShowCurrentKey();
				current.Use();
			}
		}

		private void OnDisable()
		{
			IsCapturing = false;
		}
	}
	internal class SettingRowHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		internal string Tooltip;

		internal string DefaultValueText;

		internal Action<string, string> OnHover;

		internal TMP_Dropdown Dropdown;

		private bool _pointerOver;

		private bool _dropdownWasExpanded;

		public void OnPointerEnter(PointerEventData eventData)
		{
			_pointerOver = true;
			OnHover?.Invoke(Tooltip, DefaultValueText);
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			_pointerOver = false;
			if (!((Object)(object)Dropdown != (Object)null) || !Dropdown.IsExpanded)
			{
				OnHover?.Invoke(null, null);
			}
		}

		private void Update()
		{
			if (!((Object)(object)Dropdown == (Object)null))
			{
				bool isExpanded = Dropdown.IsExpanded;
				if (_dropdownWasExpanded && !isExpanded && !_pointerOver)
				{
					OnHover?.Invoke(null, null);
				}
				_dropdownWasExpanded = isExpanded;
			}
		}
	}
	internal static class PanelChrome
	{
		internal static readonly Color DimColor = new Color(0f, 0f, 0f, 0.78f);

		internal static readonly Color PanelFillColor = new Color(0.20392157f, 28f / 85f, 0.81960785f);

		internal static readonly Color PanelBorderColor = new Color(11f / 85f, 0.192