Decompiled source of ImmersiveCameraEnhanced v1.6.1

BepInEx/plugins/ImmersiveCameraEnhanced/ImmersiveCameraEnhanced.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CameraCull
{
	internal sealed class ConfigurationManagerAttributes
	{
		public string Category;

		public string DispName;

		public int? Order;

		public bool? Browsable;
	}
	[BepInPlugin("com.kimbauer.valheim.cameracull", "Immersive Camera Enhanced", "1.6.1")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Id = "com.kimbauer.valheim.cameracull";

		public const string Version = "1.6.1";

		internal static Plugin Instance;

		internal static CameraCullController Controller;

		internal const int CameraCollisionMask = -1;

		internal static ConfigEntry<bool> EnableMod;

		internal static ConfigEntry<bool> DisableModWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> DisableCameraCullWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> DisableCameraCollisionWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> DisableCameraImprovementsWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> DisableDamageIndicatorWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> DisableBrightnessAdjustmentWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> BlockCameraDistanceScrollWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> DisableBowTrajectoryCompatibilityWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> DisableBowCrosshairMouseAimWhileBuildingHammerEquipped;

		internal static ConfigEntry<bool> DisableCrosshairWhileBuildingHammerEquipped;

		internal static int CrosshairSettingsRevision;

		internal static int RuntimeSettingsRevision;

		internal static ConfigEntry<bool> EnableCylinderOcclusion;

		internal static ConfigEntry<float> CylinderCameraWidthPercent;

		internal static ConfigEntry<float> ConeCharacterDistance;

		internal static ConfigEntry<bool> CullHousePillars;

		internal static ConfigEntry<bool> LeavesOnly;

		internal static ConfigEntry<bool> MovementLeavesOnly;

		internal static ConfigEntry<float> MovementLeavesOnlyActivationDelay;

		internal static ConfigEntry<bool> EnableFirstPersonCamera;

		internal static ConfigEntry<bool> RequireTwoScrollsToExitFirstPerson;

		internal static ConfigEntry<bool> EnableFirstPersonCameraSway;

		internal static ConfigEntry<bool> EnableFirstPersonCameraAnimations;

		internal static ConfigEntry<bool> ShowFirstPersonWeaponsAndTools;

		internal static ConfigEntry<bool> HideFirstPersonHeldItemsWhenZoomed;

		internal static ConfigEntry<bool> EnableFirstPersonBodycam;

		internal static ConfigEntry<bool> EnableFirstPersonBodycamSteps;

		internal static ConfigEntry<bool> ShowFirstPersonBody;

		internal static ConfigEntry<bool> EnableFirstPersonCameraFov;

		internal static ConfigEntry<bool> EnableThirdPersonCameraFov;

		internal static ConfigEntry<float> FirstPersonCameraFov;

		internal static ConfigEntry<float> ThirdPersonCameraFov;

		internal static ConfigEntry<bool> EnableCameraZoom;

		internal static ConfigEntry<KeyboardShortcut> CameraZoomKey;

		internal static ConfigEntry<float> CameraZoomDefaultMagnification;

		internal static ConfigEntry<float> CameraZoomMagnificationStep;

		internal static ConfigEntry<float> CameraZoomMaxMagnification;

		internal static ConfigEntry<float> CameraZoomSmoothSpeed;

		internal static ConfigEntry<float> CameraZoomMouseSensitivityFactor;

		internal static ConfigEntry<float> CameraDistanceSmoothSpeed;

		internal static ConfigEntry<bool> EnableCameraDistanceSmoothing;

		internal static ConfigEntry<bool> EnableCameraScrollDistanceStep;

		internal static ConfigEntry<float> CameraScrollDistanceStepMeters;

		internal static ConfigEntry<float> AdvancedCameraScrollDistanceStepMeters;

		internal static ConfigEntry<bool> EnableCameraDistanceLimits;

		internal static ConfigEntry<bool> EnableNewCameraCollision;

		internal static ConfigEntry<bool> EnableCameraBasePosition;

		internal static ConfigEntry<float> CameraBasePositionFullStrengthDistance;

		internal static ConfigEntry<bool> EnableAutomaticCrosshairPosition;

		internal static ConfigEntry<bool> EnableCustomCrosshair;

		internal static ConfigEntry<bool> ShowVanillaInteractionCrosshair;

		internal static ConfigEntry<bool> EnableBowCrosshairMouseAim;

		internal static ConfigEntry<bool> EnableAimAlongCrosshairDirection;

		internal static ConfigEntry<bool> EnableBowTrajectoryCompatibility;

		internal static ConfigEntry<bool> EnableBetterArcheryCrosshairCompatibility;

		internal static ConfigEntry<bool> EnableBetterArcheryBowZoomCompatibility;

		internal static ConfigEntry<bool> EnableHeadLookAtCameraDirection;

		internal static ConfigEntry<bool> EnableBowDrawCrosshairAnimation;

		internal static ConfigEntry<CrosshairStyle> CrosshairStyleDefault;

		internal static ConfigEntry<CrosshairStyle> CrosshairStyleMelee;

		internal static ConfigEntry<CrosshairStyle> CrosshairStyleBow;

		internal static ConfigEntry<CrosshairStyle> CrosshairStyleMagic;

		internal static ConfigEntry<CrosshairStyle> CrosshairStyleTools;

		internal static ConfigEntry<float> CrosshairPositionXPercent;

		internal static ConfigEntry<float> CrosshairPositionYPercent;

		internal static ConfigEntry<float> CrosshairPositionMeleeXPercent;

		internal static ConfigEntry<float> CrosshairPositionMeleeYPercent;

		internal static ConfigEntry<float> CrosshairPositionBowXPercent;

		internal static ConfigEntry<float> CrosshairPositionBowYPercent;

		internal static ConfigEntry<float> CrosshairPositionMagicXPercent;

		internal static ConfigEntry<float> CrosshairPositionMagicYPercent;

		internal static ConfigEntry<float> CrosshairPositionToolsXPercent;

		internal static ConfigEntry<float> CrosshairPositionToolsYPercent;

		internal static ConfigEntry<string> CustomCrosshairImage;

		internal static ConfigEntry<float> CrosshairSizeDefault;

		internal static ConfigEntry<float> CrosshairSizeMelee;

		internal static ConfigEntry<float> CrosshairSizeBow;

		internal static ConfigEntry<float> CrosshairSizeMagic;

		internal static ConfigEntry<float> CrosshairSizeTools;

		internal static ConfigEntry<float> CrosshairThickness;

		internal static ConfigEntry<float> CrosshairGap;

		internal static ConfigEntry<float> CrosshairColorRed;

		internal static ConfigEntry<float> CrosshairColorGreen;

		internal static ConfigEntry<float> CrosshairColorBlue;

		internal static ConfigEntry<float> CrosshairColorMeleeRed;

		internal static ConfigEntry<float> CrosshairColorMeleeGreen;

		internal static ConfigEntry<float> CrosshairColorMeleeBlue;

		internal static ConfigEntry<float> CrosshairColorBowRed;

		internal static ConfigEntry<float> CrosshairColorBowGreen;

		internal static ConfigEntry<float> CrosshairColorBowBlue;

		internal static ConfigEntry<float> CrosshairColorMagicRed;

		internal static ConfigEntry<float> CrosshairColorMagicGreen;

		internal static ConfigEntry<float> CrosshairColorMagicBlue;

		internal static ConfigEntry<float> CrosshairColorToolsRed;

		internal static ConfigEntry<float> CrosshairColorToolsGreen;

		internal static ConfigEntry<float> CrosshairColorToolsBlue;

		internal static ConfigEntry<float> LegacyCrosshairPositionX;

		internal static ConfigEntry<float> LegacyCrosshairPositionY;

		internal static bool MigrateCrosshairPositionXFromPixels;

		internal static bool MigrateCrosshairPositionYFromPixels;

		internal static ConfigEntry<float> CrosshairAimMouseSensitivity;

		internal static ConfigEntry<float> CrosshairAimAltHoldDuration;

		internal static ConfigEntry<float> CrosshairAimMouseResumeDelay;

		internal static ConfigEntry<bool> CrosshairAimMouseInvertX;

		internal static ConfigEntry<bool> CrosshairAimMouseInvertY;

		internal static ConfigEntry<float> CameraBasePositionY;

		internal static ConfigEntry<bool> EnableFirstPersonFreeLook;

		internal static ConfigEntry<KeyboardShortcut> FirstPersonFreeLookKey;

		internal static ConfigEntry<bool> EnableAdvancedCamera;

		internal static ConfigEntry<KeyboardShortcut> AdvancedCameraTemporaryDisableKey;

		internal static ConfigEntry<float> AdvancedCameraActivationInterval;

		internal static ConfigEntry<float> AdvancedCameraDeactivationInterval;

		internal static ConfigEntry<bool> EnableCaveMap;

		internal static ConfigEntry<bool> EnableCaveMapSatelliteCompatibility;

		internal static ConfigEntry<bool> EnableAdvancedCameraHeightClearance;

		internal static ConfigEntry<float> AdvancedCameraHeightFreedomPercent;

		internal static ConfigEntry<bool> EnableDamageDirectionIndicator;

		internal static ConfigEntry<bool> DamageDirectionIndicatorPointToSource;

		internal static ConfigEntry<float> DamageDirectionIndicatorDuration;

		internal static ConfigEntry<float> DamageDirectionIndicatorSourceUpdateInterval;

		internal static ConfigEntry<float> DamageDirectionIndicatorThirdPersonSize;

		internal static ConfigEntry<float> DamageDirectionIndicatorFirstPersonSize;

		internal static ConfigEntry<float> DamageDirectionIndicatorRed;

		internal static ConfigEntry<float> DamageDirectionIndicatorGreen;

		internal static ConfigEntry<float> DamageDirectionIndicatorBlue;

		internal static ConfigEntry<float> DamageDirectionIndicatorWorldPositionX;

		internal static ConfigEntry<float> DamageDirectionIndicatorWorldPositionY;

		internal static ConfigEntry<float> DamageDirectionIndicatorWorldPositionZ;

		internal static ConfigEntry<float> DamageDirectionIndicatorFirstPersonPositionX;

		internal static ConfigEntry<float> DamageDirectionIndicatorFirstPersonPositionY;

		internal static ConfigEntry<float> DamageDirectionIndicatorFirstPersonPositionZ;

		internal static ConfigEntry<float> ThirdPersonCameraDistance;

		internal static ConfigEntry<float> BoatCameraDistance;

		internal static ConfigEntry<bool> IgnoreVegetationCollision;

		internal static ConfigEntry<bool> IgnoreHousePillarCollision;

		internal static ConfigEntry<bool> IgnoreMovingDoorCollision;

		internal static ConfigEntry<bool> IgnoreHouseLightCollision;

		internal static ConfigEntry<bool> IgnoreEntityCollision;

		internal static ConfigEntry<bool> IgnoreBoatCollision;

		internal const float CameraCylinderCameraSideDiameterOffset = -0.7f;

		internal static ConfigEntry<float> CameraCollisionRecoverySpeed;

		internal static ConfigEntry<float> CameraGroundCollisionMinimumDistancePercent;

		internal const float CameraCylinderCharacterTipX = 0f;

		internal const float CameraCylinderCharacterTipY = -0.7f;

		internal const float CameraCylinderCharacterTipZ = 0f;

		internal const float CameraCylinderCameraEndOffset = 0f;

		internal const float CameraCylinderCharacterSideWidthPercent = 0f;

		internal const float CameraCylinderGrowthExponent = 2.4f;

		internal const float CameraCylinderVerticalFlattenPercent = 0f;

		internal const bool CameraCylinderFlattenBottom = false;

		internal const float CameraCylinderHorizontalFlattenPercent = 0f;

		internal static ConfigEntry<bool> EnableCollisionDistanceTransition;

		internal static ConfigEntry<float> CollisionDistanceMinimumPercent;

		internal static ConfigEntry<float> CollisionDistanceMinimumAbsoluteReduction;

		internal static ConfigEntry<bool> ShowCameraDistanceHud;

		internal static ConfigEntry<float> CameraDistanceHudX;

		internal static ConfigEntry<float> CameraDistanceHudY;

		internal static ConfigEntry<bool> EnableAdvancedCameraEdgeClearance;

		internal static ConfigEntry<bool> KeepFoundationFloorRoofCollision;

		internal static ConfigEntry<float> BackCylinderLength;

		internal static ConfigEntry<float> ConeGrowthExponent;

		internal static ConfigEntry<float> ConeRearRadiusMultiplier;

		internal static ConfigEntry<float> CylinderVerticalFlattenPercent;

		internal static ConfigEntry<bool> CylinderFlattenBottom;

		internal static ConfigEntry<float> CylinderHorizontalFlattenPercent;

		internal static ConfigEntry<float> CylinderTopFlattenPercent;

		internal static ConfigEntry<float> CylinderSlicesPerMeter;

		internal static ConfigEntry<float> CylinderExponentInfluencePercent;

		internal static ConfigEntry<float> CylinderCheckInterval;

		internal static ConfigEntry<float> CylinderRestoreDelay;

		internal static ConfigEntry<bool> PreserveVegetationShadows;

		internal static ConfigEntry<bool> EnableBrightnessAdjustment;

		internal static ConfigEntry<float> DayBrightnessPercent;

		internal static ConfigEntry<float> NightBrightnessPercent;

		internal static ConfigEntry<float> FogCaveBrightnessPercent;

		internal const string VegetationNameTokens = "tree,beech,birch,oak,pine,fir,ash,juniper,yggdrasil,stubbe,stump,treestump,tree_stump,ashlandstump,swamptree,sapling,bush,shrub,berry,raspberry,blueberry,cloudberry,mushroom,thistle,dandelion,grass,plant,fern,reed,vine,root,trunk,branch,treelog,treebase,foliage,leaf,leaves,flax,barley,carrot,turnip,onion,guck,gucksack";

		internal const string ProtectedNameTokens = "terrain,water,ocean,seafloor,sky,sun,moon,fog,minimap,map,loading,menu,ui,hud,player,character,creature,enemy,boss,vfx,particle,smoke,projectile,itemdrop,pickup,portal,rock,stone,boulder,ore,oredeposit,flint";

		internal static ConfigEntry<bool> DebugLogging;

		internal static ConfigEntry<bool> ShowOcclusionCylinder;

		internal static ConfigEntry<float> CylinderDebugOpacity;

		internal static ConfigEntry<bool> ShowCameraCollisionColliders;

		internal static ConfigEntry<bool> ShowCameraCollisionVolume;

		private const string CrosshairPositionCategory = "25 - Crosshair Position and Mouse Aim";

		private const string CrosshairAppearanceCategory = "26 - Crosshair Appearance (Style and Color)";

		private const string CompatibilityCategory = "27 - Compatibility";

		private Harmony harmony;

		internal static bool ModEnabled
		{
			get
			{
				if (EnableMod != null)
				{
					return EnableMod.Value;
				}
				return false;
			}
		}

		internal static bool CameraCullEnabled
		{
			get
			{
				if (ModEnabled)
				{
					return !IsHammerSuppressionActive(DisableCameraCullWhileBuildingHammerEquipped);
				}
				return false;
			}
		}

		internal static bool CameraCollisionEnabled => false;

		internal static bool CameraCylinderCollisionEnabled
		{
			get
			{
				if (ModEnabled && EnableNewCameraCollision != null && EnableNewCameraCollision.Value)
				{
					if (!((Object)(object)Controller == (Object)null) && Controller.IsBuildingHammerEquipped() && DisableCameraCollisionWhileBuildingHammerEquipped != null)
					{
						return !DisableCameraCollisionWhileBuildingHammerEquipped.Value;
					}
					return true;
				}
				return false;
			}
		}

		internal static bool CameraImprovementsEnabled
		{
			get
			{
				if (ModEnabled)
				{
					return !IsHammerSuppressionActive(DisableCameraImprovementsWhileBuildingHammerEquipped);
				}
				return false;
			}
		}

		internal static bool DamageIndicatorEnabled
		{
			get
			{
				if (ModEnabled)
				{
					return !IsHammerSuppressionActive(DisableDamageIndicatorWhileBuildingHammerEquipped);
				}
				return false;
			}
		}

		internal static bool BrightnessAdjustmentEnabled
		{
			get
			{
				if (EnableBrightnessAdjustment != null && EnableBrightnessAdjustment.Value)
				{
					return !IsHammerSuppressionActive(DisableBrightnessAdjustmentWhileBuildingHammerEquipped);
				}
				return false;
			}
		}

		internal static bool CrosshairEnabled
		{
			get
			{
				if (ModEnabled && EnableCustomCrosshair != null && EnableCustomCrosshair.Value)
				{
					return !IsHammerSuppressionActive(DisableCrosshairWhileBuildingHammerEquipped);
				}
				return false;
			}
		}

		internal static bool BowCrosshairMouseAimEnabled
		{
			get
			{
				if (ModEnabled && CameraImprovementsEnabled && EnableBowCrosshairMouseAim != null && EnableBowCrosshairMouseAim.Value)
				{
					return !IsHammerSuppressionActive(DisableBowCrosshairMouseAimWhileBuildingHammerEquipped);
				}
				return false;
			}
		}

		internal static bool BowTrajectoryCompatibilityEnabled
		{
			get
			{
				if (ModEnabled && EnableBowTrajectoryCompatibility != null && EnableBowTrajectoryCompatibility.Value)
				{
					return !IsHammerSuppressionActive(DisableBowTrajectoryCompatibilityWhileBuildingHammerEquipped);
				}
				return false;
			}
		}

		internal static bool ShouldBlockCameraDistanceScrollWhileBuildingHammerEquipped
		{
			get
			{
				if (ModEnabled && BlockCameraDistanceScrollWhileBuildingHammerEquipped != null && BlockCameraDistanceScrollWhileBuildingHammerEquipped.Value && (Object)(object)Controller != (Object)null)
				{
					return Controller.IsBuildingHammerEquipped();
				}
				return false;
			}
		}

		private static bool IsHammerSuppressionActive(ConfigEntry<bool> setting)
		{
			if (setting != null && setting.Value && (Object)(object)Controller != (Object)null)
			{
				return Controller.IsBuildingHammerEquipped();
			}
			return false;
		}

		private ConfigEntry<float> BindCrosshairColor(string setting, float defaultValue, string category, string channel, int order)
		{
			return ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", setting, defaultValue, UiDescription(channel + " channel for the " + category + " reticle color.", "26 - Crosshair Appearance (Style and Color)", order, category + " Crosshair Color - " + channel, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
		}

		private ConfigEntry<float> BindCrosshairSize(string setting, float defaultValue, string category, int order)
		{
			return ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", setting, defaultValue, UiDescription("Base diameter or arm length for this weapon category in pixels. Bow size tightens as the weapon's actual accuracy improves.", "26 - Crosshair Appearance (Style and Color)", order, category + " Crosshair Size (px)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 100f)));
		}

		private ConfigEntry<float> BindCrosshairPosition(string setting, string category, string axis, int order, float defaultValue = 0f)
		{
			return ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", setting, defaultValue, UiDescription((axis == "X") ? "Horizontal reticle offset for this item category, as a percentage of the gameplay viewport width from screen center." : "Vertical reticle offset for this item category, as a percentage of the gameplay viewport height from screen center.", "25 - Crosshair Position and Mouse Aim", order, category + " Crosshair Position " + axis + " (%)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-50f, 50f)));
		}

		internal static void MigrateLegacyCrosshairPosition(Camera camera)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)camera))
			{
				return;
			}
			Rect pixelRect = camera.pixelRect;
			if (((Rect)(ref pixelRect)).width <= 0f)
			{
				return;
			}
			pixelRect = camera.pixelRect;
			if (((Rect)(ref pixelRect)).height <= 0f)
			{
				return;
			}
			Rect pixelRect2 = camera.pixelRect;
			if (MigrateCrosshairPositionXFromPixels)
			{
				if (CrosshairPositionXPercent != null && LegacyCrosshairPositionX != null)
				{
					CrosshairPositionXPercent.Value = Mathf.Clamp(LegacyCrosshairPositionX.Value / ((Rect)(ref pixelRect2)).width * 100f, -50f, 50f);
				}
				MigrateCrosshairPositionXFromPixels = false;
			}
			if (MigrateCrosshairPositionYFromPixels)
			{
				if (CrosshairPositionYPercent != null && LegacyCrosshairPositionY != null)
				{
					CrosshairPositionYPercent.Value = Mathf.Clamp(LegacyCrosshairPositionY.Value / ((Rect)(ref pixelRect2)).height * 100f, -50f, 50f);
				}
				MigrateCrosshairPositionYFromPixels = false;
			}
		}

		internal static void TryInstallBowTrajectoryCompatibility()
		{
			if ((Object)(object)Instance != (Object)null && Instance.harmony != null)
			{
				BowTrajectoryCompatibility.TryInstall(Instance.harmony);
			}
		}

		private static ConfigDescription UiDescription(string description, string category, int order, string displayName = null, AcceptableValueBase acceptableValues = null)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			if (!string.IsNullOrEmpty(category))
			{
				int num = category.IndexOf(" / ", StringComparison.Ordinal);
				if (num >= 0)
				{
					category = category.Substring(0, num);
				}
			}
			order = GetUnifiedUiOrder(category, displayName, order);
			return new ConfigDescription(description, acceptableValues, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = category,
					Order = order,
					DispName = displayName
				}
			});
		}

		private static bool IsToggleDisplayName(string displayName)
		{
			if (string.IsNullOrEmpty(displayName))
			{
				return false;
			}
			if (!displayName.StartsWith("Enable ", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Disable ", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Ignore ", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Leaves Only", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Cull ", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Preserve ", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Block ", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Show ", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Point to ", StringComparison.OrdinalIgnoreCase) && !displayName.StartsWith("Flatten Lower Side", StringComparison.OrdinalIgnoreCase) && !string.Equals(displayName, "Automatic Crosshair Position", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(displayName, "Advanced Camera Corner Clearance", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static int GetUnifiedUiOrder(string category, string displayName, int originalOrder)
		{
			string text = displayName ?? string.Empty;
			bool flag = IsToggleDisplayName(text);
			if (string.Equals(category, "20 - Camera Improvements", StringComparison.Ordinal))
			{
				if (flag)
				{
					if (text.IndexOf("FOV", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 35000 + originalOrder;
					}
					if (text.IndexOf("First Person", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Free Look", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 36000 + originalOrder;
					}
					if (text.IndexOf("Zoom", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 34000 + originalOrder;
					}
					if (text.IndexOf("Camera Distance", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Distance HUD", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 33000 + originalOrder;
					}
					if (text.IndexOf("Camera Position", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Crosshair", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 32000 + originalOrder;
					}
					if (text.IndexOf("Advanced Camera", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 31000 + originalOrder;
					}
					return 30000 + originalOrder;
				}
				if (text.IndexOf("First Person", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Free Look", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 19000 + originalOrder;
				}
				if (text.IndexOf("FOV", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Field of View", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 18000 + originalOrder;
				}
				if (text.IndexOf("Zoom", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 17000 + originalOrder;
				}
				if (text.IndexOf("Advanced Camera", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 14000 + originalOrder;
				}
				if (text.IndexOf("Camera Distance", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Distance HUD", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Boat Camera Distance", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Scroll", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 16000 + originalOrder;
				}
				if (text.IndexOf("Camera Base Position", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Crosshair", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 15000 + originalOrder;
				}
			}
			if (string.Equals(category, "10 - Camera Collision", StringComparison.Ordinal))
			{
				if (flag)
				{
					if (text.IndexOf("New Camera Collision", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 36000 + originalOrder;
					}
					if (text.IndexOf("Collision Distance Cut", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 35000 + originalOrder;
					}
					if (text.IndexOf("Progressive", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Flatten Lower Side", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 34000 + originalOrder;
					}
					return 33000 + originalOrder;
				}
				if (text.IndexOf("Distance Reduction", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Camera Return", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 19000 + originalOrder;
				}
				if (text.IndexOf("Floor Collision", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Clearance Margin", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return 18000 + originalOrder;
				}
				return 17000 + originalOrder;
			}
			if (string.Equals(category, "00 - General", StringComparison.Ordinal))
			{
				return 1000000 + originalOrder;
			}
			if (flag)
			{
				if (string.Equals(category, "01 - Camera Cull", StringComparison.Ordinal))
				{
					if (text.IndexOf("Enable Immersive", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 36000 + originalOrder;
					}
					if (text.IndexOf("Enable Cylinder", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return 35000 + originalOrder;
					}
					return 34000 + originalOrder;
				}
				return 10000 + originalOrder;
			}
			return originalOrder;
		}

		private static void OnDamageDirectionIndicatorColorChanged(object sender, EventArgs args)
		{
			if ((Object)(object)Controller != (Object)null)
			{
				Controller.ApplyDamageDirectionArrowColors();
			}
		}

		private void Awake()
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Expected O, but got Unknown
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Expected O, but got Unknown
			//IL_07cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0813: Unknown result type (might be due to invalid IL or missing references)
			//IL_0837: Unknown result type (might be due to invalid IL or missing references)
			//IL_0841: Invalid comparison between Unknown and I4
			//IL_0efe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f08: Expected O, but got Unknown
			//IL_0f5a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f64: Expected O, but got Unknown
			//IL_0856: Unknown result type (might be due to invalid IL or missing references)
			//IL_171d: Unknown result type (might be due to invalid IL or missing references)
			//IL_178f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1eef: Unknown result type (might be due to invalid IL or missing references)
			//IL_1ef9: Expected O, but got Unknown
			//IL_204f: Unknown result type (might be due to invalid IL or missing references)
			//IL_2059: Expected O, but got Unknown
			//IL_22b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_22c1: Expected O, but got Unknown
			//IL_2499: Unknown result type (might be due to invalid IL or missing references)
			//IL_24a3: Expected O, but got Unknown
			//IL_26f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_2700: Expected O, but got Unknown
			//IL_28e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_28e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_28eb: Expected O, but got Unknown
			//IL_28fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_2905: Expected O, but got Unknown
			Instance = this;
			float? num = ReadOrphanedFloatConfiguration("Crosshair", "CrosshairSize");
			bool flag = HasConfigDefinition("Crosshair", "CrosshairSizeDefault");
			bool flag2 = HasConfigDefinition("Crosshair", "CrosshairSizeMelee");
			bool flag3 = HasConfigDefinition("Crosshair", "CrosshairSizeBow");
			bool flag4 = HasConfigDefinition("Crosshair", "CrosshairSizeMagic");
			bool flag5 = HasConfigDefinition("Crosshair", "CrosshairSizeTools");
			bool flag6 = RemoveRetiredCameraConfiguration();
			bool flag7 = HasConfigDefinition("Crosshair", "CrosshairPositionXPercent");
			bool flag8 = HasConfigDefinition("Crosshair", "CrosshairPositionYPercent");
			ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "Enabled", true, new ConfigDescription("Legacy key retained for migration.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -100,
					Browsable = false
				}
			}));
			EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "EnableMod", val.Value, UiDescription("Master switch. When disabled, all mod features are inactive. While the building hammer is held, brightness is unaffected by the individual feature toggles.", "00 - General", 100, "Enable Immersive Camera Enhanced"));
			DisableModWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableModWhileBuildingHammerEquipped", true, new ConfigDescription("Legacy hammer setting retained to initialize the individual hammer options.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -60,
					Browsable = false
				}
			}));
			bool value = DisableModWhileBuildingHammerEquipped.Value;
			DisableCameraCullWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableCameraCullWhileBuildingHammerEquipped", value, UiDescription("Temporarily disables Camera Cull while a building hammer is equipped. Enabled by default.", "05 - Building Hammer Behavior", 40, "Disable Camera Cull"));
			DisableCameraCollisionWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableCameraCollisionWhileBuildingHammerEquipped", value, UiDescription("Restores Valheim's original camera collision while the building hammer is equipped. Disable this only to keep the new collision cylinder active during building.", "05 - Building Hammer Behavior", 30, "Disable New Camera Collision"));
			DisableCameraImprovementsWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableCameraImprovementsWhileBuildingHammerEquipped", value, UiDescription("Temporarily disables camera improvements, including zoom, first person, and Advanced Camera, while a building hammer is equipped. Enabled by default.", "05 - Building Hammer Behavior", 20, "Disable Camera Improvements"));
			DisableDamageIndicatorWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableDamageIndicatorWhileBuildingHammerEquipped", value, UiDescription("Temporarily disables the damage-direction indicator while a building hammer is equipped. Enabled by default.", "05 - Building Hammer Behavior", 10, "Disable Damage Direction Indicator"));
			DisableBrightnessAdjustmentWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableBrightnessAdjustmentWhileBuildingHammerEquipped", false, UiDescription("Temporarily disables brightness adjustment while a building hammer is equipped. Disabled by default.", "05 - Building Hammer Behavior", 5, "Disable Brightness Adjustment"));
			BlockCameraDistanceScrollWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "BlockCameraDistanceScrollWhileBuildingHammerEquipped", true, UiDescription("Stops the scroll wheel from changing third-person camera distance while the building hammer is equipped. The wheel remains available to rotate construction pieces.", "05 - Building Hammer Behavior", 50, "Block Camera Distance Scroll"));
			DisableBowTrajectoryCompatibilityWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableBowTrajectoryCompatibilityWhileBuildingHammerEquipped", true, UiDescription("Temporarily disables the Bow Trajectory compatibility patch while a building hammer is equipped.", "05 - Building Hammer Behavior", 60, "Disable Bow Trajectory Compatibility"));
			DisableBowCrosshairMouseAimWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableBowCrosshairMouseAimWhileBuildingHammerEquipped", true, UiDescription("Temporarily disables bow/crossbow mouse aiming while a building hammer is equipped.", "05 - Building Hammer Behavior", 55, "Disable Bow Mouse Aim"));
			DisableCrosshairWhileBuildingHammerEquipped = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableCrosshairWhileBuildingHammerEquipped", true, UiDescription("Temporarily disables the custom crosshair and reticle-based aiming while a building hammer is equipped. Restores the vanilla reticle.", "05 - Building Hammer Behavior", 65, "Disable Custom Crosshair"));
			EnableCylinderOcclusion = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "EnableCameraCull", val.Value, UiDescription("Enable or disable V1 cylinder visual culling. The global Enable Mod switch controls the whole mod.", "01 - Camera Cull", 100, "Enable Cylinder Occlusion"));
			LeavesOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "LeavesOnly", false, UiDescription("V1 only: hides identified leaves on large trees; trunks and branches remain visible.", "01 - Camera Cull", 90, "Leaves Only"));
			MovementLeavesOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "MovementLeavesOnly", true, UiDescription("Temporarily uses Leaves Only while the character walks toward the camera. Direction detection is local and does not scan the scene.", "01 - Camera Cull", 80, "Leaves Only While Moving Toward Camera"));
			((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "MovementLeavesOnlyDuration", 1.5f, new ConfigDescription("Legacy value retained for compatibility; it is not used as the activation delay.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -70,
					Browsable = false
				}
			}));
			MovementLeavesOnlyActivationDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "MovementLeavesOnlyActivationDelay", 0.5f, UiDescription("Continuous movement time toward the camera before Leaves Only becomes active.", "01 - Camera Cull / Adjustments", 120, "Movement Leaves Only Activation Delay", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f)));
			EnableFirstPersonCamera = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableFirstPersonCamera", true, UiDescription("Enables first person at the minimum scroll distance, with optional Bodycam, body and held-equipment rendering. Scroll outward to return to third person.", "20 - Camera Improvements / First Person", 100, "Enable First Person"));
			RequireTwoScrollsToExitFirstPerson = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "RequireTwoScrollsToExitFirstPerson", true, UiDescription("Requires two outward wheel steps to leave first person. Entering first person still takes one step at the minimum distance. Scrolling inward cancels the pending exit.", "20 - Camera Improvements / First Person", 95, "Require Two Scrolls to Exit First Person"));
			EnableFirstPersonCameraSway = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableFirstPersonCameraSway", true, UiDescription("Adds lightweight first-person rotation sway. In Bodycam this replaces native head roll; mouse yaw and pitch remain direct.", "20 - Camera Improvements / First Person", 90, "Enable First Person Camera Sway"));
			EnableFirstPersonCameraAnimations = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableFirstPersonCameraAnimations", false, UiDescription("Smoothly lowers and raises the first-person camera while crouching. Bodycam Footsteps follows native head height instead when enabled. Does not add walking bob.", "20 - Camera Improvements / First Person", 80, "Enable First Person Crouch"));
			ShowFirstPersonWeaponsAndTools = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "ShowFirstPersonWeaponsAndTools", true, UiDescription("Shows everything equipped in either hand in first person, including weapons, shields, tools and mod-added items, with their original animations. Show First Person Body controls the body and worn equipment separately.", "20 - Camera Improvements / First Person", 75, "Show First Person Held Items"));
			EnableFirstPersonBodycam = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableFirstPersonBodycam", true, UiDescription("Follows the animated head position with direct mouse yaw and pitch. Follow Footsteps independently controls vertical head movement; Camera Sway replaces native head roll.", "20 - Camera Improvements / First Person", 74, "Enable First Person Bodycam"));
			EnableFirstPersonBodycamSteps = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableFirstPersonBodycamSteps", true, UiDescription("Lets Bodycam follow animated head height while walking and crouching. Disabled keeps walking height stable; the separate Crouch option can lower the camera. Only affects Bodycam.", "20 - Camera Improvements / First Person", 73, "Enable First Person Bodycam Footsteps"));
			ShowFirstPersonBody = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "ShowFirstPersonBody", true, UiDescription("Shows the body and worn equipment with a closed neck cut, hiding the head, hair, beard and helmet. Independent of Bodycam and held-item visibility. Disable for a held-item-only view.", "20 - Camera Improvements / First Person", 72, "Show First Person Body"));
			HideFirstPersonHeldItemsWhenZoomed = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "HideFirstPersonHeldItemsWhenZoomed", true, UiDescription("Temporarily hides everything equipped in either hand while first-person optical zoom is above 5x, including weapons, shields, tools and mod-added items. Restores the existing held-item visibility at 5x or below, on zoom release, and when leaving first person. Body visibility and attacks are unchanged.", "20 - Camera Improvements / First Person", 71, "Hide Held Items Above 5x Zoom"));
			EnableFirstPersonCameraFov = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableFirstPersonCameraFov", true, UiDescription("Applies the configured field of view while first person is active.", "20 - Camera Improvements / Field of View", 100, "Enable First Person FOV"));
			FirstPersonCameraFov = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FirstPersonCameraFov", 80f, UiDescription("Local field of view used only while vanilla first person is active. This client value overrides server and external camera settings.", "20 - Camera Improvements / Field of View / Adjustments", 100, "First Person Camera FOV", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 120f)));
			if (Mathf.Approximately(FirstPersonCameraFov.Value, 65f))
			{
				FirstPersonCameraFov.Value = 80f;
			}
			ThirdPersonCameraFov = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "ThirdPersonCameraFov", 80f, UiDescription("Local field of view used in third person. Applies immediately and overrides server or other camera-mod values while this mod is enabled.", "20 - Camera Improvements / Field of View / Adjustments", 90, "Third Person Camera FOV", (AcceptableValueBase)(object)new AcceptableValueRange<float>(30f, 120f)));
			EnableThirdPersonCameraFov = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableThirdPersonCameraFov", true, UiDescription("Applies the configured field of view while the camera is in third person.", "20 - Camera Improvements / Field of View", 90, "Enable Third Person FOV"));
			if (Mathf.Approximately(ThirdPersonCameraFov.Value, 65f))
			{
				ThirdPersonCameraFov.Value = 80f;
			}
			EnableCameraZoom = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCameraZoom", true, UiDescription("Hold the configured key to magnify the view toward the crosshair in third or first person. The wheel adjusts magnification while held; releasing the key restores the normal view.", "20 - Camera Improvements / Camera Distance", 100, "Enable Hold-to-Zoom"));
			CameraZoomKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Camera", "CameraZoomKey", new KeyboardShortcut((KeyCode)326, Array.Empty<KeyCode>()), UiDescription("Key held for temporary camera zoom. The default is Mouse4 (Unity Mouse3).", "20 - Camera Improvements / Camera Distance / Adjustments", 100, "Zoom Hold Key"));
			KeyboardShortcut value2 = CameraZoomKey.Value;
			bool flag9 = false;
			using (IEnumerator<KeyCode> enumerator = ((KeyboardShortcut)(ref value2)).Modifiers.GetEnumerator())
			{
				if (enumerator.MoveNext())
				{
					_ = enumerator.Current;
					flag9 = true;
				}
			}
			if ((int)((KeyboardShortcut)(ref value2)).MainKey == 325 && !flag9)
			{
				CameraZoomKey.Value = new KeyboardShortcut((KeyCode)326, Array.Empty<KeyCode>());
			}
			CameraZoomDefaultMagnification = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraZoomDefaultMagnification", 2f, UiDescription("Initial optical magnification when the zoom key is held.", "20 - Camera Improvements / Camera Distance / Adjustments", 90, "Default Zoom Magnification", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f)));
			CameraZoomMagnificationStep = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraZoomMagnificationStep", 0.5f, UiDescription("Change in optical magnification per scroll notch while the zoom key is held.", "20 - Camera Improvements / Camera Distance / Adjustments", 80, "Zoom Magnification per Scroll", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f)));
			CameraZoomMaxMagnification = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraZoomMaxMagnification", 20f, UiDescription("Maximum optical magnification while zooming. Values up to 40 are supported.", "20 - Camera Improvements / Camera Distance / Adjustments", 70, "Maximum Zoom Magnification", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 40f)));
			CameraZoomSmoothSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraZoomSmoothSpeed", 14f, UiDescription("Speed used to smooth optical zoom changes while the zoom key is held.", "20 - Camera Improvements / Camera Distance / Adjustments", 60, "Zoom Smooth Speed", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f)));
			CameraZoomMouseSensitivityFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraZoomMouseSensitivityFactor", 0.2f, UiDescription("Multiplier applied to mouse sensitivity while zooming. Lower values slow the view more; 0.20 is five times slower than the unscaled response.", "20 - Camera Improvements / Camera Distance / Adjustments", 50, "Zoom Mouse Sensitivity Factor", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f)));
			CameraDistanceSmoothSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraDistanceSmoothSpeed", 4f, UiDescription("Speed used to smooth normal third-person distance changes from the scroll wheel.", "20 - Camera Improvements / Camera Distance / Adjustments", 40, "Camera Distance Smooth Speed", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f)));
			if (Mathf.Approximately(CameraDistanceSmoothSpeed.Value, 12f))
			{
				CameraDistanceSmoothSpeed.Value = 4f;
			}
			EnableCameraDistanceSmoothing = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCameraDistanceSmoothing", true, UiDescription("Smooths normal third-person camera-distance changes after scrolling.", "20 - Camera Improvements / Camera Distance", 90, "Enable Camera Distance Smoothing"));
			EnableCameraScrollDistanceStep = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCameraScrollDistanceStep", true, UiDescription("Uses the configured metres-per-notch value for normal camera-distance scrolling. Optical zoom keeps its separate wheel control.", "20 - Camera Improvements / Camera Distance", 80, "Enable Camera Distance per Scroll"));
			CameraScrollDistanceStepMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraScrollDistanceStepMeters", 2f, UiDescription("Distance in metres added or removed from the selected camera orbit for one normal scroll notch. The setting also controls first-person transitions; the held optical-zoom wheel remains separate.", "20 - Camera Improvements / Camera Distance / Adjustments", 30, "Camera Distance per Scroll (m)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f)));
			AdvancedCameraScrollDistanceStepMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "AdvancedCameraScrollDistanceStepMeters", 0.75f, UiDescription("Distance added or removed per scroll notch while Advanced Camera is active. Uses Enable Camera Distance per Scroll and retains the 3 m indoor limit. Optical zoom remains separate.", "20 - Camera Improvements / Advanced Camera / Adjustments", 30, "Advanced Camera Distance per Scroll (m)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 3f)));
			EnableCameraDistanceLimits = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCameraDistanceLimits", true, UiDescription("Enforces the configured maximum orbit distances for the player and boats.", "20 - Camera Improvements / Camera Distance", 70, "Enable Camera Distance Limits"));
			EnableCameraBasePosition = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCameraBasePosition", true, UiDescription("Enables the third-person vertical camera pivot offset in metres. Its strength fades from zero at 1 metre to full at the configured distance, then stays full. First person is unchanged.", "20 - Camera Improvements / Camera Position", 100, "Enable Camera Base Position"));
			CameraBasePositionFullStrengthDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraBasePositionFullStrengthDistance", 6f, UiDescription("Camera distance in metres at which the configured Y offset reaches 100%. Strength blends linearly from 0% at 1 metre and remains at 100% beyond this distance.", "20 - Camera Improvements / Camera Position / Adjustments", 90, "Camera Base Position Full Strength Distance (m)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 20f)));
			EnableAutomaticCrosshairPosition = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableAutomaticCrosshairPosition", true, UiDescription("With Custom Crosshair disabled, moves the third-person HUD crosshair to the character's aim point to compensate for the camera's base offset. A custom crosshair keeps its configured position; the vanilla interaction indicator stays at the native center.", "25 - Crosshair Position and Mouse Aim", 150, "Automatic Crosshair Position"));
			EnableCustomCrosshair = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "EnableCustomCrosshair", true, UiDescription("Draws a configurable screen-space crosshair. Normal attacks follow the reticle's viewing direction without selecting objects or mobs. Target convergence is available only during Alt mouse-aim. It is drawn independently from Valheim's HUD crosshair, so mods that hide the vanilla reticle do not hide this one.", "25 - Crosshair Position and Mouse Aim", 200, "Enable Custom Crosshair"));
			ShowVanillaInteractionCrosshair = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "ShowVanillaInteractionCrosshair", true, UiDescription("Shows the original vanilla interaction reticle alongside an offset custom crosshair. Visual only: interactions and attack direction are unchanged. Hidden when both reticles coincide, and in Esc unless Configuration Manager is open.", "25 - Crosshair Position and Mouse Aim", 195, "Show Vanilla Interaction Crosshair"));
			EnableBowCrosshairMouseAim = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "EnableBowCrosshairMouseAim", true, UiDescription("Hold the configured Alt/free-look key while drawing a bow or crossbow to steer the reticle with the mouse. Releasing the key immediately returns mouse control to the camera; the configured delay applies only after firing.", "25 - Crosshair Position and Mouse Aim", 190, "Hold Alt to Aim with Mouse"));
			EnableBowTrajectoryCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "EnableBowTrajectoryCompatibility", true, UiDescription("Keeps Bow Trajectory aligned with the selected bow aim method and supported live arrow physics. With Better Archery, its crosshair compatibility toggle selects the preview aim; Alt mouse-aim remains available in either mode.", "27 - Compatibility", 80, "Enable Bow Trajectory Compatibility"));
			EnableAimAlongCrosshairDirection = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "EnableAimAlongCrosshairDirection", false, UiDescription("During Alt mouse-aim, enabled follows the crosshair's viewing direction and disabled converges on the object hit by its ray. Normal attacks always follow the reticle viewing direction without target convergence.", "25 - Crosshair Position and Mouse Aim", 170, "Aim Along Crosshair Direction"));
			EnableBetterArcheryCrosshairCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableBetterArcheryCrosshairCompatibility", true, UiDescription("When Better Archery is detected, selects Immersive Camera's reticle and aim direction, which Bow Trajectory also follows when its compatibility is enabled. Disable to use Better Archery's native reticle and aim; ICE Alt mouse-aim remains available while drawing a bow.", "27 - Compatibility", 100, "Use Immersive Camera Crosshair with Better Archery"));
			EnableBetterArcheryBowZoomCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableBetterArcheryBowZoomCompatibility", true, UiDescription("When Better Archery is detected, enables its bow zoom and coordinates its FOV with the selected reticle. Disable to restore vanilla right-click bow cancel and suppress Better Archery bow-zoom input and breathing sounds.", "27 - Compatibility", 90, "Enable Better Archery Bow Zoom Compatibility"));
			EnableHeadLookAtCameraDirection = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "EnableHeadLookAtCameraDirection", true, UiDescription("Keeps the character's head looking in the camera's view direction instead of turning toward the offset crosshair. Attacks follow the reticle viewing direction; target convergence is limited to Alt mouse-aim.", "25 - Crosshair Position and Mouse Aim", 160, "Head Follows Camera Direction"));
			EnableBowDrawCrosshairAnimation = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "EnableBowDrawCrosshairAnimation", true, UiDescription("Shrinks the Bow/Crossbow crosshair as Valheim's draw percentage rises, indicating improved shot accuracy.", "26 - Crosshair Appearance (Style and Color)", 85, "Bow Draw Accuracy Animation"));
			CrosshairStyleDefault = ((BaseUnityPlugin)this).Config.Bind<CrosshairStyle>("Crosshair", "CrosshairStyleDefault", CrosshairStyle.CrossDot, UiDescription("Preset used when the held item does not match a specific weapon category.", "26 - Crosshair Appearance (Style and Color)", 100, "Default Crosshair Style"));
			CrosshairStyleMelee = ((BaseUnityPlugin)this).Config.Bind<CrosshairStyle>("Crosshair", "CrosshairStyleMelee", CrosshairStyle.Cross, UiDescription("Preset used for melee weapons.", "26 - Crosshair Appearance (Style and Color)", 95, "Melee Crosshair Style"));
			CrosshairStyleBow = ((BaseUnityPlugin)this).Config.Bind<CrosshairStyle>("Crosshair", "CrosshairStyleBow", CrosshairStyle.Bow, UiDescription("Preset used for bows and crossbows. The draw animation applies to this category.", "26 - Crosshair Appearance (Style and Color)", 90, "Bow / Crossbow Crosshair Style"));
			CrosshairStyleMagic = ((BaseUnityPlugin)this).Config.Bind<CrosshairStyle>("Crosshair", "CrosshairStyleMagic", CrosshairStyle.Dot, UiDescription("Preset used for staves and other magic weapons.", "26 - Crosshair Appearance (Style and Color)", 85, "Magic Crosshair Style"));
			CrosshairStyleTools = ((BaseUnityPlugin)this).Config.Bind<CrosshairStyle>("Crosshair", "CrosshairStyleTools", CrosshairStyle.Circle, UiDescription("Preset used for tools such as the hammer, pickaxe, hoe, and cultivator.", "26 - Crosshair Appearance (Style and Color)", 80, "Tool Crosshair Style"));
			LegacyCrosshairPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairPositionX", 0f, new ConfigDescription("Legacy pixel value retained for migration to percentage-based positioning.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -20,
					Browsable = false
				}
			}));
			LegacyCrosshairPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairPositionY", 0f, new ConfigDescription("Legacy pixel value retained for migration to percentage-based positioning.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -19,
					Browsable = false
				}
			}));
			CrosshairPositionXPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairPositionXPercent", 0f, UiDescription("Horizontal reticle offset as a percentage of the gameplay viewport width, measured from screen center. +50% reaches the right edge; -50% reaches the left edge.", "25 - Crosshair Position and Mouse Aim", 85, "Default Crosshair Position X (%)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-50f, 50f)));
			CrosshairPositionYPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairPositionYPercent", 0f, UiDescription("Vertical reticle offset as a percentage of the gameplay viewport height, measured from screen center. +50% reaches the top edge; -50% reaches the bottom edge.", "25 - Crosshair Position and Mouse Aim", 80, "Default Crosshair Position Y (%)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-50f, 50f)));
			MigrateCrosshairPositionXFromPixels = !flag7;
			MigrateCrosshairPositionYFromPixels = !flag8;
			CrosshairPositionMeleeXPercent = BindCrosshairPosition("CrosshairPositionMeleeXPercent", "Melee", "X", 75);
			CrosshairPositionMeleeYPercent = BindCrosshairPosition("CrosshairPositionMeleeYPercent", "Melee", "Y", 74);
			CrosshairPositionBowXPercent = BindCrosshairPosition("CrosshairPositionBowXPercent", "Bow / Crossbow", "X", 73);
			CrosshairPositionBowYPercent = BindCrosshairPosition("CrosshairPositionBowYPercent", "Bow / Crossbow", "Y", 72, 6f);
			CrosshairPositionMagicXPercent = BindCrosshairPosition("CrosshairPositionMagicXPercent", "Magic", "X", 71);
			CrosshairPositionMagicYPercent = BindCrosshairPosition("CrosshairPositionMagicYPercent", "Magic", "Y", 70);
			CrosshairPositionToolsXPercent = BindCrosshairPosition("CrosshairPositionToolsXPercent", "Tools", "X", 69);
			CrosshairPositionToolsYPercent = BindCrosshairPosition("CrosshairPositionToolsYPercent", "Tools", "Y", 68);
			CustomCrosshairImage = ((BaseUnityPlugin)this).Config.Bind<string>("Crosshair", "CustomCrosshairImage", "crosshair.png", UiDescription("PNG filename for the Custom Image preset. Search order: plugin folder, plugin/Crosshairs, BepInEx/config, then BepInEx/config/ImmersiveCameraEnhanced/Crosshairs. Use a transparent PNG, up to 1024x1024.", "26 - Crosshair Appearance (Style and Color)", 70, "Custom Crosshair PNG Filename"));
			CrosshairSizeDefault = BindCrosshairSize("CrosshairSizeDefault", 18f, "Default", 60);
			CrosshairSizeMelee = BindCrosshairSize("CrosshairSizeMelee", 18f, "Melee", 55);
			CrosshairSizeBow = BindCrosshairSize("CrosshairSizeBow", 36f, "Bow / Crossbow", 50);
			CrosshairSizeMagic = BindCrosshairSize("CrosshairSizeMagic", 18f, "Magic", 45);
			CrosshairSizeTools = BindCrosshairSize("CrosshairSizeTools", 18f, "Tools", 40);
			if (num.HasValue)
			{
				float num2 = Mathf.Clamp(num.Value, 4f, 100f);
				if (!flag)
				{
					CrosshairSizeDefault.Value = num2;
				}
				if (!flag2)
				{
					CrosshairSizeMelee.Value = num2;
				}
				if (!flag3)
				{
					CrosshairSizeBow.Value = Mathf.Clamp(num2 * 2f, 4f, 100f);
				}
				if (!flag4)
				{
					CrosshairSizeMagic.Value = num2;
				}
				if (!flag5)
				{
					CrosshairSizeTools.Value = num2;
				}
			}
			CrosshairThickness = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairThickness", 2f, UiDescription("Thickness of crosshair arms and ring in pixels.", "25 - Crosshair Position and Mouse Aim", 105, "Crosshair Thickness (px)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 12f)));
			CrosshairGap = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairGap", 5f, UiDescription("Gap between the center and the four crosshair arms in pixels.", "25 - Crosshair Position and Mouse Aim", 100, "Crosshair Center Gap (px)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f)));
			CrosshairColorRed = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairColorRed", 1f, UiDescription("Red channel for the default-category reticle color.", "26 - Crosshair Appearance (Style and Color)", 69, "Default Crosshair Color - Red", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			CrosshairColorGreen = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairColorGreen", 1f, UiDescription("Green channel for the default-category reticle color.", "26 - Crosshair Appearance (Style and Color)", 68, "Default Crosshair Color - Green", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			CrosshairColorBlue = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairColorBlue", 1f, UiDescription("Blue channel for the default-category reticle color.", "26 - Crosshair Appearance (Style and Color)", 67, "Default Crosshair Color - Blue", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			CrosshairColorMeleeRed = BindCrosshairColor("CrosshairColorMeleeRed", 1f, "Melee", "Red", 59);
			CrosshairColorMeleeGreen = BindCrosshairColor("CrosshairColorMeleeGreen", 1f, "Melee", "Green", 58);
			CrosshairColorMeleeBlue = BindCrosshairColor("CrosshairColorMeleeBlue", 1f, "Melee", "Blue", 57);
			CrosshairColorBowRed = BindCrosshairColor("CrosshairColorBowRed", 1f, "Bow / Crossbow", "Red", 49);
			CrosshairColorBowGreen = BindCrosshairColor("CrosshairColorBowGreen", 1f, "Bow / Crossbow", "Green", 48);
			CrosshairColorBowBlue = BindCrosshairColor("CrosshairColorBowBlue", 1f, "Bow / Crossbow", "Blue", 47);
			CrosshairColorMagicRed = BindCrosshairColor("CrosshairColorMagicRed", 1f, "Magic", "Red", 39);
			CrosshairColorMagicGreen = BindCrosshairColor("CrosshairColorMagicGreen", 1f, "Magic", "Green", 38);
			CrosshairColorMagicBlue = BindCrosshairColor("CrosshairColorMagicBlue", 1f, "Magic", "Blue", 37);
			CrosshairColorToolsRed = BindCrosshairColor("CrosshairColorToolsRed", 1f, "Tools", "Red", 29);
			CrosshairColorToolsGreen = BindCrosshairColor("CrosshairColorToolsGreen", 1f, "Tools", "Green", 28);
			CrosshairColorToolsBlue = BindCrosshairColor("CrosshairColorToolsBlue", 1f, "Tools", "Blue", 27);
			CrosshairAimMouseSensitivity = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairAimMouseSensitivity", 4f, UiDescription("Mouse sensitivity multiplier while aiming with a bow or crossbow. 4.0 is the default; lower values move the reticle less for the same mouse motion.", "25 - Crosshair Position and Mouse Aim", 125, "Bow Aim Mouse Sensitivity", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 10f)));
			if (Mathf.Approximately(CrosshairAimMouseSensitivity.Value, 2f))
			{
				CrosshairAimMouseSensitivity.Value = 4f;
			}
			CrosshairAimAltHoldDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairAimAltHoldDuration", 2f, UiDescription("Hold the configured Alt key this long while drawing a bow or crossbow to keep mouse-aim active for the rest of the draw without continuing to hold Alt.", "25 - Crosshair Position and Mouse Aim", 115, "Alt Hold to Keep Bow Aim (s)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f)));
			CrosshairAimMouseResumeDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Crosshair", "CrosshairAimMouseResumeDelay", 0.25f, UiDescription("After firing a bow or crossbow while mouse-aim was used, ignores residual mouse movement for this long. Releasing Alt never starts this delay.", "25 - Crosshair Position and Mouse Aim", 120, "Post-shot Mouse Delay (s)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f)));
			CrosshairAimMouseInvertX = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "CrosshairAimMouseInvertX", false, UiDescription("Reverses horizontal mouse movement while aiming with a drawn bow or crossbow. Off by default: moving the mouse right moves the reticle right.", "25 - Crosshair Position and Mouse Aim", 140, "Invert Aim Mouse X"));
			CrosshairAimMouseInvertY = ((BaseUnityPlugin)this).Config.Bind<bool>("Crosshair", "CrosshairAimMouseInvertY", false, UiDescription("Reverses vertical mouse movement while aiming with a drawn bow or crossbow. Off by default: moving the mouse up moves the reticle up.", "25 - Crosshair Position and Mouse Aim", 130, "Invert Aim Mouse Y"));
			CameraBasePositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraBasePositionY", 0f, UiDescription("Vertical third-person pivot offset in metres. Positive values move upward. Its strength blends from 0% at 1 metre camera distance to 100% at the configured full-strength distance.", "20 - Camera Improvements / Camera Position / Adjustments", 100, "Camera Base Position Y (m)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 10f)));
			EnableFirstPersonFreeLook = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableFirstPersonFreeLook", true, UiDescription("Allows looking around freely while the configured Alt key is held without changing the character's movement direction.", "20 - Camera Improvements / First Person", 70, "Enable Alt Free Look"));
			FirstPersonFreeLookKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Camera", "FirstPersonFreeLookKey", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), UiDescription("Key held for free look. The default is Left Alt.", "20 - Camera Improvements / First Person / Adjustments", 100, "Free Look Hold Key"));
			EnableAdvancedCamera = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableAdvancedCamera", true, UiDescription("Activates only with vanilla Shelter status and a player-placed building piece overhead; natural caves and dungeons do not qualify. Applies an indoor-only three-metre camera limit.", "20 - Camera Improvements / Advanced Camera", 100, "Enable Advanced Camera"));
			AdvancedCameraTemporaryDisableKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Camera", "AdvancedCameraTemporaryDisableKey", new KeyboardShortcut((KeyCode)308, Array.Empty<KeyCode>()), UiDescription("Double-tap this key within 2 seconds to toggle Advanced Camera off or back on while inside a qualifying player-built shelter. If left off, it automatically reactivates after you have spent 1 minute outside that shelter.", "20 - Camera Improvements / Advanced Camera / Adjustments", 110, "Temporary Disable Key (Double-tap)"));
			EnableCaveMap = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCaveMap", true, UiDescription("Inside a cave or dungeon, replaces the outdoor minimap image with a zoomed cave map of explored cells on the current floor. Restores the normal minimap when you leave.", "50 - Cave Map", 100, "Enable Cave Mapping"));
			EnableCaveMapSatelliteCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCaveMapSatelliteCompatibility", true, UiDescription("When Satellite Map is detected, hides its terrain tiles while the cave plan is active, then restores them on exit. Other map markers and shared exploration are preserved.", "50 - Cave Map", 90, "Satellite Map Compatibility"));
			AdvancedCameraActivationInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "AdvancedCameraActivationInterval", 1f, UiDescription("How often to check for vanilla Shelter status and a player-placed building piece overhead. Natural caves and dungeons do not activate the feature.", "20 - Camera Improvements / Advanced Camera / Adjustments", 100, "Advanced Camera Activation Interval", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f)));
			AdvancedCameraDeactivationInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "AdvancedCameraDeactivationInterval", 3f, UiDescription("How often to recheck an active house session. After Shelter ends, a player-placed overhead piece within camera distance keeps Advanced Camera active until this check clears.", "20 - Camera Improvements / Advanced Camera / Adjustments", 90, "Advanced Camera Deactivation Interval", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f)));
			EnableAdvancedCameraHeightClearance = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableAdvancedCameraHeightClearance", true, UiDescription("Enables vertical mouse travel indoors. Height is limited to a fixed 50% of the shared free floor-to-ceiling space. Collision shortens the route toward the character.", "20 - Camera Improvements / Advanced Camera", 90, "Enable Advanced Camera Height Clearance"));
			EnableAdvancedCameraEdgeClearance = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableAdvancedCameraEdgeClearance", true, UiDescription("Keeps a rounded clearance around the camera at wall corners, raised obstacles, and changes in floor or ceiling height while Advanced Camera is active.", "20 - Camera Improvements / Advanced Camera", 80, "Advanced Camera Corner Clearance"));
			AdvancedCameraHeightFreedomPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "AdvancedCameraHeightFreedomPercent", 60f, UiDescription("Vertical mouse travel as a percentage of the selected indoor camera distance. Advanced Height clamps travel to a fixed 50% of free floor-to-ceiling space; collision retracts toward the character.", "20 - Camera Improvements / Advanced Camera / Adjustments", 80, "Advanced Camera Vertical Travel (%)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
			EnableDamageDirectionIndicator = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableDamageDirectionIndicator", true, UiDescription("Shows a local damage-direction arrow for the configured duration. Third person uses a world marker; first person pins the same 3D marker to the camera.", "40 - Damage Direction Indicator", 100, "Enable Damage Direction Indicator"));
			DamageDirectionIndicatorPointToSource = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DamageDirectionIndicatorPointToSource", true, UiDescription("When enabled, resolve the attacker's network object and point the arrow toward that character or entity.", "40 - Damage Direction Indicator", 90, "Point to Damage Source"));
			DamageDirectionIndicatorDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorDuration", 4f, UiDescription("How long the damage-direction arrow remains visible after a hit.", "40 - Damage Direction Indicator / Adjustments", 120, "Indicator Duration", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f)));
			DamageDirectionIndicatorSourceUpdateInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorSourceUpdateInterval", 0.5f, UiDescription("How often to refresh the arrow toward the moving attacker while the marker is visible.", "40 - Damage Direction Indicator / Adjustments", 115, "Attacker Direction Update Interval", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f)));
			DamageDirectionIndicatorThirdPersonSize = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorSize", 0.45f, UiDescription("Size multiplier for the 3D arrow beside the character in third person.", "40 - Damage Direction Indicator / Adjustments", 110, "Third Person Arrow Size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 2f)));
			DamageDirectionIndicatorFirstPersonSize = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorFirstPersonSize", 0.25f, UiDescription("Size multiplier for the camera-fixed 3D arrow in first person.", "40 - Damage Direction Indicator / Adjustments", 105, "First Person Arrow Size", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 2f)));
			DamageDirectionIndicatorRed = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorRed", 0.66f, UiDescription("Red channel of the arrow color (0 to 1).", "40 - Damage Direction Indicator / Adjustments", 100, "Arrow Color - Red", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			DamageDirectionIndicatorGreen = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorGreen", 0.25f, UiDescription("Green channel of the arrow color (0 to 1).", "40 - Damage Direction Indicator / Adjustments", 90, "Arrow Color - Green", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			DamageDirectionIndicatorBlue = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorBlue", 0.21f, UiDescription("Blue channel of the arrow color (0 to 1).", "40 - Damage Direction Indicator / Adjustments", 80, "Arrow Color - Blue", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			DamageDirectionIndicatorWorldPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorWorldPositionX", 0f, UiDescription("Horizontal offset from the player, in local metres.", "40 - Damage Direction Indicator / Adjustments", 70, "Third Person Position X", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f)));
			DamageDirectionIndicatorWorldPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorWorldPositionY", 1.4f, UiDescription("Height above the player origin, in metres.", "40 - Damage Direction Indicator / Adjustments", 60, "Third Person Position Y", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2.2f)));
			DamageDirectionIndicatorWorldPositionZ = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorWorldPositionZ", 0f, UiDescription("Forward offset from the player, in local metres.", "40 - Damage Direction Indicator / Adjustments", 50, "Third Person Position Z", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f)));
			DamageDirectionIndicatorFirstPersonPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorFirstPersonPositionX", 0.24f, UiDescription("Horizontal camera-local position in metres. Positive values move the arrow to the right.", "40 - Damage Direction Indicator / Adjustments", 40, "First Person Position X", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.8f, 0.8f)));
			DamageDirectionIndicatorFirstPersonPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorFirstPersonPositionY", -0.18f, UiDescription("Vertical camera-local position in metres. Negative values move the arrow down.", "40 - Damage Direction Indicator / Adjustments", 30, "First Person Position Y", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.8f, 0.8f)));
			DamageDirectionIndicatorFirstPersonPositionZ = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "DamageDirectionIndicatorFirstPersonPositionZ", 1.5f, UiDescription("Distance in front of the first-person camera, in metres.", "40 - Damage Direction Indicator / Adjustments", 20, "First Person Position Z", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.15f, 2f)));
			((BaseUnityPlugin)this).Config.SettingChanged += delegate(object sender, SettingChangedEventArgs args)
			{
				Interlocked.Increment(ref RuntimeSettingsRevision);
				if (args.ChangedSetting.Definition.Section == "Crosshair")
				{
					Interlocked.Increment(ref CrosshairSettingsRevision);
				}
				Controller?.OnRuntimeSettingChanged();
			};
			DamageDirectionIndicatorRed.SettingChanged += OnDamageDirectionIndicatorColorChanged;
			DamageDirectionIndicatorGreen.SettingChanged += OnDamageDirectionIndicatorColorChanged;
			DamageDirectionIndicatorBlue.SettingChanged += OnDamageDirectionIndicatorColorChanged;
			ThirdPersonCameraDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "ThirdPersonCameraDistance", 6f, UiDescription("Maximum local third-person distance for the character. This client value overrides server-side camera distance settings.", "20 - Camera Improvements / Camera Distance / Adjustments", 20, "Third Person Camera Distance", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 35f)));
			BoatCameraDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "BoatCameraDistance", 6f, UiDescription("Hard maximum local camera distance while attached to or controlling a boat or raft. It caps both boat camera limits and the live camera distance, overriding server and other-mod values.", "20 - Camera Improvements / Camera Distance / Adjustments", 10, "Boat Camera Distance", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 35f)));
			CullHousePillars = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "CullHousePillars", false, UiDescription("Also hides player-built support pillars and stone arches that intersect the cylinder.", "01 - Camera Cull", 70, "Cull Supports & Stone Arches"));
			IgnoreVegetationCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "IgnoreVegetationCollision", true, UiDescription("Prevents camera collision from stopping on recognized vegetation.", "10 - Camera Collision", 100, "Ignore Vegetation Collision"));
			((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "IgnoreRockCollision", false, new ConfigDescription("Legacy key retained for migration. Terrain, rocks, ores, and boulders always stop the camera.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -90,
					Browsable = false
				}
			}));
			IgnoreHousePillarCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "IgnoreHousePillarCollision", true, UiDescription("Allows the camera to pass through player-built support pillars and stone arches. Walls, foundations, floors, and roofs remain solid.", "10 - Camera Collision", 90, "Ignore Support & Arch Collision"));
			IgnoreMovingDoorCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "IgnoreMovingDoorCollision", true, UiDescription("Lets the camera pass through doors only while they open or close. Fully open and fully closed doors collide normally. Works with custom and native camera collision without changing player or projectile collision.", "10 - Camera Collision", 85, "Ignore Moving Door Collision"));
			IgnoreHouseLightCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "IgnoreHouseLightCollision", true, UiDescription("Allows the camera to pass through wall sconces, all torches, light fixtures, and tables.", "10 - Camera Collision", 80, "Ignore Props & Lights Collision"));
			IgnoreEntityCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "IgnoreEntityCollision", true, UiDescription("Allows the camera to pass through players, animals, enemies, and other entities.", "10 - Camera Collision", 70, "Ignore Entity Collision"));
			IgnoreBoatCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "IgnoreBoatCollision", false, UiDescription("When enabled, camera collision queries ignore entire native and modded boats. The bypass also activates temporarily while controlling a helm or attached to a mast; simply standing on a boat keeps normal camera collision. Player and boat physics are unchanged.", "10 - Camera Collision", 60, "Ignore All Boat Collision"));
			CameraGroundCollisionMinimumDistancePercent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraGroundCollisionMinimumDistancePercent", 15f, new ConfigDescription("Legacy floor-orbit minimum retained for config compatibility. Only the custom cylinder retracts the new camera. Advanced Height uses fixed floor-to-ceiling clearance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 95f), new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -99,
					Browsable = false
				}
			}));
			EnableNewCameraCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableNewCameraCollision", true, UiDescription("Enables the mod-owned collision cylinder. When disabled, Valheim's native collision runs. Advanced Camera works with either collision backend.", "10 - Camera Collision", 130, "Enable New Camera Collision"));
			EnableCollisionDistanceTransition = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCollisionDistanceTransition", true, UiDescription("After two seconds of stable collision, commits the shortest safe distance while respecting the configured minimum distance after cut and minimum reduction in metres. Disable this to keep the selected zoom unchanged and let the collision cylinder constrain the view.", "10 - Camera Collision", 120, "Enable Collision Distance Cut"));
			CollisionDistanceMinimumPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CollisionDistanceMinimumPercent", 10f, UiDescription("Minimum selected camera distance after a collision cut, as a percentage of the configured maximum distance. At a 35 m maximum, 10% means a 3.5 m zoom floor even if the current zoom is 10 m. Physical collision safety can still bring the rendered camera closer. The two-second stable window selects the shortest safe reading.", "10 - Camera Collision / Adjustments", 80, "Minimum Distance After Cut (%)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
			CollisionDistanceMinimumAbsoluteReduction = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CollisionDistanceMinimumAbsoluteReduction", 2f, UiDescription("After a cut, the committed distance becomes the new baseline. A later cut must shorten that baseline by at least this many metres while keeping the selected distance above Minimum Distance After Cut (%).", "10 - Camera Collision / Adjustments", 79, "Minimum Distance Reduction (m)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f)));
			CameraCollisionRecoverySpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraCollisionRecoverySpeed", 20f, UiDescription("Speed in metres per second at which the camera returns to its selected distance after the collision path clears. Each outward step is still checked against the wall before it is applied.", "10 - Camera Collision / Adjustments", 70, "Camera Return Smooth Speed (m/s)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 30f)));
			if (Mathf.Approximately(CameraCollisionRecoverySpeed.Value, 3f))
			{
				CameraCollisionRecoverySpeed.Value = 20f;
			}
			ShowCameraDistanceHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "ShowCameraDistanceHud", true, UiDescription("Shows the selected third-person camera distance after scroll changes it or a distance limit blocks outward scroll; hides after two seconds. Wall contact does not change the selected distance.", "20 - Camera Improvements / Camera Distance", 60, "Show Camera Distance HUD"));
			CameraDistanceHudX = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraDistanceHudX", 50f, UiDescription("Horizontal HUD position as a percentage of screen width, measured from the left.", "20 - Camera Improvements / Camera Distance / Adjustments", 5, "Distance HUD Horizontal Position", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
			CameraDistanceHudY = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "CameraDistanceHudY", 75f, UiDescription("Vertical HUD position as a percentage of screen height, measured from the top.", "20 - Camera Improvements / Camera Distance / Adjustments", 0, "Distance HUD Vertical Position", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
			KeepFoundationFloorRoofCollision = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "KeepFoundationFloorRoofCollision", true, new ConfigDescription("Retained for profile compatibility. The new camera cylinder always treats floors, foundations, ceilings, and roofs as solid.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -98,
					Browsable = false
				}
			}));
			PreserveVegetationShadows = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "PreserveVegetationShadows", true, UiDescription("Hides vegetation color while keeping shadows.", "01 - Camera Cull", 60, "Preserve Vegetation Shadows"));
			CylinderCameraWidthPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "CylinderCameraWidthPercent", 25f, UiDescription("Camera-side width as a screen percentage; the apex closes to zero.", "01 - Camera Cull / Adjustments", 100, "Cylinder Camera Width", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
			ConeCharacterDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "ConeCharacterDistance", 0.5f, UiDescription("Distance from the character center to the cylinder apex; the apex points toward the camera.", "01 - Camera Cull / Adjustments", 110, "Cylinder Character Distance", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f)));
			BackCylinderLength = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "BackCylinderLength", 10f, UiDescription("Additional cylinder length in metres beyond the camera.", "01 - Camera Cull / Adjustments", 90, "Cylinder Length Behind Camera", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 30f)));
			ConeGrowthExponent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "ConeGrowthExponent", 2.4f, UiDescription("Cylinder radius curvature; values above 1 keep the start narrow and expand near the camera.", "01 - Camera Cull / Adjustments", 80, "Cylinder Growth Exponent", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 6f)));
			ConeRearRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "ConeRearRadiusMultiplier", 1.75f, UiDescription("Radius multiplier at the rear tip beyond the camera.", "01 - Camera Cull / Adjustments", 60, "Cylinder Rear Radius Multiplier", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f)));
			CylinderTopFlattenPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "CylinderTopFlattenPercent", 30f, new ConfigDescription("Legacy value migrated to CylinderVerticalFlattenPercent.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -100,
					Browsable = false
				}
			}));
			CylinderVerticalFlattenPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "CylinderVerticalFlattenPercent", CylinderTopFlattenPercent.Value, UiDescription("Flattens the upper vertical side of the cylinder after applying the growth exponent.", "01 - Camera Cull / Adjustments", 40, "Cylinder Vertical Flatten", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
			CylinderFlattenBottom = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera occlusion", "CylinderFlattenBottom", false, UiDescription("Also applies the vertical flattening limit to the lower side of the cylinder.", "01 - Camera Cull / Adjustments", 30, "Flatten Bottom"));
			CylinderHorizontalFlattenPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "CylinderHorizontalFlattenPercent", 0f, UiDescription("Flattens the horizontal width of the cylinder after applying the growth exponent.", "01 - Camera Cull / Adjustments", 20, "Cylinder Horizontal Flatten", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
			CylinderSlicesPerMeter = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "CylinderSlicesPerMeter", 2f, UiDescription("Curved-cylinder profile cuts per metre. Higher values make the stepped profile denser.", "01 - Camera Cull / Adjustments", 50, "Cylinder Cuts Per Metre", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 12f)));
			CylinderExponentInfluencePercent = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "CylinderExponentInfluencePercent", 100f, UiDescription("Percentage of the growth exponent applied at each profile cut.", "01 - Camera Cull / Adjustments", 70, "Growth Exponent Influence", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
			CylinderCheckInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "CylinderCheckInterval", 0.6f, UiDescription("Seconds between cylinder contact checks. The cylinder transform still follows the camera every frame.", "90 - Performance", 100, "Cylinder Check Interval", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 2f)));
			CylinderRestoreDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Camera occlusion", "CylinderRestoreDelay", 0.6f, UiDescription("Seconds an object must remain outside the cylinder before it is restored. Set to 0 for immediate restoration.", "90 - Performance", 90, "Cylinder Restore Delay", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f)));
			EnableBrightnessAdjustment = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "EnableBrightnessAdjustment", false, UiDescription("Enables the local darkness, cave, and fog brightness adjustment.", "30 - Visual", 100, "Enable Brightness Adjustment"));
			((BaseUnityPlugin)this).Config.Bind<float>("Visual", "BrightnessBoostPercent", 25f, new ConfigDescription("Legacy key retained for compatibility. Brightness sliders now have independent neutral defaults.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Category = "99 - Legacy",
					Order = -80,
					Browsable = false
				}
			}));
			DayBrightnessPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "DayBrightnessPercent", 0f, UiDescription("Signed daylight brightness. Negative values darken, zero keeps vanilla daylight, and values above 100 apply stronger HDR light.", "30 - Visual", 90, "Day Brightness", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 300f)));
			NightBrightnessPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "NightBrightnessPercent", 0f, UiDescription("Signed brightness used at night and by always-dark environments. Negative values darken; values above 100 apply stronger HDR light.", "30 - Visual", 80, "Night Brightness", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 300f)));
			FogCaveBrightnessPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "FogCaveBrightnessPercent", 0f, UiDescription("Signed brightness for dense fog, mist, caves, crypts, and dungeons. Negative values darken; values above 100 apply stronger HDR light.", "30 - Visual", 70, "Fog & Cave Brightness", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-100f, 300f)));
			DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, UiDescription("Writes diagnostic information to the BepInEx log.", "99 - Debug", 0));
			ShowOcclusionCylinder = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ShowOcclusionCylinder", false, UiDescription("Draws the curved cylinder in green for calibration.", "99 - Debug", 1));
			CylinderDebugOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Debug", "CylinderOpacity", 0.2f, UiDescription("Diagnostic outline opacity; 0 is invisible and 1 is fully opaque.", "99 - Debug", 2, "Cylinder Outline Opacity", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f)));
			ShowCameraCollisionColliders = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ShowCameraCollisionColliders", false, UiDescription("Shows world colliders touched by the active native or custom camera collision in pink for thirty seconds. The white cross marks contact. Diagnostic only.", "99 - Debug", 3, "Show Camera Collision Colliders"));
			ShowCameraCollisionVolume = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ShowCameraCollisionVolume", false, UiDescription("Draws the active camera collision in pink: the custom cylinder when enabled, otherwise Valheim's actual native ray/sphere probes. Off by default; separate from V1 vegetation culling.", "99 - Debug", 4, "Show Camera Collision Volume"));
			if (flag6)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			GameObject val2 = new GameObject("ImmersiveCameraEnhancedController");
			Object.DontDestroyOnLoad((Object)val2);
			Controller = val2.AddComponent<CameraCullController>();
			harmony = new Harmony("com.kimbauer.valheim.cameracull");
			CaveDungeonTracking.Install();
			BetterArcheryCompatibility.RefreshDetection();
			BetterArcheryCompatibility.Install(harmony);
			NativeConstructionColliders.SetEnabled(ModEnabled);
			NativeConstructionColliders.Install(harmony);
			PatchGameCamera();
			TryInstallBowTrajectoryCompatibility();
			PatchEnvironmentManager();
			((BaseUnityPlugin)this).Logger.LogInfo((object)(ModEnabled ? "Immersive Camera Enhanced 1.6.1 loaded and active." : "Immersive Camera Enhanced 1.6.1 loaded, but disabled by Camera occlusion/EnableMod=false."));
		}

		private bool HasConfigDefinition(string section, string key)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ConfigDefinition val = new ConfigDefinition(section, key);
			if (((BaseUnityPlugin)this).Config.Keys.Contains(val))
			{
				return true;
			}
			if (AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(((BaseUnityPlugin)this).Config, null) is IDictionary dictionary)
			{
				return dictionary.Contains(val);
			}
			return false;
		}

		private float? ReadOrphanedFloatConfiguration(string section, string key)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			IDictionary dictionary = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(((BaseUnityPlugin)this).Config, null) as IDictionary;
			ConfigDefinition key2 = new ConfigDefinition(section, key);
			if (dictionary == null || !dictionary.Contains(key2))
			{
				return null;
			}
			if (!float.TryParse(Convert.ToString(dictionary[key2], CultureInfo.InvariantCulture), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return null;
			}
			return result;
		}

		private bool RemoveRetiredCameraConfiguration()
		{
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Expected O, but got Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Expected O, but got Unknown
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Expected O, but got Unknown
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Expected O, but got Unknown
			if (!(AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(((BaseUnityPlugin)this).Config, null) is IDictionary dictionary))
			{
				return false;
			}
			bool result = false;
			string[] array = new string[23]
			{
				"CameraCylinderCharacterTipX", "CameraCylinderCharacterTipY", "CameraCylinderCharacterTipZ", "CameraCylinderCameraEndOffset", "CameraCylinderCharacterSideWidthPercent", "CameraCylinderGrowthExponent", "CameraCylinderVerticalFlattenPercent", "CameraCylinderFlattenBottom", "CameraCylinderHorizontalFlattenPercent", "CameraCylinderCameraSideDiameterOffset",
				"CameraCylinderCameraSideDiameter", "CameraCylinderDiameter", "EnableCameraCylinderProgressiveGrowth", "UseVanillaCylinderRepositioning", "DisableCameraLensMarginsWhileBuildingHammerEquipped", "EnableCameraLensMargins", "EnableFirstPersonCameraSphereSizeOverride", "EnableThirdPersonCameraSphereSizeOverride", "FirstPersonCameraSphereRadiusMeters", "ThirdPersonCameraSphereRadiusMeters",
				"CameraCylinderClearanceMarginMeters", "CameraFirstPersonClearanceMarginMeters", "ShowFirstPersonArms"
			};
			foreach (string text in array)
			{
				ConfigDefinition key = new ConfigDefinition("Camera", text);
				if (dictionary.Contains(key))
				{
					dictionary.Remove(key);
					result = true;
				}
			}
			ConfigDefinition key2 = new ConfigDefinition("Crosshair", "EnableBowAimCrosshairLimit");
			if (dictionary.Contains(key2))
			{
				dictionary.Remove(key2);
				result = true;
			}
			List<ConfigDefinition> list = new List<ConfigDefinition>();
			foreach (ConfigDefinition key4 in dictionary.Keys)
			{
				ConfigDefinition val = key4;
				if (val.Section == "Detection")
				{
					list.Add(val);
				}
			}
			foreach (ConfigDefinition item in list)
			{
				dictionary.Remove(item);
				result = true;
			}
			ConfigDefinition[] array2 = (ConfigDefinition[])(object)new ConfigDefinition[2]
			{
				new ConfigDefinition("Crosshair", "CrosshairSize"),
				new ConfigDefinition("Crosshair", "BowDrawCrosshairMinimumScale")
			};
			foreach (ConfigDefinition key3 in array2)
			{
				if (dictionary.Contains(key3))
				{
					dictionary.Remove(key3);
					result = true;
				}
			}
			return result;
		}

		private void PatchGameCamera()
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_0139: Expected O, but got Unknown
			//IL_0139: Expected O, but got Unknown
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Expected O, but got Unknown
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Expected O, but got Unknown
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Expected O, but got Unknown
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Expected O, but got Unknown
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Expected O, but got Unknown
			//IL_037c: Expected O, but got Unknown
			//IL_037c: Expected O, but got Unknown
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Expected O, but got Unknown
			//IL_04f7: Expected O, but got Unknown
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Expected O, but got Unknown
			//IL_0552: Unknown result type (might be due to invalid IL or missing references)
			//IL_055f: Expected O, but got Unknown
			//IL_05f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0603: Expected O, but got Unknown
			//IL_0666: Unknown result type (might be due to invalid IL or missing references)
			//IL_0674: Expected O, but got Unknown
			//IL_06d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06df: Expected O, but got Unknown
			//IL_074b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0757: Expected O, but got Unknown
			//IL_07ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ba: Expected O, but got Unknown
			//IL_080a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0817: Expected O, but got Unknown
			//IL_0855: Unknown result type (might be due to invalid IL or missing references)
			//IL_0862: Expected O, but got Unknown
			//IL_08c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_08cd: Expected O, but got Unknown
			//IL_0a08: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a0f: Expected O, but got Unknown
			//IL_094d: Unknown result type (might be due to invalid IL or missing references)
			//IL_095a: Expected O, but got Unknown
			//IL_0a8b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a9a: Expected O, but got Unknown
			//IL_0b2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b3d: Expected O, but got Unknown
			//IL_0ba8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bb7: Expected O, but got Unknown
			//IL_09bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_09d1: Expected O, but got Unknown
			//IL_09d1: Expected O, but got Unknown
			try
			{
				Type type = AccessTools.TypeByName("GameCamera");
				if (type == null)
				{
					Debug("GameCamera was not found; using only the render callback.");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "LateUpdate", (Type[])null, (Type[])null) ?? AccessTools.Method(type, "Update", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					Debug("No GameCamera update method was found.");
					return;
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeof(GameCameraPatch), "Postfix", (Type[])null, (Type[])null);
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Debug("GameCamera patched at " + methodInfo.Name + ".");
				MethodInfo method = type.GetMethod("UpdateCamera", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(float) }, null);
				if (method != null)
				{
					MethodInfo methodInfo3 = AccessTools.Method(typeof(GameCameraPatch), "PrefixUpdateCamera", (Type[])null, (Type[])null);
					MethodInfo methodInfo4 = AccessTools.Method(typeof(GameCameraPatch), "PostfixUpdateCamera", (Type[])null, (Type[])null);
					MethodInfo methodInfo5 = AccessTools.Method(typeof(GameCameraPatch), "TranspileUpdateCamera", (Type[])null, (Type[])null);
					harmony.Patch((MethodBase)method, new Harmo