Decompiled source of BowTrajectory v1.0.7

BowTrajectory.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GUIFramework;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Valheim.SettingsGui;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("BowTrajectory")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyInformationalVersion("1.0.7")]
[assembly: AssemblyProduct("BowTrajectory")]
[assembly: AssemblyTitle("BowTrajectory")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BowTrajectory
{
	[BepInPlugin("ModdedWolf.BowTrajectory", "Bow Trajectory", "1.0.7")]
	public class BowTrajectoryPlugin : BaseUnityPlugin
	{
		public const string GUID = "ModdedWolf.BowTrajectory";

		public const string NAME = "Bow Trajectory";

		public const string VERSION = "1.0.7";

		internal static BowTrajectoryPlugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyboardShortcut> ToggleKey;

		internal static ConfigEntry<float> MinDrawPercent;

		internal static ConfigEntry<bool> StopAtCharacters;

		internal static ConfigEntry<bool> ShowForCrossbows;

		internal static ConfigEntry<string> StartColor;

		internal static ConfigEntry<string> StartColorHex;

		internal static ConfigEntry<string> EndColor;

		internal static ConfigEntry<string> EndColorHex;

		internal static ConfigEntry<float> LineWidth;

		internal static ConfigEntry<bool> ShowImpactMarker;

		internal static ConfigEntry<string> ImpactColor;

		internal static ConfigEntry<string> ImpactColorHex;

		internal static ConfigEntry<float> ImpactMarkerSize;

		internal static ConfigEntry<int> MaxPoints;

		private GameObject _manager;

		private void Awake()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Expected O, but got Unknown
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Expected O, but got Unknown
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Expected O, but got Unknown
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Expected O, but got Unknown
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Expected O, but got Unknown
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Expected O, but got Unknown
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			int num = (int)(0u | (ConfigMigration.ScrubLegacyColorPreset(((BaseUnityPlugin)this).Config, "Appearance", "StartColor", "StartColorHex", ColorConfig.ToDisplayName(ColorPreset.White)) ? 1u : 0u) | (ConfigMigration.ScrubLegacyColorPreset(((BaseUnityPlugin)this).Config, "Appearance", "EndColor", "EndColorHex", ColorConfig.ToDisplayName(ColorPreset.Red)) ? 1u : 0u)) | (ConfigMigration.ScrubLegacyColorPreset(((BaseUnityPlugin)this).Config, "Appearance", "ImpactColor", "ImpactColorHex", ColorConfig.ToDisplayName(ColorPreset.Red)) ? 1 : 0);
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle for the trajectory preview.");
			ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)98, Array.Empty<KeyCode>()), "Hotkey to toggle the trajectory preview on/off while playing.");
			MinDrawPercent = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MinDrawPercent", 0.05f, new ConfigDescription("Only show the bow trajectory once the draw passes this fraction (0-1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ShowForCrossbows = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowForCrossbows", true, "Also show the trajectory while aiming a crossbow (crossbows always fire at full power).");
			StopAtCharacters = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "StopAtCharacters", true, "If true, the predicted path and impact marker stop on creatures/animals/players too, not just terrain and structures. Set false to let the line pass through characters and only land on the world.");
			AcceptableValueList<string> val = new AcceptableValueList<string>(ColorConfig.PresetDisplayNames);
			StartColor = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "StartColor", ColorConfig.ToDisplayName(ColorPreset.White), new ConfigDescription("Line color near the bow. Named color, RGB Cycle Slow/Medium/Fast, or Custom + StartColorHex.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			StartColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "StartColorHex", "#FFFFFFD9", "Used only when StartColor is Custom. Hex as #RRGGBB or #RRGGBBAA.");
			EndColor = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "EndColor", ColorConfig.ToDisplayName(ColorPreset.Red), new ConfigDescription("Line color near the impact point. Named color, RGB Cycle Slow/Medium/Fast, or Custom + EndColorHex.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			EndColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "EndColorHex", "#FF4033D9", "Used only when EndColor is Custom. Hex as #RRGGBB or #RRGGBBAA.");
			LineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "LineWidth", 0.06f, new ConfigDescription("Width of the trajectory line in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f), Array.Empty<object>()));
			ShowImpactMarker = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "ShowImpactMarker", true, "Show a ring marker where the arrow is predicted to land.");
			ImpactColor = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "ImpactColor", ColorConfig.ToDisplayName(ColorPreset.Red), new ConfigDescription("Color of the impact marker ring. Named color, RGB Cycle Slow/Medium/Fast, or Custom + ImpactColorHex.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			ImpactColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Appearance", "ImpactColorHex", "#FF4033E6", "Used only when ImpactColor is Custom. Hex as #RRGGBB or #RRGGBBAA.");
			ImpactMarkerSize = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "ImpactMarkerSize", 0.5f, new ConfigDescription("Radius of the impact marker ring in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			MaxPoints = ((BaseUnityPlugin)this).Config.Bind<int>("Advanced", "MaxPoints", 400, new ConfigDescription("Maximum number of simulated points along the path. The simulation always uses the game's live physics timestep so the predicted arc matches the real arrow.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(16, 2048), Array.Empty<object>()));
			if (num != 0)
			{
				((BaseUnityPlugin)this).Config.Save();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Migrated legacy Appearance color values to presets / Custom + Hex.");
			}
			ConfigMigration.MigrateFromLegacy(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger, Enabled, ToggleKey, MinDrawPercent, ShowForCrossbows, StopAtCharacters, StartColor, StartColorHex, EndColor, EndColorHex, LineWidth, ShowImpactMarker, ImpactColor, ImpactColorHex, ImpactMarkerSize, MaxPoints);
			new Harmony("ModdedWolf.BowTrajectory").PatchAll();
			_manager = new GameObject("BowTrajectory_Manager");
			_manager.AddComponent<TrajectoryRenderer>();
			Object.DontDestroyOnLoad((Object)(object)_manager);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Bow Trajectory v1.0.7 loaded.");
		}

		internal static Color ResolveStartColor()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return ColorConfig.Resolve(StartColor.Value, StartColorHex.Value, ColorConfig.DefaultLineAlpha);
		}

		internal static Color ResolveEndColor()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return ColorConfig.Resolve(EndColor.Value, EndColorHex.Value, ColorConfig.DefaultLineAlpha, 0.15f);
		}

		internal static Color ResolveImpactColor()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return ColorConfig.Resolve(ImpactColor.Value, ImpactColorHex.Value, ColorConfig.DefaultMarkerAlpha);
		}

		private void OnDestroy()
		{
			if ((Object)(object)_manager != (Object)null)
			{
				Object.Destroy((Object)(object)_manager);
				_manager = null;
			}
		}
	}
	internal sealed class BowTrajectorySettingsTab : MonoBehaviour, ISettingsTab
	{
		private const string PageName = "BowTrajectorySettings";

		private const string TabButtonLabel = "Bow Trajectory";

		private const float DropdownWidth = 180f;

		private GuiDropdown _trajectoryDropdown;

		private GuiDropdown _impactDropdown;

		private Slider _lineWidthSlider;

		private TMP_Text _lineWidthValueText;

		private Slider _impactSizeSlider;

		private TMP_Text _impactSizeValueText;

		private Toggle _enabledToggle;

		private Toggle _showImpactToggle;

		private Toggle _showCrossbowToggle;

		private Button _defaultButton;

		public event Action<string, int> SharedSettingChanged;

		internal static void TryInjectTab(Settings settings)
		{
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0149: Expected O, but got Unknown
			try
			{
				if ((Object)(object)settings == (Object)null)
				{
					return;
				}
				TabHandler componentInChildren = ((Component)settings).GetComponentInChildren<TabHandler>(true);
				if ((Object)(object)componentInChildren == (Object)null || componentInChildren.m_tabs == null || componentInChildren.m_tabs.Count == 0)
				{
					LogWarning("Could not find TabHandler tabs. Skipping Bow Trajectory settings tab.");
				}
				else
				{
					if ((Object)(object)FindExistingPage(componentInChildren) != (Object)null)
					{
						return;
					}
					Tab val = FindTemplateTab(componentInChildren);
					if (val == null || (Object)(object)val.m_button == (Object)null || (Object)(object)val.m_page == (Object)null)
					{
						LogWarning("Could not find a settings tab template. Skipping Bow Trajectory settings tab.");
						return;
					}
					Button val2 = CloneTabButton(val.m_button, "Bow Trajectory");
					if ((Object)(object)val2 == (Object)null)
					{
						LogWarning("Failed to clone settings tab button. Skipping Bow Trajectory settings tab.");
						return;
					}
					RectTransform val3 = CreatePage(val.m_page);
					if ((Object)(object)val3 == (Object)null)
					{
						Object.Destroy((Object)(object)((Component)val2).gameObject);
						LogWarning("Failed to create Bow Trajectory settings page. Skipping tab.");
						return;
					}
					if (!((Component)val3).gameObject.AddComponent<BowTrajectorySettingsTab>().TryBuildUi(settings, val3))
					{
						Object.Destroy((Object)(object)((Component)val2).gameObject);
						Object.Destroy((Object)(object)((Component)val3).gameObject);
						LogWarning("Failed to build Bow Trajectory settings UI. Skipping tab.");
						return;
					}
					componentInChildren.m_tabs.Add(new Tab
					{
						m_button = val2,
						m_page = val3,
						m_default = false,
						m_onClick = new UnityEvent()
					});
					LogInfo("Added Bow Trajectory settings tab.");
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failed to inject Bow Trajectory settings tab: " + ex.Message);
			}
		}

		public void Initialize()
		{
			SyncFromConfig();
		}

		public void OnTabOpen(Button backButton, Button okButton)
		{
			try
			{
				SyncFromConfig();
				Selectable lastSelectable = GetLastSelectable();
				if (!((Object)(object)lastSelectable == (Object)null))
				{
					if ((Object)(object)backButton != (Object)null)
					{
						GuiUtils.SetNavigationDown(lastSelectable, (Selectable)(object)backButton);
						GuiUtils.SetNavigationUp((Selectable)(object)backButton, lastSelectable);
					}
					if ((Object)(object)okButton != (Object)null)
					{
						GuiUtils.SetNavigationUp((Selectable)(object)okButton, lastSelectable);
					}
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failed to update Bow Trajectory tab navigation: " + ex.Message);
			}
		}

		public void OnOkAsync(OkActionCompletedHandler okActionCompletedCallback)
		{
			if (okActionCompletedCallback != null)
			{
				okActionCompletedCallback.Invoke();
			}
		}

		public void OnBack()
		{
		}

		public void OnSharedSettingChanged(string setting, int value)
		{
		}

		public void Terminate()
		{
		}

		private bool TryBuildUi(Settings settings, RectTransform page)
		{
			GuiDropdown val = FindDropdownTemplate(settings);
			if ((Object)(object)val == (Object)null)
			{
				LogWarning("Could not find a GuiDropdown template (Graphics tab).");
				return false;
			}
			Slider val2 = FindSliderTemplate(settings);
			if ((Object)(object)val2 == (Object)null)
			{
				LogWarning("Could not find a Slider template.");
				return false;
			}
			Toggle val3 = FindToggleTemplate(settings);
			TMP_Text labelTemplate = FindLabelTemplate(settings, val3, val2);
			Transform parent = CreateContentRoot(page);
			if ((Object)(object)val3 != (Object)null)
			{
				_enabledToggle = CreateToggleRow(parent, val3, labelTemplate, "Show trajectory", OnEnabledChanged);
				_showImpactToggle = CreateToggleRow(parent, val3, labelTemplate, "Show impact marker", OnShowImpactChanged);
				_showCrossbowToggle = CreateToggleRow(parent, val3, labelTemplate, "Show for crossbows", OnShowCrossbowChanged);
			}
			else
			{
				LogWarning("Could not find a Toggle template; skipping trajectory toggles.");
			}
			_trajectoryDropdown = CreateDropdownRow(parent, val, labelTemplate, "Bow trajectory color", OnTrajectoryChanged);
			_impactDropdown = CreateDropdownRow(parent, val, labelTemplate, "Impact marker color", OnImpactChanged);
			GetFloatRange(BowTrajectoryPlugin.LineWidth, 0.01f, 0.5f, out var min, out var max);
			GetFloatRange(BowTrajectoryPlugin.ImpactMarkerSize, 0.1f, 3f, out var min2, out var max2);
			CreateSliderRow(parent, val2, labelTemplate, "Line width", min, max, OnLineWidthChanged, out _lineWidthSlider, out _lineWidthValueText);
			CreateSliderRow(parent, val2, labelTemplate, "Impact marker size", min2, max2, OnImpactSizeChanged, out _impactSizeSlider, out _impactSizeValueText);
			_defaultButton = CreateDefaultButton(parent, settings);
			WireSelectableNavigation();
			SyncFromConfig();
			if ((Object)(object)_trajectoryDropdown != (Object)null && (Object)(object)_impactDropdown != (Object)null && (Object)(object)_lineWidthSlider != (Object)null)
			{
				return (Object)(object)_impactSizeSlider != (Object)null;
			}
			return false;
		}

		private Button CreateDefaultButton(Transform parent, Settings settings)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			Button val = FindButtonTemplate(settings);
			if ((Object)(object)val == (Object)null)
			{
				LogWarning("Could not find a Button template for Default reset; skipping.");
				return null;
			}
			GameObject val2 = new GameObject("DefaultSpacer", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(parent, false);
			LayoutElement obj = val2.AddComponent<LayoutElement>();
			obj.flexibleHeight = 1f;
			obj.minHeight = 16f;
			Transform val3 = CreateRow(parent, "Default");
			HorizontalLayoutGroup component = ((Component)val3).GetComponent<HorizontalLayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				((LayoutGroup)component).childAlignment = (TextAnchor)4;
			}
			GameObject val4 = Object.Instantiate<GameObject>(((Component)val).gameObject, val3);
			((Object)val4).name = "DefaultButton";
			val4.SetActive(true);
			LayoutElement obj2 = val4.GetComponent<LayoutElement>() ?? val4.AddComponent<LayoutElement>();
			obj2.minWidth = 140f;
			obj2.preferredWidth = 180f;
			obj2.flexibleWidth = 0f;
			obj2.minHeight = 36f;
			obj2.preferredHeight = 40f;
			Button component2 = val4.GetComponent<Button>();
			((UnityEventBase)component2.onClick).RemoveAllListeners();
			((Selectable)component2).interactable = true;
			((UnityEvent)component2.onClick).AddListener(new UnityAction(ResetToDefaults));
			TMP_Text[] componentsInChildren = val4.GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].text = "Default";
				((Component)componentsInChildren[i]).gameObject.SetActive(true);
			}
			Text[] componentsInChildren2 = val4.GetComponentsInChildren<Text>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				componentsInChildren2[j].text = "Default";
			}
			return component2;
		}

		private void SyncFromConfig()
		{
			if ((Object)(object)_enabledToggle != (Object)null)
			{
				_enabledToggle.SetIsOnWithoutNotify(BowTrajectoryPlugin.Enabled.Value);
			}
			if ((Object)(object)_showImpactToggle != (Object)null)
			{
				_showImpactToggle.SetIsOnWithoutNotify(BowTrajectoryPlugin.ShowImpactMarker.Value);
			}
			if ((Object)(object)_showCrossbowToggle != (Object)null)
			{
				_showCrossbowToggle.SetIsOnWithoutNotify(BowTrajectoryPlugin.ShowForCrossbows.Value);
			}
			if ((Object)(object)_trajectoryDropdown != (Object)null)
			{
				int num = ColorConfig.IndexOfSettingsPreset(BowTrajectoryPlugin.StartColor.Value);
				if (num < 0)
				{
					num = ColorConfig.IndexOfSettingsPreset(BowTrajectoryPlugin.EndColor.Value);
				}
				((TMP_Dropdown)_trajectoryDropdown).SetValueWithoutNotify(Math.Max(0, num));
			}
			if ((Object)(object)_impactDropdown != (Object)null)
			{
				int val = ColorConfig.IndexOfSettingsPreset(BowTrajectoryPlugin.ImpactColor.Value);
				((TMP_Dropdown)_impactDropdown).SetValueWithoutNotify(Math.Max(0, val));
			}
			if ((Object)(object)_lineWidthSlider != (Object)null)
			{
				_lineWidthSlider.SetValueWithoutNotify(BowTrajectoryPlugin.LineWidth.Value);
				UpdateLineWidthLabel(BowTrajectoryPlugin.LineWidth.Value);
			}
			if ((Object)(object)_impactSizeSlider != (Object)null)
			{
				_impactSizeSlider.SetValueWithoutNotify(BowTrajectoryPlugin.ImpactMarkerSize.Value);
				UpdateImpactSizeLabel(BowTrajectoryPlugin.ImpactMarkerSize.Value);
			}
		}

		private void OnEnabledChanged(bool value)
		{
			BowTrajectoryPlugin.Enabled.Value = value;
			SaveConfig();
		}

		private void OnShowImpactChanged(bool value)
		{
			BowTrajectoryPlugin.ShowImpactMarker.Value = value;
			SaveConfig();
		}

		private void OnShowCrossbowChanged(bool value)
		{
			BowTrajectoryPlugin.ShowForCrossbows.Value = value;
			SaveConfig();
		}

		private void OnTrajectoryChanged(int index)
		{
			if (index >= 0 && index < ColorConfig.SettingsPresetDisplayNames.Length)
			{
				string value = ColorConfig.SettingsPresetDisplayNames[index];
				BowTrajectoryPlugin.StartColor.Value = value;
				BowTrajectoryPlugin.EndColor.Value = value;
				SaveConfig();
			}
		}

		private void OnImpactChanged(int index)
		{
			if (index >= 0 && index < ColorConfig.SettingsPresetDisplayNames.Length)
			{
				BowTrajectoryPlugin.ImpactColor.Value = ColorConfig.SettingsPresetDisplayNames[index];
				SaveConfig();
			}
		}

		private void OnLineWidthChanged(float value)
		{
			BowTrajectoryPlugin.LineWidth.Value = value;
			UpdateLineWidthLabel(value);
			SaveConfig();
		}

		private void OnImpactSizeChanged(float value)
		{
			BowTrajectoryPlugin.ImpactMarkerSize.Value = value;
			UpdateImpactSizeLabel(value);
			SaveConfig();
		}

		private void ResetToDefaults()
		{
			try
			{
				BowTrajectoryPlugin.Enabled.Value = (bool)((ConfigEntryBase)BowTrajectoryPlugin.Enabled).DefaultValue;
				BowTrajectoryPlugin.ShowImpactMarker.Value = (bool)((ConfigEntryBase)BowTrajectoryPlugin.ShowImpactMarker).DefaultValue;
				BowTrajectoryPlugin.ShowForCrossbows.Value = (bool)((ConfigEntryBase)BowTrajectoryPlugin.ShowForCrossbows).DefaultValue;
				BowTrajectoryPlugin.StartColor.Value = (string)((ConfigEntryBase)BowTrajectoryPlugin.StartColor).DefaultValue;
				BowTrajectoryPlugin.StartColorHex.Value = (string)((ConfigEntryBase)BowTrajectoryPlugin.StartColorHex).DefaultValue;
				BowTrajectoryPlugin.EndColor.Value = (string)((ConfigEntryBase)BowTrajectoryPlugin.EndColor).DefaultValue;
				BowTrajectoryPlugin.EndColorHex.Value = (string)((ConfigEntryBase)BowTrajectoryPlugin.EndColorHex).DefaultValue;
				BowTrajectoryPlugin.ImpactColor.Value = (string)((ConfigEntryBase)BowTrajectoryPlugin.ImpactColor).DefaultValue;
				BowTrajectoryPlugin.ImpactColorHex.Value = (string)((ConfigEntryBase)BowTrajectoryPlugin.ImpactColorHex).DefaultValue;
				BowTrajectoryPlugin.LineWidth.Value = (float)((ConfigEntryBase)BowTrajectoryPlugin.LineWidth).DefaultValue;
				BowTrajectoryPlugin.ImpactMarkerSize.Value = (float)((ConfigEntryBase)BowTrajectoryPlugin.ImpactMarkerSize).DefaultValue;
				SaveConfig();
				SyncFromConfig();
			}
			catch (Exception ex)
			{
				LogWarning("Failed to reset Bow Trajectory settings to defaults: " + ex.Message);
			}
		}

		private void UpdateLineWidthLabel(float value)
		{
			if ((Object)(object)_lineWidthValueText != (Object)null)
			{
				_lineWidthValueText.text = value.ToString("0.00");
			}
		}

		private void UpdateImpactSizeLabel(float value)
		{
			if ((Object)(object)_impactSizeValueText != (Object)null)
			{
				_impactSizeValueText.text = value.ToString("0.00");
			}
		}

		private static void SaveConfig()
		{
			try
			{
				BowTrajectoryPlugin instance = BowTrajectoryPlugin.Instance;
				if (instance != null)
				{
					((BaseUnityPlugin)instance).Config.Save();
				}
			}
			catch (Exception ex)
			{
				LogWarning("Failed to save config after settings change: " + ex.Message);
			}
		}

		private void WireSelectableNavigation()
		{
			List<Selectable> list = new List<Selectable>(9);
			AddIfNotNull(list, (Selectable)(object)_enabledToggle);
			AddIfNotNull(list, (Selectable)(object)_showImpactToggle);
			AddIfNotNull(list, (Selectable)(object)_showCrossbowToggle);
			AddIfNotNull(list, (Selectable)(object)_trajectoryDropdown);
			AddIfNotNull(list, (Selectable)(object)_impactDropdown);
			AddIfNotNull(list, (Selectable)(object)_lineWidthSlider);
			AddIfNotNull(list, (Selectable)(object)_impactSizeSlider);
			AddIfNotNull(list, (Selectable)(object)_defaultButton);
			for (int i = 0; i < list.Count - 1; i++)
			{
				GuiUtils.SetNavigationDown(list[i], list[i + 1]);
				GuiUtils.SetNavigationUp(list[i + 1], list[i]);
			}
		}

		private Selectable GetLastSelectable()
		{
			if ((Object)(object)_defaultButton != (Object)null)
			{
				return (Selectable)(object)_defaultButton;
			}
			if ((Object)(object)_impactSizeSlider != (Object)null)
			{
				return (Selectable)(object)_impactSizeSlider;
			}
			if ((Object)(object)_lineWidthSlider != (Object)null)
			{
				return (Selectable)(object)_lineWidthSlider;
			}
			if ((Object)(object)_impactDropdown != (Object)null)
			{
				return (Selectable)(object)_impactDropdown;
			}
			return (Selectable)(object)_trajectoryDropdown;
		}

		private static void AddIfNotNull(List<Selectable> list, Selectable selectable)
		{
			if ((Object)(object)selectable != (Object)null)
			{
				list.Add(selectable);
			}
		}

		private static RectTransform FindExistingPage(TabHandler tabHandler)
		{
			for (int i = 0; i < tabHandler.m_tabs.Count; i++)
			{
				Tab val = tabHandler.m_tabs[i];
				if ((Object)(object)val?.m_page != (Object)null && (Object)(object)((Component)val.m_page).GetComponent<BowTrajectorySettingsTab>() != (Object)null)
				{
					return val.m_page;
				}
			}
			return null;
		}

		private static Tab FindTemplateTab(TabHandler tabHandler)
		{
			for (int i = 0; i < tabHandler.m_tabs.Count; i++)
			{
				Tab val = tabHandler.m_tabs[i];
				if ((Object)(object)val?.m_page != (Object)null && (Object)(object)((Component)val.m_page).GetComponent<AccessibilitySettings>() != (Object)null)
				{
					return val;
				}
			}
			for (int num = tabHandler.m_tabs.Count - 1; num >= 0; num--)
			{
				Tab val2 = tabHandler.m_tabs[num];
				if ((Object)(object)val2?.m_button != (Object)null && (Object)(object)val2.m_page != (Object)null)
				{
					return val2;
				}
			}
			return null;
		}

		private static Button CloneTabButton(Button template, string label)
		{
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)template).transform.parent);
			((Object)val).name = "Tab_BowTrajectory";
			val.SetActive(true);
			Button component = val.GetComponent<Button>();
			((UnityEventBase)component.onClick).RemoveAllListeners();
			((Selectable)component).interactable = true;
			Transform val2 = val.transform.Find("Selected");
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			SetButtonLabel(component, label);
			val.transform.SetAsLastSibling();
			return component;
		}

		private static void SetButtonLabel(Button button, string label)
		{
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)button).transform.Find("Selected");
			TMP_Text val2 = null;
			if ((Object)(object)val != (Object)null)
			{
				val2 = ((Component)val).GetComponentInChildren<TMP_Text>(true);
			}
			TMP_Text val3 = null;
			TMP_Text[] componentsInChildren = ((Component)button).GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val4 in componentsInChildren)
			{
				if ((!((Object)(object)val != (Object)null) || !val4.transform.IsChildOf(val)) && ((Object)(object)val3 == (Object)null || (Object)(object)val4.transform.parent == (Object)(object)((Component)button).transform))
				{
					val3 = val4;
					if ((Object)(object)val4.transform.parent == (Object)(object)((Component)button).transform)
					{
						break;
					}
				}
			}
			foreach (TMP_Text val5 in componentsInChildren)
			{
				if ((Object)(object)val5 != (Object)(object)val3 && (Object)(object)val5 != (Object)(object)val2)
				{
					((Component)val5).gameObject.SetActive(false);
				}
			}
			Text[] componentsInChildren2 = ((Component)button).GetComponentsInChildren<Text>(true);
			for (int k = 0; k < componentsInChildren2.Length; k++)
			{
				((Component)componentsInChildren2[k]).gameObject.SetActive(false);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				val2.text = label;
				((Component)val2).gameObject.SetActive(true);
			}
			if (!((Object)(object)val3 == (Object)null))
			{
				if ((Object)(object)val2 != (Object)null)
				{
					Color color = ((Graphic)val3).color;
					val3.font = val2.font;
					val3.fontSharedMaterial = val2.fontSharedMaterial;
					val3.fontSize = val2.fontSize;
					val3.fontStyle = val2.fontStyle;
					val3.overflowMode = val2.overflowMode;
					val3.alignment = val2.alignment;
					((Graphic)val3).color = color;
				}
				val3.text = label;
				((Component)val3).gameObject.SetActive(true);
			}
		}

		private static RectTransform CreatePage(RectTransform templatePage)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("BowTrajectorySettings", new Type[1] { typeof(RectTransform) });
			val.SetActive(false);
			val.transform.SetParent(((Transform)templatePage).parent, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = templatePage.anchorMin;
			component.anchorMax = templatePage.anchorMax;
			component.pivot = templatePage.pivot;
			component.anchoredPosition = templatePage.anchoredPosition;
			component.sizeDelta = templatePage.sizeDelta;
			component.offsetMin = templatePage.offsetMin;
			component.offsetMax = templatePage.offsetMax;
			((Transform)component).localScale = ((Transform)templatePage).localScale;
			return component;
		}

		private static Transform CreateContentRoot(RectTransform page)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			GameObject val = new GameObject("Content", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)page, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 0f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(0.5f, 1f);
			component.offsetMin = new Vector2(24f, 24f);
			component.offsetMax = new Vector2(-24f, -24f);
			VerticalLayoutGroup obj = val.AddComponent<VerticalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 10f;
			((LayoutGroup)obj).padding = new RectOffset(0, 0, 8, 8);
			((LayoutGroup)obj).childAlignment = (TextAnchor)0;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true;
			return val.transform;
		}

		private static GuiDropdown CreateDropdownRow(Transform parent, GuiDropdown template, TMP_Text labelTemplate, string labelText, UnityAction<int> onChanged)
		{
			Transform val = CreateRow(parent, labelText);
			CreateLabel(val, labelTemplate, labelText);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)template).gameObject, val);
			((Object)val2).name = "Dropdown";
			val2.SetActive(true);
			LayoutElement obj = val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>();
			obj.minWidth = 160f;
			obj.preferredWidth = 180f;
			obj.flexibleWidth = 0f;
			obj.minHeight = 32f;
			obj.preferredHeight = 36f;
			GuiDropdown component = val2.GetComponent<GuiDropdown>();
			((UnityEventBase)((TMP_Dropdown)component).onValueChanged).RemoveAllListeners();
			((TMP_Dropdown)component).ClearOptions();
			((TMP_Dropdown)component).AddOptions(new List<string>(ColorConfig.SettingsPresetDisplayNames));
			((TMP_Dropdown)component).SetValueWithoutNotify(0);
			((UnityEvent<int>)(object)((TMP_Dropdown)component).onValueChanged).AddListener(onChanged);
			component.OnExpandedStateChange += OnDropdownExpanded;
			return component;
		}

		private static void CreateSliderRow(Transform parent, Slider template, TMP_Text labelTemplate, string labelText, float min, float max, UnityAction<float> onChanged, out Slider slider, out TMP_Text valueText)
		{
			Transform val = CreateRow(parent, labelText);
			CreateLabel(val, labelTemplate, labelText);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)template).gameObject, val);
			((Object)val2).name = "Slider";
			val2.SetActive(true);
			DisableExtraneousTexts(val2.transform);
			LayoutElement obj = val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>();
			obj.minWidth = 180f;
			obj.preferredWidth = 220f;
			obj.flexibleWidth = 1f;
			obj.minHeight = 28f;
			obj.preferredHeight = 32f;
			slider = val2.GetComponent<Slider>();
			((UnityEventBase)slider.onValueChanged).RemoveAllListeners();
			slider.minValue = min;
			slider.maxValue = max;
			slider.wholeNumbers = false;
			valueText = CreateValueText(val, labelTemplate);
			((UnityEvent<float>)(object)slider.onValueChanged).AddListener(onChanged);
		}

		private static Toggle CreateToggleRow(Transform parent, Toggle template, TMP_Text labelTemplate, string labelText, UnityAction<bool> onChanged)
		{
			Transform val = CreateRow(parent, labelText);
			CreateLabel(val, labelTemplate, labelText);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)template).gameObject, val);
			((Object)val2).name = "Toggle";
			val2.SetActive(true);
			DisableExtraneousTexts(val2.transform);
			LayoutElement obj = val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>();
			obj.minWidth = 40f;
			obj.preferredWidth = 48f;
			obj.flexibleWidth = 0f;
			obj.minHeight = 28f;
			obj.preferredHeight = 32f;
			Toggle component = val2.GetComponent<Toggle>();
			((UnityEventBase)component.onValueChanged).RemoveAllListeners();
			component.SetIsOnWithoutNotify(false);
			((UnityEvent<bool>)(object)component.onValueChanged).AddListener(onChanged);
			return component;
		}

		private static Button FindButtonTemplate(Settings settings)
		{
			GameplaySettings val = (((Object)(object)settings != (Object)null) ? ((Component)settings).GetComponentInChildren<GameplaySettings>(true) : null);
			if ((Object)(object)val?.m_resetTutorial != (Object)null)
			{
				return val.m_resetTutorial;
			}
			if ((Object)(object)settings?.m_okButton != (Object)null)
			{
				return settings.m_okButton;
			}
			if ((Object)(object)settings?.m_backButton != (Object)null)
			{
				return settings.m_backButton;
			}
			return null;
		}

		private static Transform CreateRow(Transform parent, string labelText)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(SanitizeName(labelText) + "_Row", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj).spacing = 16f;
			((LayoutGroup)obj).childAlignment = (TextAnchor)3;
			((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
			((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
			((LayoutGroup)obj).padding = new RectOffset(4, 4, 2, 2);
			LayoutElement obj2 = val.AddComponent<LayoutElement>();
			obj2.minHeight = 36f;
			obj2.preferredHeight = 40f;
			obj2.flexibleWidth = 1f;
			return val.transform;
		}

		private static void CreateLabel(Transform row, TMP_Text labelTemplate, string labelText)
		{
			if (!((Object)(object)labelTemplate == (Object)null))
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)labelTemplate).gameObject, row);
				((Object)val).name = "Label";
				val.SetActive(true);
				TMP_Text component = val.GetComponent<TMP_Text>();
				if ((Object)(object)component != (Object)null)
				{
					component.text = labelText;
					((Graphic)component).raycastTarget = false;
				}
				LayoutElement obj = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
				obj.minWidth = 220f;
				obj.preferredWidth = 260f;
				obj.flexibleWidth = 0f;
				obj.minHeight = 32f;
			}
		}

		private static TMP_Text CreateValueText(Transform row, TMP_Text labelTemplate)
		{
			if ((Object)(object)labelTemplate == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)labelTemplate).gameObject, row);
			((Object)val).name = "Value";
			val.SetActive(true);
			TMP_Text component = val.GetComponent<TMP_Text>();
			if ((Object)(object)component != (Object)null)
			{
				component.text = "0.00";
				((Graphic)component).raycastTarget = false;
				component.alignment = (TextAlignmentOptions)4100;
			}
			LayoutElement obj = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
			obj.minWidth = 56f;
			obj.preferredWidth = 64f;
			obj.flexibleWidth = 0f;
			obj.minHeight = 32f;
			return component;
		}

		private static void DisableExtraneousTexts(Transform root)
		{
			TMP_Text[] componentsInChildren = ((Component)root).GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.SetActive(false);
			}
		}

		private static void OnDropdownExpanded(bool expanded)
		{
			if ((Object)(object)Settings.instance != (Object)null)
			{
				Settings.instance.BlockNavigation(expanded);
			}
		}

		private static GuiDropdown FindDropdownTemplate(Settings settings)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			GraphicsSettings val = (((Object)(object)settings != (Object)null) ? ((Component)settings).GetComponentInChildren<GraphicsSettings>(true) : null);
			Scene scene;
			if ((Object)(object)val == (Object)null)
			{
				GraphicsSettings[] array = Resources.FindObjectsOfTypeAll<GraphicsSettings>();
				for (int i = 0; i < array.Length; i++)
				{
					if ((Object)(object)array[i] != (Object)null)
					{
						scene = ((Component)array[i]).gameObject.scene;
						if (((Scene)(ref scene)).IsValid())
						{
							val = array[i];
							break;
						}
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)val.m_upscalingAlgorithmDropdown != (Object)null)
				{
					return val.m_upscalingAlgorithmDropdown;
				}
				if ((Object)(object)val.m_renderScaleDropdown != (Object)null)
				{
					return val.m_renderScaleDropdown;
				}
				if ((Object)(object)val.m_resolutionDropdown != (Object)null)
				{
					return val.m_resolutionDropdown;
				}
			}
			GuiDropdown[] array2 = Resources.FindObjectsOfTypeAll<GuiDropdown>();
			for (int j = 0; j < array2.Length; j++)
			{
				if ((Object)(object)array2[j] != (Object)null)
				{
					scene = ((Component)array2[j]).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						return array2[j];
					}
				}
			}
			return null;
		}

		private static Slider FindSliderTemplate(Settings settings)
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			AccessibilitySettings val = (((Object)(object)settings != (Object)null) ? ((Component)settings).GetComponentInChildren<AccessibilitySettings>(true) : null);
			if ((Object)(object)val?.m_guiScaleSlider != (Object)null)
			{
				return val.m_guiScaleSlider;
			}
			AudioSettings val2 = (((Object)(object)settings != (Object)null) ? ((Component)settings).GetComponentInChildren<AudioSettings>(true) : null);
			if ((Object)(object)val2?.m_volumeSlider != (Object)null)
			{
				return val2.m_volumeSlider;
			}
			GraphicsSettings val3 = (((Object)(object)settings != (Object)null) ? ((Component)settings).GetComponentInChildren<GraphicsSettings>(true) : null);
			if ((Object)(object)val3?.m_fpsLimitSlider != (Object)null)
			{
				return val3.m_fpsLimitSlider;
			}
			Slider[] array = Resources.FindObjectsOfTypeAll<Slider>();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					Scene scene = ((Component)array[i]).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						return array[i];
					}
				}
			}
			return null;
		}

		private static Toggle FindToggleTemplate(Settings settings)
		{
			AccessibilitySettings val = (((Object)(object)settings != (Object)null) ? ((Component)settings).GetComponentInChildren<AccessibilitySettings>(true) : null);
			if ((Object)(object)val?.m_toggleRun != (Object)null)
			{
				return val.m_toggleRun;
			}
			if ((Object)(object)val?.m_motionblurToggle != (Object)null)
			{
				return val.m_motionblurToggle;
			}
			GameplaySettings val2 = (((Object)(object)settings != (Object)null) ? ((Component)settings).GetComponentInChildren<GameplaySettings>(true) : null);
			if ((Object)(object)val2?.m_showKeyHints != (Object)null)
			{
				return val2.m_showKeyHints;
			}
			return null;
		}

		private static TMP_Text FindLabelTemplate(Settings settings, Toggle toggleTemplate, Slider sliderTemplate)
		{
			if ((Object)(object)toggleTemplate != (Object)null)
			{
				TMP_Text componentInChildren = ((Component)toggleTemplate).GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					return componentInChildren;
				}
			}
			AccessibilitySettings val = (((Object)(object)settings != (Object)null) ? ((Component)settings).GetComponentInChildren<AccessibilitySettings>(true) : null);
			if ((Object)(object)val?.m_guiScaleText != (Object)null)
			{
				return val.m_guiScaleText;
			}
			if ((Object)(object)sliderTemplate != (Object)null)
			{
				TMP_Text componentInChildren2 = ((Component)sliderTemplate).GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)componentInChildren2 != (Object)null)
				{
					return componentInChildren2;
				}
			}
			if (!((Object)(object)settings != (Object)null))
			{
				return null;
			}
			return ((Component)settings).GetComponentInChildren<TMP_Text>(true);
		}

		private static void GetFloatRange(ConfigEntry<float> entry, float fallbackMin, float fallbackMax, out float min, out float max)
		{
			min = fallbackMin;
			max = fallbackMax;
			object obj;
			if (entry == null)
			{
				obj = null;
			}
			else
			{
				ConfigDescription description = ((ConfigEntryBase)entry).Description;
				obj = ((description != null) ? description.AcceptableValues : null);
			}
			if (obj is AcceptableValueRange<float> val)
			{
				min = val.MinValue;
				max = val.MaxValue;
			}
		}

		private static string SanitizeName(string label)
		{
			return label.Replace(' ', '_').Replace('/', '_');
		}

		private static void LogInfo(string message)
		{
			BowTrajectoryPlugin.Log.LogInfo((object)message);
		}

		private static void LogWarning(string message)
		{
			BowTrajectoryPlugin.Log.LogWarning((object)message);
		}
	}
	[HarmonyPatch(typeof(Settings))]
	internal static class BowTrajectorySettingsTabPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("InitializeTabs")]
		private static void InitializeTabsPrefix(Settings __instance)
		{
			BowTrajectorySettingsTab.TryInjectTab(__instance);
		}
	}
	public enum ColorPreset
	{
		White,
		Red,
		Green,
		Blue,
		Yellow,
		Cyan,
		Magenta,
		Orange,
		Purple,
		Black,
		RgbCycleSlow,
		RgbCycleMedium,
		RgbCycleFast,
		Custom
	}
	internal static class ColorConfig
	{
		private const float LineAlpha = 0.85f;

		private const float MarkerAlpha = 0.9f;

		private const float CycleSlowSeconds = 7f;

		private const float CycleMediumSeconds = 3.5f;

		private const float CycleFastSeconds = 1.25f;

		internal const float EndCyclePhaseOffset = 0.15f;

		internal static readonly string[] PresetDisplayNames = new string[14]
		{
			"White", "Red", "Green", "Blue", "Yellow", "Cyan", "Magenta", "Orange", "Purple", "Black",
			"RGB Cycle Slow", "RGB Cycle Medium", "RGB Cycle Fast", "Custom"
		};

		internal static readonly string[] SettingsPresetDisplayNames = new string[13]
		{
			"White", "Red", "Green", "Blue", "Yellow", "Cyan", "Magenta", "Orange", "Purple", "Black",
			"RGB Cycle Slow", "RGB Cycle Medium", "RGB Cycle Fast"
		};

		internal static float DefaultLineAlpha => 0.85f;

		internal static float DefaultMarkerAlpha => 0.9f;

		internal static int IndexOfSettingsPreset(string presetName)
		{
			if (!TryParsePresetName(presetName, out var preset) || preset == ColorPreset.Custom)
			{
				return -1;
			}
			string b = ToDisplayName(preset);
			for (int i = 0; i < SettingsPresetDisplayNames.Length; i++)
			{
				if (string.Equals(SettingsPresetDisplayNames[i], b, StringComparison.OrdinalIgnoreCase))
				{
					return i;
				}
			}
			return -1;
		}

		internal static string ToDisplayName(ColorPreset preset)
		{
			if (preset >= ColorPreset.White && (int)preset < PresetDisplayNames.Length)
			{
				return PresetDisplayNames[(int)preset];
			}
			return PresetDisplayNames[0];
		}

		internal static ColorPreset ParsePreset(string raw)
		{
			if (TryParsePresetName(raw, out var preset))
			{
				return preset;
			}
			return ColorPreset.White;
		}

		internal static bool TryParsePresetName(string raw, out ColorPreset preset)
		{
			preset = ColorPreset.White;
			if (string.IsNullOrWhiteSpace(raw))
			{
				return false;
			}
			string text = raw.Trim();
			for (int i = 0; i < PresetDisplayNames.Length; i++)
			{
				if (string.Equals(PresetDisplayNames[i], text, StringComparison.OrdinalIgnoreCase))
				{
					preset = (ColorPreset)i;
					return true;
				}
			}
			if (Enum.TryParse<ColorPreset>(text, ignoreCase: true, out var result) && Enum.IsDefined(typeof(ColorPreset), result))
			{
				preset = result;
				return true;
			}
			string b = Compact(text);
			int num = 0;
			while (num < PresetDisplayNames.Length)
			{
				if (!string.Equals(Compact(PresetDisplayNames[num]), b, StringComparison.OrdinalIgnoreCase))
				{
					ColorPreset colorPreset = (ColorPreset)num;
					if (!string.Equals(Compact(colorPreset.ToString()), b, StringComparison.OrdinalIgnoreCase))
					{
						num++;
						continue;
					}
				}
				preset = (ColorPreset)num;
				return true;
			}
			return false;
		}

		internal static Color Resolve(string presetName, string hex, float fallbackAlpha, float huePhaseOffset = 0f)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return Resolve(ParsePreset(presetName), hex, fallbackAlpha, huePhaseOffset);
		}

		internal static Color Resolve(ColorPreset preset, string hex, float fallbackAlpha, float huePhaseOffset = 0f)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (TryGetCyclePeriod(preset, out var periodSeconds))
			{
				return WithAlpha(Color.HSVToRGB(Mathf.Repeat(Time.time / periodSeconds + huePhaseOffset, 1f), 1f, 1f), fallbackAlpha);
			}
			if (preset == ColorPreset.Custom)
			{
				if (TryParseHex(hex, fallbackAlpha, out var color))
				{
					return color;
				}
				return WithAlpha(Color.white, fallbackAlpha);
			}
			return FromPreset(preset, fallbackAlpha);
		}

		internal static bool TryGetCyclePeriod(ColorPreset preset, out float periodSeconds)
		{
			switch (preset)
			{
			case ColorPreset.RgbCycleSlow:
				periodSeconds = 7f;
				return true;
			case ColorPreset.RgbCycleMedium:
				periodSeconds = 3.5f;
				return true;
			case ColorPreset.RgbCycleFast:
				periodSeconds = 1.25f;
				return true;
			default:
				periodSeconds = 0f;
				return false;
			}
		}

		internal static Color FromPreset(ColorPreset preset, float alpha)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			Color white = default(Color);
			switch (preset)
			{
			case ColorPreset.White:
				white = Color.white;
				break;
			case ColorPreset.Red:
				((Color)(ref white))..ctor(1f, 0.25f, 0.2f);
				break;
			case ColorPreset.Green:
				((Color)(ref white))..ctor(0.2f, 0.9f, 0.3f);
				break;
			case ColorPreset.Blue:
				((Color)(ref white))..ctor(0.25f, 0.45f, 1f);
				break;
			case ColorPreset.Yellow:
				((Color)(ref white))..ctor(1f, 0.92f, 0.2f);
				break;
			case ColorPreset.Cyan:
				((Color)(ref white))..ctor(0.2f, 0.95f, 0.95f);
				break;
			case ColorPreset.Magenta:
				((Color)(ref white))..ctor(1f, 0.3f, 0.9f);
				break;
			case ColorPreset.Orange:
				((Color)(ref white))..ctor(1f, 0.55f, 0.1f);
				break;
			case ColorPreset.Purple:
				((Color)(ref white))..ctor(0.7f, 0.3f, 1f);
				break;
			case ColorPreset.Black:
				((Color)(ref white))..ctor(0.05f, 0.05f, 0.05f);
				break;
			default:
				white = Color.white;
				break;
			}
			return WithAlpha(white, alpha);
		}

		internal static string ToHex(Color color)
		{
			//IL_0000: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			byte b = (byte)Mathf.Clamp(Mathf.RoundToInt(color.r * 255f), 0, 255);
			byte b2 = (byte)Mathf.Clamp(Mathf.RoundToInt(color.g * 255f), 0, 255);
			byte b3 = (byte)Mathf.Clamp(Mathf.RoundToInt(color.b * 255f), 0, 255);
			byte b4 = (byte)Mathf.Clamp(Mathf.RoundToInt(color.a * 255f), 0, 255);
			return $"#{b:X2}{b2:X2}{b3:X2}{b4:X2}";
		}

		internal static string NormalizeHexString(string hex)
		{
			if (!TryParseHex(hex, 1f, out var _))
			{
				return null;
			}
			string text = hex.Trim();
			if (!text.StartsWith("#", StringComparison.Ordinal))
			{
				text = "#" + text;
			}
			return text.ToUpperInvariant();
		}

		internal static bool TryParseHex(string hex, float fallbackAlpha, out Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color);
			if (string.IsNullOrWhiteSpace(hex))
			{
				return false;
			}
			string text = hex.Trim();
			if (text.StartsWith("#", StringComparison.Ordinal))
			{
				text = text.Substring(1);
			}
			if (text.Length != 6 && text.Length != 8)
			{
				return false;
			}
			if (!uint.TryParse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
			{
				return false;
			}
			if (text.Length == 6)
			{
				float num = (float)((result >> 16) & 0xFF) / 255f;
				float num2 = (float)((result >> 8) & 0xFF) / 255f;
				float num3 = (float)(result & 0xFF) / 255f;
				color = new Color(num, num2, num3, fallbackAlpha);
				return true;
			}
			float num4 = (float)((result >> 24) & 0xFF) / 255f;
			float num5 = (float)((result >> 16) & 0xFF) / 255f;
			float num6 = (float)((result >> 8) & 0xFF) / 255f;
			float num7 = (float)(result & 0xFF) / 255f;
			color = new Color(num4, num5, num6, num7);
			return true;
		}

		internal static bool TryParseUnityColor(string raw, out Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			color = default(Color);
			if (string.IsNullOrWhiteSpace(raw))
			{
				return false;
			}
			string[] array = raw.Split(new char[1] { ',' });
			if (array.Length < 3)
			{
				return false;
			}
			if (!float.TryParse(array[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[2].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result3))
			{
				return false;
			}
			float num = 1f;
			if (array.Length >= 4 && float.TryParse(array[3].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result4))
			{
				num = result4;
			}
			color = new Color(result, result2, result3, num);
			return true;
		}

		private static string Compact(string value)
		{
			char[] array = new char[value.Length];
			int length = 0;
			foreach (char c in value)
			{
				if (char.IsLetterOrDigit(c))
				{
					array[length++] = char.ToLowerInvariant(c);
				}
			}
			return new string(array, 0, length);
		}

		private static Color WithAlpha(Color rgb, float alpha)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			rgb.a = alpha;
			return rgb;
		}
	}
	internal static class ConfigMigration
	{
		private const string LegacyFileName = "dev.modded.bowtrajectory.cfg";

		private static readonly PropertyInfo OrphanedEntriesProperty = typeof(ConfigFile).GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);

		internal static void MigrateFromLegacy(ConfigFile current, ManualLogSource logger, ConfigEntry<bool> enabled, ConfigEntry<KeyboardShortcut> toggleKey, ConfigEntry<float> minDrawPercent, ConfigEntry<bool> showForCrossbows, ConfigEntry<bool> stopAtCharacters, ConfigEntry<string> startColor, ConfigEntry<string> startColorHex, ConfigEntry<string> endColor, ConfigEntry<string> endColorHex, ConfigEntry<float> lineWidth, ConfigEntry<bool> showImpactMarker, ConfigEntry<string> impactColor, ConfigEntry<string> impactColorHex, ConfigEntry<float> impactMarkerSize, ConfigEntry<int> maxPoints)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			string text = Path.Combine(Paths.ConfigPath, "dev.modded.bowtrajectory.cfg");
			if (!File.Exists(text))
			{
				return;
			}
			try
			{
				ConfigFile legacy = new ConfigFile(text, true);
				int num = 0;
				num += Copy<bool>(legacy, enabled);
				num += Copy<KeyboardShortcut>(legacy, toggleKey);
				num += Copy<float>(legacy, minDrawPercent);
				num += Copy<bool>(legacy, showForCrossbows);
				num += Copy<bool>(legacy, stopAtCharacters);
				num += CopyColor(legacy, "Appearance", "StartColor", startColor, startColorHex);
				num += CopyColor(legacy, "Appearance", "EndColor", endColor, endColorHex);
				num += Copy<float>(legacy, lineWidth);
				num += Copy<bool>(legacy, showImpactMarker);
				num += CopyColor(legacy, "Appearance", "ImpactColor", impactColor, impactColorHex);
				num += Copy<float>(legacy, impactMarkerSize);
				num += Copy<int>(legacy, maxPoints);
				current.Save();
				logger.LogInfo((object)string.Format("Migrated {0} setting(s) from {1} to {2}.cfg", num, "dev.modded.bowtrajectory.cfg", "ModdedWolf.BowTrajectory"));
				try
				{
					ArchiveLegacyFile(text, logger);
				}
				catch (Exception ex)
				{
					logger.LogWarning((object)("Migrated settings but could not archive dev.modded.bowtrajectory.cfg: " + ex.Message + ". Rename or delete that file to prevent re-migration on next launch."));
				}
			}
			catch (Exception ex2)
			{
				logger.LogWarning((object)("Could not migrate legacy config (dev.modded.bowtrajectory.cfg): " + ex2.Message));
			}
		}

		internal static bool ScrubLegacyColorPreset(ConfigFile config, string section, string presetKey, string hexKey, string defaultDisplayName)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ConfigDefinition, string> orphanedEntries = GetOrphanedEntries(config);
			if (orphanedEntries == null)
			{
				return false;
			}
			bool result = false;
			ConfigDefinition key = new ConfigDefinition(section, presetKey);
			if (orphanedEntries.TryGetValue(key, out var value) && !string.IsNullOrWhiteSpace(value))
			{
				string text = value.Trim();
				Color color;
				Color color2;
				if (ColorConfig.TryParsePresetName(text, out var preset))
				{
					string text2 = ColorConfig.ToDisplayName(preset);
					if (!string.Equals(text, text2, StringComparison.Ordinal))
					{
						orphanedEntries[key] = text2;
						result = true;
					}
				}
				else if (ColorConfig.TryParseHex(text, 1f, out color))
				{
					orphanedEntries[key] = ColorConfig.ToDisplayName(ColorPreset.Custom);
					if (EnsureHexOrphan(orphanedEntries, section, hexKey, ColorConfig.ToHex(color)))
					{
						result = true;
					}
					result = true;
				}
				else if (ColorConfig.TryParseUnityColor(text, out color2))
				{
					orphanedEntries[key] = ColorConfig.ToDisplayName(ColorPreset.Custom);
					if (EnsureHexOrphan(orphanedEntries, section, hexKey, ColorConfig.ToHex(color2)))
					{
						result = true;
					}
					result = true;
				}
				else
				{
					orphanedEntries[key] = defaultDisplayName;
					result = true;
				}
			}
			if (NormalizeHexOrphan(orphanedEntries, section, hexKey))
			{
				result = true;
			}
			return result;
		}

		private static bool EnsureHexOrphan(Dictionary<ConfigDefinition, string> orphans, string section, string hexKey, string fallbackHex)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ConfigDefinition key = new ConfigDefinition(section, hexKey);
			if (orphans.TryGetValue(key, out var value) && ColorConfig.TryParseHex(value, 1f, out var _))
			{
				string text = ColorConfig.NormalizeHexString(value);
				if (text != null && !string.Equals(value.Trim(), text, StringComparison.Ordinal))
				{
					orphans[key] = text;
					return true;
				}
				return false;
			}
			orphans[key] = fallbackHex;
			return true;
		}

		private static bool NormalizeHexOrphan(Dictionary<ConfigDefinition, string> orphans, string section, string hexKey)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ConfigDefinition key = new ConfigDefinition(section, hexKey);
			if (!orphans.TryGetValue(key, out var value) || string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			string text = ColorConfig.NormalizeHexString(value);
			if (text == null || string.Equals(value.Trim(), text, StringComparison.Ordinal))
			{
				return false;
			}
			orphans[key] = text;
			return true;
		}

		private static Dictionary<ConfigDefinition, string> GetOrphanedEntries(ConfigFile config)
		{
			if (OrphanedEntriesProperty == null)
			{
				return null;
			}
			return OrphanedEntriesProperty.GetValue(config) as Dictionary<ConfigDefinition, string>;
		}

		private static void ArchiveLegacyFile(string legacyPath, ManualLogSource logger)
		{
			string text = legacyPath + ".migrated";
			if (File.Exists(text))
			{
				File.Delete(text);
			}
			File.Move(legacyPath, text);
			logger.LogInfo((object)("Archived legacy config as " + Path.GetFileName(text) + " (migration will not re-run)"));
		}

		private static int Copy<T>(ConfigFile legacy, ConfigEntry<T> target)
		{
			ConfigEntry<T> val = default(ConfigEntry<T>);
			if (!legacy.TryGetEntry<T>(((ConfigEntryBase)target).Definition.Section, ((ConfigEntryBase)target).Definition.Key, ref val))
			{
				return 0;
			}
			target.Value = val.Value;
			return 1;
		}

		private static int CopyColor(ConfigFile legacy, string section, string key, ConfigEntry<string> preset, ConfigEntry<string> hex)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<Color> val = default(ConfigEntry<Color>);
			if (!legacy.TryGetEntry<Color>(section, key, ref val))
			{
				return 0;
			}
			preset.Value = ColorConfig.ToDisplayName(ColorPreset.Custom);
			hex.Value = ColorConfig.ToHex(val.Value);
			return 1;
		}
	}
	public class TrajectoryRenderer : MonoBehaviour
	{
		private LineRenderer _line;

		private LineRenderer _marker;

		private bool _userEnabled = true;

		private int _solidMask;

		private int _solidWithCharMask;

		private bool _masksReady;

		private Vector3[] _points;

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

		private Color _lastStart;

		private Color _lastEnd;

		private Color _lastImpact;

		private float _lastWidth = -1f;

		private void Awake()
		{
			_line = CreateLineRenderer("BowTrajectory_Line", loop: false);
			_marker = CreateLineRenderer("BowTrajectory_Marker", loop: true);
			SetVisible(visible: false);
		}

		private LineRenderer CreateLineRenderer(string name, bool loop)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.SetParent(((Component)this).transform, false);
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			val2.useWorldSpace = true;
			val2.loop = loop;
			val2.numCapVertices = 4;
			val2.numCornerVertices = 2;
			val2.textureMode = (LineTextureMode)0;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			val2.alignment = (LineAlignment)0;
			val2.positionCount = 0;
			Shader val3 = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Particles/Standard Unlit");
			if ((Object)(object)val3 != (Object)null)
			{
				((Renderer)val2).material = new Material(val3);
			}
			if ((Object)(object)((Renderer)val2).material != (Object)null)
			{
				((Renderer)val2).material.renderQueue = 3100;
			}
			return val2;
		}

		private void EnsureMasks()
		{
			if (!_masksReady)
			{
				_solidMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
				_solidWithCharMask = _solidMask | LayerMask.GetMask(new string[5] { "character", "character_net", "character_ghost", "hitbox", "character_noenv" });
				_masksReady = true;
			}
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = BowTrajectoryPlugin.ToggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && !IsTextFieldFocused())
			{
				_userEnabled = !_userEnabled;
			}
		}

		private void LateUpdate()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Invalid comparison between Unknown and I4
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (!BowTrajectoryPlugin.Enabled.Value || !_userEnabled)
			{
				SetVisible(visible: false);
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				SetVisible(visible: false);
				return;
			}
			ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon();
			if (currentWeapon == null || currentWeapon.m_shared == null || currentWeapon.m_shared.m_attack == null)
			{
				SetVisible(visible: false);
				return;
			}
			SkillType skillType = currentWeapon.m_shared.m_skillType;
			bool bowDraw = currentWeapon.m_shared.m_attack.m_bowDraw;
			bool flag = (int)skillType == 14;
			if (!bowDraw && (!flag || !BowTrajectoryPlugin.ShowForCrossbows.Value))
			{
				SetVisible(visible: false);
				return;
			}
			float attackDrawPercentage = ((Humanoid)localPlayer).GetAttackDrawPercentage();
			Vector3 spawn;
			Vector3 dir;
			float speed;
			float gravity;
			float drag;
			float ttl;
			if (bowDraw && attackDrawPercentage < BowTrajectoryPlugin.MinDrawPercent.Value)
			{
				SetVisible(visible: false);
			}
			else if (flag && !IsCrossbowReady(localPlayer))
			{
				SetVisible(visible: false);
			}
			else if (!ResolveLaunch(localPlayer, currentWeapon, bowDraw, attackDrawPercentage, out spawn, out dir, out speed, out gravity, out drag, out ttl))
			{
				SetVisible(visible: false);
			}
			else
			{
				Simulate(localPlayer, spawn, dir, speed, gravity, drag, ttl);
			}
		}

		private bool ResolveLaunch(Player player, ItemData weapon, bool isBow, float drawPct, out Vector3 spawn, out Vector3 dir, out float speed, out float gravity, out float drag, out float ttl)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			spawn = Vector3.zero;
			dir = Vector3.forward;
			speed = 0f;
			gravity = 0f;
			drag = 0f;
			ttl = 4f;
			Attack attack = weapon.m_shared.m_attack;
			ItemData ammoItem = ((Humanoid)player).GetAmmoItem();
			GameObject attackProjectile = attack.m_attackProjectile;
			float num = attack.m_projectileVel;
			float num2 = attack.m_projectileVelMin;
			AnimationCurve drawVelocityCurve = attack.m_drawVelocityCurve;
			if (ammoItem != null && ammoItem.m_shared != null && ammoItem.m_shared.m_attack != null && (Object)(object)ammoItem.m_shared.m_attack.m_attackProjectile != (Object)null)
			{
				attackProjectile = ammoItem.m_shared.m_attack.m_attackProjectile;
				num += ammoItem.m_shared.m_attack.m_projectileVel;
				num2 += ammoItem.m_shared.m_attack.m_projectileVelMin;
				drawVelocityCurve = ammoItem.m_shared.m_attack.m_drawVelocityCurve;
			}
			if ((Object)(object)attackProjectile == (Object)null)
			{
				return false;
			}
			if (isBow)
			{
				float num3 = ((drawVelocityCurve != null && drawVelocityCurve.length > 0) ? drawVelocityCurve.Evaluate(drawPct) : drawPct);
				speed = Mathf.Lerp(num2, num, num3);
			}
			else
			{
				speed = num;
			}
			if (speed <= 0.01f)
			{
				return false;
			}
			Projectile component = attackProjectile.GetComponent<Projectile>();
			if ((Object)(object)component != (Object)null)
			{
				gravity = component.m_gravity;
				drag = component.m_drag;
				ttl = ((component.m_ttl > 0f) ? component.m_ttl : 4f);
			}
			GetSpawnAndAim(player, weapon, attack, out spawn, out dir);
			return true;
		}

		private void GetSpawnAndAim(Player player, ItemData weapon, Attack shared, out Vector3 spawn, out Vector3 dir)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			Attack currentAttack = ((Humanoid)player).m_currentAttack;
			Attack val = shared;
			if (currentAttack != null && currentAttack.GetWeapon() == weapon)
			{
				val = currentAttack;
				try
				{
					currentAttack.GetProjectileSpawnPoint(ref spawn, ref dir);
					ApplyLaunchAngle(val, ref dir);
					return;
				}
				catch
				{
				}
			}
			Transform transform = ((Component)player).transform;
			Transform val2 = transform;
			string attackOriginJoint = val.m_attackOriginJoint;
			if (!string.IsNullOrEmpty(attackOriginJoint))
			{
				GameObject visual = ((Character)player).GetVisual();
				Transform val3 = Utils.FindChild(((Object)(object)visual != (Object)null) ? visual.transform : transform, attackOriginJoint, (IterativeSearchType)0);
				if ((Object)(object)val3 != (Object)null)
				{
					val2 = val3;
				}
			}
			spawn = val2.position + transform.up * val.m_attackHeight + transform.forward * val.m_attackRange + transform.right * val.m_attackOffset;
			dir = ((Humanoid)player).GetAimDir(spawn);
			ApplyLaunchAngle(val, ref dir);
		}

		private static void ApplyLaunchAngle(Attack attack, ref Vector3 aimDir)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			float launchAngle = attack.m_launchAngle;
			if (launchAngle != 0f)
			{
				Vector3 val = Vector3.Cross(Vector3.up, aimDir);
				aimDir = Quaternion.AngleAxis(launchAngle, val) * aimDir;
			}
		}

		private void Simulate(Player owner, Vector3 spawn, Vector3 dir, float speed, float gravity, float drag, float ttl)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			EnsureMasks();
			int value = BowTrajectoryPlugin.MaxPoints.Value;
			if (_points == null || _points.Length != value)
			{
				_points = (Vector3[])(object)new Vector3[value];
			}
			float num = Time.fixedDeltaTime;
			if (num <= 0f)
			{
				num = 0.02f;
			}
			int mask = (BowTrajectoryPlugin.StopAtCharacters.Value ? _solidWithCharMask : _solidMask);
			Vector3 val = spawn;
			Vector3 val2 = ((Vector3)(ref dir)).normalized * speed;
			_points[0] = val;
			int num2 = 1;
			float num3 = 0f;
			bool flag = false;
			Vector3 val3 = Vector3.zero;
			Vector3 normal = Vector3.up;
			while (num2 < value && num3 < ttl)
			{
				val2 += Vector3.down * (gravity * num);
				if (drag != 0f)
				{
					float num4 = ((Vector3)(ref val2)).sqrMagnitude * drag * num;
					val2 -= ((Vector3)(ref val2)).normalized * num4;
				}
				Vector3 val4 = val + val2 * num;
				Vector3 val5 = val4 - val;
				float magnitude = ((Vector3)(ref val5)).magnitude;
				if (magnitude > 0.0001f && SegmentCast(val, ((Vector3)(ref val5)).normalized, magnitude, mask, owner, out var best))
				{
					val3 = ((RaycastHit)(ref best)).point;
					normal = ((RaycastHit)(ref best)).normal;
					_points[num2++] = val3;
					flag = true;
					break;
				}
				val = val4;
				_points[num2++] = val;
				num3 += num;
			}
			ApplyStyleIfChanged();
			_line.positionCount = num2;
			_line.SetPositions(_points);
			((Renderer)_line).enabled = true;
			if (flag && BowTrajectoryPlugin.ShowImpactMarker.Value)
			{
				DrawMarker(val3, normal);
				((Renderer)_marker).enabled = true;
			}
			else
			{
				((Renderer)_marker).enabled = false;
			}
		}

		private bool SegmentCast(Vector3 origin, Vector3 dirNorm, float dist, int mask, Player owner, out RaycastHit best)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			best = default(RaycastHit);
			int num = Physics.RaycastNonAlloc(origin, dirNorm, _hitBuffer, dist, mask, (QueryTriggerInteraction)1);
			bool result = false;
			float num2 = float.MaxValue;
			for (int i = 0; i < num; i++)
			{
				RaycastHit val = _hitBuffer[i];
				if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) && (!((Object)(object)owner != (Object)null) || !((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>() == (Object)(object)owner)) && ((RaycastHit)(ref val)).distance < num2)
				{
					num2 = ((RaycastHit)(ref val)).distance;
					best = val;
					result = true;
				}
			}
			return result;
		}

		private void DrawMarker(Vector3 point, Vector3 normal)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			Vector3 normalized = ((Vector3)(ref normal)).normalized;
			Vector3 val = Vector3.Cross(normalized, Vector3.up);
			if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
			{
				val = Vector3.Cross(normalized, Vector3.forward);
			}
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = Vector3.Cross(normalized, val);
			float value = BowTrajectoryPlugin.ImpactMarkerSize.Value;
			Vector3 val3 = point + normalized * 0.03f;
			if (_marker.positionCount != 28)
			{
				_marker.positionCount = 28;
			}
			for (int i = 0; i < 28; i++)
			{
				float num = (float)i / 28f * (float)Math.PI * 2f;
				Vector3 val4 = val3 + (val * Mathf.Cos(num) + val2 * Mathf.Sin(num)) * value;
				_marker.SetPosition(i, val4);
			}
		}

		private void ApplyStyleIfChanged()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			float value = BowTrajectoryPlugin.LineWidth.Value;
			Color val = BowTrajectoryPlugin.ResolveStartColor();
			Color val2 = BowTrajectoryPlugin.ResolveEndColor();
			Color val3 = BowTrajectoryPlugin.ResolveImpactColor();
			if (!Mathf.Approximately(value, _lastWidth) || !(val == _lastStart) || !(val2 == _lastEnd) || !(val3 == _lastImpact))
			{
				_lastWidth = value;
				_lastStart = val;
				_lastEnd = val2;
				_lastImpact = val3;
				_line.widthMultiplier = value;
				Gradient val4 = new Gradient();
				val4.SetKeys((GradientColorKey[])(object)new GradientColorKey[2]
				{
					new GradientColorKey(val, 0f),
					new GradientColorKey(val2, 1f)
				}, (GradientAlphaKey[])(object)new GradientAlphaKey[2]
				{
					new GradientAlphaKey(val.a, 0f),
					new GradientAlphaKey(val2.a, 1f)
				});
				_line.colorGradient = val4;
				_marker.widthMultiplier = value;
				_marker.startColor = val3;
				_marker.endColor = val3;
			}
		}

		private void SetVisible(bool visible)
		{
			if ((Object)(object)_line != (Object)null)
			{
				((Renderer)_line).enabled = visible;
			}
			if ((Object)(object)_marker != (Object)null)
			{
				((Renderer)_marker).enabled = visible;
			}
		}

		private static bool IsCrossbowReady(Player player)
		{
			if (!((Humanoid)player).IsWeaponLoaded())
			{
				return ((Character)player).InAttack();
			}
			return true;
		}

		private static bool IsTextFieldFocused()
		{
			try
			{
				if (Console.IsVisible())
				{
					return true;
				}
				if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
				{
					return true;
				}
			}
			catch
			{
			}
			return false;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}