Decompiled source of Keep da weapons on my back plz v1.0.0

ValheimHolster.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
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("ValheimHolster")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.4")]
[assembly: AssemblyProduct("ValheimHolster")]
[assembly: AssemblyTitle("ValheimHolster")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 ValheimHolster
{
	internal static class EnglishConfig
	{
		private static readonly Dictionary<string, string> Sections = new Dictionary<string, string>
		{
			{ "1 - Geral", "1 - General" },
			{ "2 - Corpo", "2 - Body" },
			{ "3 - Tecla R", "3 - R key" },
			{ "4 - Quadril", "4 - Hips" },
			{ "5 - Escudo", "5 - Shield" },
			{ "6 - Hotbar", "6 - Hotbar" },
			{ "7 - Menu", "7 - Menu" },
			{ "8 - Recarga", "8 - Reloading" }
		};

		private static readonly Dictionary<string, string> Keys = new Dictionary<string, string>
		{
			{ "1 - Geral/Ativado", "Enabled" },
			{ "1 - Geral/Log detalhado", "Detailed logging" },
			{ "2 - Corpo/Tecla marcar", "Mark key" },
			{ "2 - Corpo/So armas marcadas ficam no corpo", "Only marked weapons on body" },
			{ "2 - Corpo/Guardar ao trocar de arma", "Holster when switching weapons" },
			{ "2 - Corpo/Mostrar todas as marcadas", "Show all marked weapons" },
			{ "2 - Corpo/Maximo de armas extras", "Maximum extra weapons" },
			{ "2 - Corpo/Cruzar armas grandes", "Cross large weapons" },
			{ "2 - Corpo/Ferramentas no corpo", "Holster tools" },
			{ "2 - Corpo/Mostrar no tooltip", "Show mark in tooltip" },
			{ "3 - Tecla R/Toque troca de arma", "Tap to switch weapons" },
			{ "3 - Tecla R/Dois toques esvaziam a mao", "Double tap to empty hands" },
			{ "3 - Tecla R/Tempo entre os dois toques", "Double tap interval" },
			{ "3 - Tecla R/Segurar abre a roda", "Hold to open weapon wheel" },
			{ "3 - Tecla R/Tempo segurando", "Wheel hold time" },
			{ "3 - Tecla R/Roda so com armas marcadas", "Only marked weapons in wheel" },
			{ "4 - Quadril/Arma de uma mao no quadril", "One-handed weapons on hips" },
			{ "4 - Quadril/Usar os dois lados", "Use both hips" },
			{ "4 - Quadril/Inclinacao pra tras", "Backward tilt" },
			{ "4 - Quadril/Giro pra fora", "Outward rotation" },
			{ "4 - Quadril/Altura", "Height" },
			{ "4 - Quadril/Frente", "Forward offset" },
			{ "4 - Quadril/Aproximar do corpo", "Inward offset" },
			{ "4 - Quadril/Faca - inclinacao", "Knife - backward tilt" },
			{ "4 - Quadril/Faca - giro pra fora", "Knife - outward rotation" },
			{ "4 - Quadril/Faca - aproximar da coxa", "Knife - inward offset" },
			{ "4 - Quadril/Faca - altura", "Knife - height" },
			{ "4 - Quadril/Faca - frente", "Knife - forward offset" },
			{ "4 - Quadril/Ajuste de posicao", "Position adjustment" },
			{ "4 - Quadril/Ajuste de rotacao", "Rotation adjustment" },
			{ "5 - Escudo/Escudo junto com arma de uma mao", "Auto-equip shield with one-handed weapon" },
			{ "5 - Escudo/Exceto com machado", "Exclude axes" },
			{ "5 - Escudo/Escudo acompanha a arma", "Unequip shield with weapon" },
			{ "6 - Hotbar/Numero so equipa", "Hotbar numbers only equip" },
			{ "7 - Menu/Mostrar armas no menu", "Show weapons in main menu" },
			{ "7 - Menu/Maos livres no menu", "Empty hands in main menu" },
			{ "8 - Recarga/Continua carregada ao guardar", "Keep loaded when holstered" },
			{ "8 - Recarga/Recarregar correndo", "Reload while running" },
			{ "8 - Recarga/So recarrega com municao", "Require ammunition to reload" },
			{ "8 - Recarga/Velocidade de recarga", "Reload speed" }
		};

		internal static string Translate(string input)
		{
			string[] array = input.Replace("\r\n", "\n").Split('\n');
			string text = "";
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.StartsWith("[") && text2.EndsWith("]"))
				{
					text = text2.Substring(1, text2.Length - 2);
					if (Sections.TryGetValue(text, out var value))
					{
						array[i] = "[" + value + "]";
					}
				}
				else if (!text2.StartsWith("#") && !text2.StartsWith(";"))
				{
					int num = array[i].IndexOf('=');
					if (num >= 0 && Keys.TryGetValue(text + "/" + array[i].Substring(0, num).Trim(), out var value2))
					{
						array[i] = value2 + " " + array[i].Substring(num);
					}
				}
			}
			return string.Join("\n", array);
		}

		internal static void Migrate(string file)
		{
			if (!File.Exists(file))
			{
				return;
			}
			string text = File.ReadAllText(file);
			string text2 = Translate(text);
			if (!(text.Replace("\r\n", "\n") == text2))
			{
				string text3 = file + ".before-english.bak";
				if (!File.Exists(text3))
				{
					File.Copy(file, text3);
				}
				File.WriteAllText(file, text2, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			}
		}
	}
	internal struct EquipState
	{
		public bool Track;

		public ItemData Right;

		public ItemData Left;

		public ItemData HiddenRight;

		public ItemData HiddenLeft;
	}
	internal struct ExtraEntry
	{
		public HolsterJoint Joint;

		public int Hash;

		public int Variant;

		public int Quality;
	}
	internal static class ExtraHolster
	{
		public const string ZdoKey = "ValheimHolster.Extra";

		private static float _timer;

		private static string _lastWritten;

		private static readonly List<ExtraEntry> _entries = new List<ExtraEntry>();

		private static readonly HashSet<HolsterJoint> _used = new HashSet<HolsterJoint>();

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

		public static void MarkDirty()
		{
			_timer = 0f;
		}

		public static void Tick()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				_lastWritten = null;
				return;
			}
			_timer -= Time.deltaTime;
			if (_timer > 0f)
			{
				return;
			}
			_timer = 0.25f;
			ZNetView component = ((Component)localPlayer).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
			{
				return;
			}
			string text = ((HolsterConfig.Enabled.Value && HolsterConfig.ShowExtras.Value) ? Compute(localPlayer, preview: false) : "");
			if (!(text == _lastWritten))
			{
				_lastWritten = text;
				component.GetZDO().Set("ValheimHolster.Extra", text);
				if (HolsterConfig.DebugLog.Value)
				{
					Plugin.Log.LogInfo((object)("Published extra holsters: " + Describe()));
				}
			}
		}

		public static string Compute(Player p, bool preview)
		{
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			_entries.Clear();
			_used.Clear();
			Inventory inventory = ((Humanoid)p).GetInventory();
			if (inventory == null)
			{
				return "";
			}
			ItemData val = (preview ? null : VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)p));
			ItemData val2 = (preview ? null : VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)p));
			bool flag = preview && HolsterConfig.MenuFreeHands.Value && MenuHelper.InMainMenu;
			if (val != null)
			{
				_used.Add(HolsterJoints.VanillaJoint(val.m_shared, rightHand: true));
			}
			if (val2 != null)
			{
				_used.Add(HolsterJoints.VanillaJoint(val2.m_shared, rightHand: false));
			}
			int value = HolsterConfig.MaxExtras.Value;
			foreach (ItemData item in HolsterLogic.PlacementOrder(inventory, p))
			{
				if (_entries.Count >= value)
				{
					break;
				}
				if (!HolsterLogic.IsMarked(item) || !HolsterLogic.CanHolster(item) || (item.m_equipped && !flag) || item == val || item == val2)
				{
					continue;
				}
				int num = HolsterLogic.ItemHash(item);
				if (num == 0)
				{
					continue;
				}
				bool flag2 = false;
				foreach (HolsterJoint item2 in HolsterJoints.Candidates(item.m_shared))
				{
					if (!_used.Contains(item2))
					{
						_used.Add(item2);
						_entries.Add(new ExtraEntry
						{
							Joint = item2,
							Hash = num,
							Variant = item.m_variant,
							Quality = item.m_quality
						});
						flag2 = true;
						break;
					}
				}
				if (!flag2 && HolsterConfig.DebugLog.Value && !_unplacedLogged.Contains(num))
				{
					_unplacedLogged.Add(num);
					Plugin.Log.LogInfo((object)string.Format("No free attachment point for {0} (type={1}). In use: {2}", item.m_shared.m_name, item.m_shared.m_itemType, string.Join(",", _used)));
				}
			}
			StringBuilder stringBuilder = new StringBuilder("1|");
			for (int i = 0; i < _entries.Count; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append(';');
				}
				ExtraEntry extraEntry = _entries[i];
				stringBuilder.Append((int)extraEntry.Joint).Append(':').Append(extraEntry.Hash)
					.Append(':')
					.Append(extraEntry.Variant)
					.Append(':')
					.Append(extraEntry.Quality);
			}
			return stringBuilder.ToString();
		}

		private static string Describe()
		{
			if (_entries.Count == 0)
			{
				return "(none)";
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (ExtraEntry entry in _entries)
			{
				GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(entry.Hash) : null);
				stringBuilder.Append(((Object)(object)val != (Object)null) ? ((Object)val).name : entry.Hash.ToString()).Append('@').Append(entry.Joint)
					.Append(' ');
			}
			return stringBuilder.ToString();
		}

		public static void Parse(string data, List<ExtraEntry> into)
		{
			into.Clear();
			if (string.IsNullOrEmpty(data) || !data.StartsWith("1|"))
			{
				return;
			}
			string text = data.Substring(2);
			if (text.Length == 0)
			{
				return;
			}
			string[] array = text.Split(';');
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(':');
				if (array2.Length >= 4 && int.TryParse(array2[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && int.TryParse(array2[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2))
				{
					int.TryParse(array2[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result3);
					int.TryParse(array2[3], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result4);
					if (result > 0 && result <= 10 && result2 != 0)
					{
						into.Add(new ExtraEntry
						{
							Joint = (HolsterJoint)result,
							Hash = result2,
							Variant = result3,
							Quality = result4
						});
					}
				}
			}
		}
	}
	public class ExtraHolsterVisual : MonoBehaviour
	{
		private VisEquipment _vis;

		private ZNetView _nview;

		private string _last;

		private int _lastRevision = -1;

		private float _timer;

		private readonly List<ExtraEntry> _entries = new List<ExtraEntry>();

		private readonly List<GameObject> _instances = new List<GameObject>();

		private Player _player;

		private bool _handsFreed;

		private void Awake()
		{
			_vis = ((Component)this).GetComponent<VisEquipment>();
			_nview = ((Component)this).GetComponent<ZNetView>();
		}

		private void OnDestroy()
		{
			Clear();
		}

		private void Update()
		{
			_timer -= Time.deltaTime;
			if (_timer > 0f || (Object)(object)_vis == (Object)null)
			{
				return;
			}
			string text;
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				_timer = 0.5f;
				if ((Object)(object)_player == (Object)null)
				{
					_player = ((Component)this).GetComponent<Player>();
				}
				if ((Object)(object)_player == (Object)null)
				{
					return;
				}
				bool flag = HolsterConfig.Enabled.Value && HolsterConfig.ShowInMenu.Value;
				text = (flag ? ExtraHolster.Compute(_player, preview: true) : "");
				UpdateMenuHands(flag && HolsterConfig.MenuFreeHands.Value && MenuHelper.InMainMenu);
			}
			else
			{
				_timer = 0.2f;
				text = (HolsterConfig.Enabled.Value ? _nview.GetZDO().GetString("ValheimHolster.Extra", "") : "");
			}
			bool flag2 = false;
			foreach (GameObject instance in _instances)
			{
				if ((Object)(object)instance == (Object)null)
				{
					flag2 = true;
					break;
				}
			}
			if (!(text == _last) || _lastRevision != HolsterConfig.VisualRevision || flag2)
			{
				_last = text;
				_lastRevision = HolsterConfig.VisualRevision;
				Rebuild();
			}
		}

		private void UpdateMenuHands(bool free)
		{
			if (free)
			{
				_vis.SetRightItem(0, 0);
				_vis.SetLeftItem(0, 0, 0);
				_handsFreed = true;
			}
			else if (_handsFreed)
			{
				_handsFreed = false;
				VanillaAccess.SetupVisEquipment((Humanoid)(object)_player);
			}
		}

		private void Clear()
		{
			foreach (GameObject instance in _instances)
			{
				if ((Object)(object)instance != (Object)null)
				{
					Object.Destroy((Object)(object)instance);
				}
			}
			_instances.Clear();
		}

		private void Rebuild()
		{
			Clear();
			ExtraHolster.Parse(_last, _entries);
			if (_entries.Count == 0 || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			foreach (ExtraEntry entry in _entries)
			{
				Transform val = HolsterJoints.Resolve(_vis, entry.Joint);
				if ((Object)(object)val == (Object)null)
				{
					if (HolsterConfig.DebugLog.Value)
					{
						Plugin.Log.LogWarning((object)$"Attachment point {entry.Joint} does not exist on this character");
					}
					continue;
				}
				GameObject val2 = VanillaAccess.AttachItem(_vis, entry.Hash, entry.Variant, entry.Quality, val);
				if ((Object)(object)val2 == (Object)null)
				{
					if (HolsterConfig.DebugLog.Value)
					{
						Plugin.Log.LogWarning((object)$"Failed to render {entry.Hash} at {entry.Joint}");
					}
					continue;
				}
				if (entry.Joint == HolsterJoint.HipRight || entry.Joint == HolsterJoint.HipLeft)
				{
					GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(entry.Hash);
					ItemDrop val3 = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
					bool knife = (Object)(object)val3 != (Object)null && HolsterLogic.IsKnife(val3.m_itemData.m_shared);
					HolsterLogic.ApplyHipOffset(val2.transform, entry.Joint == HolsterJoint.HipLeft, ((Component)_vis).transform, knife);
				}
				_instances.Add(val2);
			}
		}
	}
	public static class HolsterConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<bool> DebugLog;

		public static ConfigEntry<KeyCode> MarkKey;

		public static ConfigEntry<bool> OnlyMarked;

		public static ConfigEntry<bool> HolsterOnSwap;

		public static ConfigEntry<bool> ShowExtras;

		public static ConfigEntry<int> MaxExtras;

		public static ConfigEntry<bool> CrossBigWeapons;

		public static ConfigEntry<bool> HolsterTools;

		public static ConfigEntry<bool> ShowTooltip;

		public static ConfigEntry<bool> KeepLoaded;

		public static ConfigEntry<bool> ReloadWhileRunning;

		public static ConfigEntry<float> ReloadSpeed;

		public static ConfigEntry<bool> ReloadNeedsAmmo;

		public static ConfigEntry<bool> SwapWithHideKey;

		public static ConfigEntry<bool> DoubleTapEmpty;

		public static ConfigEntry<float> DoubleTapWindow;

		public static ConfigEntry<bool> WheelEnabled;

		public static ConfigEntry<float> WheelHoldTime;

		public static ConfigEntry<bool> WheelOnlyMarked;

		public static ConfigEntry<float> WheelMouseSensitivity;

		public static ConfigEntry<bool> OneHandOnHip;

		public static ConfigEntry<bool> UseLeftHip;

		public static ConfigEntry<float> HipTiltBack;

		public static ConfigEntry<float> HipRollOut;

		public static ConfigEntry<float> HipUp;

		public static ConfigEntry<float> HipForward;

		public static ConfigEntry<float> HipInward;

		public static ConfigEntry<float> KnifeTilt;

		public static ConfigEntry<float> KnifeRoll;

		public static ConfigEntry<float> KnifeInward;

		public static ConfigEntry<float> KnifeUp;

		public static ConfigEntry<float> KnifeForward;

		public static ConfigEntry<Vector3> HipPositionOffset;

		public static ConfigEntry<Vector3> HipRotationOffset;

		public static ConfigEntry<bool> AutoEquipShield;

		public static ConfigEntry<bool> NoShieldWithAxe;

		public static ConfigEntry<bool> AutoUnequipShield;

		public static ConfigEntry<bool> LockHotbar;

		public static ConfigEntry<bool> ShowInMenu;

		public static ConfigEntry<bool> MenuFreeHands;

		public static int VisualRevision { get; private set; }

		public static void Bind(ConfigFile cfg)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Expected O, but got Unknown
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Expected O, but got Unknown
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Expected O, but got Unknown
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Expected O, but got Unknown
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Expected O, but got Unknown
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Expected O, but got Unknown
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Expected O, but got Unknown
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Expected O, but got Unknown
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Expected O, but got Unknown
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0427: Expected O, but got Unknown
			//IL_0455: Unknown result type (might be due to invalid IL or missing references)
			//IL_045f: Expected O, but got Unknown
			//IL_048d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Expected O, but got Unknown
			//IL_04a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0600: Expected O, but got Unknown
			Enabled = cfg.Bind<bool>("1 - General", "Enabled", true, "Enable or disable the mod.");
			DebugLog = cfg.Bind<bool>("1 - General", "Detailed logging", false, "Write marking and attachment details to LogOutput.log for troubleshooting.");
			MarkKey = cfg.Bind<KeyCode>("2 - Body", "Mark key", (KeyCode)104, "With the inventory open, hover over a weapon and press this key to mark or unmark it. Marked weapons stay on your body and appear in the wheel. Also works in Safe Pouch slots.");
			OnlyMarked = cfg.Bind<bool>("2 - Body", "Only marked weapons on body", true, "Enabled: only marked weapons stay on your body. Disabled: any weapon you swap away from can be holstered.");
			HolsterOnSwap = cfg.Bind<bool>("2 - Body", "Holster when switching weapons", true, "When equipping another weapon, holster the previous weapon instead of making it disappear.");
			ShowExtras = cfg.Bind<bool>("2 - Body", "Show all marked weapons", true, "Show all marked weapons on your body, beyond the two supported by the base game.");
			MaxExtras = cfg.Bind<int>("2 - Body", "Maximum extra weapons", 10, new ConfigDescription("Maximum number of extra marked weapons shown on your body, one per available attachment point.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>()));
			CrossBigWeapons = cfg.Bind<bool>("2 - Body", "Cross large weapons", true, "Two large weapons sharing a position, such as staves, greatswords, atgeirs or bows, cross in an X on your back.");
			HolsterTools = cfg.Bind<bool>("2 - Body", "Holster tools", false, "Allow hammers, hoes, cultivators, pickaxes, fishing rods and torches on your body. Disabled: tools are never holstered.");
			ShowTooltip = cfg.Bind<bool>("2 - Body", "Show mark in tooltip", true, "Show whether a weapon is marked in its tooltip.");
			SwapWithHideKey = cfg.Bind<bool>("3 - R key", "Tap to switch weapons", true, "Tap R to switch to the weapon you were using previously.");
			DoubleTapEmpty = cfg.Bind<bool>("3 - R key", "Double tap to empty hands", true, "Double tap R to empty your hands; marked weapons are holstered. A single tap waits briefly for a possible second tap.");
			DoubleTapWindow = cfg.Bind<float>("3 - R key", "Double tap interval", 0.28f, new ConfigDescription("Maximum time between two taps, in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.15f, 0.6f), Array.Empty<object>()));
			WheelEnabled = cfg.Bind<bool>("3 - R key", "Hold to open weapon wheel", true, "Hold R to open the weapon wheel. Move the mouse sideways or scroll to rotate, release R to equip, or right-click to cancel.");
			WheelHoldTime = cfg.Bind<float>("3 - R key", "Wheel hold time", 0.25f, new ConfigDescription("Time to hold R before opening the wheel, in seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			WheelOnlyMarked = cfg.Bind<bool>("3 - R key", "Only marked weapons in wheel", true, "Enabled: show marked and currently holstered weapons. Disabled: consider all eligible inventory weapons. Includes Safe Pouch weapons.");
			WheelMouseSensitivity = cfg.Bind<float>("3 - R key", "Wheel mouse sensitivity", 3f, new ConfigDescription("Mouse sensitivity multiplier for rotating the weapon wheel. 1 = original sensitivity; 3 = one-third of the original swipe distance per weapon. Higher values require less mouse movement.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f), Array.Empty<object>()));
			OneHandOnHip = cfg.Bind<bool>("4 - Hips", "One-handed weapons on hips", true, "Place swords, axes, maces and knives on the hips instead of the back. Spears are excluded.");
			UseLeftHip = cfg.Bind<bool>("4 - Hips", "Use both hips", true, "Place a second marked one-handed weapon on the opposite hip.");
			HipTiltBack = cfg.Bind<float>("4 - Hips", "Backward tilt", 35f, new ConfigDescription("Tilt in degrees. Positive angles point the tip backward and the handle forward; zero is straight.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-90f, 90f), Array.Empty<object>()));
			HipRollOut = cfg.Bind<float>("4 - Hips", "Outward rotation", 0f, new ConfigDescription("Sideways rotation in degrees. Positive angles point the tip away from the leg, mirrored on each side; zero is straight.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-45f, 45f), Array.Empty<object>()));
			HipUp = cfg.Bind<float>("4 - Hips", "Height", 0.08f, new ConfigDescription("Move the hip weapon upward with positive values or downward with negative values, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>()));
			HipForward = cfg.Bind<float>("4 - Hips", "Forward offset", 0.06f, new ConfigDescription("Move the hip weapon forward with positive values or backward with negative values, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>()));
			HipInward = cfg.Bind<float>("4 - Hips", "Inward offset", 0.05f, new ConfigDescription("Move the hip weapon closer to the body with positive values or farther away with negative values, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>()));
			KnifeTilt = cfg.Bind<float>("4 - Hips", "Knife - backward tilt", 10f, new ConfigDescription("Knife tilt in degrees. Positive angles point the tip backward.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-90f, 90f), Array.Empty<object>()));
			KnifeRoll = cfg.Bind<float>("4 - Hips", "Knife - outward rotation", 0f, new ConfigDescription("Knife sideways rotation in degrees. Positive angles point the tip away from the leg.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-45f, 45f), Array.Empty<object>()));
			KnifeInward = cfg.Bind<float>("4 - Hips", "Knife - inward offset", 0.03f, new ConfigDescription("Move the knife closer to the leg, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>()));
			KnifeUp = cfg.Bind<float>("4 - Hips", "Knife - height", 0.06f, new ConfigDescription("Move the knife upward with positive values or downward with negative values, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>()));
			KnifeForward = cfg.Bind<float>("4 - Hips", "Knife - forward offset", 0f, new ConfigDescription("Move the knife forward with positive values or backward with negative values, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.3f, 0.3f), Array.Empty<object>()));
			HipPositionOffset = cfg.Bind<Vector3>("4 - Hips", "Position adjustment", Vector3.zero, "Fine position adjustment, mirrored on the opposite side.");
			HipRotationOffset = cfg.Bind<Vector3>("4 - Hips", "Rotation adjustment", Vector3.zero, "Fine rotation adjustment, in degrees.");
			AutoEquipShield = cfg.Bind<bool>("5 - Shield", "Auto-equip shield with one-handed weapon", true, "When equipping a one-handed weapon with an empty left hand, equip the strongest shield from the inventory or Safe Pouch.");
			NoShieldWithAxe = cfg.Bind<bool>("5 - Shield", "Exclude axes", true, "Do not automatically equip a shield with an axe, avoiding the movement penalty while chopping trees.");
			AutoUnequipShield = cfg.Bind<bool>("5 - Shield", "Unequip shield with weapon", true, "When the one-handed weapon leaves your hand, remove the shield too. Marked shields are holstered on your back.");
			LockHotbar = cfg.Bind<bool>("6 - Hotbar", "Hotbar numbers only equip", false, "Pressing the hotbar number of a weapon already in your hand keeps it equipped.");
			ShowInMenu = cfg.Bind<bool>("7 - Menu", "Show weapons in main menu", true, "Show marked weapons on menu characters, including the preview and ValheimMenu campfire.");
			MenuFreeHands = cfg.Bind<bool>("7 - Menu", "Empty hands in main menu", true, "Remove equipped weapons from the hands in the menu. Marked weapons appear holstered.");
			KeepLoaded = cfg.Bind<bool>("8 - Reloading", "Keep loaded when holstered", true, "A loaded crossbow or other reloadable weapon stays loaded when holstered and drawn again.");
			ReloadWhileRunning = cfg.Bind<bool>("8 - Reloading", "Reload while running", true, "Allow running during reload without canceling it or slowing to a walk.");
			ReloadNeedsAmmo = cfg.Bind<bool>("8 - Reloading", "Require ammunition to reload", true, "Only start reloading a crossbow when matching bolts or ammunition are available.");
			ReloadSpeed = cfg.Bind<float>("8 - Reloading", "Reload speed", 1f, new ConfigDescription("Reload speed multiplier: 1 is normal, 2 is twice as fast, and 0.5 is half speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
			Enabled.SettingChanged += delegate
			{
				Visual();
			};
			OnlyMarked.SettingChanged += delegate
			{
				Visual();
			};
			ShowExtras.SettingChanged += delegate
			{
				Visual();
			};
			MaxExtras.SettingChanged += delegate
			{
				Visual();
			};
			CrossBigWeapons.SettingChanged += delegate
			{
				Visual();
			};
			HolsterTools.SettingChanged += delegate
			{
				Visual();
			};
			OneHandOnHip.SettingChanged += delegate
			{
				Visual();
			};
			UseLeftHip.SettingChanged += delegate
			{
				Visual();
			};
			HipTiltBack.SettingChanged += delegate
			{
				Visual();
			};
			HipRollOut.SettingChanged += delegate
			{
				Visual();
			};
			HipUp.SettingChanged += delegate
			{
				Visual();
			};
			HipForward.SettingChanged += delegate
			{
				Visual();
			};
			HipInward.SettingChanged += delegate
			{
				Visual();
			};
			KnifeTilt.SettingChanged += delegate
			{
				Visual();
			};
			KnifeRoll.SettingChanged += delegate
			{
				Visual();
			};
			KnifeInward.SettingChanged += delegate
			{
				Visual();
			};
			KnifeUp.SettingChanged += delegate
			{
				Visual();
			};
			KnifeForward.SettingChanged += delegate
			{
				Visual();
			};
			HipPositionOffset.SettingChanged += delegate
			{
				Visual();
			};
			HipRotationOffset.SettingChanged += delegate
			{
				Visual();
			};
			ShowInMenu.SettingChanged += delegate
			{
				Visual();
			};
			MenuFreeHands.SettingChanged += delegate
			{
				Visual();
			};
			static void Visual()
			{
				VisualRevision++;
				VanillaAccess.RefreshAllVisuals();
				ExtraHolster.MarkDirty();
			}
		}
	}
	public enum HolsterJoint
	{
		None,
		HipRight,
		HipLeft,
		BackMelee,
		BackTwoHand,
		BackAtgeir,
		BackBow,
		BackShield,
		BackTwoHandCross,
		BackAtgeirCross,
		BackBowCross
	}
	internal static class HolsterJoints
	{
		private const string HipLeftName = "ValheimHolster_HipLeft";

		private const string TwoHandCrossName = "ValheimHolster_TwoHandCross";

		private const string AtgeirCrossName = "ValheimHolster_AtgeirCross";

		private const string BowCrossName = "ValheimHolster_BowCross";

		public const HolsterJoint MaxJoint = HolsterJoint.BackBowCross;

		private const float CrossBackOffset = 0.04f;

		public static bool IsDualWeapon(SharedData s)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			if (s != null && (int)s.m_itemType != 5)
			{
				return (int)AttachType(s) == 5;
			}
			return false;
		}

		public static bool IsStaff(SharedData s)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			if (s != null)
			{
				if ((int)s.m_skillType != 9)
				{
					return (int)s.m_skillType == 10;
				}
				return true;
			}
			return false;
		}

		public static ItemType AttachType(SharedData s)
		{
			//IL_0001: 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_0009: Unknown result type (might be due to invalid IL or missing references)
			if ((int)s.m_attachOverride == 0)
			{
				return s.m_itemType;
			}
			return s.m_attachOverride;
		}

		public static HolsterJoint VanillaJoint(SharedData s, bool rightHand)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected I4, but got Unknown
			//IL_0036: 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_0063: Expected I4, but got Unknown
			if (s == null)
			{
				return HolsterJoint.None;
			}
			if (HolsterConfig.OneHandOnHip.Value && HolsterLogic.GoesOnHip(s))
			{
				return HolsterJoint.HipRight;
			}
			ItemType val = AttachType(s);
			switch (val - 3)
			{
			default:
				switch (val - 14)
				{
				case 1:
					if (!rightHand)
					{
						return HolsterJoint.HipRight;
					}
					return HolsterJoint.BackMelee;
				case 0:
				case 8:
					return HolsterJoint.BackTwoHand;
				case 5:
					return HolsterJoint.HipRight;
				case 6:
					return HolsterJoint.BackAtgeir;
				default:
					return HolsterJoint.None;
				}
			case 0:
				return HolsterJoint.BackMelee;
			case 1:
				return HolsterJoint.BackBow;
			case 2:
				return HolsterJoint.BackShield;
			}
		}

		public static IEnumerable<HolsterJoint> Candidates(SharedData s)
		{
			bool cross = HolsterConfig.CrossBigWeapons.Value;
			if (IsDualWeapon(s))
			{
				yield return HolsterJoint.BackShield;
				yield break;
			}
			if (IsStaff(s))
			{
				yield return HolsterJoint.BackAtgeir;
				if (cross)
				{
					yield return HolsterJoint.BackAtgeirCross;
				}
				yield return HolsterJoint.BackTwoHand;
				if (cross)
				{
					yield return HolsterJoint.BackTwoHandCross;
				}
				yield return HolsterJoint.BackBow;
				if (cross)
				{
					yield return HolsterJoint.BackBowCross;
				}
				yield break;
			}
			HolsterJoint first = VanillaJoint(s, rightHand: true);
			if (first == HolsterJoint.None)
			{
				yield break;
			}
			yield return first;
			switch (first)
			{
			case HolsterJoint.HipRight:
				if (HolsterLogic.GoesOnHip(s))
				{
					if (HolsterConfig.UseLeftHip.Value)
					{
						yield return HolsterJoint.HipLeft;
					}
					yield return HolsterJoint.BackMelee;
				}
				break;
			case HolsterJoint.BackMelee:
				yield return HolsterJoint.BackAtgeir;
				break;
			case HolsterJoint.BackTwoHand:
				if (cross)
				{
					yield return HolsterJoint.BackTwoHandCross;
				}
				yield return HolsterJoint.BackAtgeir;
				if (cross)
				{
					yield return HolsterJoint.BackAtgeirCross;
				}
				break;
			case HolsterJoint.BackBow:
				if (cross)
				{
					yield return HolsterJoint.BackBowCross;
				}
				break;
			case HolsterJoint.BackAtgeir:
				if (cross)
				{
					yield return HolsterJoint.BackAtgeirCross;
				}
				yield return HolsterJoint.BackTwoHand;
				if (cross)
				{
					yield return HolsterJoint.BackTwoHandCross;
				}
				break;
			}
		}

		public static Transform Resolve(VisEquipment vis, HolsterJoint joint)
		{
			return (Transform)(joint switch
			{
				HolsterJoint.HipRight => vis.m_backTool, 
				HolsterJoint.HipLeft => GetOrCreateMirror(vis, vis.m_backTool, "ValheimHolster_HipLeft", 0f), 
				HolsterJoint.BackTwoHandCross => GetOrCreateMirror(vis, vis.m_backTwohandedMelee, "ValheimHolster_TwoHandCross", 0.04f), 
				HolsterJoint.BackAtgeirCross => GetOrCreateMirror(vis, vis.m_backAtgeir, "ValheimHolster_AtgeirCross", 0.04f), 
				HolsterJoint.BackBowCross => GetOrCreateMirror(vis, vis.m_backBow, "ValheimHolster_BowCross", 0.04f), 
				HolsterJoint.BackMelee => vis.m_backMelee, 
				HolsterJoint.BackTwoHand => vis.m_backTwohandedMelee, 
				HolsterJoint.BackAtgeir => vis.m_backAtgeir, 
				HolsterJoint.BackBow => vis.m_backBow, 
				HolsterJoint.BackShield => vis.m_backShield, 
				_ => null, 
			});
		}

		private static Transform GetOrCreateMirror(VisEquipment vis, Transform source, string name, float backOffset)
		{
			//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_0044: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (Object)(object)source.parent == (Object)null)
			{
				return null;
			}
			Transform parent = source.parent;
			Transform val = parent.Find(name);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Vector3 val2 = parent.InverseTransformDirection(((Component)vis).transform.right);
			int num = 0;
			float num2 = Mathf.Abs(val2.x);
			if (Mathf.Abs(val2.y) > num2)
			{
				num = 1;
				num2 = Mathf.Abs(val2.y);
			}
			if (Mathf.Abs(val2.z) > num2)
			{
				num = 2;
			}
			Vector3 val3 = source.localPosition;
			Quaternion localRotation = source.localRotation;
			switch (num)
			{
			case 0:
				val3.x = 0f - val3.x;
				((Quaternion)(ref localRotation))..ctor(localRotation.x, 0f - localRotation.y, 0f - localRotation.z, localRotation.w);
				break;
			case 1:
				val3.y = 0f - val3.y;
				((Quaternion)(ref localRotation))..ctor(0f - localRotation.x, localRotation.y, 0f - localRotation.z, localRotation.w);
				break;
			default:
				val3.z = 0f - val3.z;
				((Quaternion)(ref localRotation))..ctor(0f - localRotation.x, 0f - localRotation.y, localRotation.z, localRotation.w);
				break;
			}
			if (backOffset != 0f)
			{
				val3 += parent.InverseTransformDirection(-((Component)vis).transform.forward) * backOffset / Mathf.Max(parent.lossyScale.x, 0.0001f);
			}
			Transform transform = new GameObject(name).transform;
			transform.SetParent(parent, false);
			transform.localPosition = val3;
			transform.localRotation = localRotation;
			transform.localScale = source.localScale;
			return transform;
		}
	}
	internal static class HolsterLogic
	{
		public static bool Busy;

		public static bool HideKeyThisFrame;

		public static int EquipDepth;

		public static bool ModCall;

		public static bool SuppressVanillaHide;

		public static ItemData LastRight;

		public static ItemData LastLeft;

		public const string CustomDataKey = "ValheimHolster.Marked";

		private static readonly List<Vector3> _corners = new List<Vector3>(8);

		public static bool IsLocal(Humanoid h)
		{
			if ((Object)(object)h != (Object)null)
			{
				return (Object)(object)h == (Object)(object)Player.m_localPlayer;
			}
			return false;
		}

		public static bool IsActive(Humanoid h)
		{
			if (HolsterConfig.Enabled.Value)
			{
				return IsLocal(h);
			}
			return false;
		}

		public static bool IsTool(ItemData item)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			SharedData val = item?.m_shared;
			if (val == null)
			{
				return false;
			}
			ItemType itemType = val.m_itemType;
			if ((int)itemType == 15 || (int)itemType == 19)
			{
				return true;
			}
			if ((int)val.m_skillType != 12)
			{
				return (int)val.m_skillType == 104;
			}
			return true;
		}

		public static bool IsHandItem(ItemData item)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Invalid comparison between Unknown and I4
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			//IL_001e: 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_0022: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			SharedData val = item?.m_shared;
			if (val == null)
			{
				return false;
			}
			ItemType itemType = val.m_itemType;
			if ((int)itemType <= 15)
			{
				if (itemType - 3 <= 2 || itemType - 14 <= 1)
				{
					goto IL_0037;
				}
			}
			else if ((int)itemType == 19 || (int)itemType == 22)
			{
				goto IL_0037;
			}
			return false;
			IL_0037:
			return true;
		}

		public static bool CanHolster(ItemData item)
		{
			if (!IsHandItem(item))
			{
				return false;
			}
			if (IsTool(item))
			{
				return HolsterConfig.HolsterTools.Value;
			}
			if (HolsterConfig.OnlyMarked.Value && !IsMarked(item))
			{
				return false;
			}
			return true;
		}

		public static bool IsOneHandWeapon(ItemData item)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if (item?.m_shared != null && (int)item.m_shared.m_itemType == 3)
			{
				return !IsTool(item);
			}
			return false;
		}

		public static bool IsShield(ItemData item)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if (item?.m_shared != null)
			{
				return (int)item.m_shared.m_itemType == 5;
			}
			return false;
		}

		public static bool GoesOnHip(SharedData s)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			if (s != null && (int)s.m_itemType == 3 && (int)s.m_skillType != 5 && (int)s.m_skillType != 12)
			{
				return (int)s.m_skillType != 104;
			}
			return false;
		}

		public static bool StillHolsterable(Humanoid h, ItemData item)
		{
			if (item == null || item.m_equipped)
			{
				return false;
			}
			if (!CanHolster(item))
			{
				return false;
			}
			return SafePouchCompat.Contains(h, item);
		}

		public static void RememberLast(Humanoid h, ItemData right, ItemData left)
		{
			if (IsLocal(h))
			{
				if (right != null && IsHandItem(right) && !IsTool(right))
				{
					LastRight = right;
				}
				if (left != null && IsHandItem(left) && !IsTool(left))
				{
					LastLeft = left;
				}
				else if (right != null && IsHandItem(right) && !IsTool(right))
				{
					LastLeft = null;
				}
			}
		}

		private static bool UsableLast(Humanoid h, ItemData item)
		{
			if (item == null || item.m_equipped)
			{
				return false;
			}
			return SafePouchCompat.Contains(h, item);
		}

		public static bool SwapWithHolster(Humanoid h)
		{
			ItemData val = VanillaAccess.RightItem.Invoke(h);
			ItemData val2 = VanillaAccess.LeftItem.Invoke(h);
			ItemData val3 = VanillaAccess.HiddenRightItem.Invoke(h);
			ItemData val4 = VanillaAccess.HiddenLeftItem.Invoke(h);
			if (!StillHolsterable(h, val3))
			{
				val3 = null;
			}
			if (!StillHolsterable(h, val4))
			{
				val4 = null;
			}
			if (val3 == null && val4 == null)
			{
				val3 = (UsableLast(h, LastRight) ? LastRight : null);
				val4 = (UsableLast(h, LastLeft) ? LastLeft : null);
				if (val3 == null && val4 == null)
				{
					return false;
				}
			}
			Busy = true;
			try
			{
				if (val != null)
				{
					h.UnequipItem(val, false);
				}
				if (val2 != null)
				{
					h.UnequipItem(val2, false);
				}
				VanillaAccess.HiddenRightItem.Invoke(h) = null;
				VanillaAccess.HiddenLeftItem.Invoke(h) = null;
				if (val4 != null)
				{
					h.EquipItem(val4, true);
				}
				if (val3 != null)
				{
					h.EquipItem(val3, true);
				}
				VanillaAccess.HiddenRightItem.Invoke(h) = (StillHolsterable(h, val) ? val : null);
				VanillaAccess.HiddenLeftItem.Invoke(h) = (StillHolsterable(h, val2) ? val2 : null);
				if (val != null || val2 != null)
				{
					LastRight = val;
					LastLeft = val2;
				}
				VanillaAccess.SetupVisEquipment(h);
				VanillaAccess.TriggerHolsterAnim(h);
			}
			finally
			{
				Busy = false;
			}
			return true;
		}

		public static ItemData FindBestShield(Humanoid h)
		{
			Inventory inventory = h.GetInventory();
			if (inventory == null)
			{
				return null;
			}
			ItemData result = null;
			float num = float.MinValue;
			foreach (ItemData item in SafePouchCompat.AllItems(inventory, (Player)(object)((h is Player) ? h : null)))
			{
				if (IsShield(item) && (!item.m_shared.m_useDurability || !(item.m_durability <= 0f)))
				{
					float baseBlockPower = item.GetBaseBlockPower(item.m_quality);
					if (baseBlockPower > num)
					{
						num = baseBlockPower;
						result = item;
					}
				}
			}
			return result;
		}

		public static void TryAutoEquipShield(Humanoid h, ItemData weapon)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			if (!HolsterConfig.AutoEquipShield.Value || !IsOneHandWeapon(weapon) || VanillaAccess.LeftItem.Invoke(h) != null || (HolsterConfig.NoShieldWithAxe.Value && (int)weapon.m_shared.m_skillType == 7))
			{
				return;
			}
			ItemData val = FindBestShield(h);
			if (val == null || val.m_equipped)
			{
				return;
			}
			ItemData val2 = VanillaAccess.HiddenRightItem.Invoke(h);
			ItemData val3 = VanillaAccess.HiddenLeftItem.Invoke(h);
			Busy = true;
			try
			{
				if (val3 == val)
				{
					val3 = null;
				}
				h.EquipItem(val, false);
				VanillaAccess.HiddenRightItem.Invoke(h) = (StillHolsterable(h, val2) ? val2 : null);
				VanillaAccess.HiddenLeftItem.Invoke(h) = (StillHolsterable(h, val3) ? val3 : null);
				VanillaAccess.SetupVisEquipment(h);
			}
			finally
			{
				Busy = false;
			}
		}

		public static void TryAutoUnequipShield(Humanoid h)
		{
			if (!HolsterConfig.AutoUnequipShield.Value)
			{
				return;
			}
			ItemData val = VanillaAccess.LeftItem.Invoke(h);
			if (!IsShield(val) || IsOneHandWeapon(VanillaAccess.RightItem.Invoke(h)))
			{
				return;
			}
			Busy = true;
			try
			{
				h.UnequipItem(val, false);
				if (StillHolsterable(h, val))
				{
					VanillaAccess.HiddenLeftItem.Invoke(h) = val;
					VanillaAccess.SetupVisEquipment(h);
				}
			}
			finally
			{
				Busy = false;
			}
		}

		private static bool TextBlocked()
		{
			if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
			{
				return true;
			}
			if (Console.IsVisible())
			{
				return true;
			}
			if (TextInput.IsVisible())
			{
				return true;
			}
			if (Menu.IsVisible())
			{
				return true;
			}
			return false;
		}

		public static void HandleHotkeys()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && HolsterConfig.Enabled.Value)
			{
				KeyCode value = HolsterConfig.MarkKey.Value;
				if ((int)value != 0 && InventoryGui.IsVisible() && !TextBlocked() && UnityInput.Current.GetKeyDown(value))
				{
					ToggleMark(localPlayer);
				}
			}
		}

		public static bool IsMarked(ItemData item)
		{
			if (item?.m_customData != null)
			{
				return item.m_customData.ContainsKey("ValheimHolster.Marked");
			}
			return false;
		}

		public static void SetMarked(ItemData item, bool marked)
		{
			if (item != null)
			{
				if (item.m_customData == null)
				{
					item.m_customData = new Dictionary<string, string>();
				}
				if (marked)
				{
					item.m_customData["ValheimHolster.Marked"] = "1";
				}
				else
				{
					item.m_customData.Remove("ValheimHolster.Marked");
				}
			}
		}

		public static int ItemHash(ItemData item)
		{
			if (!((Object)(object)item?.m_dropPrefab != (Object)null))
			{
				return 0;
			}
			return StringExtensionMethods.GetStableHashCode(((Object)item.m_dropPrefab).name);
		}

		public static IEnumerable<ItemData> SortedInventory(Inventory inv, Player owner = null)
		{
			return from i in SafePouchCompat.AllItems(inv, owner)
				where i != null
				orderby i.m_gridPos.y, i.m_gridPos.x
				select i;
		}

		public static IEnumerable<ItemData> PlacementOrder(Inventory inv, Player owner = null)
		{
			return from i in SortedInventory(inv, owner)
				orderby HolsterJoints.IsDualWeapon(i.m_shared) ? 1 : 0
				select i;
		}

		public static List<ItemData> WheelItems(Player p)
		{
			List<ItemData> list = new List<ItemData>();
			Inventory inventory = ((Humanoid)p).GetInventory();
			if (inventory == null)
			{
				return list;
			}
			ItemData val = VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)p);
			ItemData val2 = VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)p);
			foreach (ItemData item in SortedInventory(inventory))
			{
				if (item.m_equipped || !CanHolster(item) || IsShield(item))
				{
					continue;
				}
				bool flag = item == val || item == val2;
				if (!HolsterConfig.WheelOnlyMarked.Value || IsMarked(item) || flag)
				{
					list.Add(item);
					if (list.Count >= 12)
					{
						break;
					}
				}
			}
			return list;
		}

		public static void TapHide(Player p)
		{
			ModCall = true;
			bool hideKeyThisFrame = HideKeyThisFrame;
			HideKeyThisFrame = true;
			try
			{
				if (VanillaAccess.RightItem.Invoke((Humanoid)(object)p) != null || VanillaAccess.LeftItem.Invoke((Humanoid)(object)p) != null)
				{
					if (!((Character)p).InAttack() && !((Character)p).InDodge())
					{
						((Humanoid)p).HideHandItems(false, true);
					}
				}
				else
				{
					if ((((Character)p).IsSwimming() && !((Character)p).IsOnGround()) || ((Character)p).InDodge())
					{
						return;
					}
					if (VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)p) != null || VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)p) != null)
					{
						VanillaAccess.ShowHandItems((Humanoid)(object)p);
						return;
					}
					ItemData val = (UsableLast((Humanoid)(object)p, LastLeft) ? LastLeft : null);
					ItemData val2 = (UsableLast((Humanoid)(object)p, LastRight) ? LastRight : null);
					if (val != null)
					{
						((Humanoid)p).EquipItem(val, true);
					}
					if (val2 != null)
					{
						((Humanoid)p).EquipItem(val2, true);
					}
				}
			}
			finally
			{
				ModCall = false;
				HideKeyThisFrame = hideKeyThisFrame;
			}
		}

		public static void ApplyHipOffset(Transform t, bool left, Transform character, bool knife = false)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: 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_012b: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: 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_013f: 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)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)character == (Object)null))
			{
				float num = (knife ? HolsterConfig.KnifeTilt.Value : HolsterConfig.HipTiltBack.Value);
				float num2 = (knife ? HolsterConfig.KnifeRoll.Value : HolsterConfig.HipRollOut.Value);
				float num3 = (knife ? HolsterConfig.KnifeUp.Value : HolsterConfig.HipUp.Value);
				float num4 = (knife ? HolsterConfig.KnifeForward.Value : HolsterConfig.HipForward.Value);
				float num5 = (knife ? HolsterConfig.KnifeInward.Value : HolsterConfig.HipInward.Value);
				float num6 = (left ? 1f : (-1f));
				Vector3 right = character.right;
				Vector3 up = character.up;
				Vector3 forward = character.forward;
				Quaternion val = Quaternion.AngleAxis(num2 * num6, forward) * Quaternion.AngleAxis(num, right);
				Vector3 val2 = val * -up;
				Vector3 val3 = val * forward;
				if (TryGetBladeAxes(t, out var blade, out var edge))
				{
					Quaternion val4 = Quaternion.LookRotation(val2, val3);
					Quaternion val5 = Quaternion.LookRotation(blade, edge);
					t.rotation = val4 * Quaternion.Inverse(val5);
				}
				else
				{
					t.rotation = val * t.rotation;
				}
				Vector3 value = HolsterConfig.HipPositionOffset.Value;
				Vector3 value2 = HolsterConfig.HipRotationOffset.Value;
				if (left)
				{
					value.x = 0f - value.x;
					value2.y = 0f - value2.y;
					value2.z = 0f - value2.z;
				}
				t.rotation *= Quaternion.Euler(value2);
				float num7 = Mathf.Abs(character.lossyScale.x);
				t.position += (up * num3 + forward * num4 - num6 * right * num5 + right * value.x + up * value.y + forward * value.z) * num7;
			}
		}

		private static bool TryGetBladeAxes(Transform root, out Vector3 blade, out Vector3 edge)
		{
			//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_000c: 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_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_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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: 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_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			blade = Vector3.zero;
			edge = Vector3.zero;
			bool flag = false;
			Vector3 val = Vector3.positiveInfinity;
			Vector3 val2 = Vector3.negativeInfinity;
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				Mesh val4 = null;
				if (val3 is MeshRenderer)
				{
					MeshFilter component = ((Component)val3).GetComponent<MeshFilter>();
					if ((Object)(object)component != (Object)null)
					{
						val4 = component.sharedMesh;
					}
				}
				else
				{
					SkinnedMeshRenderer val5 = (SkinnedMeshRenderer)(object)((val3 is SkinnedMeshRenderer) ? val3 : null);
					if (val5 != null)
					{
						val4 = val5.sharedMesh;
					}
				}
				if (!((Object)(object)val4 == (Object)null))
				{
					Bounds bounds = val4.bounds;
					Matrix4x4 val6 = root.worldToLocalMatrix * ((Component)val3).transform.localToWorldMatrix;
					for (int j = 0; j < 8; j++)
					{
						Vector3 val7 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))));
						Vector3 val8 = ((Matrix4x4)(ref val6)).MultiplyPoint3x4(val7);
						val = Vector3.Min(val, val8);
						val2 = Vector3.Max(val2, val8);
						flag = true;
					}
				}
			}
			if (!flag)
			{
				return false;
			}
			Vector3 val9 = val2 - val;
			int num = 0;
			if (val9.y > ((Vector3)(ref val9))[num])
			{
				num = 1;
			}
			if (val9.z > ((Vector3)(ref val9))[num])
			{
				num = 2;
			}
			int num2 = ((num == 0) ? 1 : 0);
			for (int k = 0; k < 3; k++)
			{
				if (k != num && ((Vector3)(ref val9))[k] > ((Vector3)(ref val9))[num2])
				{
					num2 = k;
				}
			}
			if (((Vector3)(ref val9))[num] < 0.01f)
			{
				return false;
			}
			float num3 = ((Mathf.Abs(((Vector3)(ref val2))[num]) >= Mathf.Abs(((Vector3)(ref val))[num])) ? 1f : (-1f));
			blade = Vector3.zero;
			((Vector3)(ref blade))[num] = num3;
			edge = Vector3.zero;
			((Vector3)(ref edge))[num2] = 1f;
			return true;
		}

		public static bool IsKnife(SharedData s)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (s != null)
			{
				return (int)s.m_skillType == 2;
			}
			return false;
		}

		public static void EmptyHands(Player p)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			if (((Character)p).InAttack() || ((Character)p).InDodge())
			{
				return;
			}
			ItemData val = VanillaAccess.RightItem.Invoke((Humanoid)(object)p);
			ItemData val2 = VanillaAccess.LeftItem.Invoke((Humanoid)(object)p);
			if (val == null && val2 == null)
			{
				return;
			}
			ItemData val3 = VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)p);
			ItemData val4 = VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)p);
			LastRight = val;
			LastLeft = val2;
			Busy = true;
			try
			{
				if (val != null)
				{
					((Humanoid)p).UnequipItem(val, false);
				}
				if (val2 != null)
				{
					((Humanoid)p).UnequipItem(val2, false);
				}
				ref ItemData reference = ref VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)p);
				object obj = ((!StillHolsterable((Humanoid)(object)p, val)) ? (StillHolsterable((Humanoid)(object)p, val3) ? val3 : null) : val);
				reference = (ItemData)obj;
				ref ItemData reference2 = ref VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)p);
				object obj2 = ((!StillHolsterable((Humanoid)(object)p, val2)) ? (StillHolsterable((Humanoid)(object)p, val4) ? val4 : null) : val2);
				reference2 = (ItemData)obj2;
				VanillaAccess.SetupVisEquipment((Humanoid)(object)p);
				VanillaAccess.TriggerHolsterAnim((Humanoid)(object)p);
			}
			finally
			{
				Busy = false;
			}
			ExtraHolster.MarkDirty();
		}

		private static void ToggleMark(Player player)
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			ItemData hoveredPlayerItem = VanillaAccess.GetHoveredPlayerItem();
			if (hoveredPlayerItem == null)
			{
				if (HolsterConfig.DebugLog.Value)
				{
					Plugin.Log.LogInfo((object)("Mark: no item under the mouse (" + HoverTracker.Describe() + ")"));
				}
				return;
			}
			string text = ((Localization.instance != null) ? Localization.instance.Localize(hoveredPlayerItem.m_shared.m_name) : hoveredPlayerItem.m_shared.m_name);
			if (!IsHandItem(hoveredPlayerItem))
			{
				((Character)player).Message((MessageType)1, "This item cannot be holstered.", 0, (Sprite)null, false);
				return;
			}
			if (IsTool(hoveredPlayerItem) && !HolsterConfig.HolsterTools.Value)
			{
				((Character)player).Message((MessageType)1, "Tool holstering is disabled.", 0, (Sprite)null, false);
				return;
			}
			bool flag = !IsMarked(hoveredPlayerItem);
			SetMarked(hoveredPlayerItem, flag);
			SafePouchCompat.StoreMark(hoveredPlayerItem);
			if (!flag && HolsterConfig.OnlyMarked.Value)
			{
				bool flag2 = false;
				if (VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)player) == hoveredPlayerItem)
				{
					VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)player) = null;
					flag2 = true;
				}
				if (VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)player) == hoveredPlayerItem)
				{
					VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)player) = null;
					flag2 = true;
				}
				if (flag2)
				{
					VanillaAccess.SetupVisEquipment((Humanoid)(object)player);
				}
			}
			if (HolsterConfig.DebugLog.Value)
			{
				Plugin.Log.LogInfo((object)string.Format("Mark: {0} type={1} attach={2} skill={3} -> {4}", hoveredPlayerItem.m_shared.m_name, hoveredPlayerItem.m_shared.m_itemType, hoveredPlayerItem.m_shared.m_attachOverride, hoveredPlayerItem.m_shared.m_skillType, flag ? "marked" : "unmarked"));
			}
			((Character)player).Message((MessageType)1, flag ? (text + ": marked for holstering") : (text + ": no longer marked for holstering"), 0, (Sprite)null, false);
			ExtraHolster.MarkDirty();
		}
	}
	internal static class HolsterWheel
	{
		private class Slot
		{
			public RectTransform Root;

			public CanvasGroup Group;

			public Image Glow;

			public Image Base;

			public Image Rim;

			public Image Icon;

			public float Pop;

			public bool Holstered;
		}

		private const float RingRadius = 175f;

		private const float SlotSize = 84f;

		private const float IconSize = 58f;

		private const float MouseStep = 55f;

		private const float SpinSmooth = 0.075f;

		private const float FadeInTime = 0.14f;

		private const float FadeOutTime = 0.1f;

		private const float SlotInTime = 0.22f;

		private const float SlotStagger = 0.03f;

		private const float LabelPopTime = 0.16f;

		private const float SelectSpring = 18f;

		private static readonly Color Gold = new Color(1f, 0.78f, 0.38f, 1f);

		private static readonly Color BgCenter = new Color(0f, 0f, 0f, 0.92f);

		private static readonly Color PlateColor = new Color(0.03f, 0.025f, 0.02f, 0.88f);

		private static readonly Color TrackColor = new Color(1f, 0.82f, 0.5f, 0.28f);

		private static readonly Color SlotBase = new Color(0.03f, 0.025f, 0.02f, 0.95f);

		private static readonly Color SlotBaseSelected = new Color(0.2f, 0.12f, 0.04f, 0.97f);

		private static readonly Color RimIdle = new Color(1f, 0.85f, 0.6f, 0.35f);

		private static readonly Color RimHolstered = new Color(0.55f, 0.8f, 1f, 0.6f);

		private static readonly Color LabelColor = new Color(1f, 0.92f, 0.75f, 1f);

		private static readonly Color SubLabelColor = new Color(0.8f, 0.74f, 0.62f, 0.85f);

		private static float _holdStart;

		private static float _pendingTapAt = -1f;

		private static bool _secondPress;

		private static float _openedAt;

		private static float _closingAt = -1f;

		private static float _labelChangedAt;

		private static List<ItemData> _items = new List<ItemData>();

		private static int _targetIndex;

		private static float _currentIndex;

		private static float _spinVelocity;

		private static float _mouseAccum;

		private static int _shownSelected = -1;

		private static GameObject _root;

		private static CanvasGroup _group;

		private static RectTransform _content;

		private static RectTransform _ring;

		private static RectTransform _pointer;

		private static TMP_Text _label;

		private static TMP_Text _subLabel;

		private static readonly List<Slot> _slots = new List<Slot>();

		private static TMP_FontAsset _font;

		public static bool Holding { get; private set; }

		public static bool IsOpen { get; private set; }

		private static int Selected
		{
			get
			{
				if (_items.Count != 0)
				{
					return Mod(_targetIndex, _items.Count);
				}
				return -1;
			}
		}

		private static float Dt => Time.unscaledDeltaTime;

		private static float Now => Time.unscaledTime;

		private static int Mod(int a, int n)
		{
			return (a % n + n) % n;
		}

		public static void OnHideDown()
		{
			Holding = true;
			_holdStart = Now;
			_secondPress = _pendingTapAt >= 0f && Now - _pendingTapAt <= HolsterConfig.DoubleTapWindow.Value;
		}

		public static void Tick()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || InventoryGui.IsVisible() || Menu.IsVisible())
			{
				Holding = false;
				_pendingTapAt = -1f;
				_secondPress = false;
				Close(instant: true);
				return;
			}
			if (IsOpen || _closingAt >= 0f)
			{
				Animate();
			}
			if (!Holding && _pendingTapAt >= 0f && Now - _pendingTapAt > HolsterConfig.DoubleTapWindow.Value)
			{
				_pendingTapAt = -1f;
				HolsterLogic.TapHide(localPlayer);
			}
			if (!Holding)
			{
				return;
			}
			if (ZInput.GetButton("Hide"))
			{
				if (!IsOpen && !_secondPress && Now - _holdStart >= HolsterConfig.WheelHoldTime.Value)
				{
					_items = HolsterLogic.WheelItems(localPlayer);
					if (_items.Count > 0)
					{
						Open(localPlayer);
					}
				}
				if (IsOpen)
				{
					if (UnityInput.Current.GetMouseButtonDown(1))
					{
						Holding = false;
						Close(instant: false);
					}
					else
					{
						ReadSpinInput();
					}
				}
				return;
			}
			Holding = false;
			if (IsOpen)
			{
				int selected = Selected;
				ItemData val = ((selected >= 0) ? _items[selected] : null);
				Close(instant: false);
				if (val != null && !val.m_equipped && !((Character)localPlayer).InAttack() && !((Character)localPlayer).InDodge())
				{
					((Humanoid)localPlayer).EquipItem(val, true);
				}
			}
			else if (_secondPress)
			{
				_secondPress = false;
				_pendingTapAt = -1f;
				HolsterLogic.EmptyHands(localPlayer);
			}
			else if (HolsterConfig.DoubleTapEmpty.Value && (VanillaAccess.RightItem.Invoke((Humanoid)(object)localPlayer) != null || VanillaAccess.LeftItem.Invoke((Humanoid)(object)localPlayer) != null))
			{
				_pendingTapAt = Now;
			}
			else
			{
				HolsterLogic.TapHide(localPlayer);
			}
		}

		private static void ReadSpinInput()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			if (_items.Count > 1)
			{
				_mouseAccum += ZInput.GetMouseDelta().x * HolsterConfig.WheelMouseSensitivity.Value;
				while (_mouseAccum >= 55f)
				{
					_targetIndex++;
					_mouseAccum -= 55f;
				}
				while (_mouseAccum <= -55f)
				{
					_targetIndex--;
					_mouseAccum += 55f;
				}
				float y = UnityInput.Current.mouseScrollDelta.y;
				if (y > 0.01f)
				{
					_targetIndex--;
				}
				else if (y < -0.01f)
				{
					_targetIndex++;
				}
			}
		}

		private static void Open(Player p)
		{
			EnsureUI();
			IsOpen = true;
			_closingAt = -1f;
			_openedAt = Now;
			_mouseAccum = 0f;
			_spinVelocity = 0f;
			_shownSelected = -1;
			ItemData val = VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)p);
			ItemData val2 = VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)p);
			_targetIndex = 0;
			for (int i = 0; i < _items.Count; i++)
			{
				if (_items[i] == val || _items[i] == val2)
				{
					_targetIndex = i;
					break;
				}
			}
			_currentIndex = (float)_targetIndex - 1.2f;
			foreach (Slot slot in _slots)
			{
				Object.Destroy((Object)(object)((Component)slot.Root).gameObject);
			}
			_slots.Clear();
			for (int j = 0; j < _items.Count; j++)
			{
				_slots.Add(CreateSlot(j, _items[j], _items[j] == val || _items[j] == val2));
			}
			SetLabels(null);
			_group.alpha = 0f;
			_root.SetActive(true);
			Animate();
		}

		private static void Close(bool instant)
		{
			if (!IsOpen && _closingAt < 0f)
			{
				return;
			}
			IsOpen = false;
			if (instant || (Object)(object)_root == (Object)null)
			{
				_closingAt = -1f;
				if ((Object)(object)_root != (Object)null)
				{
					_root.SetActive(false);
				}
			}
			else if (_closingAt < 0f)
			{
				_closingAt = Now;
			}
		}

		private static void Animate()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null)
			{
				return;
			}
			if (!IsOpen)
			{
				float num = Mathf.Clamp01((Now - _closingAt) / 0.1f);
				_group.alpha = 1f - num;
				((Transform)_content).localScale = Vector3.one * Mathf.Lerp(1f, 0.9f, UiUtil.EaseOutCubic(num));
				if (num >= 1f)
				{
					_closingAt = -1f;
					_root.SetActive(false);
				}
				return;
			}
			int count = _items.Count;
			if (count != 0)
			{
				float num2 = Now - _openedAt;
				_group.alpha = UiUtil.EaseOutCubic(num2 / 0.14f);
				((Transform)_content).localScale = Vector3.one * Mathf.Lerp(0.85f, 1f, UiUtil.EaseOutBack(num2 / 0.224f));
				_currentIndex = Mathf.SmoothDamp(_currentIndex, (float)_targetIndex, ref _spinVelocity, 0.075f, float.PositiveInfinity, Dt);
				float num3 = 360f / (float)count;
				int selected = Selected;
				for (int i = 0; i < count; i++)
				{
					Slot slot = _slots[i];
					float t = (num2 - (float)i * 0.03f) / 0.22f;
					float num4 = 175f * UiUtil.EaseOutBack(t);
					float num5 = UiUtil.EaseOutCubic(t);
					float num6 = Mathf.DeltaAngle(0f, (_currentIndex - (float)i) * num3);
					float num7 = (90f + num6) * (MathF.PI / 180f);
					slot.Root.anchoredPosition = new Vector2(Mathf.Cos(num7), Mathf.Sin(num7)) * num4;
					float num8 = 1f - Mathf.Clamp01(Mathf.Abs(num6) / 150f);
					slot.Group.alpha = num5 * Mathf.Lerp(0.35f, 1f, num8);
					float num9 = ((i == selected) ? 1f : 0f);
					slot.Pop = Mathf.Lerp(slot.Pop, num9, 1f - Mathf.Exp(-18f * Dt));
					float num10 = Mathf.Lerp(0.82f, 1f, num8) + slot.Pop * 0.3f;
					((Transform)slot.Root).localScale = Vector3.one * num10 * Mathf.Lerp(0.4f, 1f, num5);
					((Graphic)slot.Base).color = Color.Lerp(SlotBase, SlotBaseSelected, slot.Pop);
					((Graphic)slot.Rim).color = Color.Lerp(slot.Holstered ? RimHolstered : RimIdle, Gold, slot.Pop);
					Color gold = Gold;
					gold.a = 0.55f * slot.Pop * (0.85f + 0.15f * Mathf.Sin(Now * 6f));
					((Graphic)slot.Glow).color = gold;
				}
				float num11 = Mathf.Sin(Now * 5f) * 3f;
				_pointer.anchoredPosition = new Vector2(0f, 243f + num11);
				if (selected != _shownSelected)
				{
					_shownSelected = selected;
					_labelChangedAt = Now;
					SetLabels(_items[selected]);
				}
				float t2 = Mathf.Clamp01((Now - _labelChangedAt) / 0.16f);
				float num12 = Mathf.Lerp(1.15f, 1f, UiUtil.EaseOutCubic(t2));
				((Transform)_label.rectTransform).localScale = Vector3.one * num12;
				_label.alpha = Mathf.Lerp(0.2f, 1f, UiUtil.EaseOutCubic(t2));
				_subLabel.alpha = _label.alpha * SubLabelColor.a;
			}
		}

		private static void SetLabels(ItemData item)
		{
			if (!((Object)(object)_label == (Object)null))
			{
				if (item == null)
				{
					_label.text = "";
					_subLabel.text = "";
					return;
				}
				_label.text = ((Localization.instance != null) ? Localization.instance.Localize(item.m_shared.m_name) : item.m_shared.m_name);
				Player localPlayer = Player.m_localPlayer;
				bool flag = (Object)(object)localPlayer != (Object)null && (item == VanillaAccess.HiddenRightItem.Invoke((Humanoid)(object)localPlayer) || item == VanillaAccess.HiddenLeftItem.Invoke((Humanoid)(object)localPlayer));
				_subLabel.text = KindName(item) + (flag ? "  ·  holstered" : "");
			}
		}

		private static string KindName(ItemData item)
		{
			//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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0021: 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_0035: Expected I4, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Invalid comparison between Unknown and I4
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Invalid comparison between Unknown and I4
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Invalid comparison between Unknown and I4
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Invalid comparison between Unknown and I4
			SharedData shared = item.m_shared;
			if (HolsterJoints.IsStaff(shared))
			{
				return "Staff";
			}
			ItemType itemType = shared.m_itemType;
			if ((int)itemType <= 14)
			{
				switch (itemType - 3)
				{
				case 1:
					if ((int)shared.m_skillType != 14)
					{
						return "Bow";
					}
					return "Crossbow";
				case 2:
					return "Shield";
				case 0:
					if ((int)shared.m_skillType != 5)
					{
						if ((int)shared.m_skillType != 2)
						{
							return "One-handed";
						}
						return "Knife";
					}
					return "Spear";
				}
				if ((int)itemType == 14)
				{
					goto IL_0069;
				}
			}
			else
			{
				if ((int)itemType == 15)
				{
					return "Torch";
				}
				if ((int)itemType == 19)
				{
					return "Tool";
				}
				if ((int)itemType == 22)
				{
					goto IL_0069;
				}
			}
			return "";
			IL_0069:
			return "Two-handed";
		}

		private static Slot CreateSlot(int index, ItemData item, bool holstered)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Slot" + index, new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)_ring, false);
			val2.sizeDelta = new Vector2(84f, 84f);
			Slot obj = new Slot
			{
				Root = val2,
				Group = val.AddComponent<CanvasGroup>(),
				Holstered = holstered
			};
			obj.Group.interactable = false;
			obj.Group.blocksRaycasts = false;
			obj.Glow = NewImage("Glow", (Transform)(object)val2, UiUtil.Glow(), 159.59999f);
			((Graphic)obj.Glow).color = Color.clear;
			obj.Base = NewImage("Base", (Transform)(object)val2, UiUtil.Circle(), 84f);
			obj.Rim = NewImage("Rim", (Transform)(object)val2, UiUtil.Ring(), 90f);
			obj.Icon = NewImage("Icon", (Transform)(object)val2, item.GetIcon(), 58f);
			obj.Icon.preserveAspect = true;
			return obj;
		}

		private static void EnsureUI()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root != (Object)null))
			{
				_root = new GameObject("ValheimHolster_Wheel");
				Object.DontDestroyOnLoad((Object)(object)_root);
				Canvas obj = _root.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 500;
				CanvasScaler obj2 = _root.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				obj2.matchWidthOrHeight = 1f;
				_group = _root.AddComponent<CanvasGroup>();
				_group.interactable = false;
				_group.blocksRaycasts = false;
				_content = (RectTransform)new GameObject("Content", new Type[1] { typeof(RectTransform) }).transform;
				((Transform)_content).SetParent(_root.transform, false);
				_content.sizeDelta = Vector2.zero;
				((Graphic)NewImage("Background", (Transform)(object)_content, UiUtil.Glow(), 621.60004f)).color = BgCenter;
				((Graphic)NewImage("Track", (Transform)(object)_content, UiUtil.Ring(), 354f)).color = TrackColor;
				((Graphic)NewImage("Plate", (Transform)(object)_content, UiUtil.Circle(), 256f)).color = PlateColor;
				_ring = (RectTransform)new GameObject("Ring", new Type[1] { typeof(RectTransform) }).transform;
				((Transform)_ring).SetParent((Transform)(object)_content, false);
				_ring.sizeDelta = Vector2.zero;
				Image obj3 = NewImage("Pointer", (Transform)(object)_content, UiUtil.Triangle(), 26f);
				((Graphic)obj3).color = Gold;
				_pointer = ((Graphic)obj3).rectTransform;
				TMP_FontAsset font = FindGameFont();
				float width = 226f;
				_label = NewText("Label", (Transform)(object)_content, font, 24f, 14f, LabelColor, new Vector2(0f, 12f), width, (FontStyles)1);
				_subLabel = NewText("SubLabel", (Transform)(object)_content, font, 15f, 12f, SubLabelColor, new Vector2(0f, -18f), width, (FontStyles)2);
				_root.SetActive(false);
			}
		}

		private static TMP_Text NewText(string name, Transform parent, TMP_FontAsset font, float maxSize, float minSize, Color color, Vector2 pos, float width, FontStyles style)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			RectTransform val2 = (RectTransform)val.transform;
			val2.sizeDelta = new Vector2(width, maxSize + 12f);
			val2.anchoredPosition = pos;
			val.SetActive(false);
			TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val3).font = font;
			}
			val.SetActive(true);
			((TMP_Text)val3).fontStyle = style;
			((TMP_Text)val3).enableAutoSizing = true;
			((TMP_Text)val3).fontSizeMax = maxSize;
			((TMP_Text)val3).fontSizeMin = minSize;
			((TMP_Text)val3).fontSize = maxSize;
			((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
			((Graphic)val3).color = color;
			((TMP_Text)val3).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val3).overflowMode = (TextOverflowModes)1;
			((Graphic)val3).raycastTarget = false;
			((TMP_Text)val3).outlineWidth = 0.18f;
			((TMP_Text)val3).outlineColor = new Color32((byte)0, (byte)0, (byte)0, (byte)220);
			return (TMP_Text)(object)val3;
		}

		private static TMP_FontAsset FindGameFont()
		{
			if ((Object)(object)_font != (Object)null)
			{
				return _font;
			}
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			TMP_FontAsset[] array2 = array;
			foreach (TMP_FontAsset val in array2)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name.ToLowerInvariant().Contains("averia") && ((Object)val).name.ToLowerInvariant().Contains("bold"))
				{
					return _font = val;
				}
			}
			array2 = array;
			foreach (TMP_FontAsset val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)val2).name.ToLowerInvariant().Contains("averia"))
				{
					return _font = val2;
				}
			}
			Dictionary<TMP_FontAsset, int> dictionary = new Dictionary<TMP_FontAsset, int>();
			TMP_Text[] array3 = (((Object)(object)Hud.instance != (Object)null) ? ((Component)Hud.instance).GetComponentsInChildren<TMP_Text>(true) : Resources.FindObjectsOfTypeAll<TMP_Text>());
			foreach (TMP_Text val3 in array3)
			{
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.font == (Object)null))
				{
					dictionary.TryGetValue(val3.font, out var value);
					dictionary[val3.font] = value + 1;
				}
			}
			int num = -1;
			foreach (KeyValuePair<TMP_FontAsset, int> item in dictionary)
			{
				if (item.Value > num)
				{
					num = item.Value;
					_font = item.Key;
				}
			}
			if (HolsterConfig.DebugLog.Value)
			{
				Plugin.Log.LogInfo((object)("Wheel: font " + (((Object)(object)_font != (Object)null) ? ((Object)_font).name : "NONE")));
			}
			return _font;
		}

		private static Image NewImage(string name, Transform parent, Sprite sprite, float size)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(parent, false);
			Image obj = val.AddComponent<Image>();
			obj.sprite = sprite;
			((Graphic)obj).raycastTarget = false;
			((Graphic)obj).rectTransform.sizeDelta = new Vector2(size, size);
			return obj;
		}
	}
	internal static class HoverTracker
	{
		private static GameObject _source;

		public static InventoryGrid Grid { get; private set; }

		public static InventoryElement Element { get; private set; }

		public static bool IsValid
		{
			get
			{
				if ((Object)(object)Element != (Object)null && ((Object)(object)Grid != (Object)null || SafePouchCompat.OwnsElement(Element)))
				{
					return ((Component)Element).gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		public static void Enter(GameObject tooltipGo)
		{
			InventoryElement componentInParent = tooltipGo.GetComponentInParent<InventoryElement>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				_source = tooltipGo;
				Element = componentInParent;
				Grid = ((Component)componentInParent).GetComponentInParent<InventoryGrid>();
			}
		}

		public static void Exit(GameObject tooltipGo)
		{
			if (!((Object)(object)tooltipGo != (Object)(object)_source))
			{
				_source = null;
				Element = null;
				Grid = null;
			}
		}

		public static string Describe()
		{
			return "grid=" + (((Object)(object)Grid != (Object)null) ? ((Object)Grid).name : "null") + " element=" + (((Object)(object)Element != (Object)null) ? ((Object)Element).name : "null");
		}
	}
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	internal static class Humanoid_EquipItem_Patch
	{
		private static void Prefix(Humanoid __instance, ItemData item, out EquipState __state)
		{
			HolsterLogic.EquipDepth++;
			__state = default(EquipState);
			if (!HolsterLogic.Busy && HolsterLogic.IsActive(__instance) && HolsterConfig.HolsterOnSwap.Value && HolsterLogic.IsHandItem(item))
			{
				__state = new EquipState
				{
					Track = true,
					Right = VanillaAccess.RightItem.Invoke(__instance),
					Left = VanillaAccess.LeftItem.Invoke(__instance),
					HiddenRight = VanillaAccess.HiddenRightItem.Invoke(__instance),
					HiddenLeft = VanillaAccess.HiddenLeftItem.Invoke(__instance)
				};
			}
		}

		private static void Postfix(Humanoid __instance, ItemData item, bool __result, EquipState __state)
		{
			if (!__result)
			{
				return;
			}
			if (__state.Track)
			{
				ItemData val = VanillaAccess.RightItem.Invoke(__instance);
				ItemData val2 = VanillaAccess.LeftItem.Invoke(__instance);
				ItemData val3 = ((__state.Right != null && __state.Right != val && __state.Right != val2) ? __state.Right : null);
				ItemData val4 = ((__state.Left != null && __state.Left != val && __state.Left != val2) ? __state.Left : null);
				if (val3 != null || val4 != null)
				{
					HolsterLogic.RememberLast(__instance, val3, val4);
				}
				ItemData val5 = ((!HolsterLogic.StillHolsterable(__instance, val3)) ? ((HolsterLogic.StillHolsterable(__instance, __state.HiddenRight) && __state.HiddenRight != item) ? __state.HiddenRight : null) : val3);
				ItemData val6 = ((!HolsterLogic.StillHolsterable(__instance, val4)) ? ((HolsterLogic.StillHolsterable(__instance, __state.HiddenLeft) && __state.HiddenLeft != item) ? __state.HiddenLeft : null) : val4);
				VanillaAccess.HiddenRightItem.Invoke(__instance) = val5;
				VanillaAccess.HiddenLeftItem.Invoke(__instance) = val6;
				VanillaAccess.SetupVisEquipment(__instance);
			}
			if (!HolsterLogic.Busy && HolsterLogic.EquipDepth == 1 && HolsterLogic.IsActive(__instance))
			{
				HolsterLogic.TryAutoEquipShield(__instance, item);
			}
		}

		private static void Finalizer()
		{
			HolsterLogic.EquipDepth--;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "HideHandItems")]
	internal static class Humanoid_HideHandItems_Patch
	{
		private static bool Prefix(Humanoid __instance, bool onlyRightHand, ref bool __result)
		{
			if (HolsterLogic.SuppressVanillaHide && !HolsterLogic.ModCall && HolsterLogic.IsLocal(__instance))
			{
				__result = false;
				return false;
			}
			if (HolsterLogic.Busy || onlyRightHand || !HolsterLogic.HideKeyThisFrame)
			{
				return true;
			}
			if (!HolsterLogic.IsActive(__instance) || !HolsterConfig.SwapWithHideKey.Value)
			{
				return true;
			}
			if (((Character)__instance).IsSwimming())
			{
				return true;
			}
			if (HolsterLogic.SwapWithHolster(__instance))
			{
				__result = true;
				return false;
			}
			if (HolsterLogic.ModCall && HolsterConfig.DoubleTapEmpty.Value)
			{
				__result = false;
				return false;
			}
			return true;
		}

		private static void Postfix(Humanoid __instance)
		{
			if (HolsterLogic.HideKeyThisFrame && HolsterLogic.IsActive(__instance) && HolsterConfig.OnlyMarked.Value)
			{
				bool flag = false;
				ItemData val = VanillaAccess.HiddenRightItem.Invoke(__instance);
				ItemData val2 = VanillaAccess.HiddenLeftItem.Invoke(__instance);
				if (val != null && !HolsterLogic.CanHolster(val))
				{
					VanillaAccess.HiddenRightItem.Invoke(__instance) = null;
					flag = true;
				}
				if (val2 != null && !HolsterLogic.CanHolster(val2))
				{
					VanillaAccess.HiddenLeftItem.Invoke(__instance) = null;
					flag = true;
				}
				if (flag)
				{
					VanillaAccess.SetupVisEquipment(__instance);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "ShowHandItems")]
	internal static class Humanoid_ShowHandItems_Patch
	{
		private static bool Prefix(Humanoid __instance)
		{
			if (HolsterLogic.SuppressVanillaHide && !HolsterLogic.ModCall)
			{
				return !HolsterLogic.IsLocal(__instance);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "ToggleEquipped")]
	internal static class Humanoid_ToggleEquipped_Patch
	{
		private static bool Prefix(Humanoid __instance, ItemData item, ref bool __result)
		{
			if (!HolsterConfig.LockHotbar.Value || !HolsterLogic.IsActive(__instance))
			{
				return true;
			}
			if (InventoryGui.IsVisible())
			{
				return true;
			}
			if (!__instance.IsItemEquiped(item) || !HolsterLogic.IsHandItem(item) || HolsterLogic.IsTool(item))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UnequipItem")]
	internal static class Humanoid_UnequipItem_Patch
	{
		private static void Postfix(Humanoid __instance, ItemData item)
		{
			if (!HolsterLogic.Busy && HolsterLogic.EquipDepth <= 0 && HolsterLogic.IsActive(__instance) && HolsterLogic.IsOneHandWeapon(item))
			{
				HolsterLogic.TryAutoUnequipShield(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGri